blob: b25f96a3fd3a4642d5a7d7b5a1d3b61300cfd32f [file] [log] [blame]
Bill Yi7fb3c4c2015-03-23 09:04:07 -07001// 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
5package net
6
7import (
8 "reflect"
9 "runtime"
Bill Yi7fb3c4c2015-03-23 09:04:07 -070010 "testing"
11 "time"
12)
13
Anton Carver17285b12015-10-16 10:26:06 +010014type resolveUDPAddrTest struct {
15 network string
16 litAddrOrName string
17 addr *UDPAddr
18 err error
Bill Yi7fb3c4c2015-03-23 09:04:07 -070019}
20
Anton Carver17285b12015-10-16 10:26:06 +010021var resolveUDPAddrTests = []resolveUDPAddrTest{
22 {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
23 {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
Bill Yi7fb3c4c2015-03-23 09:04:07 -070024
Anton Carver17285b12015-10-16 10:26:06 +010025 {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
26 {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
Bill Yi7fb3c4c2015-03-23 09:04:07 -070027
Anton Carver17285b12015-10-16 10:26:06 +010028 {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
29 {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
Bill Yi7fb3c4c2015-03-23 09:04:07 -070030
Anton Carver17285b12015-10-16 10:26:06 +010031 {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
32 {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil}, // Go 1.0 behavior
Bill Yi7fb3c4c2015-03-23 09:04:07 -070033
Anton Carver17285b12015-10-16 10:26:06 +010034 {"udp", ":12345", &UDPAddr{Port: 12345}, nil},
Bill Yi7fb3c4c2015-03-23 09:04:07 -070035
Anton Carver17285b12015-10-16 10:26:06 +010036 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
37}
38
39func TestResolveUDPAddr(t *testing.T) {
40 origTestHookLookupIP := testHookLookupIP
41 defer func() { testHookLookupIP = origTestHookLookupIP }()
42 testHookLookupIP = lookupLocalhost
43
44 for i, tt := range resolveUDPAddrTests {
45 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName)
46 if err != tt.err {
47 t.Errorf("#%d: %v", i, err)
48 } else if !reflect.DeepEqual(addr, tt.addr) {
49 t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
50 }
51 if err != nil {
52 continue
53 }
54 rtaddr, err := ResolveUDPAddr(addr.Network(), addr.String())
55 if err != nil {
56 t.Errorf("#%d: %v", i, err)
57 } else if !reflect.DeepEqual(rtaddr, addr) {
58 t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
59 }
Bill Yi7fb3c4c2015-03-23 09:04:07 -070060 }
61}
62
63func TestWriteToUDP(t *testing.T) {
64 switch runtime.GOOS {
65 case "plan9":
Anton Carver17285b12015-10-16 10:26:06 +010066 t.Skipf("not supported on %s", runtime.GOOS)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070067 }
68
Anton Carver17285b12015-10-16 10:26:06 +010069 c, err := ListenPacket("udp", "127.0.0.1:0")
Bill Yi7fb3c4c2015-03-23 09:04:07 -070070 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +010071 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070072 }
Anton Carver17285b12015-10-16 10:26:06 +010073 defer c.Close()
Bill Yi7fb3c4c2015-03-23 09:04:07 -070074
Anton Carver17285b12015-10-16 10:26:06 +010075 testWriteToConn(t, c.LocalAddr().String())
76 testWriteToPacketConn(t, c.LocalAddr().String())
Bill Yi7fb3c4c2015-03-23 09:04:07 -070077}
78
79func testWriteToConn(t *testing.T, raddr string) {
80 c, err := Dial("udp", raddr)
81 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +010082 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070083 }
84 defer c.Close()
85
86 ra, err := ResolveUDPAddr("udp", raddr)
87 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +010088 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070089 }
90
Anton Carver17285b12015-10-16 10:26:06 +010091 b := []byte("CONNECTED-MODE SOCKET")
92 _, err = c.(*UDPConn).WriteToUDP(b, ra)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070093 if err == nil {
Anton Carver17285b12015-10-16 10:26:06 +010094 t.Fatal("should fail")
Bill Yi7fb3c4c2015-03-23 09:04:07 -070095 }
96 if err != nil && err.(*OpError).Err != ErrWriteToConnected {
Anton Carver17285b12015-10-16 10:26:06 +010097 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -070098 }
Anton Carver17285b12015-10-16 10:26:06 +010099 _, err = c.(*UDPConn).WriteTo(b, ra)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700100 if err == nil {
Anton Carver17285b12015-10-16 10:26:06 +0100101 t.Fatal("should fail")
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700102 }
103 if err != nil && err.(*OpError).Err != ErrWriteToConnected {
Anton Carver17285b12015-10-16 10:26:06 +0100104 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700105 }
Anton Carver17285b12015-10-16 10:26:06 +0100106 _, err = c.Write(b)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700107 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100108 t.Fatal(err)
109 }
110 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
111 if err == nil {
112 t.Fatal("should fail")
113 }
114 if err != nil && err.(*OpError).Err != ErrWriteToConnected {
115 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
116 }
117 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
118 switch runtime.GOOS {
119 case "nacl", "windows": // see golang.org/issue/9252
120 t.Skipf("not implemented yet on %s", runtime.GOOS)
121 default:
122 if err != nil {
123 t.Fatal(err)
124 }
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700125 }
126}
127
128func testWriteToPacketConn(t *testing.T, raddr string) {
129 c, err := ListenPacket("udp", "127.0.0.1:0")
130 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100131 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700132 }
133 defer c.Close()
134
135 ra, err := ResolveUDPAddr("udp", raddr)
136 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100137 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700138 }
139
Anton Carver17285b12015-10-16 10:26:06 +0100140 b := []byte("UNCONNECTED-MODE SOCKET")
141 _, err = c.(*UDPConn).WriteToUDP(b, ra)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700142 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100143 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700144 }
Anton Carver17285b12015-10-16 10:26:06 +0100145 _, err = c.WriteTo(b, ra)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700146 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100147 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700148 }
Anton Carver17285b12015-10-16 10:26:06 +0100149 _, err = c.(*UDPConn).Write(b)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700150 if err == nil {
Anton Carver17285b12015-10-16 10:26:06 +0100151 t.Fatal("should fail")
152 }
153 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
154 if err == nil {
155 t.Fatal("should fail")
156 }
157 if err != nil && err.(*OpError).Err != errMissingAddress {
158 t.Fatalf("should fail as errMissingAddress: %v", err)
159 }
160 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
161 switch runtime.GOOS {
162 case "nacl", "windows": // see golang.org/issue/9252
163 t.Skipf("not implemented yet on %s", runtime.GOOS)
164 default:
165 if err != nil {
166 t.Fatal(err)
167 }
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700168 }
169}
170
171var udpConnLocalNameTests = []struct {
172 net string
173 laddr *UDPAddr
174}{
175 {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}},
176 {"udp4", &UDPAddr{}},
177 {"udp4", nil},
178}
179
180func TestUDPConnLocalName(t *testing.T) {
181 if testing.Short() || !*testExternal {
Anton Carver17285b12015-10-16 10:26:06 +0100182 t.Skip("avoid external network")
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700183 }
184
185 for _, tt := range udpConnLocalNameTests {
186 c, err := ListenUDP(tt.net, tt.laddr)
187 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100188 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700189 }
190 defer c.Close()
191 la := c.LocalAddr()
192 if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
193 t.Fatalf("got %v; expected a proper address with non-zero port number", la)
194 }
195 }
196}
197
198func TestUDPConnLocalAndRemoteNames(t *testing.T) {
199 for _, laddr := range []string{"", "127.0.0.1:0"} {
200 c1, err := ListenPacket("udp", "127.0.0.1:0")
201 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100202 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700203 }
204 defer c1.Close()
205
206 var la *UDPAddr
207 if laddr != "" {
208 var err error
209 if la, err = ResolveUDPAddr("udp", laddr); err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100210 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700211 }
212 }
213 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
214 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100215 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700216 }
217 defer c2.Close()
218
219 var connAddrs = [4]struct {
220 got Addr
221 ok bool
222 }{
223 {c1.LocalAddr(), true},
224 {c1.(*UDPConn).RemoteAddr(), false},
225 {c2.LocalAddr(), true},
226 {c2.RemoteAddr(), true},
227 }
228 for _, ca := range connAddrs {
229 if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
230 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
231 }
232 }
233 }
234}
235
236func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
237 if testing.Short() || !*testExternal {
Anton Carver17285b12015-10-16 10:26:06 +0100238 t.Skip("avoid external network")
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700239 }
240 if !supportsIPv6 {
Anton Carver17285b12015-10-16 10:26:06 +0100241 t.Skip("IPv6 is not supported")
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700242 }
243
Anton Carver17285b12015-10-16 10:26:06 +0100244 for i, tt := range ipv6LinkLocalUnicastUDPTests {
245 c1, err := ListenPacket(tt.network, tt.address)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700246 if err != nil {
247 // It might return "LookupHost returned no
248 // suitable address" error on some platforms.
Anton Carver17285b12015-10-16 10:26:06 +0100249 t.Log(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700250 continue
251 }
Anton Carver17285b12015-10-16 10:26:06 +0100252 ls, err := (&packetListener{PacketConn: c1}).newLocalServer()
253 if err != nil {
254 t.Fatal(err)
255 }
256 defer ls.teardown()
257 ch := make(chan error, 1)
258 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) }
259 if err := ls.buildup(handler); err != nil {
260 t.Fatal(err)
261 }
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700262 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
263 t.Fatalf("got %v; expected a proper address with zone identifier", la)
264 }
265
Anton Carver17285b12015-10-16 10:26:06 +0100266 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String())
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700267 if err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100268 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700269 }
270 defer c2.Close()
271 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
272 t.Fatalf("got %v; expected a proper address with zone identifier", la)
273 }
274 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
275 t.Fatalf("got %v; expected a proper address with zone identifier", ra)
276 }
277
278 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil {
Anton Carver17285b12015-10-16 10:26:06 +0100279 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700280 }
281 b := make([]byte, 32)
Anton Carver17285b12015-10-16 10:26:06 +0100282 if _, err := c2.Read(b); err != nil {
283 t.Fatal(err)
284 }
285
286 for err := range ch {
287 t.Errorf("#%d: %v", i, err)
288 }
289 }
290}
291
292func TestUDPZeroBytePayload(t *testing.T) {
293 switch runtime.GOOS {
294 case "nacl", "plan9":
295 t.Skipf("not supported on %s", runtime.GOOS)
296 }
297
298 c, err := newLocalPacketListener("udp")
299 if err != nil {
300 t.Fatal(err)
301 }
302 defer c.Close()
303
304 for _, genericRead := range []bool{false, true} {
305 n, err := c.WriteTo(nil, c.LocalAddr())
306 if err != nil {
307 t.Fatal(err)
308 }
309 if n != 0 {
310 t.Errorf("got %d; want 0", n)
311 }
312 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
313 var b [1]byte
314 if genericRead {
315 _, err = c.(Conn).Read(b[:])
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700316 } else {
Anton Carver17285b12015-10-16 10:26:06 +0100317 _, _, err = c.ReadFrom(b[:])
318 }
319 switch err {
320 case nil: // ReadFrom succeeds
321 default: // Read may timeout, it depends on the platform
322 if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
323 t.Fatal(err)
324 }
325 }
326 }
327}
328
329func TestUDPZeroByteBuffer(t *testing.T) {
330 switch runtime.GOOS {
331 case "nacl", "plan9":
332 t.Skipf("not supported on %s", runtime.GOOS)
333 }
334
335 c, err := newLocalPacketListener("udp")
336 if err != nil {
337 t.Fatal(err)
338 }
339 defer c.Close()
340
341 b := []byte("UDP ZERO BYTE BUFFER TEST")
342 for _, genericRead := range []bool{false, true} {
343 n, err := c.WriteTo(b, c.LocalAddr())
344 if err != nil {
345 t.Fatal(err)
346 }
347 if n != len(b) {
348 t.Errorf("got %d; want %d", n, len(b))
349 }
350 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
351 if genericRead {
352 _, err = c.(Conn).Read(nil)
353 } else {
354 _, _, err = c.ReadFrom(nil)
355 }
356 switch err {
357 case nil: // ReadFrom succeeds
358 default: // Read may timeout, it depends on the platform
359 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows retruns WSAEMSGSIZ
360 t.Fatal(err)
Bill Yi7fb3c4c2015-03-23 09:04:07 -0700361 }
362 }
363 }
364}