初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"oci-portal/internal/oci"
|
||||
)
|
||||
|
||||
func TestCreateInstanceValidation(t *testing.T) {
|
||||
valid := oci.CreateInstanceInput{
|
||||
AvailabilityDomain: "AD-1",
|
||||
DisplayName: "vm1",
|
||||
Shape: "VM.Standard.A1.Flex",
|
||||
ImageID: "ocid1.image..a",
|
||||
SubnetID: "ocid1.subnet..s",
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*oci.CreateInstanceInput)
|
||||
wantErr string
|
||||
}{
|
||||
{name: "合法输入", mutate: func(*oci.CreateInstanceInput) {}},
|
||||
{name: "缺名称", mutate: func(in *oci.CreateInstanceInput) { in.DisplayName = "" }, wantErr: "displayName"},
|
||||
{name: "可用域可空(默认 ad-1)", mutate: func(in *oci.CreateInstanceInput) { in.AvailabilityDomain = "" }},
|
||||
{name: "缺 shape", mutate: func(in *oci.CreateInstanceInput) { in.Shape = "" }, wantErr: "shape"},
|
||||
{name: "缺启动源", mutate: func(in *oci.CreateInstanceInput) { in.ImageID = "" }, wantErr: "imageId or bootVolumeId"},
|
||||
{name: "启动源互斥", mutate: func(in *oci.CreateInstanceInput) { in.BootVolumeID = "bv" }, wantErr: "mutually exclusive"},
|
||||
{name: "子网可空(自动建网)", mutate: func(in *oci.CreateInstanceInput) { in.SubnetID = "" }},
|
||||
{name: "密钥与密码互斥", mutate: func(in *oci.CreateInstanceInput) {
|
||||
in.SSHPublicKey = "ssh-ed25519 AAA"
|
||||
in.RootPassword = "pw"
|
||||
}, wantErr: "sshPublicKey and rootPassword"},
|
||||
{name: "随机密码与密钥互斥", mutate: func(in *oci.CreateInstanceInput) {
|
||||
in.GenerateRootPassword = true
|
||||
in.SSHPublicKey = "ssh-ed25519 AAA"
|
||||
}, wantErr: "generateRootPassword"},
|
||||
{name: "随机密码与固定密码互斥", mutate: func(in *oci.CreateInstanceInput) {
|
||||
in.GenerateRootPassword = true
|
||||
in.RootPassword = "pw"
|
||||
}, wantErr: "generateRootPassword"},
|
||||
}
|
||||
svc := newTestService(t, &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}})
|
||||
cfg := importAliveConfig(t, svc)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
in := valid
|
||||
tt.mutate(&in)
|
||||
_, _, err := svc.CreateInstances(context.Background(), cfg.ID, in, 1)
|
||||
if tt.wantErr == "" {
|
||||
if err != nil {
|
||||
t.Errorf("CreateInstances: %v, want success", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
|
||||
t.Errorf("CreateInstances error = %v, want contains %q", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateInstancesBatch(t *testing.T) {
|
||||
client := &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}}
|
||||
svc := newTestService(t, client)
|
||||
cfg := importAliveConfig(t, svc)
|
||||
in := oci.CreateInstanceInput{DisplayName: "vm", Shape: "VM.Standard.A1.Flex", ImageID: "img"}
|
||||
|
||||
for _, count := range []int{0, 11} {
|
||||
if _, _, err := svc.CreateInstances(context.Background(), cfg.ID, in, count); err == nil {
|
||||
t.Errorf("count=%d: got nil error, want out-of-range failure", count)
|
||||
}
|
||||
}
|
||||
|
||||
instances, failures, err := svc.CreateInstances(context.Background(), cfg.ID, in, 3)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateInstances: %v", err)
|
||||
}
|
||||
if len(failures) != 0 {
|
||||
t.Errorf("failures = %v, want none", failures)
|
||||
}
|
||||
got := make([]string, 0, len(instances))
|
||||
for _, inst := range instances {
|
||||
got = append(got, inst.DisplayName)
|
||||
}
|
||||
want := []string{"vm-1", "vm-2", "vm-3"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("created %d instances %v, want %v", len(got), got, want)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Errorf("instance %d name = %q, want %q", i, got[i], want[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateInstancesGeneratedRootPassword(t *testing.T) {
|
||||
client := &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}}
|
||||
svc := newTestService(t, client)
|
||||
cfg := importAliveConfig(t, svc)
|
||||
in := oci.CreateInstanceInput{
|
||||
DisplayName: "vm",
|
||||
Shape: "VM.Standard.A1.Flex",
|
||||
ImageID: "img",
|
||||
GenerateRootPassword: true,
|
||||
FreeformTags: map[string]string{"env": "prod"},
|
||||
}
|
||||
|
||||
if _, _, err := svc.CreateInstances(context.Background(), cfg.ID, in, 2); err != nil {
|
||||
t.Fatalf("CreateInstances: %v", err)
|
||||
}
|
||||
if len(client.launched) != 2 {
|
||||
t.Fatalf("launched %d instances, want 2", len(client.launched))
|
||||
}
|
||||
pwds := map[string]bool{}
|
||||
for i, got := range client.launched {
|
||||
if got.RootPassword == "" {
|
||||
t.Errorf("instance %d: RootPassword empty, want generated", i)
|
||||
}
|
||||
if got.FreeformTags["RootPassword"] != got.RootPassword {
|
||||
t.Errorf("instance %d: tag RootPassword = %q, want %q", i, got.FreeformTags["RootPassword"], got.RootPassword)
|
||||
}
|
||||
if got.FreeformTags["env"] != "prod" {
|
||||
t.Errorf("instance %d: tag env = %q, want prod (原有标签须保留)", i, got.FreeformTags["env"])
|
||||
}
|
||||
pwds[got.RootPassword] = true
|
||||
}
|
||||
if len(pwds) != 2 {
|
||||
t.Errorf("批量创建密码应各台独立, got %d 个不同密码", len(pwds))
|
||||
}
|
||||
if in.FreeformTags["RootPassword"] != "" {
|
||||
t.Error("原始输入 FreeformTags 被修改, 应复制后再写入")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateInstanceRequiresChange(t *testing.T) {
|
||||
svc := newTestService(t, &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}})
|
||||
cfg := importAliveConfig(t, svc)
|
||||
if _, err := svc.UpdateInstance(context.Background(), cfg.ID, "ocid1.instance..i", oci.UpdateInstanceInput{}); err == nil {
|
||||
t.Error("UpdateInstance with empty input: got nil error, want failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateConsoleConnectionValidation(t *testing.T) {
|
||||
svc := newTestService(t, &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}})
|
||||
cfg := importAliveConfig(t, svc)
|
||||
tests := []struct {
|
||||
name string
|
||||
key string
|
||||
}{
|
||||
{name: "空公钥", key: ""},
|
||||
{name: "非 RSA 公钥", key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA test"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if _, err := svc.CreateConsoleConnection(context.Background(), cfg.ID, "", "ocid1.instance..i", tt.key); err == nil {
|
||||
t.Error("CreateConsoleConnection: got nil error, want failure")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteInstanceIpv6RequiresAddress(t *testing.T) {
|
||||
svc := newTestService(t, &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}})
|
||||
cfg := importAliveConfig(t, svc)
|
||||
if err := svc.DeleteInstanceIpv6(context.Background(), cfg.ID, "", "ocid1.instance..i", ""); err == nil {
|
||||
t.Error("DeleteInstanceIpv6 with empty address: got nil error, want failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateBootVolumeRequiresChange(t *testing.T) {
|
||||
svc := newTestService(t, &fakeClient{tenancy: oci.TenancyInfo{Name: "t"}})
|
||||
cfg := importAliveConfig(t, svc)
|
||||
if _, err := svc.UpdateBootVolume(context.Background(), cfg.ID, "ocid1.bootvolume..b", oci.UpdateBootVolumeInput{}); err == nil {
|
||||
t.Error("UpdateBootVolume with empty input: got nil error, want failure")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user