test(01-04): cover config, lifecycle, services, events and context

- Table-driven compass precedence, malformed YAML, snake_case env and concurrent reads
- Party duplicate/missing/cycle, reordered manifest, HasConfig/HasCommands discovery
- Isolated backpack services, festival panic payload omission, towel nested isolation
This commit is contained in:
Jakub Zych
2026-09-16 14:08:17 +02:00
parent 4093d4230e
commit a43c734546
6 changed files with 840 additions and 0 deletions

View File

@@ -1,9 +1,11 @@
package backpack
import (
"sync"
"testing"
"git.golem15.com/golem15/summercms/compass"
"git.golem15.com/golem15/summercms/pact"
)
type ping interface {
@@ -70,3 +72,90 @@ func TestHasPluginUsesCompleteSet(t *testing.T) {
t.Fatal("HasPlugin(golem15.missing) = true")
}
}
func TestTwoAppsIsolateHasPluginAndServices(t *testing.T) {
a := New(&compass.Config{})
b := New(&compass.Config{})
a.SetPlugins([]string{"golem15.optional"})
b.SetPlugins([]string{"golem15.hello"})
if err := a.Publish[pact.OptionalMessage](msgService{s: "from-a"}); err != nil {
t.Fatalf("Publish A: %v", err)
}
if !a.HasPlugin("golem15.optional") {
t.Fatal("app A should see optional")
}
if a.HasPlugin("golem15.hello") {
t.Fatal("app A should not see hello")
}
if !b.HasPlugin("golem15.hello") {
t.Fatal("app B should see hello")
}
if b.HasPlugin("golem15.optional") {
t.Fatal("app B should not see optional")
}
got, ok := a.Lookup[pact.OptionalMessage]()
if !ok || got.Message() != "from-a" {
t.Fatalf("app A lookup = (%v, %v)", got, ok)
}
if _, ok := b.Lookup[pact.OptionalMessage](); ok {
t.Fatal("app B must not see app A's OptionalMessage")
}
}
func TestPublishNilRejectedAndLookupStaysAbsent(t *testing.T) {
app := New(&compass.Config{})
var nilPing ping
if err := app.Publish[ping](nilPing); err == nil {
t.Fatal("expected nil publish error")
}
if _, ok := app.Lookup[ping](); ok {
t.Fatal("nil publish must not store a value")
}
}
func TestDuplicatePublishKeepsFirstValue(t *testing.T) {
app := New(&compass.Config{})
if err := app.Publish[ping](pingImpl{s: "first"}); err != nil {
t.Fatalf("Publish: %v", err)
}
if err := app.Publish[ping](pingImpl{s: "second"}); err == nil {
t.Fatal("expected duplicate error")
}
got, ok := app.Lookup[ping]()
if !ok || got.Ping() != "first" {
t.Fatalf("Lookup = (%v, %v), want first", got, ok)
}
}
func TestConcurrentLookupAndHasPlugin(t *testing.T) {
app := New(&compass.Config{})
app.SetPlugins([]string{"golem15.hello"})
if err := app.Publish[ping](pingImpl{s: "pong"}); err != nil {
t.Fatal(err)
}
var wg sync.WaitGroup
for i := 0; i < 16; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 80; j++ {
got, ok := app.Lookup[ping]()
if !ok || got.Ping() != "pong" {
t.Errorf("Lookup = (%v, %v)", got, ok)
return
}
if !app.HasPlugin("golem15.hello") || app.HasPlugin("golem15.missing") {
t.Error("HasPlugin concurrent mismatch")
return
}
}
}()
}
wg.Wait()
}
type msgService struct{ s string }
func (m msgService) Message() string { return m.s }