package rgb import ( "encoding/json" "errors" "reflect" "testing" intrgb "github.com/wobkey/rgb/internal/rgb" "github.com/wobkey/rgb/internal/via" ) type infoKey struct { channel via.LEDType param uint8 } type fakeInfoProtocol struct { values map[infoKey][]byte errors map[infoKey]error calls []infoKey } func (f *fakeInfoProtocol) GetValue(channel via.LEDType, param uint8) ([]byte, error) { key := infoKey{channel: channel, param: param} f.calls = append(f.calls, key) if err := f.errors[key]; err != nil { return nil, err } return append([]byte(nil), f.values[key]...), nil } func TestInfoSuccessfulRecord(t *testing.T) { protocol := &fakeInfoProtocol{ values: map[infoKey][]byte{ {channel: 3, param: 1}: {160}, {channel: 3, param: 2}: {17}, {channel: 3, param: 3}: {2}, {channel: 3, param: 4}: {85, 255}, {channel: 2, param: 1}: {80}, {channel: 2, param: 2}: {4}, {channel: 2, param: 3}: {1}, {channel: 2, param: 4}: {0, 128}, }, errors: make(map[infoKey]error), } zones := []intrgb.Zone{intrgb.ZoneBacklight, intrgb.ZoneLogo} got, err := readInfo(protocol, zones) if err != nil { t.Fatalf("readInfo() unexpected error: %v", err) } want := infoOutput{ Enabled: true, Mode: "rainbow_moving_chevron", Brightness: 160, Speed: 2, Zones: []zoneInfo{ { Zone: intrgb.ZoneBacklight, Channel: 3, Enabled: true, Effect: "rainbow_moving_chevron", EffectID: 17, Brightness: 160, Speed: 2, Color: infoColor{Hue: 85, Saturation: 255}, }, { Zone: intrgb.ZoneLogo, Channel: 2, Enabled: true, Effect: "breathing", EffectID: 4, Brightness: 80, Speed: 1, Color: infoColor{Hue: 0, Saturation: 128}, }, }, } if !reflect.DeepEqual(got, want) { t.Fatalf("readInfo() = %+v, want %+v", got, want) } data, err := json.Marshal(got) if err != nil { t.Fatalf("json.Marshal() error = %v", err) } wantJSON := `{"enabled":true,"mode":"rainbow_moving_chevron","brightness":160,"speed":2,"zones":[{"zone":"backlight","channel":3,"enabled":true,"effect":"rainbow_moving_chevron","effectId":17,"brightness":160,"speed":2,"color":{"hue":85,"saturation":255}},{"zone":"logo","channel":2,"enabled":true,"effect":"breathing","effectId":4,"brightness":80,"speed":1,"color":{"hue":0,"saturation":128}}]}` if string(data) != wantJSON { t.Errorf("JSON = %s, want %s", data, wantJSON) } } func TestInfoErrorRecord(t *testing.T) { protocol := &fakeInfoProtocol{ values: map[infoKey][]byte{ {channel: 2, param: 1}: {120}, {channel: 2, param: 2}: {4}, {channel: 2, param: 3}: {3}, {channel: 2, param: 4}: {10, 20}, {channel: 3, param: 1}: {90}, {channel: 3, param: 2}: {5}, {channel: 3, param: 3}: {4}, {channel: 3, param: 4}: {30, 40}, }, errors: map[infoKey]error{ {channel: 4, param: 1}: errors.New("side unavailable"), }, } zones := []intrgb.Zone{intrgb.ZoneLogo, intrgb.ZoneSide, intrgb.ZoneBacklight} got, err := readInfo(protocol, zones) if err == nil { t.Fatal("readInfo() expected error, got nil") } want := infoOutput{ Enabled: true, Mode: "breathing", Brightness: 120, Speed: 3, Zones: []zoneInfo{ { Zone: intrgb.ZoneLogo, Channel: 2, Enabled: true, Effect: "breathing", EffectID: 4, Brightness: 120, Speed: 3, Color: infoColor{Hue: 10, Saturation: 20}, }, { Zone: intrgb.ZoneSide, Channel: 4, Error: "side unavailable", }, { Zone: intrgb.ZoneBacklight, Channel: 3, Enabled: true, Effect: "breathing", EffectID: 5, Brightness: 90, Speed: 4, Color: infoColor{Hue: 30, Saturation: 40}, }, }, } if !reflect.DeepEqual(got, want) { t.Fatalf("readInfo() = %+v, want %+v", got, want) } data, err := json.Marshal(got) if err != nil { t.Fatalf("json.Marshal() error = %v", err) } var envelope struct { Zones []map[string]json.RawMessage `json:"zones"` } if err := json.Unmarshal(data, &envelope); err != nil { t.Fatalf("json.Unmarshal() error = %v", err) } if len(envelope.Zones) != 3 { t.Fatalf("zones = %d, want 3", len(envelope.Zones)) } if _, ok := envelope.Zones[1]["error"]; !ok { t.Errorf("error zone JSON = %v, want error key", envelope.Zones[1]) } }