tests
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package video
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestPatterns(t *testing.T) {
|
||||
got := Patterns()
|
||||
if len(got) == 0 {
|
||||
t.Fatal("Patterns returned no video patterns")
|
||||
}
|
||||
|
||||
seen := make(map[string]struct{}, len(got))
|
||||
for i, pattern := range got {
|
||||
if pattern.Name == "" {
|
||||
t.Fatalf("pattern %d has an empty name", i)
|
||||
}
|
||||
if pattern.Description == "" {
|
||||
t.Fatalf("pattern %q has an empty description", pattern.Name)
|
||||
}
|
||||
if !HasPattern(pattern.Name) {
|
||||
t.Fatalf("Patterns returned %q, but HasPattern rejected it", pattern.Name)
|
||||
}
|
||||
if _, exists := seen[pattern.Name]; exists {
|
||||
t.Fatalf("duplicate pattern name %q", pattern.Name)
|
||||
}
|
||||
seen[pattern.Name] = struct{}{}
|
||||
if i > 0 && got[i-1].Name >= pattern.Name {
|
||||
t.Fatalf("patterns are not sorted: %q appears before %q", got[i-1].Name, pattern.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasPatternRejectsUnknownName(t *testing.T) {
|
||||
if HasPattern("not-a-pattern") {
|
||||
t.Fatal("HasPattern accepted an unknown pattern")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatternRegistryKeysMatchNames(t *testing.T) {
|
||||
for name, pattern := range patterns {
|
||||
if pattern.Name != name {
|
||||
t.Errorf("pattern map key %q does not match pattern name %q", name, pattern.Name)
|
||||
}
|
||||
if pattern.kernelPath == "" {
|
||||
t.Errorf("pattern %q has an empty kernel path", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,11 +101,6 @@ func buildTextOverlay(cfg Config) (overlay *generator.TextOverlay, resultErr err
|
||||
if cfg.Overlay.Text == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if cfg.Overlay.X < 0 || cfg.Overlay.X > int(cfg.Width()) ||
|
||||
cfg.Overlay.Y < 0 || cfg.Overlay.Y > int(cfg.Height()) {
|
||||
return nil, fmt.Errorf("text overlay position (%d, %d) is outside the %dx%d video frame",
|
||||
cfg.Overlay.X, cfg.Overlay.Y, cfg.Width(), cfg.Height())
|
||||
}
|
||||
|
||||
face, err := generator.LoadFace("assets/fonts/JetBrainsMonoNLNerdFontMono-Regular.ttf", 48)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package video
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"mxl-pattern-generator/internal/flowdef"
|
||||
)
|
||||
|
||||
const testVideoID = "b3bb5be7-9fe9-4324-a5bb-4c70e1084449"
|
||||
|
||||
func testConfig(t *testing.T, overlay OverlayConfig) Config {
|
||||
t.Helper()
|
||||
definition, err := flowdef.NewV210Video(
|
||||
testVideoID,
|
||||
1920,
|
||||
1080,
|
||||
flowdef.Rational{Numerator: 50, Denominator: 1},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("NewV210Video: %v", err)
|
||||
}
|
||||
return Config{Definition: definition, Pattern: "ebu75", Overlay: overlay}
|
||||
}
|
||||
|
||||
func TestBuildTextOverlayDisabled(t *testing.T) {
|
||||
overlay, err := buildTextOverlay(testConfig(t, OverlayConfig{}))
|
||||
if err != nil {
|
||||
t.Fatalf("buildTextOverlay: %v", err)
|
||||
}
|
||||
if overlay != nil {
|
||||
t.Fatal("buildTextOverlay returned an overlay for empty text")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTextOverlayPositioning(t *testing.T) {
|
||||
// Production assets are resolved from the repository root.
|
||||
t.Chdir("../..")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
overlay OverlayConfig
|
||||
}{
|
||||
{name: "explicit", overlay: OverlayConfig{Text: "MXL", X: 120, Y: 48}},
|
||||
{name: "preset", overlay: OverlayConfig{Text: "MXL", Position: "cc"}},
|
||||
{name: "preset ignores explicit coordinates", overlay: OverlayConfig{Text: "MXL", X: -1, Y: -1, Position: "cc"}},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
overlay, err := buildTextOverlay(testConfig(t, tc.overlay))
|
||||
if err != nil {
|
||||
t.Fatalf("buildTextOverlay: %v", err)
|
||||
}
|
||||
if overlay == nil {
|
||||
t.Fatal("buildTextOverlay returned nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildTextOverlayRejectsInvalidPosition(t *testing.T) {
|
||||
t.Chdir("../..")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
overlay OverlayConfig
|
||||
wantErrSub string
|
||||
}{
|
||||
{name: "negative", overlay: OverlayConfig{Text: "MXL", X: -6}, wantErrSub: "must not be negative"},
|
||||
{name: "unaligned x", overlay: OverlayConfig{Text: "MXL", X: 7}, wantErrSub: "divisible by 6"},
|
||||
{name: "right overflow", overlay: OverlayConfig{Text: "MXL", X: 1902}, wantErrSub: "does not fit"},
|
||||
{name: "bottom overflow", overlay: OverlayConfig{Text: "MXL", Y: 1070}, wantErrSub: "does not fit"},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := buildTextOverlay(testConfig(t, tc.overlay))
|
||||
if err == nil || !strings.Contains(err.Error(), tc.wantErrSub) {
|
||||
t.Fatalf("error = %v, want substring %q", err, tc.wantErrSub)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user