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.
6 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
17 "golang.org/x/net/internal/nettest"
18 "golang.org/x/net/internal/socket"
21 type mockControl struct {
27 func TestControlMessage(t *testing.T) {
28 for _, tt := range []struct {
38 {Level: 2, Type: 2, Data: []byte{0xfe}},
43 {Level: 3, Type: 3, Data: []byte{0xfe, 0xff, 0xff, 0xfe}},
48 {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
53 {Level: 4, Type: 4, Data: []byte{0xfe, 0xff, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0xfe}},
54 {Level: 2, Type: 2, Data: []byte{0xfe}},
60 mm := socket.NewControlMessage([]int{0})
61 for i, c := range tt.cs {
62 m := socket.NewControlMessage([]int{len(c.Data)})
64 if i == len(tt.cs)-1 && l > len(c.Data) {
65 tailPadLen = l - len(c.Data)
71 ww := make([]byte, len(w))
73 m := socket.ControlMessage(ww)
74 for _, c := range tt.cs {
75 if err = m.MarshalHeader(c.Level, c.Type, len(c.Data)); err != nil {
76 t.Fatalf("(%v).MarshalHeader() = %v", tt.cs, err)
78 copy(m.Data(len(c.Data)), c.Data)
79 m = m.Next(len(c.Data))
81 m = socket.ControlMessage(w)
82 for _, c := range tt.cs {
83 m, err = m.Marshal(c.Level, c.Type, c.Data)
85 t.Fatalf("(%v).Marshal() = %v", tt.cs, err)
88 if !bytes.Equal(ww, w) {
89 t.Fatalf("got %#v; want %#v", ww, w)
94 // Test a message with no tail padding.
95 nopad := w[:len(w)-tailPadLen]
96 ws = append(ws, [][]byte{nopad}...)
98 for _, w := range ws {
99 ms, err := socket.ControlMessage(w).Parse()
101 t.Fatalf("(%v).Parse() = %v", tt.cs, err)
103 for i, m := range ms {
104 lvl, typ, dataLen, err := m.ParseHeader()
106 t.Fatalf("(%v).ParseHeader() = %v", tt.cs, err)
108 if lvl != tt.cs[i].Level || typ != tt.cs[i].Type || dataLen != len(tt.cs[i].Data) {
109 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))
116 func TestUDP(t *testing.T) {
117 c, err := nettest.NewLocalPacketListener("udp")
119 t.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
122 cc, err := socket.NewConn(c.(net.Conn))
127 t.Run("Message", func(t *testing.T) {
128 data := []byte("HELLO-R-U-THERE")
129 wm := socket.Message{
130 Buffers: bytes.SplitAfter(data, []byte("-")),
133 if err := cc.SendMsg(&wm, 0); err != nil {
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:]},
140 if err := cc.RecvMsg(&rm, 0); err != nil {
143 if !bytes.Equal(b[:rm.N], data) {
144 t.Fatalf("got %#v; want %#v", b[:rm.N], data)
147 switch runtime.GOOS {
148 case "android", "linux":
149 t.Run("Messages", func(t *testing.T) {
150 data := []byte("HELLO-R-U-THERE")
151 wmbs := bytes.SplitAfter(data, []byte("-"))
152 wms := []socket.Message{
153 {Buffers: wmbs[:1], Addr: c.LocalAddr()},
154 {Buffers: wmbs[1:], Addr: c.LocalAddr()},
156 n, err := cc.SendMsgs(wms, 0)
161 t.Fatalf("got %d; want %d", n, len(wms))
163 b := make([]byte, 32)
164 rmbs := [][][]byte{{b[:len(wmbs[0])]}, {b[len(wmbs[0]):]}}
165 rms := []socket.Message{
169 n, err = cc.RecvMsgs(rms, 0)
174 t.Fatalf("got %d; want %d", n, len(rms))
177 for i := 0; i < n; i++ {
180 if !bytes.Equal(b[:nn], data) {
181 t.Fatalf("got %#v; want %#v", b[:nn], data)
186 // The behavior of transmission for zero byte paylaod depends
187 // on each platform implementation. Some may transmit only
188 // protocol header and options, other may transmit nothing.
189 // We test only that SendMsg and SendMsgs will not crash with
191 wm := socket.Message{
192 Buffers: [][]byte{{}},
196 wms := []socket.Message{
197 {Buffers: [][]byte{{}}, Addr: c.LocalAddr()},
202 func BenchmarkUDP(b *testing.B) {
203 c, err := nettest.NewLocalPacketListener("udp")
205 b.Skipf("not supported on %s/%s: %v", runtime.GOOS, runtime.GOARCH, err)
208 cc, err := socket.NewConn(c.(net.Conn))
212 data := []byte("HELLO-R-U-THERE")
213 wm := socket.Message{
214 Buffers: [][]byte{data},
217 rm := socket.Message{
218 Buffers: [][]byte{make([]byte, 128)},
219 OOB: make([]byte, 128),
222 for M := 1; M <= 1<<9; M = M << 1 {
223 b.Run(fmt.Sprintf("Iter-%d", M), func(b *testing.B) {
224 for i := 0; i < b.N; i++ {
225 for j := 0; j < M; j++ {
226 if err := cc.SendMsg(&wm, 0); err != nil {
229 if err := cc.RecvMsg(&rm, 0); err != nil {
235 switch runtime.GOOS {
236 case "android", "linux":
237 wms := make([]socket.Message, M)
239 wms[i].Buffers = [][]byte{data}
240 wms[i].Addr = c.LocalAddr()
242 rms := make([]socket.Message, M)
244 rms[i].Buffers = [][]byte{make([]byte, 128)}
245 rms[i].OOB = make([]byte, 128)
247 b.Run(fmt.Sprintf("Batch-%d", M), func(b *testing.B) {
248 for i := 0; i < b.N; i++ {
249 if _, err := cc.SendMsgs(wms, 0); err != nil {
252 if _, err := cc.RecvMsgs(rms, 0); err != nil {