protocol_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package protocol
  5. import (
  6. "errors"
  7. "io"
  8. "testing"
  9. "testing/quick"
  10. "github.com/calmh/syncthing/xdr"
  11. )
  12. var (
  13. c0ID = NewNodeID([]byte{1})
  14. c1ID = NewNodeID([]byte{2})
  15. )
  16. func TestHeaderFunctions(t *testing.T) {
  17. f := func(ver, id, typ int) bool {
  18. ver = int(uint(ver) % 16)
  19. id = int(uint(id) % 4096)
  20. typ = int(uint(typ) % 256)
  21. h0 := header{version: ver, msgID: id, msgType: typ}
  22. h1 := decodeHeader(encodeHeader(h0))
  23. return h0 == h1
  24. }
  25. if err := quick.Check(f, nil); err != nil {
  26. t.Error(err)
  27. }
  28. }
  29. func TestHeaderLayout(t *testing.T) {
  30. var e, a uint32
  31. // Version are the first four bits
  32. e = 0xf0000000
  33. a = encodeHeader(header{version: 0xf})
  34. if a != e {
  35. t.Errorf("Header layout incorrect; %08x != %08x", a, e)
  36. }
  37. // Message ID are the following 12 bits
  38. e = 0x0fff0000
  39. a = encodeHeader(header{msgID: 0xfff})
  40. if a != e {
  41. t.Errorf("Header layout incorrect; %08x != %08x", a, e)
  42. }
  43. // Type are the last 8 bits before reserved
  44. e = 0x0000ff00
  45. a = encodeHeader(header{msgType: 0xff})
  46. if a != e {
  47. t.Errorf("Header layout incorrect; %08x != %08x", a, e)
  48. }
  49. }
  50. func TestPing(t *testing.T) {
  51. ar, aw := io.Pipe()
  52. br, bw := io.Pipe()
  53. c0 := NewConnection(c0ID, ar, bw, nil, "name", true).(wireFormatConnection).next.(*rawConnection)
  54. c1 := NewConnection(c1ID, br, aw, nil, "name", true).(wireFormatConnection).next.(*rawConnection)
  55. if ok := c0.ping(); !ok {
  56. t.Error("c0 ping failed")
  57. }
  58. if ok := c1.ping(); !ok {
  59. t.Error("c1 ping failed")
  60. }
  61. }
  62. func TestPingErr(t *testing.T) {
  63. e := errors.New("something broke")
  64. for i := 0; i < 16; i++ {
  65. for j := 0; j < 16; j++ {
  66. m0 := newTestModel()
  67. m1 := newTestModel()
  68. ar, aw := io.Pipe()
  69. br, bw := io.Pipe()
  70. eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
  71. ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}
  72. c0 := NewConnection(c0ID, ar, ebw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
  73. NewConnection(c1ID, br, eaw, m1, "name", true)
  74. res := c0.ping()
  75. if (i < 8 || j < 8) && res {
  76. t.Errorf("Unexpected ping success; i=%d, j=%d", i, j)
  77. } else if (i >= 12 && j >= 12) && !res {
  78. t.Errorf("Unexpected ping fail; i=%d, j=%d", i, j)
  79. }
  80. }
  81. }
  82. }
  83. // func TestRequestResponseErr(t *testing.T) {
  84. // e := errors.New("something broke")
  85. // var pass bool
  86. // for i := 0; i < 48; i++ {
  87. // for j := 0; j < 38; j++ {
  88. // m0 := newTestModel()
  89. // m0.data = []byte("response data")
  90. // m1 := newTestModel()
  91. // ar, aw := io.Pipe()
  92. // br, bw := io.Pipe()
  93. // eaw := &ErrPipe{PipeWriter: *aw, max: i, err: e}
  94. // ebw := &ErrPipe{PipeWriter: *bw, max: j, err: e}
  95. // NewConnection(c0ID, ar, ebw, m0, nil)
  96. // c1 := NewConnection(c1ID, br, eaw, m1, nil).(wireFormatConnection).next.(*rawConnection)
  97. // d, err := c1.Request("default", "tn", 1234, 5678)
  98. // if err == e || err == ErrClosed {
  99. // t.Logf("Error at %d+%d bytes", i, j)
  100. // if !m1.isClosed() {
  101. // t.Fatal("c1 not closed")
  102. // }
  103. // if !m0.isClosed() {
  104. // t.Fatal("c0 not closed")
  105. // }
  106. // continue
  107. // }
  108. // if err != nil {
  109. // t.Fatal(err)
  110. // }
  111. // if string(d) != "response data" {
  112. // t.Fatalf("Incorrect response data %q", string(d))
  113. // }
  114. // if m0.repo != "default" {
  115. // t.Fatalf("Incorrect repo %q", m0.repo)
  116. // }
  117. // if m0.name != "tn" {
  118. // t.Fatalf("Incorrect name %q", m0.name)
  119. // }
  120. // if m0.offset != 1234 {
  121. // t.Fatalf("Incorrect offset %d", m0.offset)
  122. // }
  123. // if m0.size != 5678 {
  124. // t.Fatalf("Incorrect size %d", m0.size)
  125. // }
  126. // t.Logf("Pass at %d+%d bytes", i, j)
  127. // pass = true
  128. // }
  129. // }
  130. // if !pass {
  131. // t.Fatal("Never passed")
  132. // }
  133. // }
  134. func TestVersionErr(t *testing.T) {
  135. m0 := newTestModel()
  136. m1 := newTestModel()
  137. ar, aw := io.Pipe()
  138. br, bw := io.Pipe()
  139. c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
  140. NewConnection(c1ID, br, aw, m1, "name", true)
  141. w := xdr.NewWriter(c0.cw)
  142. w.WriteUint32(encodeHeader(header{
  143. version: 2,
  144. msgID: 0,
  145. msgType: 0,
  146. }))
  147. w.WriteUint32(0)
  148. if !m1.isClosed() {
  149. t.Error("Connection should close due to unknown version")
  150. }
  151. }
  152. func TestTypeErr(t *testing.T) {
  153. m0 := newTestModel()
  154. m1 := newTestModel()
  155. ar, aw := io.Pipe()
  156. br, bw := io.Pipe()
  157. c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
  158. NewConnection(c1ID, br, aw, m1, "name", true)
  159. w := xdr.NewWriter(c0.cw)
  160. w.WriteUint32(encodeHeader(header{
  161. version: 0,
  162. msgID: 0,
  163. msgType: 42,
  164. }))
  165. w.WriteUint32(0)
  166. if !m1.isClosed() {
  167. t.Error("Connection should close due to unknown message type")
  168. }
  169. }
  170. func TestClose(t *testing.T) {
  171. m0 := newTestModel()
  172. m1 := newTestModel()
  173. ar, aw := io.Pipe()
  174. br, bw := io.Pipe()
  175. c0 := NewConnection(c0ID, ar, bw, m0, "name", true).(wireFormatConnection).next.(*rawConnection)
  176. NewConnection(c1ID, br, aw, m1, "name", true)
  177. c0.close(nil)
  178. <-c0.closed
  179. if !m0.isClosed() {
  180. t.Fatal("Connection should be closed")
  181. }
  182. // None of these should panic, some should return an error
  183. if c0.ping() {
  184. t.Error("Ping should not return true")
  185. }
  186. c0.Index("default", nil)
  187. c0.Index("default", nil)
  188. if _, err := c0.Request("default", "foo", 0, 0); err == nil {
  189. t.Error("Request should return an error")
  190. }
  191. }