Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

461 rader
11 KiB

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