lib_test.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. package lib
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "net"
  7. "net/http"
  8. "testing"
  9. "github.com/keroserene/go-webrtc"
  10. . "github.com/smartystreets/goconvey/convey"
  11. )
  12. type MockDataChannel struct {
  13. destination bytes.Buffer
  14. done chan bool
  15. }
  16. func (m *MockDataChannel) Send(data []byte) {
  17. m.destination.Write(data)
  18. m.done <- true
  19. }
  20. func (*MockDataChannel) Close() error { return nil }
  21. type MockResponse struct{}
  22. func (m *MockResponse) Read(p []byte) (int, error) {
  23. p = []byte(`{"type":"answer","sdp":"fake"}`)
  24. return 0, nil
  25. }
  26. func (m *MockResponse) Close() error { return nil }
  27. type MockTransport struct {
  28. statusOverride int
  29. body []byte
  30. }
  31. // Just returns a response with fake SDP answer.
  32. func (m *MockTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  33. s := ioutil.NopCloser(bytes.NewReader(m.body))
  34. r := &http.Response{
  35. StatusCode: m.statusOverride,
  36. Body: s,
  37. }
  38. return r, nil
  39. }
  40. type FakeDialer struct{}
  41. func (w FakeDialer) Catch() (Snowflake, error) {
  42. fmt.Println("Caught a dummy snowflake.")
  43. return &WebRTCPeer{}, nil
  44. }
  45. type FakeSocksConn struct {
  46. net.Conn
  47. rejected bool
  48. }
  49. func (f FakeSocksConn) Reject() error {
  50. f.rejected = true
  51. return nil
  52. }
  53. func (f FakeSocksConn) Grant(addr *net.TCPAddr) error { return nil }
  54. type FakePeers struct{ toRelease *WebRTCPeer }
  55. func (f FakePeers) Collect() (Snowflake, error) { return &WebRTCPeer{}, nil }
  56. func (f FakePeers) Pop() Snowflake { return nil }
  57. func (f FakePeers) Melted() <-chan struct{} { return nil }
  58. func TestSnowflakeClient(t *testing.T) {
  59. Convey("Peers", t, func() {
  60. Convey("Can construct", func() {
  61. p := NewPeers(1)
  62. So(p.capacity, ShouldEqual, 1)
  63. So(p.snowflakeChan, ShouldNotBeNil)
  64. So(cap(p.snowflakeChan), ShouldEqual, 1)
  65. })
  66. Convey("Collecting a Snowflake requires a Tongue.", func() {
  67. p := NewPeers(1)
  68. _, err := p.Collect()
  69. So(err, ShouldNotBeNil)
  70. So(p.Count(), ShouldEqual, 0)
  71. // Set the dialer so that collection is possible.
  72. p.Tongue = FakeDialer{}
  73. _, err = p.Collect()
  74. So(err, ShouldBeNil)
  75. So(p.Count(), ShouldEqual, 1)
  76. // S
  77. _, err = p.Collect()
  78. })
  79. Convey("Collection continues until capacity.", func() {
  80. c := 5
  81. p := NewPeers(c)
  82. p.Tongue = FakeDialer{}
  83. // Fill up to capacity.
  84. for i := 0; i < c; i++ {
  85. fmt.Println("Adding snowflake ", i)
  86. _, err := p.Collect()
  87. So(err, ShouldBeNil)
  88. So(p.Count(), ShouldEqual, i+1)
  89. }
  90. // But adding another gives an error.
  91. So(p.Count(), ShouldEqual, c)
  92. _, err := p.Collect()
  93. So(err, ShouldNotBeNil)
  94. So(p.Count(), ShouldEqual, c)
  95. // But popping and closing allows it to continue.
  96. s := p.Pop()
  97. s.Close()
  98. So(s, ShouldNotBeNil)
  99. So(p.Count(), ShouldEqual, c-1)
  100. _, err = p.Collect()
  101. So(err, ShouldBeNil)
  102. So(p.Count(), ShouldEqual, c)
  103. })
  104. Convey("Count correctly purges peers marked for deletion.", func() {
  105. p := NewPeers(4)
  106. p.Tongue = FakeDialer{}
  107. p.Collect()
  108. p.Collect()
  109. p.Collect()
  110. p.Collect()
  111. So(p.Count(), ShouldEqual, 4)
  112. s := p.Pop()
  113. s.Close()
  114. So(p.Count(), ShouldEqual, 3)
  115. s = p.Pop()
  116. s.Close()
  117. So(p.Count(), ShouldEqual, 2)
  118. })
  119. Convey("End Closes all peers.", func() {
  120. cnt := 5
  121. p := NewPeers(cnt)
  122. for i := 0; i < cnt; i++ {
  123. p.activePeers.PushBack(&WebRTCPeer{})
  124. }
  125. So(p.Count(), ShouldEqual, cnt)
  126. p.End()
  127. <-p.Melted()
  128. So(p.Count(), ShouldEqual, 0)
  129. })
  130. Convey("Pop skips over closed peers.", func() {
  131. p := NewPeers(4)
  132. p.Tongue = FakeDialer{}
  133. wc1, _ := p.Collect()
  134. wc2, _ := p.Collect()
  135. wc3, _ := p.Collect()
  136. So(wc1, ShouldNotBeNil)
  137. So(wc2, ShouldNotBeNil)
  138. So(wc3, ShouldNotBeNil)
  139. wc1.Close()
  140. r := p.Pop()
  141. So(p.Count(), ShouldEqual, 2)
  142. So(r, ShouldEqual, wc2)
  143. wc4, _ := p.Collect()
  144. wc2.Close()
  145. wc3.Close()
  146. r = p.Pop()
  147. So(r, ShouldEqual, wc4)
  148. })
  149. })
  150. Convey("Snowflake", t, func() {
  151. SkipConvey("Handler Grants correctly", func() {
  152. socks := &FakeSocksConn{}
  153. snowflakes := &FakePeers{}
  154. So(socks.rejected, ShouldEqual, false)
  155. snowflakes.toRelease = nil
  156. Handler(socks, snowflakes)
  157. So(socks.rejected, ShouldEqual, true)
  158. })
  159. Convey("WebRTC Connection", func() {
  160. c := NewWebRTCPeer(nil, nil)
  161. So(c.buffer.Bytes(), ShouldEqual, nil)
  162. Convey("Can construct a WebRTCConn", func() {
  163. s := NewWebRTCPeer(nil, nil)
  164. So(s, ShouldNotBeNil)
  165. So(s.offerChannel, ShouldNotBeNil)
  166. So(s.answerChannel, ShouldNotBeNil)
  167. s.Close()
  168. })
  169. Convey("Write buffers when datachannel is nil", func() {
  170. c.Write([]byte("test"))
  171. c.transport = nil
  172. So(c.buffer.Bytes(), ShouldResemble, []byte("test"))
  173. })
  174. Convey("Write sends to datachannel when not nil", func() {
  175. mock := new(MockDataChannel)
  176. c.transport = mock
  177. mock.done = make(chan bool, 1)
  178. c.Write([]byte("test"))
  179. <-mock.done
  180. So(c.buffer.Bytes(), ShouldEqual, nil)
  181. So(mock.destination.Bytes(), ShouldResemble, []byte("test"))
  182. })
  183. Convey("Exchange SDP sets remote description", func() {
  184. c.offerChannel = make(chan *webrtc.SessionDescription, 1)
  185. c.answerChannel = make(chan *webrtc.SessionDescription, 1)
  186. c.config = webrtc.NewConfiguration()
  187. c.preparePeerConnection()
  188. c.offerChannel <- nil
  189. answer := webrtc.DeserializeSessionDescription(
  190. `{"type":"answer","sdp":""}`)
  191. c.answerChannel <- answer
  192. c.exchangeSDP()
  193. })
  194. SkipConvey("Exchange SDP fails on nil answer", func() {
  195. c.reset = make(chan struct{})
  196. c.offerChannel = make(chan *webrtc.SessionDescription, 1)
  197. c.answerChannel = make(chan *webrtc.SessionDescription, 1)
  198. c.offerChannel <- nil
  199. c.answerChannel <- nil
  200. c.exchangeSDP()
  201. <-c.reset
  202. })
  203. })
  204. })
  205. Convey("Dialers", t, func() {
  206. Convey("Can construct WebRTCDialer.", func() {
  207. broker := &BrokerChannel{Host: "test"}
  208. d := NewWebRTCDialer(broker, nil)
  209. So(d, ShouldNotBeNil)
  210. So(d.BrokerChannel, ShouldNotBeNil)
  211. So(d.BrokerChannel.Host, ShouldEqual, "test")
  212. })
  213. Convey("WebRTCDialer cannot Catch a snowflake with nil broker.", func() {
  214. d := NewWebRTCDialer(nil, nil)
  215. conn, err := d.Catch()
  216. So(conn, ShouldBeNil)
  217. So(err, ShouldNotBeNil)
  218. })
  219. SkipConvey("WebRTCDialer can Catch a snowflake.", func() {
  220. broker := &BrokerChannel{Host: "test"}
  221. d := NewWebRTCDialer(broker, nil)
  222. conn, err := d.Catch()
  223. So(conn, ShouldBeNil)
  224. So(err, ShouldNotBeNil)
  225. })
  226. })
  227. Convey("Rendezvous", t, func() {
  228. webrtc.SetLoggingVerbosity(0)
  229. transport := &MockTransport{
  230. http.StatusOK,
  231. []byte(`{"type":"answer","sdp":"fake"}`),
  232. }
  233. fakeOffer := webrtc.DeserializeSessionDescription("test")
  234. Convey("Construct BrokerChannel with no front domain", func() {
  235. b := NewBrokerChannel("test.broker", "", transport)
  236. So(b.url, ShouldNotBeNil)
  237. So(b.url.Path, ShouldResemble, "test.broker")
  238. So(b.transport, ShouldNotBeNil)
  239. })
  240. Convey("Construct BrokerChannel *with* front domain", func() {
  241. b := NewBrokerChannel("test.broker", "front", transport)
  242. So(b.url, ShouldNotBeNil)
  243. So(b.url.Path, ShouldResemble, "test.broker")
  244. So(b.url.Host, ShouldResemble, "front")
  245. So(b.transport, ShouldNotBeNil)
  246. })
  247. Convey("BrokerChannel.Negotiate responds with answer", func() {
  248. b := NewBrokerChannel("test.broker", "", transport)
  249. answer, err := b.Negotiate(fakeOffer)
  250. So(err, ShouldBeNil)
  251. So(answer, ShouldNotBeNil)
  252. So(answer.Sdp, ShouldResemble, "fake")
  253. })
  254. Convey("BrokerChannel.Negotiate fails with 503", func() {
  255. b := NewBrokerChannel("test.broker", "",
  256. &MockTransport{http.StatusServiceUnavailable, []byte("\n")})
  257. answer, err := b.Negotiate(fakeOffer)
  258. So(err, ShouldNotBeNil)
  259. So(answer, ShouldBeNil)
  260. So(err.Error(), ShouldResemble, BrokerError503)
  261. })
  262. Convey("BrokerChannel.Negotiate fails with 400", func() {
  263. b := NewBrokerChannel("test.broker", "",
  264. &MockTransport{http.StatusBadRequest, []byte("\n")})
  265. answer, err := b.Negotiate(fakeOffer)
  266. So(err, ShouldNotBeNil)
  267. So(answer, ShouldBeNil)
  268. So(err.Error(), ShouldResemble, BrokerError400)
  269. })
  270. Convey("BrokerChannel.Negotiate fails with large read", func() {
  271. b := NewBrokerChannel("test.broker", "",
  272. &MockTransport{http.StatusOK, make([]byte, 100001, 100001)})
  273. answer, err := b.Negotiate(fakeOffer)
  274. So(err, ShouldNotBeNil)
  275. So(answer, ShouldBeNil)
  276. So(err.Error(), ShouldResemble, "unexpected EOF")
  277. })
  278. Convey("BrokerChannel.Negotiate fails with unexpected error", func() {
  279. b := NewBrokerChannel("test.broker", "",
  280. &MockTransport{123, []byte("")})
  281. answer, err := b.Negotiate(fakeOffer)
  282. So(err, ShouldNotBeNil)
  283. So(answer, ShouldBeNil)
  284. So(err.Error(), ShouldResemble, BrokerErrorUnexpected)
  285. })
  286. })
  287. }