package api import ( "context" "crypto/ed25519" "crypto/rand" "encoding/base64" "encoding/json" "os" "path/filepath" "testing" "github.com/gin-gonic/gin" "github.com/go-admin-team/go-admin-core/sdk" "gorm.io/driver/sqlite" "gorm.io/gorm" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/integration/bell_connector" "git.ilapage.cn/ila/yovision/Sense/server/app/sense/outbox" ) func TestBellConnectorRuntimeWiringIsOptionalAndMigrationGated(t *testing.T) { gin.SetMode(gin.TestMode) db, err := gorm.Open(sqlite.Open("file:sense-api-bell-connector?mode=memory&cache=shared"), &gorm.Config{}) if err != nil { t.Fatal(err) } engine := gin.New() disabled := func(string) string { return "" } if err = startBellConnectorRuntime(context.Background(), engine, db, disabled); err != nil { t.Fatalf("disabled connector prevented Sense startup: %v", err) } if len(engine.Routes()) != 0 { t.Fatalf("disabled connector registered routes: %#v", engine.Routes()) } enabled := func(key string) string { if key == "SENSE_EVENT_INGRESS_ENABLED" { return "true" } return "" } if err = startBellConnectorRuntime(context.Background(), gin.New(), db, enabled); err == nil { t.Fatal("enabled connector started without its formal migration") } if err = db.AutoMigrate( &bell_connector.InboundEvent{}, &bell_connector.EvidenceRecord{}, &bell_connector.ReplayToken{}, &outbox.Message{}, &outbox.DeliveryRecord{}, &outbox.Attempt{}, ); err != nil { t.Fatal(err) } registryPath := writeSenseRegistry(t) runtimeEnvironment := func(key string) string { switch key { case "SENSE_EVENT_INGRESS_ENABLED": return "true" case "SENSE_MACHINE_PRINCIPAL_REGISTRY": return registryPath default: return "" } } registered := gin.New() if err = startBellConnectorRuntime(context.Background(), registered, db, runtimeEnvironment); err != nil { t.Fatalf("enabled connector did not register after migration: %v", err) } routes := registered.Routes() if len(routes) != 2 || routes[0].Path != "/v1/events" || routes[1].Path != "/v1/evidence/:evidence_id" { t.Fatalf("unexpected connector routes: %#v", routes) } } func TestConnectorRuntimeUsesOnlyTheExplicitDefaultDatabase(t *testing.T) { defaultDB, err := gorm.Open(sqlite.Open("file:sense-default-runtime?mode=memory&cache=shared"), &gorm.Config{}) if err != nil { t.Fatal(err) } secondaryDB, err := gorm.Open(sqlite.Open("file:sense-secondary-runtime?mode=memory&cache=shared"), &gorm.Config{}) if err != nil { t.Fatal(err) } sdk.Runtime.SetDb("", defaultDB) sdk.Runtime.SetDb("analytics", secondaryDB) t.Cleanup(func() { sdk.Runtime.SetDb("", nil) sdk.Runtime.SetDb("analytics", nil) }) if selected := defaultRuntimeDatabase(); selected != defaultDB { t.Fatalf("runtime selected a non-default database: %p", selected) } } func writeSenseRegistry(t *testing.T) string { t.Helper() publicKey, _, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } document := map[string]any{ "version": "yovision.machine-principal-registry/v1", "audience": "yovision-sense", "principals": []any{map[string]any{ "principal_id": "yv:brain:school-a", "enabled": true, "keys": []any{map[string]any{ "kid": "brain-key-0001", "public_key_base64url": base64.RawURLEncoding.EncodeToString(publicKey), "status": "active", "scopes": []string{"events:ingest"}, }}, }}, } encoded, err := json.Marshal(document) if err != nil { t.Fatal(err) } path := filepath.Join(t.TempDir(), "sense-registry.json") if err = os.WriteFile(path, encoded, 0o600); err != nil { t.Fatal(err) } return path }