package via import ( "bytes" "testing" ) type fakeTransport struct { reportIDs []byte reports [][]byte response []byte queue [][]byte readCalls int readErr error readErrAfter int } func (f *fakeTransport) SendReport(reportID byte, report []byte) (int, error) { f.reportIDs = append(f.reportIDs, reportID) f.reports = append(f.reports, bytes.Clone(report)) return len(report), nil } func (f *fakeTransport) Read(buf []byte) (int, error) { f.readCalls++ if f.readErr != nil && f.readCalls > f.readErrAfter { return 0, f.readErr } if len(f.queue) > 0 { next := f.queue[0] f.queue = f.queue[1:] return copy(buf, next), nil } if len(f.response) > 0 { return copy(buf, f.response), nil } if len(f.reports) > 0 { return copy(buf, f.reports[len(f.reports)-1]), nil } return copy(buf, make([]byte, 32)), nil } func (f *fakeTransport) Close() error { return nil } func TestSetValueUsesQMKRGBLightPayload(t *testing.T) { transport := &fakeTransport{} protocol := Protocol{handle: transport} if err := protocol.SetValue(ChannelRgblight, 0x02, 0x00); err != nil { t.Fatalf("SetValue() error = %v", err) } want := make([]byte, 32) want[0] = 0x07 want[1] = 0x02 want[2] = 0x02 want[3] = 0x00 if len(transport.reports) != 1 { t.Fatalf("SendReport() calls = %d, want 1", len(transport.reports)) } if transport.reportIDs[0] != 0x00 { t.Errorf("report ID = 0x%02x, want 0x00", transport.reportIDs[0]) } if !bytes.Equal(transport.reports[0], want) { t.Errorf("report = %v, want %v", transport.reports[0], want) } } func TestSetValueConsumesQMKResponse(t *testing.T) { response := make([]byte, 32) response[0] = 0x07 response[1] = 0x02 response[2] = 0x02 response[3] = 0x00 transport := &fakeTransport{response: response} protocol := Protocol{handle: transport} if err := protocol.SetValue(ChannelRgblight, 0x02, 0x00); err != nil { t.Fatalf("SetValue() error = %v", err) } if transport.readCalls != 1 { t.Errorf("Read() calls = %d, want 1", transport.readCalls) } } func TestSetColorUsesQMKColorValue(t *testing.T) { transport := &fakeTransport{} protocol := Protocol{handle: transport} if err := protocol.SetColor(ChannelRgblight, 0x2a, 0x80); err != nil { t.Fatalf("SetColor() error = %v", err) } want := make([]byte, 32) want[0] = 0x07 want[1] = 0x02 want[2] = 0x04 want[3] = 0x2a want[4] = 0x80 if !bytes.Equal(transport.reports[0], want) { t.Errorf("report = %v, want %v", transport.reports[0], want) } } func TestGetValueReturnsQMKValueData(t *testing.T) { response := make([]byte, 32) response[0] = 0x08 response[1] = 0x02 response[2] = 0x01 response[3] = 0xc8 transport := &fakeTransport{response: response} protocol := Protocol{handle: transport} got, err := protocol.GetValue(ChannelRgblight, 0x01) if err != nil { t.Fatalf("GetValue() error = %v", err) } if !bytes.Equal(got, []byte{0xc8}) { t.Errorf("GetValue() = %v, want [192]", got) } want := make([]byte, 32) want[0] = 0x08 want[1] = 0x02 want[2] = 0x01 if !bytes.Equal(transport.reports[0], want) { t.Errorf("request = %v, want %v", transport.reports[0], want) } } func TestGetValueRejectsUnhandledResponse(t *testing.T) { response := make([]byte, 32) response[0] = 0xff protocol := Protocol{handle: &fakeTransport{response: response}} if _, err := protocol.GetValue(ChannelRgblight, 0x01); err == nil { t.Fatal("GetValue() error = nil, want unhandled response error") } } func TestSetValueWritesEachImpact80EffectChannel(t *testing.T) { transport := &fakeTransport{} protocol := Protocol{handle: transport} cases := []struct { channel Channel effect byte }{ {ChannelRgblight, 4}, {ChannelRgbMatrix, 5}, {ChannelAudio, 4}, } for _, tc := range cases { if err := protocol.SetValue(tc.channel, 0x02, tc.effect); err != nil { t.Fatalf("SetValue(%d) error = %v", tc.channel, err) } } if len(transport.reports) != len(cases) { t.Fatalf("SendReport() calls = %d, want %d", len(transport.reports), len(cases)) } for i, tc := range cases { report := transport.reports[i] if report[0] != 0x07 || report[1] != byte(tc.channel) || report[2] != 0x02 || report[3] != tc.effect { t.Errorf("effect report %d = %v, want channel 0x%02x effect %d", i, report, tc.channel, tc.effect) } } } func TestGetValueReturnsTwoByteColor(t *testing.T) { response := make([]byte, 32) response[0] = 0x08 response[1] = 0x03 response[2] = 0x04 response[3] = 0x2a response[4] = 0x80 transport := &fakeTransport{response: response} protocol := Protocol{handle: transport} got, err := protocol.GetValue(ChannelRgbMatrix, 0x04) if err != nil { t.Fatalf("GetValue() error = %v", err) } if !bytes.Equal(got, []byte{0x2a, 0x80}) { t.Errorf("GetValue() = %v, want [42 128]", got) } want := make([]byte, 32) want[0] = 0x08 want[1] = 0x03 want[2] = 0x04 if !bytes.Equal(transport.reports[0], want) { t.Errorf("request = %v, want %v", transport.reports[0], want) } }