commands_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package main
  2. import (
  3. "errors"
  4. "reflect"
  5. "testing"
  6. intrgb "netdome.biz/paul/qmk-rgb/internal/rgb"
  7. "netdome.biz/paul/qmk-rgb/internal/via"
  8. )
  9. type commandReport struct {
  10. channel via.Channel
  11. param uint8
  12. value uint8
  13. hue uint8
  14. saturation uint8
  15. }
  16. type fakeZoneProtocol struct {
  17. reports []commandReport
  18. failAt int
  19. }
  20. func (f *fakeZoneProtocol) SetValue(channel via.Channel, param, value uint8) error {
  21. if f.failAt >= 0 && f.failAt == len(f.reports) {
  22. return errors.New("write failed")
  23. }
  24. f.reports = append(f.reports, commandReport{
  25. channel: channel,
  26. param: param,
  27. value: value,
  28. })
  29. return nil
  30. }
  31. func (f *fakeZoneProtocol) SetColor(channel via.Channel, hue, saturation uint8) error {
  32. if f.failAt >= 0 && f.failAt == len(f.reports) {
  33. return errors.New("write failed")
  34. }
  35. f.reports = append(f.reports, commandReport{
  36. channel: channel,
  37. param: 4,
  38. hue: hue,
  39. saturation: saturation,
  40. })
  41. return nil
  42. }
  43. func (f *fakeZoneProtocol) GetValue(via.Channel, uint8) ([]byte, error) {
  44. return nil, errors.New("unexpected GetValue call")
  45. }
  46. func (f *fakeZoneProtocol) Close() error {
  47. return nil
  48. }
  49. func TestSelectedChannelOperations(t *testing.T) {
  50. defaultZones := []intrgb.Zone{intrgb.ZoneLogo, intrgb.ZoneBacklight, intrgb.ZoneSide}
  51. sideZones := []intrgb.Zone{intrgb.ZoneSide}
  52. operations := []struct {
  53. name string
  54. zones []intrgb.Zone
  55. sideZones []intrgb.Zone
  56. run func(zoneProtocol, []intrgb.Zone) error
  57. want []commandReport
  58. wantSide []commandReport
  59. }{
  60. {
  61. name: "brightness",
  62. zones: defaultZones,
  63. sideZones: sideZones,
  64. run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
  65. return setBrightnessOnZones(protocol, zones, 160)
  66. },
  67. want: []commandReport{
  68. {channel: 2, param: 1, value: 160},
  69. {channel: 3, param: 1, value: 160},
  70. {channel: 4, param: 1, value: 160},
  71. },
  72. wantSide: []commandReport{{channel: 4, param: 1, value: 160}},
  73. },
  74. {
  75. name: "speed",
  76. zones: defaultZones,
  77. sideZones: sideZones,
  78. run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
  79. return setSpeedOnZones(protocol, zones, 2)
  80. },
  81. want: []commandReport{
  82. {channel: 2, param: 3, value: 2},
  83. {channel: 3, param: 3, value: 2},
  84. {channel: 4, param: 3, value: 2},
  85. },
  86. wantSide: []commandReport{{channel: 4, param: 3, value: 2}},
  87. },
  88. {
  89. name: "color",
  90. zones: defaultZones,
  91. sideZones: sideZones,
  92. run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
  93. return setColorOnZones(protocol, zones, 85, 255)
  94. },
  95. want: []commandReport{
  96. {channel: 2, param: 4, hue: 85, saturation: 255},
  97. {channel: 3, param: 4, hue: 85, saturation: 255},
  98. {channel: 4, param: 4, hue: 85, saturation: 255},
  99. },
  100. wantSide: []commandReport{{channel: 4, param: 4, hue: 85, saturation: 255}},
  101. },
  102. {
  103. name: "disable",
  104. zones: defaultZones,
  105. sideZones: sideZones,
  106. run: disableLightingOnZones,
  107. want: []commandReport{
  108. {channel: 2, param: 2, value: 0},
  109. {channel: 2, param: 1, value: 0},
  110. {channel: 3, param: 2, value: 0},
  111. {channel: 3, param: 1, value: 0},
  112. {channel: 4, param: 2, value: 0},
  113. {channel: 4, param: 1, value: 0},
  114. },
  115. wantSide: []commandReport{
  116. {channel: 4, param: 2, value: 0},
  117. {channel: 4, param: 1, value: 0},
  118. },
  119. },
  120. {
  121. name: "enable",
  122. zones: defaultZones,
  123. sideZones: sideZones,
  124. run: enableLightingOnZones,
  125. want: []commandReport{
  126. {channel: 2, param: 2, value: 4},
  127. {channel: 2, param: 1, value: 160},
  128. {channel: 3, param: 2, value: 5},
  129. {channel: 3, param: 1, value: 160},
  130. {channel: 4, param: 2, value: 4},
  131. {channel: 4, param: 1, value: 160},
  132. },
  133. wantSide: []commandReport{
  134. {channel: 4, param: 2, value: 4},
  135. {channel: 4, param: 1, value: 160},
  136. },
  137. },
  138. {
  139. name: "mode",
  140. zones: defaultZones,
  141. sideZones: sideZones,
  142. run: func(protocol zoneProtocol, zones []intrgb.Zone) error {
  143. return setModeOnZones(protocol, zones, 17)
  144. },
  145. want: []commandReport{
  146. {channel: 2, param: 2, value: 17},
  147. {channel: 3, param: 2, value: 17},
  148. {channel: 4, param: 2, value: 17},
  149. },
  150. wantSide: []commandReport{{channel: 4, param: 2, value: 17}},
  151. },
  152. }
  153. for _, tc := range operations {
  154. t.Run(tc.name+"/default", func(t *testing.T) {
  155. protocol := &fakeZoneProtocol{failAt: -1}
  156. if err := tc.run(protocol, tc.zones); err != nil {
  157. t.Fatalf("operation error = %v", err)
  158. }
  159. if !reflect.DeepEqual(protocol.reports, tc.want) {
  160. t.Errorf("reports = %v, want %v", protocol.reports, tc.want)
  161. }
  162. })
  163. t.Run(tc.name+"/side", func(t *testing.T) {
  164. protocol := &fakeZoneProtocol{failAt: -1}
  165. if err := tc.run(protocol, tc.sideZones); err != nil {
  166. t.Fatalf("operation error = %v", err)
  167. }
  168. if !reflect.DeepEqual(protocol.reports, tc.wantSide) {
  169. t.Errorf("reports = %v, want %v", protocol.reports, tc.wantSide)
  170. }
  171. })
  172. }
  173. }
  174. func TestSelectedChannelStopsOnFirstError(t *testing.T) {
  175. protocol := &fakeZoneProtocol{failAt: 1}
  176. err := setBrightnessOnZones(protocol, intrgb.AllZones(), 160)
  177. if err == nil {
  178. t.Fatal("setBrightnessOnZones() expected error, got nil")
  179. }
  180. if len(protocol.reports) != 1 {
  181. t.Errorf("reports = %v, want one report before failure", protocol.reports)
  182. }
  183. }