manager_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package device
  2. import (
  3. "context"
  4. "errors"
  5. "testing"
  6. "vocat/internal/modem"
  7. )
  8. func TestManagerRefreshBuildsEC20Snapshot(t *testing.T) {
  9. client := &transcriptClient{steps: []clientStep{
  10. {
  11. command: "ATI",
  12. response: okResponse(
  13. "Quectel",
  14. "EC20CEFAGR06A04M4G",
  15. "Revision: EC20CEHCLGR06A04M1G",
  16. ),
  17. },
  18. {command: "AT+CPIN?", response: okResponse("+CPIN: READY")},
  19. {command: "AT+CSQ", response: okResponse("+CSQ: 20,99")},
  20. {
  21. command: `AT+QENG="servingcell"`,
  22. response: okResponse(
  23. `+QENG: "servingcell","NOCONN","LTE","FDD",460,01,5F1E805,37,1650,3,5,5,8340,-97,-10,-68,15,9`,
  24. ),
  25. },
  26. {command: "AT+COPS?", response: okResponse(`+COPS: 0,0,"China Mobile",7`)},
  27. {command: "AT+CGSN", response: okResponse("867123456789012")},
  28. {
  29. command: "AT+CCID",
  30. response: modem.Response{Final: "+CME ERROR: 100"},
  31. err: errors.New("CCID unsupported"),
  32. },
  33. {command: "AT+QCCID", response: okResponse("+QCCID: 8986001234567890123F")},
  34. {command: "AT+CIMI", response: okResponse("460001234567890")},
  35. {command: "AT+CFUN?", response: okResponse("+CFUN: 1")},
  36. {command: "AT+CNUM", response: okResponse(`+CNUM: "","+8613800138000",145`)},
  37. }}
  38. manager, id := newStartedTestManager(t, client)
  39. snapshot, err := manager.Refresh(context.Background(), id)
  40. if err != nil {
  41. t.Fatalf("Refresh: %v", err)
  42. }
  43. if !snapshot.Responsive || !snapshot.SIMReady || snapshot.SIMStatus != "ready" {
  44. t.Fatalf("modem/SIM state = %#v", snapshot)
  45. }
  46. if snapshot.Manufacturer != "Quectel" ||
  47. snapshot.Model != "EC20CEFAGR06A04M4G" ||
  48. snapshot.Firmware != "EC20CEHCLGR06A04M1G" {
  49. t.Fatalf(
  50. "identity = manufacturer %q, model %q, firmware %q",
  51. snapshot.Manufacturer,
  52. snapshot.Model,
  53. snapshot.Firmware,
  54. )
  55. }
  56. if snapshot.SignalRaw == nil || *snapshot.SignalRaw != 20 ||
  57. snapshot.SignalPercent == nil || *snapshot.SignalPercent != 65 ||
  58. snapshot.RSSIDBm == nil || *snapshot.RSSIDBm != -68 ||
  59. snapshot.RSRP == nil || *snapshot.RSRP != -97 ||
  60. snapshot.RSRQ == nil || *snapshot.RSRQ != -10 ||
  61. snapshot.SINR == nil || *snapshot.SINR != 15 {
  62. t.Fatalf("signal metrics = %#v", snapshot)
  63. }
  64. if snapshot.AccessTech != "LTE" || snapshot.Band != "B3" ||
  65. snapshot.Channel != "1650" || snapshot.OperatorName != "China Mobile" {
  66. t.Fatalf("network = %#v", snapshot)
  67. }
  68. if snapshot.IMEI != "867123456789012" ||
  69. snapshot.ICCID != "8986001234567890123" ||
  70. snapshot.IMSI != "460001234567890" {
  71. t.Fatalf("subscriber identifiers = %#v", snapshot)
  72. }
  73. if !snapshot.ModeKnown || snapshot.OperatingMode != 1 ||
  74. snapshot.FlightMode || snapshot.RadioOff {
  75. t.Fatalf("operating mode = %#v", snapshot)
  76. }
  77. if snapshot.Phone.Number != "+8613800138000" ||
  78. snapshot.Phone.Source != PhoneSourceCNUM {
  79. t.Fatalf("phone = %#v", snapshot.Phone)
  80. }
  81. device, err := manager.Get(id)
  82. if err != nil {
  83. t.Fatalf("Get: %v", err)
  84. }
  85. if device.Snapshot == nil || device.Snapshot.Phone.Number != snapshot.Phone.Number {
  86. t.Fatalf("stored device = %#v", device)
  87. }
  88. client.assertDone(t)
  89. }
  90. func TestParseICCIDIdentifierStripsTwoFillerNibbles(t *testing.T) {
  91. response := modem.Response{Lines: []string{"+CCID: 894921007608519523FF"}}
  92. if got := parseICCIDIdentifier(response, []string{"+CCID:", "+QCCID:"}, 18, 22); got != "894921007608519523" {
  93. t.Fatalf("parseICCIDIdentifier = %q", got)
  94. }
  95. }
  96. func TestManagerRequiresStartAndKnownDevice(t *testing.T) {
  97. manager, err := NewManager(Options{
  98. Discoverer: staticDiscoverer{},
  99. Opener: &staticOpener{},
  100. })
  101. if err != nil {
  102. t.Fatal(err)
  103. }
  104. if _, err := manager.Refresh(context.Background(), "missing"); !errors.Is(err, ErrNotStarted) {
  105. t.Fatalf("before Start error = %v", err)
  106. }
  107. if err := manager.Start(context.Background()); err != nil {
  108. t.Fatal(err)
  109. }
  110. if _, err := manager.Refresh(context.Background(), "missing"); !errors.Is(err, ErrNotFound) {
  111. t.Fatalf("unknown device error = %v", err)
  112. }
  113. }
  114. func TestExecuteSensitiveATDoesNotPersistCommandOrModemError(t *testing.T) {
  115. const secretCommand = `AT+CSIM=78,"00880081221000112233445566778899AABBCCDDEEFF1000112233445566778899AABBCCDDEEFF00"`
  116. client := &transcriptClient{steps: []clientStep{{
  117. command: secretCommand,
  118. err: &modem.CommandError{Command: secretCommand, Final: "ERROR"},
  119. }}}
  120. manager, id := newStartedTestManager(t, client)
  121. if _, err := manager.ExecuteSensitiveAT(context.Background(), id, secretCommand); err == nil {
  122. t.Fatal("ExecuteSensitiveAT() error = nil")
  123. }
  124. entry, err := manager.Get(id)
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. if entry.LastError != "sensitive AT command failed" {
  129. t.Fatalf("LastError = %q", entry.LastError)
  130. }
  131. client.assertDone(t)
  132. }