120 lines
3.6 KiB
Go
120 lines
3.6 KiB
Go
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
|
|
}
|