package app_test import ( "testing" "github.com/andyleap/hnh-map/internal/app" ) func TestCoordName(t *testing.T) { tests := []struct { coord app.Coord want string }{ {app.Coord{X: 0, Y: 0}, "0_0"}, {app.Coord{X: 5, Y: -3}, "5_-3"}, {app.Coord{X: -1, Y: -1}, "-1_-1"}, } for _, tt := range tests { got := tt.coord.Name() if got != tt.want { t.Errorf("Coord{%d,%d}.Name() = %q, want %q", tt.coord.X, tt.coord.Y, got, tt.want) } } } func TestCoordParent(t *testing.T) { tests := []struct { coord app.Coord parent app.Coord }{ {app.Coord{X: 0, Y: 0}, app.Coord{X: 0, Y: 0}}, {app.Coord{X: 2, Y: 4}, app.Coord{X: 1, Y: 2}}, {app.Coord{X: 3, Y: 5}, app.Coord{X: 1, Y: 2}}, {app.Coord{X: -1, Y: -1}, app.Coord{X: -1, Y: -1}}, {app.Coord{X: -2, Y: -3}, app.Coord{X: -1, Y: -2}}, } for _, tt := range tests { got := tt.coord.Parent() if got != tt.parent { t.Errorf("Coord{%d,%d}.Parent() = %v, want %v", tt.coord.X, tt.coord.Y, got, tt.parent) } } } func TestAuthsHas(t *testing.T) { auths := app.Auths{"admin", "map", "upload"} if !auths.Has("admin") { t.Error("expected Has(admin)=true") } if !auths.Has("map") { t.Error("expected Has(map)=true") } if auths.Has("markers") { t.Error("expected Has(markers)=false") } } func TestAuthsHasEmpty(t *testing.T) { var auths app.Auths if auths.Has("anything") { t.Error("expected nil auths to return false") } } func TestTopicSendAndWatch(t *testing.T) { topic := &app.Topic[string]{} ch := make(chan *string, 10) topic.Watch(ch) msg := "hello" topic.Send(&msg) select { case got := <-ch: if *got != "hello" { t.Fatalf("expected hello, got %s", *got) } default: t.Fatal("expected message on channel") } } func TestTopicClose(t *testing.T) { topic := &app.Topic[int]{} ch := make(chan *int, 10) topic.Watch(ch) topic.Close() _, ok := <-ch if ok { t.Fatal("expected channel to be closed") } } func TestTopicSkipsFullChannel(t *testing.T) { topic := &app.Topic[int]{} slow := make(chan *int) // unbuffered, so Send will skip this subscriber fast := make(chan *int, 10) topic.Watch(slow) topic.Watch(fast) val := 42 topic.Send(&val) // slow is full (unbuffered), message dropped for slow only; fast receives topic.Send(&val) // Fast subscriber got both messages for i := 0; i < 2; i++ { select { case got := <-fast: if *got != 42 { t.Fatalf("fast got %d", *got) } default: t.Fatalf("expected fast to have message %d", i+1) } } // Slow subscriber was skipped (channel full), not closed - channel still open and empty select { case _, ok := <-slow: if !ok { t.Fatal("slow channel should not be closed when subscriber is skipped") } t.Fatal("slow should have received no message") default: // slow is open and empty, which is correct } topic.Close() _, ok := <-slow if ok { t.Fatal("expected slow channel closed after topic.Close()") } }