tcp_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // Copyright 2012 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 net
  5. import (
  6. "fmt"
  7. "io"
  8. "reflect"
  9. "runtime"
  10. "sync"
  11. "testing"
  12. "time"
  13. )
  14. func BenchmarkTCP4OneShot(b *testing.B) {
  15. benchmarkTCP(b, false, false, "127.0.0.1:0")
  16. }
  17. func BenchmarkTCP4OneShotTimeout(b *testing.B) {
  18. benchmarkTCP(b, false, true, "127.0.0.1:0")
  19. }
  20. func BenchmarkTCP4Persistent(b *testing.B) {
  21. benchmarkTCP(b, true, false, "127.0.0.1:0")
  22. }
  23. func BenchmarkTCP4PersistentTimeout(b *testing.B) {
  24. benchmarkTCP(b, true, true, "127.0.0.1:0")
  25. }
  26. func BenchmarkTCP6OneShot(b *testing.B) {
  27. if !supportsIPv6 {
  28. b.Skip("ipv6 is not supported")
  29. }
  30. benchmarkTCP(b, false, false, "[::1]:0")
  31. }
  32. func BenchmarkTCP6OneShotTimeout(b *testing.B) {
  33. if !supportsIPv6 {
  34. b.Skip("ipv6 is not supported")
  35. }
  36. benchmarkTCP(b, false, true, "[::1]:0")
  37. }
  38. func BenchmarkTCP6Persistent(b *testing.B) {
  39. if !supportsIPv6 {
  40. b.Skip("ipv6 is not supported")
  41. }
  42. benchmarkTCP(b, true, false, "[::1]:0")
  43. }
  44. func BenchmarkTCP6PersistentTimeout(b *testing.B) {
  45. if !supportsIPv6 {
  46. b.Skip("ipv6 is not supported")
  47. }
  48. benchmarkTCP(b, true, true, "[::1]:0")
  49. }
  50. func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) {
  51. const msgLen = 512
  52. conns := b.N
  53. numConcurrent := runtime.GOMAXPROCS(-1) * 2
  54. msgs := 1
  55. if persistent {
  56. conns = numConcurrent
  57. msgs = b.N / conns
  58. if msgs == 0 {
  59. msgs = 1
  60. }
  61. if conns > b.N {
  62. conns = b.N
  63. }
  64. }
  65. sendMsg := func(c Conn, buf []byte) bool {
  66. n, err := c.Write(buf)
  67. if n != len(buf) || err != nil {
  68. b.Logf("Write failed: %v", err)
  69. return false
  70. }
  71. return true
  72. }
  73. recvMsg := func(c Conn, buf []byte) bool {
  74. for read := 0; read != len(buf); {
  75. n, err := c.Read(buf)
  76. read += n
  77. if err != nil {
  78. b.Logf("Read failed: %v", err)
  79. return false
  80. }
  81. }
  82. return true
  83. }
  84. ln, err := Listen("tcp", laddr)
  85. if err != nil {
  86. b.Fatalf("Listen failed: %v", err)
  87. }
  88. defer ln.Close()
  89. serverSem := make(chan bool, numConcurrent)
  90. // Acceptor.
  91. go func() {
  92. for {
  93. c, err := ln.Accept()
  94. if err != nil {
  95. break
  96. }
  97. serverSem <- true
  98. // Server connection.
  99. go func(c Conn) {
  100. defer func() {
  101. c.Close()
  102. <-serverSem
  103. }()
  104. if timeout {
  105. c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
  106. }
  107. var buf [msgLen]byte
  108. for m := 0; m < msgs; m++ {
  109. if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
  110. break
  111. }
  112. }
  113. }(c)
  114. }
  115. }()
  116. clientSem := make(chan bool, numConcurrent)
  117. for i := 0; i < conns; i++ {
  118. clientSem <- true
  119. // Client connection.
  120. go func() {
  121. defer func() {
  122. <-clientSem
  123. }()
  124. c, err := Dial("tcp", ln.Addr().String())
  125. if err != nil {
  126. b.Logf("Dial failed: %v", err)
  127. return
  128. }
  129. defer c.Close()
  130. if timeout {
  131. c.SetDeadline(time.Now().Add(time.Hour)) // Not intended to fire.
  132. }
  133. var buf [msgLen]byte
  134. for m := 0; m < msgs; m++ {
  135. if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
  136. break
  137. }
  138. }
  139. }()
  140. }
  141. for i := 0; i < numConcurrent; i++ {
  142. clientSem <- true
  143. serverSem <- true
  144. }
  145. }
  146. func BenchmarkTCP4ConcurrentReadWrite(b *testing.B) {
  147. benchmarkTCPConcurrentReadWrite(b, "127.0.0.1:0")
  148. }
  149. func BenchmarkTCP6ConcurrentReadWrite(b *testing.B) {
  150. if !supportsIPv6 {
  151. b.Skip("ipv6 is not supported")
  152. }
  153. benchmarkTCPConcurrentReadWrite(b, "[::1]:0")
  154. }
  155. func benchmarkTCPConcurrentReadWrite(b *testing.B, laddr string) {
  156. // The benchmark creates GOMAXPROCS client/server pairs.
  157. // Each pair creates 4 goroutines: client reader/writer and server reader/writer.
  158. // The benchmark stresses concurrent reading and writing to the same connection.
  159. // Such pattern is used in net/http and net/rpc.
  160. b.StopTimer()
  161. P := runtime.GOMAXPROCS(0)
  162. N := b.N / P
  163. W := 1000
  164. // Setup P client/server connections.
  165. clients := make([]Conn, P)
  166. servers := make([]Conn, P)
  167. ln, err := Listen("tcp", laddr)
  168. if err != nil {
  169. b.Fatalf("Listen failed: %v", err)
  170. }
  171. defer ln.Close()
  172. done := make(chan bool)
  173. go func() {
  174. for p := 0; p < P; p++ {
  175. s, err := ln.Accept()
  176. if err != nil {
  177. b.Errorf("Accept failed: %v", err)
  178. return
  179. }
  180. servers[p] = s
  181. }
  182. done <- true
  183. }()
  184. for p := 0; p < P; p++ {
  185. c, err := Dial("tcp", ln.Addr().String())
  186. if err != nil {
  187. b.Fatalf("Dial failed: %v", err)
  188. }
  189. clients[p] = c
  190. }
  191. <-done
  192. b.StartTimer()
  193. var wg sync.WaitGroup
  194. wg.Add(4 * P)
  195. for p := 0; p < P; p++ {
  196. // Client writer.
  197. go func(c Conn) {
  198. defer wg.Done()
  199. var buf [1]byte
  200. for i := 0; i < N; i++ {
  201. v := byte(i)
  202. for w := 0; w < W; w++ {
  203. v *= v
  204. }
  205. buf[0] = v
  206. _, err := c.Write(buf[:])
  207. if err != nil {
  208. b.Errorf("Write failed: %v", err)
  209. return
  210. }
  211. }
  212. }(clients[p])
  213. // Pipe between server reader and server writer.
  214. pipe := make(chan byte, 128)
  215. // Server reader.
  216. go func(s Conn) {
  217. defer wg.Done()
  218. var buf [1]byte
  219. for i := 0; i < N; i++ {
  220. _, err := s.Read(buf[:])
  221. if err != nil {
  222. b.Errorf("Read failed: %v", err)
  223. return
  224. }
  225. pipe <- buf[0]
  226. }
  227. }(servers[p])
  228. // Server writer.
  229. go func(s Conn) {
  230. defer wg.Done()
  231. var buf [1]byte
  232. for i := 0; i < N; i++ {
  233. v := <-pipe
  234. for w := 0; w < W; w++ {
  235. v *= v
  236. }
  237. buf[0] = v
  238. _, err := s.Write(buf[:])
  239. if err != nil {
  240. b.Errorf("Write failed: %v", err)
  241. return
  242. }
  243. }
  244. s.Close()
  245. }(servers[p])
  246. // Client reader.
  247. go func(c Conn) {
  248. defer wg.Done()
  249. var buf [1]byte
  250. for i := 0; i < N; i++ {
  251. _, err := c.Read(buf[:])
  252. if err != nil {
  253. b.Errorf("Read failed: %v", err)
  254. return
  255. }
  256. }
  257. c.Close()
  258. }(clients[p])
  259. }
  260. wg.Wait()
  261. }
  262. type resolveTCPAddrTest struct {
  263. net string
  264. litAddrOrName string
  265. addr *TCPAddr
  266. err error
  267. }
  268. var resolveTCPAddrTests = []resolveTCPAddrTest{
  269. {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
  270. {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
  271. {"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil},
  272. {"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil},
  273. {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
  274. {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
  275. {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
  276. {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
  277. {"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
  278. {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
  279. }
  280. func init() {
  281. if ifi := loopbackInterface(); ifi != nil {
  282. index := fmt.Sprintf("%v", ifi.Index)
  283. resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
  284. {"tcp6", "[fe80::1%" + ifi.Name + "]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone: zoneToString(ifi.Index)}, nil},
  285. {"tcp6", "[fe80::1%" + index + "]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone: index}, nil},
  286. }...)
  287. }
  288. if ips, err := LookupIP("localhost"); err == nil && len(ips) > 1 && supportsIPv4 && supportsIPv6 {
  289. resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
  290. {"tcp", "localhost:5", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 5}, nil},
  291. {"tcp4", "localhost:6", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 6}, nil},
  292. {"tcp6", "localhost:7", &TCPAddr{IP: IPv6loopback, Port: 7}, nil},
  293. }...)
  294. }
  295. }
  296. func TestResolveTCPAddr(t *testing.T) {
  297. for _, tt := range resolveTCPAddrTests {
  298. addr, err := ResolveTCPAddr(tt.net, tt.litAddrOrName)
  299. if err != tt.err {
  300. t.Fatalf("ResolveTCPAddr(%q, %q) failed: %v", tt.net, tt.litAddrOrName, err)
  301. }
  302. if !reflect.DeepEqual(addr, tt.addr) {
  303. t.Fatalf("ResolveTCPAddr(%q, %q) = %#v, want %#v", tt.net, tt.litAddrOrName, addr, tt.addr)
  304. }
  305. if err == nil {
  306. str := addr.String()
  307. addr1, err := ResolveTCPAddr(tt.net, str)
  308. if err != nil {
  309. t.Fatalf("ResolveTCPAddr(%q, %q) [from %q]: %v", tt.net, str, tt.litAddrOrName, err)
  310. }
  311. if !reflect.DeepEqual(addr1, addr) {
  312. t.Fatalf("ResolveTCPAddr(%q, %q) [from %q] = %#v, want %#v", tt.net, str, tt.litAddrOrName, addr1, addr)
  313. }
  314. }
  315. }
  316. }
  317. var tcpListenerNameTests = []struct {
  318. net string
  319. laddr *TCPAddr
  320. }{
  321. {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}},
  322. {"tcp4", &TCPAddr{}},
  323. {"tcp4", nil},
  324. }
  325. func TestTCPListenerName(t *testing.T) {
  326. if testing.Short() || !*testExternal {
  327. t.Skip("skipping test to avoid external network")
  328. }
  329. for _, tt := range tcpListenerNameTests {
  330. ln, err := ListenTCP(tt.net, tt.laddr)
  331. if err != nil {
  332. t.Fatalf("ListenTCP failed: %v", err)
  333. }
  334. defer ln.Close()
  335. la := ln.Addr()
  336. if a, ok := la.(*TCPAddr); !ok || a.Port == 0 {
  337. t.Fatalf("got %v; expected a proper address with non-zero port number", la)
  338. }
  339. }
  340. }
  341. func TestIPv6LinkLocalUnicastTCP(t *testing.T) {
  342. if testing.Short() || !*testExternal {
  343. t.Skip("skipping test to avoid external network")
  344. }
  345. if !supportsIPv6 {
  346. t.Skip("ipv6 is not supported")
  347. }
  348. ifi := loopbackInterface()
  349. if ifi == nil {
  350. t.Skip("loopback interface not found")
  351. }
  352. laddr := ipv6LinkLocalUnicastAddr(ifi)
  353. if laddr == "" {
  354. t.Skip("ipv6 unicast address on loopback not found")
  355. }
  356. type test struct {
  357. net, addr string
  358. nameLookup bool
  359. }
  360. var tests = []test{
  361. {"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false},
  362. {"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false},
  363. }
  364. switch runtime.GOOS {
  365. case "darwin", "freebsd", "openbsd", "netbsd":
  366. tests = append(tests, []test{
  367. {"tcp", "[localhost%" + ifi.Name + "]:0", true},
  368. {"tcp6", "[localhost%" + ifi.Name + "]:0", true},
  369. }...)
  370. case "linux":
  371. tests = append(tests, []test{
  372. {"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
  373. {"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
  374. }...)
  375. }
  376. for _, tt := range tests {
  377. ln, err := Listen(tt.net, tt.addr)
  378. if err != nil {
  379. // It might return "LookupHost returned no
  380. // suitable address" error on some platforms.
  381. t.Logf("Listen failed: %v", err)
  382. continue
  383. }
  384. defer ln.Close()
  385. if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
  386. t.Fatalf("got %v; expected a proper address with zone identifier", la)
  387. }
  388. done := make(chan int)
  389. go transponder(t, ln, done)
  390. c, err := Dial(tt.net, ln.Addr().String())
  391. if err != nil {
  392. t.Fatalf("Dial failed: %v", err)
  393. }
  394. defer c.Close()
  395. if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup && la.Zone == "" {
  396. t.Fatalf("got %v; expected a proper address with zone identifier", la)
  397. }
  398. if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
  399. t.Fatalf("got %v; expected a proper address with zone identifier", ra)
  400. }
  401. if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); err != nil {
  402. t.Fatalf("Conn.Write failed: %v", err)
  403. }
  404. b := make([]byte, 32)
  405. if _, err := c.Read(b); err != nil {
  406. t.Fatalf("Conn.Read failed: %v", err)
  407. }
  408. <-done
  409. }
  410. }
  411. func TestTCPConcurrentAccept(t *testing.T) {
  412. defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
  413. ln, err := Listen("tcp", "127.0.0.1:0")
  414. if err != nil {
  415. t.Fatalf("Listen failed: %v", err)
  416. }
  417. const N = 10
  418. var wg sync.WaitGroup
  419. wg.Add(N)
  420. for i := 0; i < N; i++ {
  421. go func() {
  422. for {
  423. c, err := ln.Accept()
  424. if err != nil {
  425. break
  426. }
  427. c.Close()
  428. }
  429. wg.Done()
  430. }()
  431. }
  432. attempts := 10 * N
  433. fails := 0
  434. d := &Dialer{Timeout: 200 * time.Millisecond}
  435. for i := 0; i < attempts; i++ {
  436. c, err := d.Dial("tcp", ln.Addr().String())
  437. if err != nil {
  438. fails++
  439. } else {
  440. c.Close()
  441. }
  442. }
  443. ln.Close()
  444. wg.Wait()
  445. if fails > attempts/9 { // see issues 7400 and 7541
  446. t.Fatalf("too many Dial failed: %v", fails)
  447. }
  448. if fails > 0 {
  449. t.Logf("# of failed Dials: %v", fails)
  450. }
  451. }
  452. func TestTCPReadWriteMallocs(t *testing.T) {
  453. if testing.Short() {
  454. t.Skip("skipping malloc count in short mode")
  455. }
  456. ln, err := Listen("tcp", "127.0.0.1:0")
  457. if err != nil {
  458. t.Fatalf("Listen failed: %v", err)
  459. }
  460. defer ln.Close()
  461. var server Conn
  462. errc := make(chan error)
  463. go func() {
  464. var err error
  465. server, err = ln.Accept()
  466. errc <- err
  467. }()
  468. client, err := Dial("tcp", ln.Addr().String())
  469. if err != nil {
  470. t.Fatalf("Dial failed: %v", err)
  471. }
  472. if err := <-errc; err != nil {
  473. t.Fatalf("Accept failed: %v", err)
  474. }
  475. defer server.Close()
  476. var buf [128]byte
  477. mallocs := testing.AllocsPerRun(1000, func() {
  478. _, err := server.Write(buf[:])
  479. if err != nil {
  480. t.Fatalf("Write failed: %v", err)
  481. }
  482. _, err = io.ReadFull(client, buf[:])
  483. if err != nil {
  484. t.Fatalf("Read failed: %v", err)
  485. }
  486. })
  487. if mallocs > 0 {
  488. t.Fatalf("Got %v allocs, want 0", mallocs)
  489. }
  490. }
  491. func TestTCPStress(t *testing.T) {
  492. const conns = 2
  493. const msgLen = 512
  494. msgs := int(1e4)
  495. if testing.Short() {
  496. msgs = 1e2
  497. }
  498. sendMsg := func(c Conn, buf []byte) bool {
  499. n, err := c.Write(buf)
  500. if n != len(buf) || err != nil {
  501. t.Logf("Write failed: %v", err)
  502. return false
  503. }
  504. return true
  505. }
  506. recvMsg := func(c Conn, buf []byte) bool {
  507. for read := 0; read != len(buf); {
  508. n, err := c.Read(buf)
  509. read += n
  510. if err != nil {
  511. t.Logf("Read failed: %v", err)
  512. return false
  513. }
  514. }
  515. return true
  516. }
  517. ln, err := Listen("tcp", "127.0.0.1:0")
  518. if err != nil {
  519. t.Fatalf("Listen failed: %v", err)
  520. }
  521. defer ln.Close()
  522. // Acceptor.
  523. go func() {
  524. for {
  525. c, err := ln.Accept()
  526. if err != nil {
  527. break
  528. }
  529. // Server connection.
  530. go func(c Conn) {
  531. defer c.Close()
  532. var buf [msgLen]byte
  533. for m := 0; m < msgs; m++ {
  534. if !recvMsg(c, buf[:]) || !sendMsg(c, buf[:]) {
  535. break
  536. }
  537. }
  538. }(c)
  539. }
  540. }()
  541. done := make(chan bool)
  542. for i := 0; i < conns; i++ {
  543. // Client connection.
  544. go func() {
  545. defer func() {
  546. done <- true
  547. }()
  548. c, err := Dial("tcp", ln.Addr().String())
  549. if err != nil {
  550. t.Logf("Dial failed: %v", err)
  551. return
  552. }
  553. defer c.Close()
  554. var buf [msgLen]byte
  555. for m := 0; m < msgs; m++ {
  556. if !sendMsg(c, buf[:]) || !recvMsg(c, buf[:]) {
  557. break
  558. }
  559. }
  560. }()
  561. }
  562. for i := 0; i < conns; i++ {
  563. <-done
  564. }
  565. }