package rgb import ( "reflect" "testing" ) func TestAllImpact80Zones(t *testing.T) { want := []Zone{ZoneLogo, ZoneBacklight, ZoneSide} got := AllZones() if !reflect.DeepEqual(got, want) { t.Fatalf("AllZones() = %v, want %v", got, want) } } func TestImpact80ZoneChannels(t *testing.T) { cases := []struct { zone Zone want uint8 }{ {ZoneLogo, 2}, {ZoneBacklight, 3}, {ZoneSide, 4}, } for _, tc := range cases { if got := tc.zone.Channel(); got != tc.want { t.Errorf("%s.Channel() = %d, want %d", tc.zone, got, tc.want) } } } func TestImpact80ParseZone(t *testing.T) { cases := []struct { input string want Zone valid bool }{ {"logo", ZoneLogo, true}, {"backlight", ZoneBacklight, true}, {"side", ZoneSide, true}, {"matrix", "", false}, {"", "", false}, } for _, tc := range cases { got, err := ParseZone(tc.input) if tc.valid { if err != nil { t.Errorf("ParseZone(%q) unexpected error: %v", tc.input, err) continue } if got != tc.want { t.Errorf("ParseZone(%q) = %q, want %q", tc.input, got, tc.want) } continue } if err == nil { t.Errorf("ParseZone(%q) expected error, got nil", tc.input) } } } func TestImpact80BacklightCatalog(t *testing.T) { want := []string{ "none", "solid_color", "alphas_mods", "gradient_up_down", "gradient_left_right", "breathing", "band_sat", "band_val", "band_pinwheel_sat", "band_pinwheel_val", "band_spiral_sat", "band_spiral_val", "cycle_all", "cycle_left_right", "cycle_up_down", "cycle_out_in", "cycle_out_in_dual", "rainbow_moving_chevron", "cycle_pinwheel", "cycle_spiral", "dual_beacon", "rainbow_beacon", "rainbow_pinwheels", "flower_blooming", "raindrops", "jellybean_raindrops", "hue_breathing", "hue_pendulum", "hue_wave", "pixel_flow", "digital_rain", "solid_reactive", "solid_reactive_wide", "solid_reactive_multiwide", "solid_reactive_cross", "solid_reactive_multicross", "solid_reactive_nexus", "solid_reactive_multinexus", "splash", "multisplash", "solid_splash", "solid_multisplash", "starlight", "starlight_dual_hue", "starlight_dual_sat", "riverflow", } for id, name := range want { if id > 45 { t.Fatalf("test catalog has %d entries", len(want)) } if got := EffectName(ZoneBacklight, uint8(id)); got != name { t.Errorf("EffectName(%q, %d) = %q, want %q", ZoneBacklight, id, got, name) } } if got := EffectName(ZoneBacklight, 46); got != "unknown" { t.Errorf("EffectName(%q, 46) = %q, want %q", ZoneBacklight, got, "unknown") } } func TestImpact80LogoAndSideCatalog(t *testing.T) { want := []string{ "none", "wave", "fixed_wave", "spectrum", "breathing", "light", "shutdown", } for _, zone := range []Zone{ZoneLogo, ZoneSide} { for id, name := range want { if got := EffectName(zone, uint8(id)); got != name { t.Errorf("EffectName(%q, %d) = %q, want %q", zone, id, got, name) } } if got := EffectName(zone, 7); got != "unknown" { t.Errorf("EffectName(%q, 7) = %q, want %q", zone, got, "unknown") } } if got := EffectName(Zone("matrix"), 0); got != "unknown" { t.Errorf("EffectName(%q, 0) = %q, want %q", "matrix", got, "unknown") } } func TestImpact80DefaultEffects(t *testing.T) { cases := []struct { zone Zone want uint8 }{ {ZoneLogo, 4}, {ZoneBacklight, 5}, {ZoneSide, 4}, {Zone("matrix"), 0}, } for _, tc := range cases { if got := DefaultEffect(tc.zone); got != tc.want { t.Errorf("DefaultEffect(%q) = %d, want %d", tc.zone, got, tc.want) } } } func TestImpact80ResolveAliases(t *testing.T) { cases := []struct { name string targets []EffectTarget skipped []Zone }{ { name: "off", targets: []EffectTarget{ {ZoneLogo, 0}, {ZoneBacklight, 0}, {ZoneSide, 0}, }, }, { name: "breathe", targets: []EffectTarget{ {ZoneLogo, 4}, {ZoneBacklight, 5}, {ZoneSide, 4}, }, }, { name: "rainbow", targets: []EffectTarget{ {ZoneLogo, 3}, {ZoneBacklight, 17}, {ZoneSide, 3}, }, }, { name: "rainbow_wave", targets: []EffectTarget{ {ZoneLogo, 1}, {ZoneSide, 1}, }, skipped: []Zone{ZoneBacklight}, }, { name: "solid", targets: []EffectTarget{ {ZoneLogo, 5}, {ZoneBacklight, 1}, {ZoneSide, 5}, }, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { targets, skipped, err := ResolveEffect(tc.name, AllZones()) if err != nil { t.Fatalf("ResolveEffect(%q) unexpected error: %v", tc.name, err) } if !reflect.DeepEqual(targets, tc.targets) { t.Errorf("ResolveEffect(%q) targets = %v, want %v", tc.name, targets, tc.targets) } if !reflect.DeepEqual(skipped, tc.skipped) { t.Errorf("ResolveEffect(%q) skipped = %v, want %v", tc.name, skipped, tc.skipped) } }) } } func TestResolveBacklightOnlyEffect(t *testing.T) { targets, skipped, err := ResolveEffect("rainbow_moving_chevron", AllZones()) if err != nil { t.Fatal(err) } wantTargets := []EffectTarget{{ZoneBacklight, 17}} if !reflect.DeepEqual(targets, wantTargets) { t.Fatalf("ResolveEffect() targets = %v, want %v", targets, wantTargets) } wantSkipped := []Zone{ZoneLogo, ZoneSide} if !reflect.DeepEqual(skipped, wantSkipped) { t.Fatalf("ResolveEffect() skipped = %v, want %v", skipped, wantSkipped) } } func TestResolveEffectPreservesZoneOrder(t *testing.T) { zones := []Zone{ZoneSide, ZoneBacklight, ZoneLogo} want := []EffectTarget{ {ZoneSide, 4}, {ZoneBacklight, 5}, {ZoneLogo, 4}, } targets, skipped, err := ResolveEffect("breathing", zones) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(targets, want) { t.Fatalf("ResolveEffect() targets = %v, want %v", targets, want) } if len(skipped) != 0 { t.Fatalf("ResolveEffect() skipped = %v, want none", skipped) } } func TestResolveEffectExplicitUnsupported(t *testing.T) { cases := []struct { name string zones []Zone }{ {"rainbow_moving_chevron", []Zone{ZoneLogo}}, {"rainbow_wave", []Zone{ZoneBacklight}}, {"splash", []Zone{ZoneSide}}, } for _, tc := range cases { t.Run(tc.name+string(tc.zones[0]), func(t *testing.T) { targets, skipped, err := ResolveEffect(tc.name, tc.zones) if err == nil { t.Fatal("ResolveEffect() expected error, got nil") } if len(targets) != 0 { t.Errorf("ResolveEffect() targets = %v, want none", targets) } if len(skipped) != 0 { t.Errorf("ResolveEffect() skipped = %v, want none", skipped) } }) } } func TestResolveEffectUnknownName(t *testing.T) { targets, skipped, err := ResolveEffect("not_an_effect", AllZones()) if err == nil { t.Fatal("ResolveEffect() expected error, got nil") } if len(targets) != 0 { t.Errorf("ResolveEffect() targets = %v, want none", targets) } if len(skipped) != 0 { t.Errorf("ResolveEffect() skipped = %v, want none", skipped) } } func TestResolveEffectInvalidZone(t *testing.T) { if _, _, err := ResolveEffect("breathing", []Zone{Zone("matrix")}); err == nil { t.Fatal("ResolveEffect() expected error, got nil") } }