effect_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package rgb
  2. import (
  3. "bytes"
  4. "reflect"
  5. "strings"
  6. "testing"
  7. intrgb "github.com/wobkey/rgb/internal/rgb"
  8. )
  9. func TestResolveEffectTargetsBacklightOnly(t *testing.T) {
  10. targets, skipped, err := resolveEffectTargets("rainbow_moving_chevron", intrgb.AllZones())
  11. if err != nil {
  12. t.Fatalf("resolveEffectTargets() unexpected error: %v", err)
  13. }
  14. wantTargets := []intrgb.EffectTarget{{Zone: intrgb.ZoneBacklight, ID: 17}}
  15. if !reflect.DeepEqual(targets, wantTargets) {
  16. t.Errorf("resolveEffectTargets() targets = %v, want %v", targets, wantTargets)
  17. }
  18. wantSkipped := []intrgb.Zone{intrgb.ZoneLogo, intrgb.ZoneSide}
  19. if !reflect.DeepEqual(skipped, wantSkipped) {
  20. t.Errorf("resolveEffectTargets() skipped = %v, want %v", skipped, wantSkipped)
  21. }
  22. }
  23. func TestResolveEffectTargetsBreathing(t *testing.T) {
  24. targets, skipped, err := resolveEffectTargets("breathing", intrgb.AllZones())
  25. if err != nil {
  26. t.Fatalf("resolveEffectTargets() unexpected error: %v", err)
  27. }
  28. wantTargets := []intrgb.EffectTarget{
  29. {Zone: intrgb.ZoneLogo, ID: 4},
  30. {Zone: intrgb.ZoneBacklight, ID: 5},
  31. {Zone: intrgb.ZoneSide, ID: 4},
  32. }
  33. if !reflect.DeepEqual(targets, wantTargets) {
  34. t.Errorf("resolveEffectTargets() targets = %v, want %v", targets, wantTargets)
  35. }
  36. if len(skipped) != 0 {
  37. t.Errorf("resolveEffectTargets() skipped = %v, want none", skipped)
  38. }
  39. }
  40. func TestResolveEffectTargetsExplicitUnsupported(t *testing.T) {
  41. cases := []struct {
  42. name string
  43. zones []intrgb.Zone
  44. }{
  45. {"rainbow_moving_chevron", []intrgb.Zone{intrgb.ZoneLogo}},
  46. {"rainbow_wave", []intrgb.Zone{intrgb.ZoneBacklight}},
  47. {"splash", []intrgb.Zone{intrgb.ZoneSide}},
  48. }
  49. for _, tc := range cases {
  50. t.Run(tc.name+string(tc.zones[0]), func(t *testing.T) {
  51. targets, skipped, err := resolveEffectTargets(tc.name, tc.zones)
  52. if err == nil {
  53. t.Fatal("resolveEffectTargets() expected error, got nil")
  54. }
  55. if len(targets) != 0 {
  56. t.Errorf("resolveEffectTargets() targets = %v, want none", targets)
  57. }
  58. if len(skipped) != 0 {
  59. t.Errorf("resolveEffectTargets() skipped = %v, want none", skipped)
  60. }
  61. })
  62. }
  63. }
  64. func TestResolveEffectTargetsUnknownName(t *testing.T) {
  65. targets, skipped, err := resolveEffectTargets("not_an_effect", intrgb.AllZones())
  66. if err == nil {
  67. t.Fatal("resolveEffectTargets() expected error, got nil")
  68. }
  69. if len(targets) != 0 {
  70. t.Errorf("resolveEffectTargets() targets = %v, want none", targets)
  71. }
  72. if len(skipped) != 0 {
  73. t.Errorf("resolveEffectTargets() skipped = %v, want none", skipped)
  74. }
  75. }
  76. func TestResolveEffectTargetsStaticCompatibility(t *testing.T) {
  77. targets, skipped, err := resolveEffectTargets("static", intrgb.AllZones())
  78. if err != nil {
  79. t.Fatalf("resolveEffectTargets() unexpected error: %v", err)
  80. }
  81. wantTargets := []intrgb.EffectTarget{
  82. {Zone: intrgb.ZoneLogo, ID: 5},
  83. {Zone: intrgb.ZoneBacklight, ID: 1},
  84. {Zone: intrgb.ZoneSide, ID: 5},
  85. }
  86. if !reflect.DeepEqual(targets, wantTargets) {
  87. t.Errorf("resolveEffectTargets() targets = %v, want %v", targets, wantTargets)
  88. }
  89. if len(skipped) != 0 {
  90. t.Errorf("resolveEffectTargets() skipped = %v, want none", skipped)
  91. }
  92. }
  93. func executeEffectCommand(t *testing.T, protocol *fakeZoneProtocol, target string, args ...string) (string, string, error) {
  94. t.Helper()
  95. originalOpen := openRGBProtocol
  96. originalZone := targetZone
  97. openRGBProtocol = func() (rgbProtocol, error) {
  98. return protocol, nil
  99. }
  100. targetZone = target
  101. t.Cleanup(func() {
  102. openRGBProtocol = originalOpen
  103. targetZone = originalZone
  104. })
  105. var stdout bytes.Buffer
  106. var stderr bytes.Buffer
  107. cmd := NewEffectCmd()
  108. cmd.SetOut(&stdout)
  109. cmd.SetErr(&stderr)
  110. cmd.SilenceErrors = true
  111. cmd.SilenceUsage = true
  112. cmd.SetArgs(args)
  113. err := cmd.Execute()
  114. return stdout.String(), stderr.String(), err
  115. }
  116. func TestEffectCommandWarnsForSkippedZones(t *testing.T) {
  117. protocol := &fakeZoneProtocol{failAt: -1}
  118. stdout, stderr, err := executeEffectCommand(t, protocol, "", "rainbow_moving_chevron")
  119. if err != nil {
  120. t.Fatalf("Execute() unexpected error: %v", err)
  121. }
  122. if !strings.Contains(stderr, "effect not supported on zone(s): logo, side") {
  123. t.Errorf("stderr = %q, want skipped-zone warning", stderr)
  124. }
  125. if !strings.Contains(stdout, `Effect set to "rainbow_moving_chevron"`) {
  126. t.Errorf("stdout = %q, want success output", stdout)
  127. }
  128. if len(protocol.reports) != 1 {
  129. t.Fatalf("reports = %v, want one Backlight report", protocol.reports)
  130. }
  131. if protocol.reports[0].channel != 3 || protocol.reports[0].param != 2 || protocol.reports[0].value != 17 {
  132. t.Errorf("report = %+v, want Backlight Effect 17", protocol.reports[0])
  133. }
  134. }
  135. func TestEffectCommandRejectsBeforeOpeningProtocol(t *testing.T) {
  136. protocol := &fakeZoneProtocol{failAt: -1}
  137. stdout, _, err := executeEffectCommand(t, protocol, "logo", "rainbow_moving_chevron")
  138. if err == nil {
  139. t.Fatal("Execute() expected error, got nil")
  140. }
  141. if len(protocol.reports) != 0 {
  142. t.Errorf("reports = %v, want no writes before rejection", protocol.reports)
  143. }
  144. if stdout != "" {
  145. t.Errorf("stdout = %q, want no success output", stdout)
  146. }
  147. }
  148. func TestEffectCommandSuppressesSuccessAfterLaterWriteFailure(t *testing.T) {
  149. protocol := &fakeZoneProtocol{failAt: 1}
  150. stdout, _, err := executeEffectCommand(t, protocol, "", "breathing")
  151. if err == nil {
  152. t.Fatal("Execute() expected write error, got nil")
  153. }
  154. if len(protocol.reports) != 1 {
  155. t.Fatalf("reports = %v, want one report before failure", protocol.reports)
  156. }
  157. if strings.Contains(stdout, "Effect set") {
  158. t.Errorf("stdout = %q, want success output suppressed", stdout)
  159. }
  160. }