| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package main
- import (
- "bytes"
- "errors"
- "strings"
- "testing"
- intrgb "netdome.biz/paul/qmk-rgb/internal/rgb"
- "netdome.biz/paul/qmk-rgb/internal/via"
- )
- // verifyingProtocol records writes and reports what the keyboard actually
- // applied, which on real hardware is not always the requested value.
- type verifyingProtocol struct {
- reports []commandReport
- applied map[via.LEDType]uint8
- getErr error
- getCalls int
- }
- func (f *verifyingProtocol) SetValue(channel via.LEDType, param, value uint8) error {
- f.reports = append(f.reports, commandReport{channel: channel, param: param, value: value})
- return nil
- }
- func (f *verifyingProtocol) SetColor(via.LEDType, uint8, uint8) error { return nil }
- func (f *verifyingProtocol) GetValue(channel via.LEDType, _ uint8) ([]byte, error) {
- f.getCalls++
- if f.getErr != nil {
- return nil, f.getErr
- }
- return []byte{f.applied[channel]}, nil
- }
- func (f *verifyingProtocol) Close() error { return nil }
- func appliedFor(p *verifyingProtocol, channel via.LEDType) uint8 { return p.applied[channel] }
- func TestSetBrightnessVerifiedReportsAppliedValue(t *testing.T) {
- tests := []struct {
- name string
- requested uint8
- applied uint8
- wantWarning bool
- }{
- {"keyboard honours the value", 100, 100, false},
- {"keyboard clamps to 160", 200, 160, true},
- {"keyboard scales up", 100, 159, true},
- {"both zones clamp", 255, 160, true},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- proto := &verifyingProtocol{
- applied: map[via.LEDType]uint8{
- via.RGBLight: tt.applied,
- via.RGBMatrix: tt.applied,
- via.SideLight: tt.applied,
- },
- }
- zones := []intrgb.Zone{intrgb.ZoneLogo}
- results, err := setBrightnessVerified(proto, zones, tt.requested)
- if err != nil {
- t.Fatalf("setBrightnessVerified() error = %v", err)
- }
- if len(results) != 1 {
- t.Fatalf("results = %d entries, want 1", len(results))
- }
- got := results[0]
- if got.Zone != intrgb.ZoneLogo {
- t.Errorf("results[0].Zone = %q, want %q", got.Zone, intrgb.ZoneLogo)
- }
- if got.Requested != tt.requested {
- t.Errorf("results[0].Requested = %d, want %d", got.Requested, tt.requested)
- }
- if got.Applied != tt.applied {
- t.Errorf("results[0].Applied = %d, want %d", got.Applied, tt.applied)
- }
- if got.Mismatch() != tt.wantWarning {
- t.Errorf("results[0].Mismatch() = %t, want %t", got.Mismatch(), tt.wantWarning)
- }
- })
- }
- }
- // The read-back must happen once per written zone, on the right channel.
- func TestSetBrightnessVerifiedReadsBackEveryZone(t *testing.T) {
- proto := &verifyingProtocol{
- applied: map[via.LEDType]uint8{
- via.RGBLight: 160,
- via.RGBMatrix: 255,
- via.SideLight: 160,
- },
- }
- results, err := setBrightnessVerified(proto, intrgb.AllZones(), 200)
- if err != nil {
- t.Fatalf("setBrightnessVerified() error = %v", err)
- }
- if len(results) != 3 {
- t.Fatalf("results = %d entries, want 3", len(results))
- }
- if proto.getCalls != 3 {
- t.Errorf("GetValue calls = %d, want 3", proto.getCalls)
- }
- // A set that fails must not be reported as applied.
- if got := appliedFor(proto, via.RGBLight); got != 160 {
- t.Errorf("unexpected applied value %d", got)
- }
- want := map[intrgb.Zone]uint8{
- intrgb.ZoneLogo: 160,
- intrgb.ZoneBacklight: 255,
- intrgb.ZoneSide: 160,
- }
- for _, r := range results {
- if r.Applied != want[r.Zone] {
- t.Errorf("%s applied = %d, want %d", r.Zone, r.Applied, want[r.Zone])
- }
- if !r.Mismatch() {
- t.Errorf("%s: Mismatch() = false, want true (requested 200)", r.Zone)
- }
- }
- }
- // A failed read-back must not be silently reported as success.
- func TestSetBrightnessVerifiedPropagatesReadError(t *testing.T) {
- proto := &verifyingProtocol{getErr: errors.New("read timeout")}
- if _, err := setBrightnessVerified(proto, []intrgb.Zone{intrgb.ZoneLogo}, 100); err == nil {
- t.Fatal("setBrightnessVerified() expected read error, got nil")
- }
- }
- func TestBrightnessCommandStaysQuietWhenApplied(t *testing.T) {
- proto := &verifyingProtocol{applied: map[via.LEDType]uint8{via.RGBLight: 200}}
- originalOpen := openRGBProtocol
- originalZone := targetZone
- t.Cleanup(func() {
- openRGBProtocol = originalOpen
- targetZone = originalZone
- })
- openRGBProtocol = func() (rgbProtocol, error) { return proto, nil }
- targetZone = "logo"
- var out, errOut bytes.Buffer
- cmd := NewBrightnessCmd()
- cmd.SetOut(&out)
- cmd.SetErr(&errOut)
- cmd.SetArgs([]string{"200"})
- if err := cmd.Execute(); err != nil {
- t.Fatalf("brightness returned error: %v", err)
- }
- if errOut.Len() != 0 {
- t.Errorf("stderr = %q, want no warning when the keyboard applied the requested value", errOut.String())
- }
- if !strings.Contains(out.String(), "200") {
- t.Errorf("stdout = %q, want the applied value reported", out.String())
- }
- }
|