socket_go1_9_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Copyright 2017 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. // +build go1.9
  5. // +build darwin dragonfly freebsd linux netbsd openbsd solaris
  6. package socket_test
  7. import (
  8. "bytes"
  9. "fmt"
  10. "net"
  11. "runtime"
  12. "testing"
  13. "golang.org/x/net/internal/nettest"
  14. "golang.org/x/net/internal/socket"
  15. )
  16. type mockControl struct {
  17. Level int
  18. Type int
  19. Data []byte
  20. }
  21. func TestControlMessage(t *testing.T) {
  22. for _, tt := range []struct {
  23. cs []mockControl
  24. }{
  25. {
  26. []mockControl{
  27. {Level: 1, Type: 1},
  28. },
  29. },
  30. {
  31. []mockControl{
  32. {Level: 2, Type: 2, Data: []byte{0xfe}},
  33. },
  34. },
  35. {
  36. []mockControl{
  37. {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
  38. },
  39. },
  40. {
  41. []mockControl{
  42. {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
  43. },
  44. },
  45. {
  46. []mockControl{
  47. {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
  48. {Level: 2, Type: 2, Data: []byte{0xfe}},
  49. },
  50. },
  51. } {
  52. var w []byte
  53. var tailPadLen int
  54. mm := socket.NewControlMessage([]int{0})
  55. for i, c := range tt.cs {
  56. m := socket.NewControlMessage([]int{len(c.Data)})
  57. l := len(m) - len(mm)
  58. if i == len(tt.cs)-1 && l > len(c.Data) {
  59. tailPadLen = l - len(c.Data)
  60. }
  61. w = append(w, m...)
  62. }
  63. var err error
  64. ww := make([]byte, len(w))
  65. copy(ww, w)
  66. m := socket.ControlMessage(ww)
  67. for _, c := range tt.cs {
  68. if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
  69. t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
  70. }
  71. copy(m.Data(len(c.Data)), c.Data)
  72. m = m.Next(len(c.Data))
  73. }
  74. m = socket.ControlMessage(w)
  75. for _, c := range tt.cs {
  76. m, err = m.Marshal(c.Level, c.Type, c.Data)
  77. if err != nil {
  78. t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
  79. }
  80. }
  81. if !bytes.Equal(ww, w) {
  82. t.Fatalf("got %#v; want %#v", ww, w)
  83. }
  84. ws := [][]byte{w}
  85. if tailPadLen > 0 {
  86. // Test a message with no tail padding.
  87. nopad := w[:len(w)-tailPadLen]
  88. ws = append(ws, [][]byte{nopad}...)
  89. }
  90. for _, w := range ws {
  91. ms, err := socket.ControlMessage(w).Parse()
  92. if err != nil {
  93. t.Fatalf("(%v).Parse() = %v", tt.cs, err)
  94. }
  95. for i, m := range ms {
  96. lvl, typ, dataLen, err := m.ParseHeader()
  97. if err != nil {
  98. t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
  99. }
  100. if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
  101. t.Fatalf("%v: got %d, %d, %d; want %d, %d, %d", tt.cs[i], lvl, typ, dataLen, tt.cs[i].Level, tt.cs[i].Type, len(tt.cs[i].Data))
  102. }
  103. }
  104. }
  105. }
  106. }
  107. func TestUDP(t *testing.T) {
  108. c, err := nettest.NewLocalPacketListener("udp")
  109. if err != nil {
  110. t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  111. }
  112. defer c.Close()
  113. t.Run("Message", func(t *testing.T) {
  114. testUDPMessage(t, c.(net.Conn))
  115. })
  116. switch runtime.GOOS {
  117. case "linux":
  118. t.Run("Messages", func(t *testing.T) {
  119. testUDPMessages(t, c.(net.Conn))
  120. })
  121. }
  122. }
  123. func testUDPMessage(t *testing.T, c net.Conn) {
  124. cc, err := socket.NewConn(c)
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. data := []byte("HELLO-R-U-THERE")
  129. wm := socket.Message{
  130. Buffers: bytes.SplitAfter(data, []byte("-")),
  131. Addr: c.LocalAddr(),
  132. }
  133. if err := cc.SendMsg(&wm, 0); err != nil {
  134. t.Fatal(err)
  135. }
  136. b := make([]byte, 32)
  137. rm := socket.Message{
  138. Buffers: [][]byte{b[:1], b[1:3], b[3:7], b[7:11], b[11:]},
  139. }
  140. if err := cc.RecvMsg(&rm, 0); err != nil {
  141. t.Fatal(err)
  142. }
  143. if !bytes.Equal(b[:rm.N], data) {
  144. t.Fatalf("got %#v; want %#v", b[:rm.N], data)
  145. }
  146. }
  147. func testUDPMessages(t *testing.T, c net.Conn) {
  148. cc, err := socket.NewConn(c)
  149. if err != nil {
  150. t.Fatal(err)
  151. }
  152. data := []byte("HELLO-R-U-THERE")
  153. wmbs := bytes.SplitAfter(data, []byte("-"))
  154. wms := []socket.Message{
  155. {Buffers: wmbs[:1], Addr: c.LocalAddr()},
  156. {Buffers: wmbs[1:], Addr: c.LocalAddr()},
  157. }
  158. n, err := cc.SendMsgs(wms, 0)
  159. if err != nil {
  160. t.Fatal(err)
  161. }
  162. if n != len(wms) {
  163. t.Fatalf("got %d; want %d", n, len(wms))
  164. }
  165. b := make([]byte, 32)
  166. rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
  167. rms := []socket.Message{
  168. {Buffers: rmbs[0]},
  169. {Buffers: rmbs[1]},
  170. }
  171. n, err = cc.RecvMsgs(rms, 0)
  172. if err != nil {
  173. t.Fatal(err)
  174. }
  175. if n != len(rms) {
  176. t.Fatalf("got %d; want %d", n, len(rms))
  177. }
  178. nn := 0
  179. for i := 0; i < n; i++ {
  180. nn += rms[i].N
  181. }
  182. if !bytes.Equal(b[:nn], data) {
  183. t.Fatalf("got %#v; want %#v", b[:nn], data)
  184. }
  185. }
  186. func BenchmarkUDP(b *testing.B) {
  187. c, err := nettest.NewLocalPacketListener("udp")
  188. if err != nil {
  189. b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
  190. }
  191. defer c.Close()
  192. cc, err := socket.NewConn(c.(net.Conn))
  193. if err != nil {
  194. b.Fatal(err)
  195. }
  196. data := []byte("HELLO-R-U-THERE")
  197. wm := socket.Message{
  198. Buffers: [][]byte{data},
  199. Addr: c.LocalAddr(),
  200. }
  201. rm := socket.Message{
  202. Buffers: [][]byte{make([]byte, 128)},
  203. OOB: make([]byte, 128),
  204. }
  205. for M := 1; M <= 1<<9; M = M << 1 {
  206. b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
  207. for i := 0; i < b.N; i++ {
  208. for j := 0; j < M; j++ {
  209. if err := cc.SendMsg(&wm, 0); err != nil {
  210. b.Fatal(err)
  211. }
  212. if err := cc.RecvMsg(&rm, 0); err != nil {
  213. b.Fatal(err)
  214. }
  215. }
  216. }
  217. })
  218. switch runtime.GOOS {
  219. case "linux":
  220. wms := make([]socket.Message, M)
  221. for i := range wms {
  222. wms[i].Buffers = [][]byte{data}
  223. wms[i].Addr = c.LocalAddr()
  224. }
  225. rms := make([]socket.Message, M)
  226. for i := range rms {
  227. rms[i].Buffers = [][]byte{make([]byte, 128)}
  228. rms[i].OOB = make([]byte, 128)
  229. }
  230. b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
  231. for i := 0; i < b.N; i++ {
  232. if _, err := cc.SendMsgs(wms, 0); err != nil {
  233. b.Fatal(err)
  234. }
  235. if _, err := cc.RecvMsgs(rms, 0); err != nil {
  236. b.Fatal(err)
  237. }
  238. }
  239. })
  240. }
  241. }
  242. }