This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/sandbox/realtime_module_test.go
Jeffrey Smith 680ec3b897
All checks were successful
CI/CD / detect-changes (push) Successful in 3s
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-go-pg (push) Successful in 2m34s
CI/CD / test-sqlite (push) Successful in 2m46s
CI/CD / build-and-deploy (push) Successful in 1m55s
Feat rebrand armature (#43)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
2026-03-31 23:25:37 +00:00

159 lines
4.2 KiB
Go

package sandbox
import (
"context"
"encoding/json"
"strings"
"sync"
"testing"
"go.starlark.net/starlark"
"armature/events"
)
func TestRealtimePublish_HappyPath(t *testing.T) {
bus := events.NewBus()
var mu sync.Mutex
var received events.Event
bus.Subscribe("realtime.*", func(e events.Event) {
mu.Lock()
received = e
mu.Unlock()
})
mod := BuildRealtimeModule(context.Background(), bus, "test-pkg")
sb := New(DefaultConfig())
_, err := sb.Exec(context.Background(), "test.star", `
result = realtime.publish("room:123", "chat.message", {"text": "hello", "from": "alice"})
`, map[string]starlark.Value{"realtime": mod})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
mu.Lock()
defer mu.Unlock()
if received.Label != "realtime.chat.message" {
t.Errorf("expected label 'realtime.chat.message', got %q", received.Label)
}
if received.Room != "room:123" {
t.Errorf("expected room 'room:123', got %q", received.Room)
}
var payload map[string]any
if err := json.Unmarshal(received.Payload, &payload); err != nil {
t.Fatalf("payload unmarshal error: %v", err)
}
if payload["text"] != "hello" {
t.Errorf("expected text 'hello', got %v", payload["text"])
}
if payload["from"] != "alice" {
t.Errorf("expected from 'alice', got %v", payload["from"])
}
if payload["_pkg"] != "test-pkg" {
t.Errorf("expected _pkg 'test-pkg', got %v", payload["_pkg"])
}
}
func TestRealtimePublish_EmptyData(t *testing.T) {
bus := events.NewBus()
var received events.Event
bus.Subscribe("realtime.*", func(e events.Event) { received = e })
mod := BuildRealtimeModule(context.Background(), bus, "my-pkg")
sb := New(DefaultConfig())
_, err := sb.Exec(context.Background(), "test.star", `
realtime.publish("ch:1", "heartbeat")
`, map[string]starlark.Value{"realtime": mod})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var payload map[string]any
json.Unmarshal(received.Payload, &payload)
if payload["_pkg"] != "my-pkg" {
t.Errorf("expected _pkg 'my-pkg', got %v", payload["_pkg"])
}
// Should only have _pkg
if len(payload) != 1 {
t.Errorf("expected 1 key (_pkg only), got %d", len(payload))
}
}
func TestRealtimePublish_MissingArgs(t *testing.T) {
bus := events.NewBus()
mod := BuildRealtimeModule(context.Background(), bus, "pkg")
sb := New(DefaultConfig())
// Missing event
_, err := sb.Exec(context.Background(), "test.star", `
realtime.publish("ch:1")
`, map[string]starlark.Value{"realtime": mod})
if err == nil {
t.Fatal("expected error for missing event arg")
}
}
func TestRealtimePublish_ReservedPrefix(t *testing.T) {
bus := events.NewBus()
mod := BuildRealtimeModule(context.Background(), bus, "pkg")
sb := New(DefaultConfig())
_, err := sb.Exec(context.Background(), "test.star", `
realtime.publish("ch:1", "system.notify", {})
`, map[string]starlark.Value{"realtime": mod})
if err == nil {
t.Fatal("expected error for reserved prefix")
}
if !strings.Contains(err.Error(), "reserved prefix") {
t.Errorf("error should mention reserved prefix, got: %v", err)
}
}
func TestRealtimePublish_PayloadTooLarge(t *testing.T) {
bus := events.NewBus()
mod := BuildRealtimeModule(context.Background(), bus, "pkg")
sb := New(DefaultConfig())
// Build a large string via repeated concatenation in Starlark
_, err := sb.Exec(context.Background(), "test.star", `
big = "x" * 8000
realtime.publish("ch:1", "big.event", {"data": big})
`, map[string]starlark.Value{"realtime": mod})
if err == nil {
t.Fatal("expected error for payload too large")
}
if !strings.Contains(err.Error(), "too large") {
t.Errorf("error should mention 'too large', got: %v", err)
}
}
func TestStarlarkToGoVal(t *testing.T) {
tests := []struct {
name string
val starlark.Value
want any
}{
{"none", starlark.None, nil},
{"true", starlark.True, true},
{"false", starlark.False, false},
{"int", starlark.MakeInt(42), int64(42)},
{"float", starlark.Float(3.14), float64(3.14)},
{"string", starlark.String("hello"), "hello"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := starlarkToGoVal(tt.val)
if got != tt.want {
t.Errorf("starlarkToGoVal(%s) = %v (%T), want %v (%T)", tt.val, got, got, tt.want, tt.want)
}
})
}
}