conntest.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package nettest provides utilities for network testing.
  5. package nettest
  6. import (
  7. "bytes"
  8. "encoding/binary"
  9. "io"
  10. "io/ioutil"
  11. "math/rand"
  12. "net"
  13. "sync"
  14. "testing"
  15. "time"
  16. )
  17. var (
  18. aLongTimeAgo = time.Unix(233431200, 0)
  19. neverTimeout = time.Time{}
  20. )
  21. // MakePipe creates a connection between two endpoints and returns the pair
  22. // as c1 and c2, such that anything written to c1 is read by c2 and vice-versa.
  23. // The stop function closes all resources, including c1, c2, and the underlying
  24. // net.Listener (if there is one), and should not be nil.
  25. type MakePipe func() (c1, c2 net.Conn, stop func(), err error)
  26. // TestConn tests that a net.Conn implementation properly satisfies the interface.
  27. // The tests should not produce any false positives, but may experience
  28. // false negatives. Thus, some issues may only be detected when the test is
  29. // run multiple times. For maximal effectiveness, run the tests under the
  30. // race detector.
  31. func TestConn(t *testing.T, mp MakePipe) {
  32. testConn(t, mp)
  33. }
  34. type connTester func(t *testing.T, c1, c2 net.Conn)
  35. func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) {
  36. c1, c2, stop, err := mp()
  37. if err != nil {
  38. t.Fatalf("unable to make pipe: %v", err)
  39. }
  40. var once sync.Once
  41. defer once.Do(func() { stop() })
  42. timer := time.AfterFunc(time.Minute, func() {
  43. once.Do(func() {
  44. t.Error("test timed out; terminating pipe")
  45. stop()
  46. })
  47. })
  48. defer timer.Stop()
  49. f(t, c1, c2)
  50. }
  51. // testBasicIO tests that the data sent on c1 is properly received on c2.
  52. func testBasicIO(t *testing.T, c1, c2 net.Conn) {
  53. want := make([]byte, 1<<20)
  54. rand.New(rand.NewSource(0)).Read(want)
  55. dataCh := make(chan []byte)
  56. go func() {
  57. rd := bytes.NewReader(want)
  58. if err := chunkedCopy(c1, rd); err != nil {
  59. t.Errorf("unexpected c1.Write error: %v", err)
  60. }
  61. if err := c1.Close(); err != nil {
  62. t.Errorf("unexpected c1.Close error: %v", err)
  63. }
  64. }()
  65. go func() {
  66. wr := new(bytes.Buffer)
  67. if err := chunkedCopy(wr, c2); err != nil {
  68. t.Errorf("unexpected c2.Read error: %v", err)
  69. }
  70. if err := c2.Close(); err != nil {
  71. t.Errorf("unexpected c2.Close error: %v", err)
  72. }
  73. dataCh <- wr.Bytes()
  74. }()
  75. if got := <-dataCh; !bytes.Equal(got, want) {
  76. t.Errorf("transmitted data differs")
  77. }
  78. }
  79. // testPingPong tests that the two endpoints can synchronously send data to
  80. // each other in a typical request-response pattern.
  81. func testPingPong(t *testing.T, c1, c2 net.Conn) {
  82. var wg sync.WaitGroup
  83. defer wg.Wait()
  84. pingPonger := func(c net.Conn) {
  85. defer wg.Done()
  86. buf := make([]byte, 8)
  87. var prev uint64
  88. for {
  89. if _, err := io.ReadFull(c, buf); err != nil {
  90. if err == io.EOF {
  91. break
  92. }
  93. t.Errorf("unexpected Read error: %v", err)
  94. }
  95. v := binary.LittleEndian.Uint64(buf)
  96. binary.LittleEndian.PutUint64(buf, v+1)
  97. if prev != 0 && prev+2 != v {
  98. t.Errorf("mismatching value: got %d, want %d", v, prev+2)
  99. }
  100. prev = v
  101. if v == 1000 {
  102. break
  103. }
  104. if _, err := c.Write(buf); err != nil {
  105. t.Errorf("unexpected Write error: %v", err)
  106. break
  107. }
  108. }
  109. if err := c.Close(); err != nil {
  110. t.Errorf("unexpected Close error: %v", err)
  111. }
  112. }
  113. wg.Add(2)
  114. go pingPonger(c1)
  115. go pingPonger(c2)
  116. // Start off the chain reaction.
  117. if _, err := c1.Write(make([]byte, 8)); err != nil {
  118. t.Errorf("unexpected c1.Write error: %v", err)
  119. }
  120. }
  121. // testRacyRead tests that it is safe to mutate the input Read buffer
  122. // immediately after cancelation has occurred.
  123. func testRacyRead(t *testing.T, c1, c2 net.Conn) {
  124. go chunkedCopy(c2, rand.New(rand.NewSource(0)))
  125. var wg sync.WaitGroup
  126. defer wg.Wait()
  127. c1.SetReadDeadline(time.Now().Add(time.Millisecond))
  128. for i := 0; i < 10; i++ {
  129. wg.Add(1)
  130. go func() {
  131. defer wg.Done()
  132. b1 := make([]byte, 1024)
  133. b2 := make([]byte, 1024)
  134. for j := 0; j < 100; j++ {
  135. _, err := c1.Read(b1)
  136. copy(b1, b2) // Mutate b1 to trigger potential race
  137. if err != nil {
  138. checkForTimeoutError(t, err)
  139. c1.SetReadDeadline(time.Now().Add(time.Millisecond))
  140. }
  141. }
  142. }()
  143. }
  144. }
  145. // testRacyWrite tests that it is safe to mutate the input Write buffer
  146. // immediately after cancelation has occurred.
  147. func testRacyWrite(t *testing.T, c1, c2 net.Conn) {
  148. go chunkedCopy(ioutil.Discard, c2)
  149. var wg sync.WaitGroup
  150. defer wg.Wait()
  151. c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
  152. for i := 0; i < 10; i++ {
  153. wg.Add(1)
  154. go func() {
  155. defer wg.Done()
  156. b1 := make([]byte, 1024)
  157. b2 := make([]byte, 1024)
  158. for j := 0; j < 100; j++ {
  159. _, err := c1.Write(b1)
  160. copy(b1, b2) // Mutate b1 to trigger potential race
  161. if err != nil {
  162. checkForTimeoutError(t, err)
  163. c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
  164. }
  165. }
  166. }()
  167. }
  168. }
  169. // testReadTimeout tests that Read timeouts do not affect Write.
  170. func testReadTimeout(t *testing.T, c1, c2 net.Conn) {
  171. go chunkedCopy(ioutil.Discard, c2)
  172. c1.SetReadDeadline(aLongTimeAgo)
  173. _, err := c1.Read(make([]byte, 1024))
  174. checkForTimeoutError(t, err)
  175. if _, err := c1.Write(make([]byte, 1024)); err != nil {
  176. t.Errorf("unexpected Write error: %v", err)
  177. }
  178. }
  179. // testWriteTimeout tests that Write timeouts do not affect Read.
  180. func testWriteTimeout(t *testing.T, c1, c2 net.Conn) {
  181. go chunkedCopy(c2, rand.New(rand.NewSource(0)))
  182. c1.SetWriteDeadline(aLongTimeAgo)
  183. _, err := c1.Write(make([]byte, 1024))
  184. checkForTimeoutError(t, err)
  185. if _, err := c1.Read(make([]byte, 1024)); err != nil {
  186. t.Errorf("unexpected Read error: %v", err)
  187. }
  188. }
  189. // testPastTimeout tests that a deadline set in the past immediately times out
  190. // Read and Write requests.
  191. func testPastTimeout(t *testing.T, c1, c2 net.Conn) {
  192. go chunkedCopy(c2, c2)
  193. testRoundtrip(t, c1)
  194. c1.SetDeadline(aLongTimeAgo)
  195. n, err := c1.Write(make([]byte, 1024))
  196. if n != 0 {
  197. t.Errorf("unexpected Write count: got %d, want 0", n)
  198. }
  199. checkForTimeoutError(t, err)
  200. n, err = c1.Read(make([]byte, 1024))
  201. if n != 0 {
  202. t.Errorf("unexpected Read count: got %d, want 0", n)
  203. }
  204. checkForTimeoutError(t, err)
  205. testRoundtrip(t, c1)
  206. }
  207. // testPresentTimeout tests that a deadline set while there are pending
  208. // Read and Write operations immediately times out those operations.
  209. func testPresentTimeout(t *testing.T, c1, c2 net.Conn) {
  210. var wg sync.WaitGroup
  211. defer wg.Wait()
  212. wg.Add(3)
  213. deadlineSet := make(chan bool, 1)
  214. go func() {
  215. defer wg.Done()
  216. time.Sleep(100 * time.Millisecond)
  217. deadlineSet <- true
  218. c1.SetReadDeadline(aLongTimeAgo)
  219. c1.SetWriteDeadline(aLongTimeAgo)
  220. }()
  221. go func() {
  222. defer wg.Done()
  223. n, err := c1.Read(make([]byte, 1024))
  224. if n != 0 {
  225. t.Errorf("unexpected Read count: got %d, want 0", n)
  226. }
  227. checkForTimeoutError(t, err)
  228. if len(deadlineSet) == 0 {
  229. t.Error("Read timed out before deadline is set")
  230. }
  231. }()
  232. go func() {
  233. defer wg.Done()
  234. var err error
  235. for err == nil {
  236. _, err = c1.Write(make([]byte, 1024))
  237. }
  238. checkForTimeoutError(t, err)
  239. if len(deadlineSet) == 0 {
  240. t.Error("Write timed out before deadline is set")
  241. }
  242. }()
  243. }
  244. // testFutureTimeout tests that a future deadline will eventually time out
  245. // Read and Write operations.
  246. func testFutureTimeout(t *testing.T, c1, c2 net.Conn) {
  247. var wg sync.WaitGroup
  248. wg.Add(2)
  249. c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
  250. go func() {
  251. defer wg.Done()
  252. _, err := c1.Read(make([]byte, 1024))
  253. checkForTimeoutError(t, err)
  254. }()
  255. go func() {
  256. defer wg.Done()
  257. var err error
  258. for err == nil {
  259. _, err = c1.Write(make([]byte, 1024))
  260. }
  261. checkForTimeoutError(t, err)
  262. }()
  263. wg.Wait()
  264. go chunkedCopy(c2, c2)
  265. resyncConn(t, c1)
  266. testRoundtrip(t, c1)
  267. }
  268. // testCloseTimeout tests that calling Close immediately times out pending
  269. // Read and Write operations.
  270. func testCloseTimeout(t *testing.T, c1, c2 net.Conn) {
  271. go chunkedCopy(c2, c2)
  272. var wg sync.WaitGroup
  273. defer wg.Wait()
  274. wg.Add(3)
  275. // Test for cancelation upon connection closure.
  276. c1.SetDeadline(neverTimeout)
  277. go func() {
  278. defer wg.Done()
  279. time.Sleep(100 * time.Millisecond)
  280. c1.Close()
  281. }()
  282. go func() {
  283. defer wg.Done()
  284. var err error
  285. buf := make([]byte, 1024)
  286. for err == nil {
  287. _, err = c1.Read(buf)
  288. }
  289. }()
  290. go func() {
  291. defer wg.Done()
  292. var err error
  293. buf := make([]byte, 1024)
  294. for err == nil {
  295. _, err = c1.Write(buf)
  296. }
  297. }()
  298. }
  299. // testConcurrentMethods tests that the methods of net.Conn can safely
  300. // be called concurrently.
  301. func testConcurrentMethods(t *testing.T, c1, c2 net.Conn) {
  302. go chunkedCopy(c2, c2)
  303. // The results of the calls may be nonsensical, but this should
  304. // not trigger a race detector warning.
  305. var wg sync.WaitGroup
  306. for i := 0; i < 100; i++ {
  307. wg.Add(7)
  308. go func() {
  309. defer wg.Done()
  310. c1.Read(make([]byte, 1024))
  311. }()
  312. go func() {
  313. defer wg.Done()
  314. c1.Write(make([]byte, 1024))
  315. }()
  316. go func() {
  317. defer wg.Done()
  318. c1.SetDeadline(time.Now().Add(10 * time.Millisecond))
  319. }()
  320. go func() {
  321. defer wg.Done()
  322. c1.SetReadDeadline(aLongTimeAgo)
  323. }()
  324. go func() {
  325. defer wg.Done()
  326. c1.SetWriteDeadline(aLongTimeAgo)
  327. }()
  328. go func() {
  329. defer wg.Done()
  330. c1.LocalAddr()
  331. }()
  332. go func() {
  333. defer wg.Done()
  334. c1.RemoteAddr()
  335. }()
  336. }
  337. wg.Wait() // At worst, the deadline is set 10ms into the future
  338. resyncConn(t, c1)
  339. testRoundtrip(t, c1)
  340. }
  341. // checkForTimeoutError checks that the error satisfies the Error interface
  342. // and that Timeout returns true.
  343. func checkForTimeoutError(t *testing.T, err error) {
  344. if nerr, ok := err.(net.Error); ok {
  345. if !nerr.Timeout() {
  346. t.Errorf("err.Timeout() = false, want true")
  347. }
  348. } else {
  349. t.Errorf("got %T, want net.Error", err)
  350. }
  351. }
  352. // testRoundtrip writes something into c and reads it back.
  353. // It assumes that everything written into c is echoed back to itself.
  354. func testRoundtrip(t *testing.T, c net.Conn) {
  355. if err := c.SetDeadline(neverTimeout); err != nil {
  356. t.Errorf("roundtrip SetDeadline error: %v", err)
  357. }
  358. const s = "Hello, world!"
  359. buf := []byte(s)
  360. if _, err := c.Write(buf); err != nil {
  361. t.Errorf("roundtrip Write error: %v", err)
  362. }
  363. if _, err := io.ReadFull(c, buf); err != nil {
  364. t.Errorf("roundtrip Read error: %v", err)
  365. }
  366. if string(buf) != s {
  367. t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s)
  368. }
  369. }
  370. // resyncConn resynchronizes the connection into a sane state.
  371. // It assumes that everything written into c is echoed back to itself.
  372. // It assumes that 0xff is not currently on the wire or in the read buffer.
  373. func resyncConn(t *testing.T, c net.Conn) {
  374. c.SetDeadline(neverTimeout)
  375. errCh := make(chan error)
  376. go func() {
  377. _, err := c.Write([]byte{0xff})
  378. errCh <- err
  379. }()
  380. buf := make([]byte, 1024)
  381. for {
  382. n, err := c.Read(buf)
  383. if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 {
  384. break
  385. }
  386. if err != nil {
  387. t.Errorf("unexpected Read error: %v", err)
  388. }
  389. }
  390. if err := <-errCh; err != nil {
  391. t.Errorf("unexpected Write error: %v", err)
  392. }
  393. }
  394. // chunkedCopy copies from r to w in fixed-width chunks to avoid
  395. // causing a Write that exceeds the maximum packet size for packet-based
  396. // connections like "unixpacket".
  397. // We assume that the maximum packet size is at least 1024.
  398. func chunkedCopy(w io.Writer, r io.Reader) error {
  399. b := make([]byte, 1024)
  400. _, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b)
  401. return err
  402. }