fetch_ml/internal/auth/keychain_test.go
Jeremie Fraeys 803677be57 feat: implement Go backend with comprehensive API and internal packages
- Add API server with WebSocket support and REST endpoints
- Implement authentication system with API keys and permissions
- Add task queue system with Redis backend and error handling
- Include storage layer with database migrations and schemas
- Add comprehensive logging, metrics, and telemetry
- Implement security middleware and network utilities
- Add experiment management and container orchestration
- Include configuration management with smart defaults
2025-12-04 16:53:53 -05:00

129 lines
3.2 KiB
Go

package auth
import (
"errors"
"os"
"path/filepath"
"testing"
"github.com/zalando/go-keyring"
)
type fakeKeyring struct {
secrets map[string]string
setErr error
getErr error
deleteErr error
}
func newFakeKeyring() *fakeKeyring {
return &fakeKeyring{secrets: make(map[string]string)}
}
func (f *fakeKeyring) Set(service, account, secret string) error {
if f.setErr != nil {
return f.setErr
}
f.secrets[key(service, account)] = secret
return nil
}
func (f *fakeKeyring) Get(service, account string) (string, error) {
if f.getErr != nil {
return "", f.getErr
}
if secret, ok := f.secrets[key(service, account)]; ok {
return secret, nil
}
return "", keyring.ErrNotFound
}
func (f *fakeKeyring) Delete(service, account string) error {
if f.deleteErr != nil {
return f.deleteErr
}
delete(f.secrets, key(service, account))
return nil
}
func key(service, account string) string {
return service + ":" + account
}
func newTestManager(t *testing.T, kr systemKeyring) (*KeychainManager, string) {
t.Helper()
baseDir := t.TempDir()
return newKeychainManagerWithKeyring(kr, baseDir), baseDir
}
func TestKeychainStoreAndGetPrimary(t *testing.T) {
kr := newFakeKeyring()
km, baseDir := newTestManager(t, kr)
if err := km.StoreAPIKey("fetch-ml", "alice", "super-secret"); err != nil {
t.Fatalf("StoreAPIKey failed: %v", err)
}
got, err := km.GetAPIKey("fetch-ml", "alice")
if err != nil {
t.Fatalf("GetAPIKey failed: %v", err)
}
if got != "super-secret" {
t.Fatalf("expected secret to be stored in primary keyring")
}
// Ensure fallback file was not created when primary succeeds
path := filepath.Join(baseDir, filepath.Base(km.fallback.path("fetch-ml", "alice")))
if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("expected no fallback file, got err=%v", err)
}
}
func TestKeychainFallbackWhenUnsupported(t *testing.T) {
kr := newFakeKeyring()
kr.setErr = keyring.ErrUnsupportedPlatform
kr.getErr = keyring.ErrUnsupportedPlatform
kr.deleteErr = keyring.ErrUnsupportedPlatform
km, _ := newTestManager(t, kr)
if err := km.StoreAPIKey("fetch-ml", "bob", "fallback-secret"); err != nil {
t.Fatalf("StoreAPIKey should fallback: %v", err)
}
got, err := km.GetAPIKey("fetch-ml", "bob")
if err != nil {
t.Fatalf("GetAPIKey should use fallback: %v", err)
}
if got != "fallback-secret" {
t.Fatalf("expected fallback secret, got %s", got)
}
}
func TestKeychainDeleteRemovesFallback(t *testing.T) {
kr := newFakeKeyring()
kr.deleteErr = keyring.ErrNotFound
km, _ := newTestManager(t, kr)
if err := km.fallback.store("fetch-ml", "carol", "temp"); err != nil {
t.Fatalf("failed to seed fallback store: %v", err)
}
if err := km.DeleteAPIKey("fetch-ml", "carol"); err != nil {
t.Fatalf("DeleteAPIKey failed: %v", err)
}
if _, err := km.fallback.get("fetch-ml", "carol"); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("expected fallback secret removed, err=%v", err)
}
}
func TestListAvailableMethodsIncludesFallback(t *testing.T) {
kr := newFakeKeyring()
kr.getErr = keyring.ErrUnsupportedPlatform
km, _ := newTestManager(t, kr)
methods := km.ListAvailableMethods()
if len(methods) != 1 || methods[0] == "OS keyring" {
t.Fatalf("expected only fallback method, got %v", methods)
}
}