]> Cypherpunks.ru repositories - gostls13.git/blob - src/net/udpsock_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / net / udpsock_test.go
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
5 package net
6
7 import (
8         "errors"
9         "fmt"
10         "internal/testenv"
11         "net/netip"
12         "os"
13         "reflect"
14         "runtime"
15         "testing"
16         "time"
17 )
18
19 func BenchmarkUDP6LinkLocalUnicast(b *testing.B) {
20         testHookUninstaller.Do(uninstallTestHooks)
21
22         if !supportsIPv6() {
23                 b.Skip("IPv6 is not supported")
24         }
25         ifi := loopbackInterface()
26         if ifi == nil {
27                 b.Skip("loopback interface not found")
28         }
29         lla := ipv6LinkLocalUnicastAddr(ifi)
30         if lla == "" {
31                 b.Skip("IPv6 link-local unicast address not found")
32         }
33
34         c1, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0"))
35         if err != nil {
36                 b.Fatal(err)
37         }
38         defer c1.Close()
39         c2, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0"))
40         if err != nil {
41                 b.Fatal(err)
42         }
43         defer c2.Close()
44
45         var buf [1]byte
46         for i := 0; i < b.N; i++ {
47                 if _, err := c1.WriteTo(buf[:], c2.LocalAddr()); err != nil {
48                         b.Fatal(err)
49                 }
50                 if _, _, err := c2.ReadFrom(buf[:]); err != nil {
51                         b.Fatal(err)
52                 }
53         }
54 }
55
56 type resolveUDPAddrTest struct {
57         network       string
58         litAddrOrName string
59         addr          *UDPAddr
60         err           error
61 }
62
63 var resolveUDPAddrTests = []resolveUDPAddrTest{
64         {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
65         {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
66
67         {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
68         {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
69
70         {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
71         {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
72
73         {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, // Go 1.0 behavior
74         {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},         // Go 1.0 behavior
75
76         {"udp", ":12345", &UDPAddr{Port: 12345}, nil},
77
78         {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
79
80         {"udp", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
81         {"udp", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 53}, nil},
82         {"udp", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
83         {"udp4", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
84         {"udp4", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
85         {"udp6", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
86
87         {"udp4", "[2001:db8::1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
88         {"udp6", "127.0.0.1:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
89         {"udp6", "[::ffff:127.0.0.1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
90 }
91
92 func TestResolveUDPAddr(t *testing.T) {
93         origTestHookLookupIP := testHookLookupIP
94         defer func() { testHookLookupIP = origTestHookLookupIP }()
95         testHookLookupIP = lookupLocalhost
96
97         for _, tt := range resolveUDPAddrTests {
98                 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName)
99                 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
100                         t.Errorf("ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
101                         continue
102                 }
103                 if err == nil {
104                         addr2, err := ResolveUDPAddr(addr.Network(), addr.String())
105                         if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
106                                 t.Errorf("(%q, %q): ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
107                         }
108                 }
109         }
110 }
111
112 func TestWriteToUDP(t *testing.T) {
113         switch runtime.GOOS {
114         case "plan9":
115                 t.Skipf("not supported on %s", runtime.GOOS)
116         }
117
118         if !testableNetwork("udp") {
119                 t.Skipf("skipping: udp not supported")
120         }
121
122         c, err := ListenPacket("udp", "127.0.0.1:0")
123         if err != nil {
124                 t.Fatal(err)
125         }
126         defer c.Close()
127
128         testWriteToConn(t, c.LocalAddr().String())
129         testWriteToPacketConn(t, c.LocalAddr().String())
130 }
131
132 func testWriteToConn(t *testing.T, raddr string) {
133         c, err := Dial("udp", raddr)
134         if err != nil {
135                 t.Fatal(err)
136         }
137         defer c.Close()
138
139         ra, err := ResolveUDPAddr("udp", raddr)
140         if err != nil {
141                 t.Fatal(err)
142         }
143
144         b := []byte("CONNECTED-MODE SOCKET")
145         _, err = c.(*UDPConn).WriteToUDP(b, ra)
146         if err == nil {
147                 t.Fatal("should fail")
148         }
149         if err != nil && err.(*OpError).Err != ErrWriteToConnected {
150                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
151         }
152         _, err = c.(*UDPConn).WriteTo(b, ra)
153         if err == nil {
154                 t.Fatal("should fail")
155         }
156         if err != nil && err.(*OpError).Err != ErrWriteToConnected {
157                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
158         }
159         _, err = c.Write(b)
160         if err != nil {
161                 t.Fatal(err)
162         }
163         _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
164         if err == nil {
165                 t.Fatal("should fail")
166         }
167         if err != nil && err.(*OpError).Err != ErrWriteToConnected {
168                 t.Fatalf("should fail as ErrWriteToConnected: %v", err)
169         }
170         _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
171         if err != nil {
172                 t.Fatal(err)
173         }
174 }
175
176 func testWriteToPacketConn(t *testing.T, raddr string) {
177         c, err := ListenPacket("udp", "127.0.0.1:0")
178         if err != nil {
179                 t.Fatal(err)
180         }
181         defer c.Close()
182
183         ra, err := ResolveUDPAddr("udp", raddr)
184         if err != nil {
185                 t.Fatal(err)
186         }
187
188         b := []byte("UNCONNECTED-MODE SOCKET")
189         _, err = c.(*UDPConn).WriteToUDP(b, ra)
190         if err != nil {
191                 t.Fatal(err)
192         }
193         _, err = c.WriteTo(b, ra)
194         if err != nil {
195                 t.Fatal(err)
196         }
197         _, err = c.(*UDPConn).Write(b)
198         if err == nil {
199                 t.Fatal("should fail")
200         }
201         _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
202         if err == nil {
203                 t.Fatal("should fail")
204         }
205         if err != nil && err.(*OpError).Err != errMissingAddress {
206                 t.Fatalf("should fail as errMissingAddress: %v", err)
207         }
208         _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
209         if err != nil {
210                 t.Fatal(err)
211         }
212 }
213
214 var udpConnLocalNameTests = []struct {
215         net   string
216         laddr *UDPAddr
217 }{
218         {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}},
219         {"udp4", &UDPAddr{}},
220         {"udp4", nil},
221 }
222
223 func TestUDPConnLocalName(t *testing.T) {
224         testenv.MustHaveExternalNetwork(t)
225
226         for _, tt := range udpConnLocalNameTests {
227                 t.Run(fmt.Sprint(tt.laddr), func(t *testing.T) {
228                         if !testableNetwork(tt.net) {
229                                 t.Skipf("skipping: %s not available", tt.net)
230                         }
231
232                         c, err := ListenUDP(tt.net, tt.laddr)
233                         if err != nil {
234                                 t.Fatal(err)
235                         }
236                         defer c.Close()
237                         la := c.LocalAddr()
238                         if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
239                                 t.Fatalf("got %v; expected a proper address with non-zero port number", la)
240                         }
241                 })
242         }
243 }
244
245 func TestUDPConnLocalAndRemoteNames(t *testing.T) {
246         if !testableNetwork("udp") {
247                 t.Skipf("skipping: udp not available")
248         }
249
250         for _, laddr := range []string{"", "127.0.0.1:0"} {
251                 c1, err := ListenPacket("udp", "127.0.0.1:0")
252                 if err != nil {
253                         t.Fatal(err)
254                 }
255                 defer c1.Close()
256
257                 var la *UDPAddr
258                 if laddr != "" {
259                         var err error
260                         if la, err = ResolveUDPAddr("udp", laddr); err != nil {
261                                 t.Fatal(err)
262                         }
263                 }
264                 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
265                 if err != nil {
266                         t.Fatal(err)
267                 }
268                 defer c2.Close()
269
270                 var connAddrs = [4]struct {
271                         got Addr
272                         ok  bool
273                 }{
274                         {c1.LocalAddr(), true},
275                         {c1.(*UDPConn).RemoteAddr(), false},
276                         {c2.LocalAddr(), true},
277                         {c2.RemoteAddr(), true},
278                 }
279                 for _, ca := range connAddrs {
280                         if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
281                                 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
282                         }
283                 }
284         }
285 }
286
287 func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
288         testenv.MustHaveExternalNetwork(t)
289
290         if !supportsIPv6() {
291                 t.Skip("IPv6 is not supported")
292         }
293
294         for i, tt := range ipv6LinkLocalUnicastUDPTests {
295                 c1, err := ListenPacket(tt.network, tt.address)
296                 if err != nil {
297                         // It might return "LookupHost returned no
298                         // suitable address" error on some platforms.
299                         t.Log(err)
300                         continue
301                 }
302                 ls := (&packetListener{PacketConn: c1}).newLocalServer()
303                 defer ls.teardown()
304                 ch := make(chan error, 1)
305                 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) }
306                 if err := ls.buildup(handler); err != nil {
307                         t.Fatal(err)
308                 }
309                 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
310                         t.Fatalf("got %v; expected a proper address with zone identifier", la)
311                 }
312
313                 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String())
314                 if err != nil {
315                         t.Fatal(err)
316                 }
317                 defer c2.Close()
318                 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
319                         t.Fatalf("got %v; expected a proper address with zone identifier", la)
320                 }
321                 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
322                         t.Fatalf("got %v; expected a proper address with zone identifier", ra)
323                 }
324
325                 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil {
326                         t.Fatal(err)
327                 }
328                 b := make([]byte, 32)
329                 if _, err := c2.Read(b); err != nil {
330                         t.Fatal(err)
331                 }
332
333                 for err := range ch {
334                         t.Errorf("#%d: %v", i, err)
335                 }
336         }
337 }
338
339 func TestUDPZeroBytePayload(t *testing.T) {
340         switch runtime.GOOS {
341         case "plan9":
342                 t.Skipf("not supported on %s", runtime.GOOS)
343         case "darwin", "ios":
344                 testenv.SkipFlaky(t, 29225)
345         }
346         if !testableNetwork("udp") {
347                 t.Skipf("skipping: udp not available")
348         }
349
350         c := newLocalPacketListener(t, "udp")
351         defer c.Close()
352
353         for _, genericRead := range []bool{false, true} {
354                 n, err := c.WriteTo(nil, c.LocalAddr())
355                 if err != nil {
356                         t.Fatal(err)
357                 }
358                 if n != 0 {
359                         t.Errorf("got %d; want 0", n)
360                 }
361                 c.SetReadDeadline(time.Now().Add(30 * time.Second))
362                 var b [1]byte
363                 var name string
364                 if genericRead {
365                         _, err = c.(Conn).Read(b[:])
366                         name = "Read"
367                 } else {
368                         _, _, err = c.ReadFrom(b[:])
369                         name = "ReadFrom"
370                 }
371                 if err != nil {
372                         t.Errorf("%s of zero byte packet failed: %v", name, err)
373                 }
374         }
375 }
376
377 func TestUDPZeroByteBuffer(t *testing.T) {
378         switch runtime.GOOS {
379         case "plan9":
380                 t.Skipf("not supported on %s", runtime.GOOS)
381         }
382         if !testableNetwork("udp") {
383                 t.Skipf("skipping: udp not available")
384         }
385
386         c := newLocalPacketListener(t, "udp")
387         defer c.Close()
388
389         b := []byte("UDP ZERO BYTE BUFFER TEST")
390         for _, genericRead := range []bool{false, true} {
391                 n, err := c.WriteTo(b, c.LocalAddr())
392                 if err != nil {
393                         t.Fatal(err)
394                 }
395                 if n != len(b) {
396                         t.Errorf("got %d; want %d", n, len(b))
397                 }
398                 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
399                 if genericRead {
400                         _, err = c.(Conn).Read(nil)
401                 } else {
402                         _, _, err = c.ReadFrom(nil)
403                 }
404                 switch err {
405                 case nil: // ReadFrom succeeds
406                 default: // Read may timeout, it depends on the platform
407                         if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE
408                                 t.Fatal(err)
409                         }
410                 }
411         }
412 }
413
414 func TestUDPReadSizeError(t *testing.T) {
415         switch runtime.GOOS {
416         case "plan9":
417                 t.Skipf("not supported on %s", runtime.GOOS)
418         }
419         if !testableNetwork("udp") {
420                 t.Skipf("skipping: udp not available")
421         }
422
423         c1 := newLocalPacketListener(t, "udp")
424         defer c1.Close()
425
426         c2, err := Dial("udp", c1.LocalAddr().String())
427         if err != nil {
428                 t.Fatal(err)
429         }
430         defer c2.Close()
431
432         b1 := []byte("READ SIZE ERROR TEST")
433         for _, genericRead := range []bool{false, true} {
434                 n, err := c2.Write(b1)
435                 if err != nil {
436                         t.Fatal(err)
437                 }
438                 if n != len(b1) {
439                         t.Errorf("got %d; want %d", n, len(b1))
440                 }
441                 b2 := make([]byte, len(b1)-1)
442                 if genericRead {
443                         n, err = c1.(Conn).Read(b2)
444                 } else {
445                         n, _, err = c1.ReadFrom(b2)
446                 }
447                 if err != nil && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE
448                         t.Fatal(err)
449                 }
450                 if n != len(b1)-1 {
451                         t.Fatalf("got %d; want %d", n, len(b1)-1)
452                 }
453         }
454 }
455
456 // TestUDPReadTimeout verifies that ReadFromUDP with timeout returns an error
457 // without data or an address.
458 func TestUDPReadTimeout(t *testing.T) {
459         if !testableNetwork("udp4") {
460                 t.Skipf("skipping: udp4 not available")
461         }
462
463         la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
464         if err != nil {
465                 t.Fatal(err)
466         }
467         c, err := ListenUDP("udp4", la)
468         if err != nil {
469                 t.Fatal(err)
470         }
471         defer c.Close()
472
473         c.SetDeadline(time.Now())
474         b := make([]byte, 1)
475         n, addr, err := c.ReadFromUDP(b)
476         if !errors.Is(err, os.ErrDeadlineExceeded) {
477                 t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err)
478         }
479         if n != 0 {
480                 t.Errorf("ReadFromUDP got n %d want 0", n)
481         }
482         if addr != nil {
483                 t.Errorf("ReadFromUDP got addr %+#v want nil", addr)
484         }
485 }
486
487 func TestAllocs(t *testing.T) {
488         switch runtime.GOOS {
489         case "plan9", "js", "wasip1":
490                 // These implementations have not been optimized.
491                 t.Skipf("skipping on %v", runtime.GOOS)
492         }
493         if !testableNetwork("udp4") {
494                 t.Skipf("skipping: udp4 not available")
495         }
496
497         // Optimizations are required to remove the allocs.
498         testenv.SkipIfOptimizationOff(t)
499
500         conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
501         if err != nil {
502                 t.Fatal(err)
503         }
504         defer conn.Close()
505         addr := conn.LocalAddr()
506         addrPort := addr.(*UDPAddr).AddrPort()
507         buf := make([]byte, 8)
508
509         allocs := testing.AllocsPerRun(1000, func() {
510                 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort)
511                 if err != nil {
512                         t.Fatal(err)
513                 }
514                 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil)
515                 if err != nil {
516                         t.Fatal(err)
517                 }
518         })
519         if got := int(allocs); got != 0 {
520                 t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got)
521         }
522
523         allocs = testing.AllocsPerRun(1000, func() {
524                 _, err := conn.WriteToUDPAddrPort(buf, addrPort)
525                 if err != nil {
526                         t.Fatal(err)
527                 }
528                 _, _, err = conn.ReadFromUDPAddrPort(buf)
529                 if err != nil {
530                         t.Fatal(err)
531                 }
532         })
533         if got := int(allocs); got != 0 {
534                 t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got)
535         }
536
537         allocs = testing.AllocsPerRun(1000, func() {
538                 _, err := conn.WriteTo(buf, addr)
539                 if err != nil {
540                         t.Fatal(err)
541                 }
542                 _, _, err = conn.ReadFromUDP(buf)
543                 if err != nil {
544                         t.Fatal(err)
545                 }
546         })
547         if got := int(allocs); got != 1 {
548                 t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got)
549         }
550 }
551
552 func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) {
553         conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
554         if err != nil {
555                 b.Fatal(err)
556         }
557         defer conn.Close()
558         addr := conn.LocalAddr().(*UDPAddr).AddrPort()
559         buf := make([]byte, 8)
560         b.ResetTimer()
561         b.ReportAllocs()
562         for i := 0; i < b.N; i++ {
563                 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr)
564                 if err != nil {
565                         b.Fatal(err)
566                 }
567                 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil)
568                 if err != nil {
569                         b.Fatal(err)
570                 }
571         }
572 }
573
574 func BenchmarkWriteToReadFromUDP(b *testing.B) {
575         conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
576         if err != nil {
577                 b.Fatal(err)
578         }
579         defer conn.Close()
580         addr := conn.LocalAddr()
581         buf := make([]byte, 8)
582         b.ResetTimer()
583         b.ReportAllocs()
584         for i := 0; i < b.N; i++ {
585                 _, err := conn.WriteTo(buf, addr)
586                 if err != nil {
587                         b.Fatal(err)
588                 }
589                 _, _, err = conn.ReadFromUDP(buf)
590                 if err != nil {
591                         b.Fatal(err)
592                 }
593         }
594 }
595
596 func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) {
597         conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
598         if err != nil {
599                 b.Fatal(err)
600         }
601         defer conn.Close()
602         addr := conn.LocalAddr().(*UDPAddr).AddrPort()
603         buf := make([]byte, 8)
604         b.ResetTimer()
605         b.ReportAllocs()
606         for i := 0; i < b.N; i++ {
607                 _, err := conn.WriteToUDPAddrPort(buf, addr)
608                 if err != nil {
609                         b.Fatal(err)
610                 }
611                 _, _, err = conn.ReadFromUDPAddrPort(buf)
612                 if err != nil {
613                         b.Fatal(err)
614                 }
615         }
616 }
617
618 func TestUDPIPVersionReadMsg(t *testing.T) {
619         switch runtime.GOOS {
620         case "plan9":
621                 t.Skipf("skipping on %v", runtime.GOOS)
622         }
623         if !testableNetwork("udp4") {
624                 t.Skipf("skipping: udp4 not available")
625         }
626
627         conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
628         if err != nil {
629                 t.Fatal(err)
630         }
631         defer conn.Close()
632         daddr := conn.LocalAddr().(*UDPAddr).AddrPort()
633         buf := make([]byte, 8)
634         _, err = conn.WriteToUDPAddrPort(buf, daddr)
635         if err != nil {
636                 t.Fatal(err)
637         }
638         _, _, _, saddr, err := conn.ReadMsgUDPAddrPort(buf, nil)
639         if err != nil {
640                 t.Fatal(err)
641         }
642         if !saddr.Addr().Is4() {
643                 t.Error("returned AddrPort is not IPv4")
644         }
645         _, err = conn.WriteToUDPAddrPort(buf, daddr)
646         if err != nil {
647                 t.Fatal(err)
648         }
649         _, _, _, soldaddr, err := conn.ReadMsgUDP(buf, nil)
650         if err != nil {
651                 t.Fatal(err)
652         }
653         if len(soldaddr.IP) != 4 {
654                 t.Error("returned UDPAddr is not IPv4")
655         }
656 }
657
658 // TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
659 // WriteMsgUDPAddrPort accepts IPv4, IPv4-mapped IPv6, and IPv6 target addresses
660 // on a UDPConn listening on "::".
661 func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
662         if !testableNetwork("udp4") {
663                 t.Skipf("skipping: udp4 not available")
664         }
665         if !testableNetwork("udp6") {
666                 t.Skipf("skipping: udp6 not available")
667         }
668
669         switch runtime.GOOS {
670         case "dragonfly", "openbsd":
671                 // DragonflyBSD's IPv6 sockets are always IPv6-only, according to the man page:
672                 // https://www.dragonflybsd.org/cgi/web-man?command=ip6 (search for IPV6_V6ONLY).
673                 // OpenBSD's IPv6 sockets are always IPv6-only, according to the man page:
674                 // https://man.openbsd.org/ip6#IPV6_V6ONLY
675                 t.Skipf("skipping on %v", runtime.GOOS)
676         }
677
678         conn, err := ListenUDP("udp", nil)
679         if err != nil {
680                 t.Fatal(err)
681         }
682         defer conn.Close()
683
684         daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
685         daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
686         daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
687         buf := make([]byte, 8)
688
689         _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4)
690         if err != nil {
691                 t.Fatal(err)
692         }
693
694         _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6)
695         if err != nil {
696                 t.Fatal(err)
697         }
698
699         _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6)
700         if err != nil {
701                 t.Fatal(err)
702         }
703 }