- Introduced mechanisms to detect stale connections in the map updates, allowing for automatic reconnection if no messages are received within a specified timeframe. - Updated the `refresh` method in `SmartTileLayer` to return a boolean indicating whether the tile was refreshed, improving the handling of tile updates. - Enhanced the `Send` method in the `Topic` struct to drop messages for full subscribers while keeping them subscribed, ensuring continuous delivery of future updates. - Added a keepalive mechanism in the `WatchGridUpdates` handler to maintain the connection and prevent timeouts.
134 lines
3.0 KiB
Go
134 lines
3.0 KiB
Go
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()")
|
|
}
|
|
}
|