package provider import ( "strings" "testing" ) func TestLoadConfig_valid(t *testing.T) { t.Parallel() data := []byte(` providers: - name: mock type: mock mock: provisionDelaySeconds: 2 - name: gcp-eu type: gcp gcp: project: my-project network: custom-net `) cfg, err := LoadConfig(data) if err != nil { t.Fatalf("LoadConfig() error = %v, want nil", err) } if len(cfg.Providers) != 2 { t.Fatalf("len(cfg.Providers) = %d, want 2", len(cfg.Providers)) } if cfg.Providers[0].Mock == nil || cfg.Providers[0].Mock.ProvisionDelaySeconds != 2 { t.Errorf("providers[0].mock = %+v, want ProvisionDelaySeconds=2", cfg.Providers[0].Mock) } if cfg.Providers[1].GCP == nil || cfg.Providers[1].GCP.Project != "my-project" { t.Errorf("providers[1].gcp = %+v, want Project=my-project", cfg.Providers[1].GCP) } } func TestLoadConfig_invalid(t *testing.T) { t.Parallel() tests := []struct { name string yaml string wantErrSub string }{ { name: "empty providers list", yaml: `providers: []`, wantErrSub: "at least one provider", }, { name: "missing name", yaml: ` providers: - type: mock`, wantErrSub: "name is required", }, { name: "duplicate name", yaml: ` providers: - name: mock type: mock - name: mock type: mock`, wantErrSub: "duplicate provider name", }, { name: "unknown type", yaml: ` providers: - name: p1 type: azure`, wantErrSub: `unknown provider type "azure"`, }, { name: "missing type", yaml: ` providers: - name: p1`, wantErrSub: "type is required", }, { name: "gcp missing project", yaml: ` providers: - name: gcp-eu type: gcp`, wantErrSub: "gcp.project is required", }, { name: "gcp with empty project", yaml: ` providers: - name: gcp-eu type: gcp gcp: project: ""`, wantErrSub: "gcp.project is required", }, { name: "mock type with gcp block", yaml: ` providers: - name: p1 type: mock gcp: project: my-project`, wantErrSub: "type is mock but a gcp block is set", }, { name: "gcp type with mock block", yaml: ` providers: - name: p1 type: gcp gcp: project: my-project mock: failNextCreates: 1`, wantErrSub: "type is gcp but a mock block is set", }, { name: "unknown mock.failWith", yaml: ` providers: - name: p1 type: mock mock: failWith: oops`, wantErrSub: `unknown mock.failWith "oops"`, }, { name: "strict mode rejects unknown top-level key", yaml: ` providers: - name: p1 type: mock extraneous: true`, wantErrSub: "parsing providers config", }, { name: "strict mode rejects unknown provider key", yaml: ` providers: - name: p1 type: mock bogus: true`, wantErrSub: "parsing providers config", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { t.Parallel() _, err := LoadConfig([]byte(tc.yaml)) if err == nil { t.Fatalf("LoadConfig() error = nil, want error containing %q", tc.wantErrSub) } if !strings.Contains(err.Error(), tc.wantErrSub) { t.Errorf("LoadConfig() error = %q, want substring %q", err.Error(), tc.wantErrSub) } }) } } func TestLoadConfigFile_missingFile(t *testing.T) { t.Parallel() _, err := LoadConfigFile("/nonexistent/providers.yaml") if err == nil { t.Fatal("LoadConfigFile() error = nil, want error") } if !strings.Contains(err.Error(), "reading providers config") { t.Errorf("LoadConfigFile() error = %q, want substring %q", err.Error(), "reading providers config") } }