package cli import ( "errors" "testing" "forge.lclr.dev/AI/mcp-framework/secretstore" ) type testSecretStore struct { values map[string]string errs map[string]error } func (s testSecretStore) SetSecret(name, label, secret string) error { return nil } func (s testSecretStore) GetSecret(name string) (string, error) { if err, ok := s.errs[name]; ok { return "", err } value, ok := s.values[name] if !ok { return "", secretstore.ErrNotFound } return value, nil } func (s testSecretStore) DeleteSecret(name string) error { return nil } func TestResolveLookupWithStandardProviders(t *testing.T) { t.Setenv("MCP_PASSWORD", "") lookup := ResolveLookup(ResolveLookupOptions{ Flag: MapLookup(map[string]string{"host": "https://flag.example.com"}), Env: EnvLookup(nil), Config: ConfigMap(map[string]string{"username": "config-user"}), Secret: SecretStore(testSecretStore{ values: map[string]string{"smtp-password": "secret-password"}, }), }) resolution, err := ResolveFields(ResolveOptions{ Fields: []FieldSpec{ { Name: "host", Required: true, FlagKey: "host", }, { Name: "username", Required: true, EnvKey: "MCP_USERNAME", ConfigKey: "username", }, { Name: "password", Required: true, EnvKey: "MCP_PASSWORD", SecretKey: "smtp-password", }, }, Lookup: lookup, }) if err != nil { t.Fatalf("ResolveFields returned error: %v", err) } host, _ := resolution.Get("host") if host.Source != SourceFlag || host.Value != "https://flag.example.com" { t.Fatalf("host = %+v", host) } username, _ := resolution.Get("username") if username.Source != SourceConfig || username.Value != "config-user" { t.Fatalf("username = %+v", username) } password, _ := resolution.Get("password") if password.Source != SourceSecret || password.Value != "secret-password" { t.Fatalf("password = %+v", password) } } func TestSecretStoreProviderTreatsErrNotFoundAsMissing(t *testing.T) { lookup := ResolveLookup(ResolveLookupOptions{ Secret: SecretStore(testSecretStore{ errs: map[string]error{"smtp-password": secretstore.ErrNotFound}, }), }) resolution, err := ResolveFields(ResolveOptions{ Fields: []FieldSpec{ { Name: "password", Required: true, SecretKey: "smtp-password", DefaultValue: "fallback-password", }, }, Lookup: lookup, }) if err != nil { t.Fatalf("ResolveFields returned error: %v", err) } password, _ := resolution.Get("password") if password.Source != SourceDefault || password.Value != "fallback-password" { t.Fatalf("password = %+v", password) } } func TestSecretStoreProviderPropagatesBackendErrors(t *testing.T) { backendErr := errors.New("backend unavailable") lookup := ResolveLookup(ResolveLookupOptions{ Secret: SecretStore(testSecretStore{ errs: map[string]error{"smtp-password": backendErr}, }), }) _, err := ResolveFields(ResolveOptions{ Fields: []FieldSpec{ { Name: "password", Required: true, SecretKey: "smtp-password", }, }, Lookup: lookup, }) var sourceErr *SourceLookupError if !errors.As(err, &sourceErr) { t.Fatalf("ResolveFields error = %v, want SourceLookupError", err) } if sourceErr.Source != SourceSecret { t.Fatalf("sourceErr.Source = %q, want %q", sourceErr.Source, SourceSecret) } if !errors.Is(err, backendErr) { t.Fatalf("ResolveFields error should wrap backend error") } }