github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/net/udpsock_test.go (about)

     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  	"reflect"
     9  	"runtime"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  type resolveUDPAddrTest struct {
    15  	network       string
    16  	litAddrOrName string
    17  	addr          *UDPAddr
    18  	err           error
    19  }
    20  
    21  var 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},
    24  
    25  	{"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
    26  	{"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
    27  
    28  	{"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},
    30  
    31  	{"", "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
    33  
    34  	{"udp", ":12345", &UDPAddr{Port: 12345}, nil},
    35  
    36  	{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
    37  }
    38  
    39  func 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  		}
    60  	}
    61  }
    62  
    63  func TestWriteToUDP(t *testing.T) {
    64  	switch runtime.GOOS {
    65  	case "plan9":
    66  		t.Skipf("not supported on %s", runtime.GOOS)
    67  	}
    68  
    69  	c, err := ListenPacket("udp", "127.0.0.1:0")
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	defer c.Close()
    74  
    75  	testWriteToConn(t, c.LocalAddr().String())
    76  	testWriteToPacketConn(t, c.LocalAddr().String())
    77  }
    78  
    79  func testWriteToConn(t *testing.T, raddr string) {
    80  	c, err := Dial("udp", raddr)
    81  	if err != nil {
    82  		t.Fatal(err)
    83  	}
    84  	defer c.Close()
    85  
    86  	ra, err := ResolveUDPAddr("udp", raddr)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	b := []byte("CONNECTED-MODE SOCKET")
    92  	_, err = c.(*UDPConn).WriteToUDP(b, ra)
    93  	if err == nil {
    94  		t.Fatal("should fail")
    95  	}
    96  	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
    97  		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
    98  	}
    99  	_, err = c.(*UDPConn).WriteTo(b, ra)
   100  	if err == nil {
   101  		t.Fatal("should fail")
   102  	}
   103  	if err != nil && err.(*OpError).Err != ErrWriteToConnected {
   104  		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
   105  	}
   106  	_, err = c.Write(b)
   107  	if err != nil {
   108  		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  		}
   125  	}
   126  }
   127  
   128  func testWriteToPacketConn(t *testing.T, raddr string) {
   129  	c, err := ListenPacket("udp", "127.0.0.1:0")
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	defer c.Close()
   134  
   135  	ra, err := ResolveUDPAddr("udp", raddr)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	b := []byte("UNCONNECTED-MODE SOCKET")
   141  	_, err = c.(*UDPConn).WriteToUDP(b, ra)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  	_, err = c.WriteTo(b, ra)
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	_, err = c.(*UDPConn).Write(b)
   150  	if err == nil {
   151  		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  		}
   168  	}
   169  }
   170  
   171  var 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  
   180  func TestUDPConnLocalName(t *testing.T) {
   181  	if testing.Short() || !*testExternal {
   182  		t.Skip("avoid external network")
   183  	}
   184  
   185  	for _, tt := range udpConnLocalNameTests {
   186  		c, err := ListenUDP(tt.net, tt.laddr)
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   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  
   198  func 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 {
   202  			t.Fatal(err)
   203  		}
   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 {
   210  				t.Fatal(err)
   211  			}
   212  		}
   213  		c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
   214  		if err != nil {
   215  			t.Fatal(err)
   216  		}
   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  
   236  func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
   237  	if testing.Short() || !*testExternal {
   238  		t.Skip("avoid external network")
   239  	}
   240  	if !supportsIPv6 {
   241  		t.Skip("IPv6 is not supported")
   242  	}
   243  
   244  	for i, tt := range ipv6LinkLocalUnicastUDPTests {
   245  		c1, err := ListenPacket(tt.network, tt.address)
   246  		if err != nil {
   247  			// It might return "LookupHost returned no
   248  			// suitable address" error on some platforms.
   249  			t.Log(err)
   250  			continue
   251  		}
   252  		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  		}
   262  		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  
   266  		c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String())
   267  		if err != nil {
   268  			t.Fatal(err)
   269  		}
   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 {
   279  			t.Fatal(err)
   280  		}
   281  		b := make([]byte, 32)
   282  		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  
   292  func 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[:])
   316  		} else {
   317  			_, _, 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  
   329  func 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 returns WSAEMSGSIZ
   360  				t.Fatal(err)
   361  			}
   362  		}
   363  	}
   364  }