channels_test.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package main
  2. import (
  3. "strings"
  4. "testing"
  5. intdevice "netdome.biz/paul/qmk-rgb/internal/device"
  6. "netdome.biz/paul/qmk-rgb/internal/via"
  7. )
  8. func TestResolveZoneNameAcceptsASubsystemName(t *testing.T) {
  9. got, err := resolveZoneName("rgb_matrix", map[uint16]string{2: "logo"})
  10. if err != nil {
  11. t.Fatalf("resolveZoneName() error = %v", err)
  12. }
  13. if len(got) != 1 || got[0] != via.ChannelRgbMatrix {
  14. t.Errorf("resolveZoneName() = %v, want [3]", got)
  15. }
  16. }
  17. func TestResolveZoneNameAcceptsADisplayName(t *testing.T) {
  18. got, err := resolveZoneName("logo", map[uint16]string{2: "logo", 3: "backlight", 4: "side"})
  19. if err != nil {
  20. t.Fatalf("resolveZoneName() error = %v", err)
  21. }
  22. if len(got) != 1 || got[0] != via.ChannelRgblight {
  23. t.Errorf("resolveZoneName() = %v, want [2]", got)
  24. }
  25. }
  26. func TestResolveZoneNameRejectsAnUnknownName(t *testing.T) {
  27. _, err := resolveZoneName("nope", map[uint16]string{2: "logo"})
  28. if err == nil {
  29. t.Fatal("resolveZoneName() expected an error, got nil")
  30. }
  31. if !strings.Contains(err.Error(), "rgb_matrix") {
  32. t.Errorf("error = %q, want it to name an accepted form", err)
  33. }
  34. }
  35. // A board that supplies no display names keeps the subsystem vocabulary, so the
  36. // physical names that work on the Impact 80 do not work elsewhere.
  37. func TestResolveZoneNameIgnoresDisplayNamesForAnotherBoard(t *testing.T) {
  38. if _, err := resolveZoneName("logo", nil); err == nil {
  39. t.Fatal("resolveZoneName(\"logo\", nil) expected an error, got nil")
  40. }
  41. }
  42. // Two channels carrying the same display name are ambiguous, and the tool
  43. // reports that rather than picking one. Whether a display name shadows another
  44. // channel's subsystem name cannot be decided here, because presence is only
  45. // known after the probe; displayNameConflicts decides that.
  46. func TestResolveZoneNameReportsAnAmbiguousName(t *testing.T) {
  47. _, err := resolveZoneName("backlight", map[uint16]string{2: "logo", 3: "backlight", 4: "backlight"})
  48. if err == nil {
  49. t.Fatal("resolveZoneName() expected an error for a name two channels answer to")
  50. }
  51. if !strings.Contains(err.Error(), "backlight") {
  52. t.Errorf("error = %q, want it to name the conflicting name", err)
  53. }
  54. }
  55. func TestDisplayNameConflictsRejectsAShadowedSubsystemName(t *testing.T) {
  56. // Channel 1 is present and its subsystem is "backlight", while the file
  57. // also calls channel 3 "backlight": two channels, one name.
  58. err := displayNameConflicts(
  59. map[uint16]string{3: "backlight"},
  60. []via.Channel{via.ChannelBacklight, via.ChannelRgbMatrix},
  61. )
  62. if err == nil {
  63. t.Fatal("displayNameConflicts() expected an error, got nil")
  64. }
  65. if !strings.Contains(err.Error(), "backlight") {
  66. t.Errorf("error = %q, want it to name the conflicting name", err)
  67. }
  68. }
  69. func TestDisplayNameConflictsAllowsTheImpact80Naming(t *testing.T) {
  70. // The Impact 80 calls channel 3 "backlight" and has no channel 1, so
  71. // nothing shadows anything.
  72. err := displayNameConflicts(
  73. map[uint16]string{2: "logo", 3: "backlight", 4: "side"},
  74. []via.Channel{via.ChannelRgblight, via.ChannelRgbMatrix, via.ChannelAudio},
  75. )
  76. if err != nil {
  77. t.Fatalf("displayNameConflicts() error = %v, want nil", err)
  78. }
  79. }
  80. func TestChannelNamePrefersTheDisplayName(t *testing.T) {
  81. display := map[uint16]string{2: "logo"}
  82. if got := channelName(via.ChannelRgblight, display); got != "logo" {
  83. t.Errorf("channelName(2) = %q, want %q", got, "logo")
  84. }
  85. if got := channelName(via.ChannelRgbMatrix, display); got != "rgb_matrix" {
  86. t.Errorf("channelName(3) = %q, want %q", got, "rgb_matrix")
  87. }
  88. }
  89. // The display names must come from the keyboard the command targets, not from
  90. // whichever one enumeration returned first.
  91. func TestPrepareTargetUsesTheSelectedKeyboard(t *testing.T) {
  92. devices := []intdevice.Device{
  93. {VendorID: 0x6666, ProductID: 0x0001},
  94. {VendorID: 0x36B0, ProductID: 0x309F, Name: "Wobkey Impact 80"},
  95. }
  96. originalDiscover := discoverAll
  97. originalKeyboardFor := keyboardFor
  98. originalTarget := targetDevice
  99. originalZone := targetZone
  100. t.Cleanup(func() {
  101. discoverAll = originalDiscover
  102. keyboardFor = originalKeyboardFor
  103. targetDevice = originalTarget
  104. targetZone = originalZone
  105. })
  106. discoverAll = func() ([]intdevice.Device, error) { return devices, nil }
  107. keyboardFor = func(vendorID, productID uint16) (intdevice.Keyboard, bool, error) {
  108. switch {
  109. case vendorID == 0x6666:
  110. return intdevice.Keyboard{Name: "Wobkey Rainy 75", Channels: map[uint16]string{2: "deck"}}, true, nil
  111. case vendorID == 0x36B0:
  112. return intdevice.Keyboard{Name: "Wobkey Impact 80", Channels: map[uint16]string{2: "logo"}}, true, nil
  113. }
  114. return intdevice.Keyboard{}, false, nil
  115. }
  116. targetDevice = "2"
  117. targetZone = "logo"
  118. got, err := prepareTarget()
  119. if err != nil {
  120. t.Fatalf("prepareTarget() error = %v", err)
  121. }
  122. if got.Display[2] != "logo" {
  123. t.Errorf("display names = %v, want the Impact 80's", got.Display)
  124. }
  125. }