header_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package header
  2. import (
  3. "reflect"
  4. "testing"
  5. "github.com/stretchr/testify/assert"
  6. "github.com/stretchr/testify/require"
  7. )
  8. type headerTest struct {
  9. expectedBytes []byte
  10. *H
  11. }
  12. // 0001 0010 00010010
  13. var headerBigEndianTests = []headerTest{{
  14. expectedBytes: []byte{0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9},
  15. // 1010 0000
  16. H: &H{
  17. // 1111 1+2+4+8 = 15
  18. Version: 5,
  19. Type: 4,
  20. Subtype: 0,
  21. Reserved: 0,
  22. RemoteIndex: 10,
  23. MessageCounter: 9,
  24. },
  25. },
  26. }
  27. func TestEncode(t *testing.T) {
  28. for _, tt := range headerBigEndianTests {
  29. b, err := tt.Encode(make([]byte, Len))
  30. if err != nil {
  31. t.Fatal(err)
  32. }
  33. assert.Equal(t, tt.expectedBytes, b)
  34. }
  35. }
  36. func TestParse(t *testing.T) {
  37. for _, tt := range headerBigEndianTests {
  38. b := tt.expectedBytes
  39. parsedHeader := &H{}
  40. parsedHeader.Parse(b)
  41. if !reflect.DeepEqual(tt.H, parsedHeader) {
  42. t.Fatalf("got %#v; want %#v", parsedHeader, tt.H)
  43. }
  44. }
  45. }
  46. func TestEncodeLane(t *testing.T) {
  47. b := EncodeLane(make([]byte, Len), Version, Message, MessageNone, 10, 9, 3)
  48. assert.Equal(t, []byte{0x11, 0x0, 0x0, 0x3}, b[:4])
  49. h := &H{}
  50. require.NoError(t, h.Parse(b))
  51. assert.Equal(t, uint16(3), h.Reserved)
  52. assert.Equal(t, uint8(3), h.Lane())
  53. // Encode is EncodeLane on the base tunnel, and the H method round trips the lane.
  54. assert.Equal(t,
  55. EncodeLane(make([]byte, Len), Version, Message, MessageNone, 10, 9, 0),
  56. Encode(make([]byte, Len), Version, Message, MessageNone, 10, 9))
  57. rt, err := h.Encode(make([]byte, Len))
  58. require.NoError(t, err)
  59. assert.Equal(t, b, rt)
  60. // Only the low 8 bits of Reserved are the lane.
  61. assert.Equal(t, uint8(0x2a), (&H{Reserved: 0xff2a}).Lane())
  62. }
  63. func TestTypeName(t *testing.T) {
  64. assert.Equal(t, "test", TypeName(Test))
  65. assert.Equal(t, "test", (&H{Type: Test}).TypeName())
  66. assert.Equal(t, "unknown", TypeName(99))
  67. assert.Equal(t, "unknown", (&H{Type: 99}).TypeName())
  68. }
  69. func TestSubTypeName(t *testing.T) {
  70. assert.Equal(t, "testRequest", SubTypeName(Test, TestRequest))
  71. assert.Equal(t, "testRequest", (&H{Type: Test, Subtype: TestRequest}).SubTypeName())
  72. assert.Equal(t, "unknown", SubTypeName(99, TestRequest))
  73. assert.Equal(t, "unknown", (&H{Type: 99, Subtype: TestRequest}).SubTypeName())
  74. assert.Equal(t, "unknown", SubTypeName(Test, 99))
  75. assert.Equal(t, "unknown", (&H{Type: Test, Subtype: 99}).SubTypeName())
  76. assert.Equal(t, "none", SubTypeName(Message, 0))
  77. assert.Equal(t, "none", (&H{Type: Message, Subtype: 0}).SubTypeName())
  78. }
  79. func TestTypeMap(t *testing.T) {
  80. // Force people to document this stuff
  81. assert.Equal(t, map[MessageType]string{
  82. Handshake: "handshake",
  83. Message: "message",
  84. RecvError: "recvError",
  85. LightHouse: "lightHouse",
  86. Test: "test",
  87. CloseTunnel: "closeTunnel",
  88. Control: "control",
  89. }, typeMap)
  90. assert.Equal(t, map[MessageType]*map[MessageSubType]string{
  91. Message: {
  92. MessageNone: "none",
  93. MessageRelay: "relay",
  94. },
  95. RecvError: &subTypeNoneMap,
  96. LightHouse: &subTypeNoneMap,
  97. Test: &subTypeTestMap,
  98. CloseTunnel: &subTypeNoneMap,
  99. Handshake: {
  100. HandshakeIXPSK0: "ix_psk0",
  101. },
  102. Control: &subTypeNoneMap,
  103. }, subTypeMap)
  104. }
  105. // mapIsValidSubType is the pre-refactor, map-driven definition of a valid
  106. // subtype. IsValidSubType was reimplemented as an explicit switch; this keeps
  107. // the original behavior around so we can prove the switch is equivalent to it.
  108. func mapIsValidSubType(t MessageType, s MessageSubType) bool {
  109. if n, ok := subTypeMap[t]; ok {
  110. if _, ok := (*n)[s]; ok {
  111. return true
  112. }
  113. }
  114. return false
  115. }
  116. func TestIsValidSubType(t *testing.T) {
  117. // Explicit intent table: documents exactly which subtypes are valid so the
  118. // test stays meaningful even if both the switch and subTypeMap change.
  119. assert.True(t, IsValidSubType(Message, MessageNone))
  120. assert.True(t, IsValidSubType(Message, MessageRelay))
  121. assert.False(t, IsValidSubType(Message, 2))
  122. assert.True(t, IsValidSubType(Handshake, HandshakeIXPSK0))
  123. // HandshakeXXPSK0 is defined but not a wire-valid subtype.
  124. assert.False(t, IsValidSubType(Handshake, HandshakeXXPSK0))
  125. assert.True(t, IsValidSubType(Test, TestRequest))
  126. assert.True(t, IsValidSubType(Test, TestReply))
  127. assert.True(t, IsValidSubType(Test, LaneProbe))
  128. assert.True(t, IsValidSubType(Test, LaneProbeAck))
  129. assert.False(t, IsValidSubType(Test, 4))
  130. // These types only ever carry subtype 0.
  131. for _, mt := range []MessageType{Control, CloseTunnel, RecvError, LightHouse} {
  132. assert.True(t, IsValidSubType(mt, 0), "type %d subtype 0 should be valid", mt)
  133. assert.False(t, IsValidSubType(mt, 1), "type %d subtype 1 should be invalid", mt)
  134. }
  135. // Unknown/unassigned types are never valid.
  136. assert.False(t, IsValidSubType(99, 0))
  137. // Exhaustive proof of equivalence with the original map-driven logic across
  138. // the entire (type, subtype) input space.
  139. for ti := 0; ti <= 0xff; ti++ {
  140. for si := 0; si <= 0xff; si++ {
  141. mt, mst := MessageType(ti), MessageSubType(si)
  142. assert.Equalf(t, mapIsValidSubType(mt, mst), IsValidSubType(mt, mst),
  143. "IsValidSubType(%d, %d) diverged from map-driven definition", ti, si)
  144. }
  145. }
  146. // H method must delegate to the package function.
  147. assert.True(t, (&H{Type: Test, Subtype: TestReply}).IsValidSubType())
  148. assert.False(t, (&H{Type: Handshake, Subtype: HandshakeXXPSK0}).IsValidSubType())
  149. }
  150. func TestHeader_String(t *testing.T) {
  151. assert.Equal(
  152. t,
  153. "ver=100 type=test subtype=testRequest reserved=0x63 remoteindex=98 messagecounter=97",
  154. (&H{100, Test, TestRequest, 99, 98, 97}).String(),
  155. )
  156. }
  157. func TestHeader_MarshalJSON(t *testing.T) {
  158. b, err := (&H{100, Test, TestRequest, 99, 98, 97}).MarshalJSON()
  159. require.NoError(t, err)
  160. assert.Equal(
  161. t,
  162. "{\"messageCounter\":97,\"remoteIndex\":98,\"reserved\":99,\"subType\":\"testRequest\",\"type\":\"test\",\"version\":100}",
  163. string(b),
  164. )
  165. }