commands_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. channels []via.Channel
  20. }
  21. // DetectChannels reports the board's three channels unless a test asks for a
  22. // different set.
  23. func (f *fakeZoneProtocol) DetectChannels() ([]via.Channel, error) {
  24. if f.channels == nil {
  25. return impact80Channels(), nil
  26. }
  27. return f.channels, nil
  28. }
  29. func (f *fakeZoneProtocol) SetValue(channel via.Channel, param, value uint8) error {
  30. if f.failAt >= 0 && f.failAt == len(f.reports) {
  31. return errors.New("write failed")
  32. }
  33. f.reports = append(f.reports, commandReport{
  34. channel: channel,
  35. param: param,
  36. value: value,
  37. })
  38. return nil
  39. }
  40. func (f *fakeZoneProtocol) SetColor(channel via.Channel, hue, saturation uint8) error {
  41. if f.failAt >= 0 && f.failAt == len(f.reports) {
  42. return errors.New("write failed")
  43. }
  44. f.reports = append(f.reports, commandReport{
  45. channel: channel,
  46. param: 4,
  47. hue: hue,
  48. saturation: saturation,
  49. })
  50. return nil
  51. }
  52. func (f *fakeZoneProtocol) GetValue(via.Channel, uint8) ([]byte, error) {
  53. return nil, errors.New("unexpected GetValue call")
  54. }
  55. func (f *fakeZoneProtocol) Close() error {
  56. return nil
  57. }
  58. func TestSelectedChannelOperations(t *testing.T) {
  59. defaultZones := []via.Channel{via.ChannelRgblight, via.ChannelRgbMatrix, via.ChannelAudio}
  60. sideZones := []via.Channel{via.ChannelAudio}
  61. operations := []struct {
  62. name string
  63. zones []via.Channel
  64. sideZones []via.Channel
  65. run func(zoneProtocol, []via.Channel) error
  66. want []commandReport
  67. wantSide []commandReport
  68. }{
  69. {
  70. name: "brightness",
  71. zones: defaultZones,
  72. sideZones: sideZones,
  73. run: func(protocol zoneProtocol, zones []via.Channel) error {
  74. return setBrightnessOnChannels(protocol, zones, 160)
  75. },
  76. want: []commandReport{
  77. {channel: 2, param: 1, value: 160},
  78. {channel: 3, param: 1, value: 160},
  79. {channel: 4, param: 1, value: 160},
  80. },
  81. wantSide: []commandReport{{channel: 4, param: 1, value: 160}},
  82. },
  83. {
  84. name: "speed",
  85. zones: defaultZones,
  86. sideZones: sideZones,
  87. run: func(protocol zoneProtocol, zones []via.Channel) error {
  88. return setSpeedChannels(protocol, zones, 2)
  89. },
  90. want: []commandReport{
  91. {channel: 2, param: 3, value: 2},
  92. {channel: 3, param: 3, value: 2},
  93. {channel: 4, param: 3, value: 2},
  94. },
  95. wantSide: []commandReport{{channel: 4, param: 3, value: 2}},
  96. },
  97. {
  98. name: "color",
  99. zones: defaultZones,
  100. sideZones: sideZones,
  101. run: func(protocol zoneProtocol, zones []via.Channel) error {
  102. return setColorOnChannels(protocol, zones, 85, 255)
  103. },
  104. want: []commandReport{
  105. {channel: 2, param: 4, hue: 85, saturation: 255},
  106. {channel: 3, param: 4, hue: 85, saturation: 255},
  107. {channel: 4, param: 4, hue: 85, saturation: 255},
  108. },
  109. wantSide: []commandReport{{channel: 4, param: 4, hue: 85, saturation: 255}},
  110. },
  111. {
  112. name: "disable",
  113. zones: defaultZones,
  114. sideZones: sideZones,
  115. run: disableLightingOnChannels,
  116. want: []commandReport{
  117. {channel: 2, param: 2, value: 0},
  118. {channel: 2, param: 1, value: 0},
  119. {channel: 3, param: 2, value: 0},
  120. {channel: 3, param: 1, value: 0},
  121. {channel: 4, param: 2, value: 0},
  122. {channel: 4, param: 1, value: 0},
  123. },
  124. wantSide: []commandReport{
  125. {channel: 4, param: 2, value: 0},
  126. {channel: 4, param: 1, value: 0},
  127. },
  128. },
  129. {
  130. name: "enable",
  131. zones: defaultZones,
  132. sideZones: sideZones,
  133. run: func(protocol zoneProtocol, channels []via.Channel) error {
  134. catalog, _ := intrgb.CatalogFor(0x36B0, 0x309F)
  135. return enableLightingOnChannels(protocol, channels, catalog)
  136. },
  137. want: []commandReport{
  138. {channel: 2, param: 2, value: 4},
  139. {channel: 2, param: 1, value: 160},
  140. {channel: 3, param: 2, value: 5},
  141. {channel: 3, param: 1, value: 160},
  142. {channel: 4, param: 2, value: 4},
  143. {channel: 4, param: 1, value: 160},
  144. },
  145. wantSide: []commandReport{
  146. {channel: 4, param: 2, value: 4},
  147. {channel: 4, param: 1, value: 160},
  148. },
  149. },
  150. {
  151. name: "mode",
  152. zones: defaultZones,
  153. sideZones: sideZones,
  154. run: func(protocol zoneProtocol, zones []via.Channel) error {
  155. return setModeOnChannels(protocol, zones, 17)
  156. },
  157. want: []commandReport{
  158. {channel: 2, param: 2, value: 17},
  159. {channel: 3, param: 2, value: 17},
  160. {channel: 4, param: 2, value: 17},
  161. },
  162. wantSide: []commandReport{{channel: 4, param: 2, value: 17}},
  163. },
  164. }
  165. for _, tc := range operations {
  166. t.Run(tc.name+"/default", func(t *testing.T) {
  167. protocol := &fakeZoneProtocol{failAt: -1}
  168. if err := tc.run(protocol, tc.zones); err != nil {
  169. t.Fatalf("operation error = %v", err)
  170. }
  171. if !reflect.DeepEqual(protocol.reports, tc.want) {
  172. t.Errorf("reports = %v, want %v", protocol.reports, tc.want)
  173. }
  174. })
  175. t.Run(tc.name+"/side", func(t *testing.T) {
  176. protocol := &fakeZoneProtocol{failAt: -1}
  177. if err := tc.run(protocol, tc.sideZones); err != nil {
  178. t.Fatalf("operation error = %v", err)
  179. }
  180. if !reflect.DeepEqual(protocol.reports, tc.wantSide) {
  181. t.Errorf("reports = %v, want %v", protocol.reports, tc.wantSide)
  182. }
  183. })
  184. }
  185. }
  186. func TestSelectedChannelStopsOnFirstError(t *testing.T) {
  187. protocol := &fakeZoneProtocol{failAt: 1}
  188. err := setBrightnessOnChannels(protocol, impact80Channels(), 160)
  189. if err == nil {
  190. t.Fatal("setBrightnessOnChannels() expected error, got nil")
  191. }
  192. if len(protocol.reports) != 1 {
  193. t.Errorf("reports = %v, want one report before failure", protocol.reports)
  194. }
  195. }