|
|
@@ -0,0 +1,187 @@
|
|
|
+package rgb
|
|
|
+
|
|
|
+import (
|
|
|
+ "errors"
|
|
|
+ "reflect"
|
|
|
+ "testing"
|
|
|
+
|
|
|
+ intrgb "github.com/wobkey/rgb/internal/rgb"
|
|
|
+ "github.com/wobkey/rgb/internal/via"
|
|
|
+)
|
|
|
+
|
|
|
+type commandReport struct {
|
|
|
+ channel via.LEDType
|
|
|
+ param uint8
|
|
|
+ value uint8
|
|
|
+ hue uint8
|
|
|
+ saturation uint8
|
|
|
+}
|
|
|
+
|
|
|
+type fakeZoneProtocol struct {
|
|
|
+ reports []commandReport
|
|
|
+ failAt int
|
|
|
+}
|
|
|
+
|
|
|
+func (f *fakeZoneProtocol) SetValue(channel via.LEDType, param, value uint8) error {
|
|
|
+ if f.failAt >= 0 && f.failAt == len(f.reports) {
|
|
|
+ return errors.New("write failed")
|
|
|
+ }
|
|
|
+ f.reports = append(f.reports, commandReport{
|
|
|
+ channel: channel,
|
|
|
+ param: param,
|
|
|
+ value: value,
|
|
|
+ })
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (f *fakeZoneProtocol) SetColor(channel via.LEDType, hue, saturation uint8) error {
|
|
|
+ if f.failAt >= 0 && f.failAt == len(f.reports) {
|
|
|
+ return errors.New("write failed")
|
|
|
+ }
|
|
|
+ f.reports = append(f.reports, commandReport{
|
|
|
+ channel: channel,
|
|
|
+ param: 4,
|
|
|
+ hue: hue,
|
|
|
+ saturation: saturation,
|
|
|
+ })
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func TestSelectedChannelOperations(t *testing.T) {
|
|
|
+ defaultZones := []intrgb.Zone{intrgb.ZoneLogo, intrgb.ZoneBacklight, intrgb.ZoneSide}
|
|
|
+ sideZones := []intrgb.Zone{intrgb.ZoneSide}
|
|
|
+
|
|
|
+ operations := []struct {
|
|
|
+ name string
|
|
|
+ zones []intrgb.Zone
|
|
|
+ sideZones []intrgb.Zone
|
|
|
+ run func(zoneProtocol, []intrgb.Zone) error
|
|
|
+ want []commandReport
|
|
|
+ wantSide []commandReport
|
|
|
+ }{
|
|
|
+ {
|
|
|
+ name: "brightness",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
|
|
|
+ return setBrightnessOnZones(protocol, zones, 160)
|
|
|
+ },
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 1, value: 160},
|
|
|
+ {channel: 3, param: 1, value: 160},
|
|
|
+ {channel: 4, param: 1, value: 160},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{{channel: 4, param: 1, value: 160}},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "speed",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
|
|
|
+ return setSpeedOnZones(protocol, zones, 2)
|
|
|
+ },
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 3, value: 2},
|
|
|
+ {channel: 3, param: 3, value: 2},
|
|
|
+ {channel: 4, param: 3, value: 2},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{{channel: 4, param: 3, value: 2}},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "color",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
|
|
|
+ return setColorOnZones(protocol, zones, 85, 255)
|
|
|
+ },
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 4, hue: 85, saturation: 255},
|
|
|
+ {channel: 3, param: 4, hue: 85, saturation: 255},
|
|
|
+ {channel: 4, param: 4, hue: 85, saturation: 255},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{{channel: 4, param: 4, hue: 85, saturation: 255}},
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "disable",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: disableLightingOnZones,
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 2, value: 0},
|
|
|
+ {channel: 2, param: 1, value: 0},
|
|
|
+ {channel: 3, param: 2, value: 0},
|
|
|
+ {channel: 3, param: 1, value: 0},
|
|
|
+ {channel: 4, param: 2, value: 0},
|
|
|
+ {channel: 4, param: 1, value: 0},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{
|
|
|
+ {channel: 4, param: 2, value: 0},
|
|
|
+ {channel: 4, param: 1, value: 0},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "enable",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: enableLightingOnZones,
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 2, value: 4},
|
|
|
+ {channel: 2, param: 1, value: 160},
|
|
|
+ {channel: 3, param: 2, value: 5},
|
|
|
+ {channel: 3, param: 1, value: 160},
|
|
|
+ {channel: 4, param: 2, value: 4},
|
|
|
+ {channel: 4, param: 1, value: 160},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{
|
|
|
+ {channel: 4, param: 2, value: 4},
|
|
|
+ {channel: 4, param: 1, value: 160},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "mode",
|
|
|
+ zones: defaultZones,
|
|
|
+ sideZones: sideZones,
|
|
|
+ run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
|
|
|
+ return setModeOnZones(protocol, zones, 17)
|
|
|
+ },
|
|
|
+ want: []commandReport{
|
|
|
+ {channel: 2, param: 2, value: 17},
|
|
|
+ {channel: 3, param: 2, value: 17},
|
|
|
+ {channel: 4, param: 2, value: 17},
|
|
|
+ },
|
|
|
+ wantSide: []commandReport{{channel: 4, param: 2, value: 17}},
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, tc := range operations {
|
|
|
+ t.Run(tc.name+"/default", func(t *testing.T) {
|
|
|
+ protocol := &fakeZoneProtocol{failAt: -1}
|
|
|
+ if err := tc.run(protocol, tc.zones); err != nil {
|
|
|
+ t.Fatalf("operation error = %v", err)
|
|
|
+ }
|
|
|
+ if !reflect.DeepEqual(protocol.reports, tc.want) {
|
|
|
+ t.Errorf("reports = %v, want %v", protocol.reports, tc.want)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ t.Run(tc.name+"/side", func(t *testing.T) {
|
|
|
+ protocol := &fakeZoneProtocol{failAt: -1}
|
|
|
+ if err := tc.run(protocol, tc.sideZones); err != nil {
|
|
|
+ t.Fatalf("operation error = %v", err)
|
|
|
+ }
|
|
|
+ if !reflect.DeepEqual(protocol.reports, tc.wantSide) {
|
|
|
+ t.Errorf("reports = %v, want %v", protocol.reports, tc.wantSide)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestSelectedChannelStopsOnFirstError(t *testing.T) {
|
|
|
+ protocol := &fakeZoneProtocol{failAt: 1}
|
|
|
+ err := setBrightnessOnZones(protocol, intrgb.AllZones(), 160)
|
|
|
+ if err == nil {
|
|
|
+ t.Fatal("setBrightnessOnZones() expected error, got nil")
|
|
|
+ }
|
|
|
+ if len(protocol.reports) != 1 {
|
|
|
+ t.Errorf("reports = %v, want one report before failure", protocol.reports)
|
|
|
+ }
|
|
|
+}
|