package config import "testing" func TestEffectiveTilesFromSlots(t *testing.T) { l := Layout{Name: "l", Grid: "2x2", Slots: []string{"a", "", "", "b"}} tiles := l.EffectiveTiles() if len(tiles) != 2 { t.Fatalf("got %d tiles, want 2", len(tiles)) } // "a" at cell 0 -> (0,0); "b" at cell 3 -> (1,1). if tiles[0].Camera != "a" || tiles[0].Col != 0 || tiles[0].Row != 0 { t.Errorf("tile0 = %+v", tiles[0]) } if tiles[1].Camera != "b" || tiles[1].Col != 1 || tiles[1].Row != 1 { t.Errorf("tile1 = %+v", tiles[1]) } } func TestValidateTiles(t *testing.T) { base := func(tiles []Tile) *Config { c := &Config{ Cameras: []Camera{{Name: "a"}, {Name: "b"}}, Layouts: []Layout{{Name: "l", Grid: "4x4", Tiles: tiles}}, } c.Defaults() return c } // Valid: a 3x4 main plus a 1x1 side. if err := base([]Tile{{Camera: "a", Col: 0, Row: 0, ColSpan: 3, RowSpan: 4}, {Camera: "b", Col: 3, Row: 0}}).Validate(); err != nil { t.Errorf("valid layout rejected: %v", err) } // Overlap. if err := base([]Tile{{Camera: "a", Col: 0, Row: 0, ColSpan: 2, RowSpan: 2}, {Camera: "b", Col: 1, Row: 1}}).Validate(); err == nil { t.Error("expected overlap error") } // Out of bounds. if err := base([]Tile{{Camera: "a", Col: 3, Row: 0, ColSpan: 2, RowSpan: 1}}).Validate(); err == nil { t.Error("expected out-of-bounds error") } // Unknown camera. if err := base([]Tile{{Camera: "ghost", Col: 0, Row: 0}}).Validate(); err == nil { t.Error("expected unknown-camera error") } } func TestCameraStreamURL(t *testing.T) { cam := Camera{Name: "c", Streams: map[string]string{"high": "H", "low": "L"}} if got := cam.StreamURL("low"); got != "L" { t.Errorf(`StreamURL("low") = %q, want "L"`, got) } if got := cam.StreamURL("high"); got != "H" { t.Errorf(`StreamURL("high") = %q, want "H"`, got) } // Requested quality missing → fall down the preference list, then any. if got := cam.StreamURL("medium"); got != "L" { t.Errorf(`StreamURL("medium") = %q, want fallback "L"`, got) } if got := cam.StreamURL(""); got != "H" { t.Errorf(`StreamURL("") = %q, want best "H"`, got) } // Legacy single-URL camera. legacy := Camera{Name: "old", RTSP: "R"} if got := legacy.StreamURL("low"); got != "R" { t.Errorf("legacy StreamURL = %q, want RTSP fallback R", got) } } func TestValidateTilesCap(t *testing.T) { var tiles []Tile for i := 0; i < MaxTiles+1; i++ { tiles = append(tiles, Tile{Camera: "a", Col: i, Row: 0}) } c := &Config{Cameras: []Camera{{Name: "a"}}, Layouts: []Layout{{Name: "l", Grid: "20x1", Tiles: tiles}}} c.Defaults() if err := c.Validate(); err == nil { t.Errorf("expected error exceeding %d-tile cap", MaxTiles) } }