Home | History | Annotate | Download | only in net
      1 // Copyright 2011 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 	"os"
      9 	"reflect"
     10 	"runtime"
     11 	"testing"
     12 )
     13 
     14 type listenerFile interface {
     15 	Listener
     16 	File() (f *os.File, err error)
     17 }
     18 
     19 type packetConnFile interface {
     20 	PacketConn
     21 	File() (f *os.File, err error)
     22 }
     23 
     24 type connFile interface {
     25 	Conn
     26 	File() (f *os.File, err error)
     27 }
     28 
     29 func testFileListener(t *testing.T, net, laddr string) {
     30 	l, err := Listen(net, laddr)
     31 	if err != nil {
     32 		t.Fatal(err)
     33 	}
     34 	defer l.Close()
     35 	lf := l.(listenerFile)
     36 	f, err := lf.File()
     37 	if err != nil {
     38 		t.Fatal(err)
     39 	}
     40 	c, err := FileListener(f)
     41 	if err != nil {
     42 		t.Fatal(err)
     43 	}
     44 	if !reflect.DeepEqual(l.Addr(), c.Addr()) {
     45 		t.Fatalf("got %#v; want%#v", l.Addr(), c.Addr())
     46 	}
     47 	if err := c.Close(); err != nil {
     48 		t.Fatal(err)
     49 	}
     50 	if err := f.Close(); err != nil {
     51 		t.Fatal(err)
     52 	}
     53 }
     54 
     55 var fileListenerTests = []struct {
     56 	net   string
     57 	laddr string
     58 }{
     59 	{net: "tcp", laddr: ":0"},
     60 	{net: "tcp", laddr: "0.0.0.0:0"},
     61 	{net: "tcp", laddr: "[::ffff:0.0.0.0]:0"},
     62 	{net: "tcp", laddr: "[::]:0"},
     63 
     64 	{net: "tcp", laddr: "127.0.0.1:0"},
     65 	{net: "tcp", laddr: "[::ffff:127.0.0.1]:0"},
     66 	{net: "tcp", laddr: "[::1]:0"},
     67 
     68 	{net: "tcp4", laddr: ":0"},
     69 	{net: "tcp4", laddr: "0.0.0.0:0"},
     70 	{net: "tcp4", laddr: "[::ffff:0.0.0.0]:0"},
     71 
     72 	{net: "tcp4", laddr: "127.0.0.1:0"},
     73 	{net: "tcp4", laddr: "[::ffff:127.0.0.1]:0"},
     74 
     75 	{net: "tcp6", laddr: ":0"},
     76 	{net: "tcp6", laddr: "[::]:0"},
     77 
     78 	{net: "tcp6", laddr: "[::1]:0"},
     79 
     80 	{net: "unix", laddr: "@gotest/net"},
     81 	{net: "unixpacket", laddr: "@gotest/net"},
     82 }
     83 
     84 func TestFileListener(t *testing.T) {
     85 	switch runtime.GOOS {
     86 	case "nacl", "windows":
     87 		t.Skipf("not supported on %s", runtime.GOOS)
     88 	}
     89 
     90 	for _, tt := range fileListenerTests {
     91 		if !testableListenArgs(tt.net, tt.laddr, "") {
     92 			t.Logf("skipping %s test", tt.net+" "+tt.laddr)
     93 			continue
     94 		}
     95 		testFileListener(t, tt.net, tt.laddr)
     96 	}
     97 }
     98 
     99 func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
    100 	f, err := pcf.File()
    101 	if err != nil {
    102 		t.Fatal(err)
    103 	}
    104 	c, err := FilePacketConn(f)
    105 	if err != nil {
    106 		t.Fatal(err)
    107 	}
    108 	if !reflect.DeepEqual(pcf.LocalAddr(), c.LocalAddr()) {
    109 		t.Fatalf("got %#v; want %#v", pcf.LocalAddr(), c.LocalAddr())
    110 	}
    111 	if listen {
    112 		if _, err := c.WriteTo([]byte{}, c.LocalAddr()); err != nil {
    113 			t.Fatal(err)
    114 		}
    115 	}
    116 	if err := c.Close(); err != nil {
    117 		t.Fatal(err)
    118 	}
    119 	if err := f.Close(); err != nil {
    120 		t.Fatal(err)
    121 	}
    122 }
    123 
    124 func testFilePacketConnListen(t *testing.T, net, laddr string) {
    125 	l, err := ListenPacket(net, laddr)
    126 	if err != nil {
    127 		t.Fatal(err)
    128 	}
    129 	testFilePacketConn(t, l.(packetConnFile), true)
    130 	if err := l.Close(); err != nil {
    131 		t.Fatal(err)
    132 	}
    133 }
    134 
    135 func testFilePacketConnDial(t *testing.T, net, raddr string) {
    136 	c, err := Dial(net, raddr)
    137 	if err != nil {
    138 		t.Fatal(err)
    139 	}
    140 	testFilePacketConn(t, c.(packetConnFile), false)
    141 	if err := c.Close(); err != nil {
    142 		t.Fatal(err)
    143 	}
    144 }
    145 
    146 var filePacketConnTests = []struct {
    147 	net  string
    148 	addr string
    149 }{
    150 	{net: "udp", addr: "127.0.0.1:0"},
    151 	{net: "udp", addr: "[::ffff:127.0.0.1]:0"},
    152 	{net: "udp", addr: "[::1]:0"},
    153 
    154 	{net: "udp4", addr: "127.0.0.1:0"},
    155 	{net: "udp4", addr: "[::ffff:127.0.0.1]:0"},
    156 
    157 	{net: "udp6", addr: "[::1]:0"},
    158 
    159 	// TODO(mikioh,bradfitz): reenable once 10730 is fixed
    160 	// {net: "ip4:icmp", addr: "127.0.0.1"},
    161 
    162 	{net: "unixgram", addr: "@gotest3/net"},
    163 }
    164 
    165 func TestFilePacketConn(t *testing.T) {
    166 	switch runtime.GOOS {
    167 	case "nacl", "plan9", "windows":
    168 		t.Skipf("not supported on %s", runtime.GOOS)
    169 	}
    170 
    171 	for _, tt := range filePacketConnTests {
    172 		if !testableListenArgs(tt.net, tt.addr, "") {
    173 			t.Logf("skipping %s test", tt.net+" "+tt.addr)
    174 			continue
    175 		}
    176 		if os.Getuid() != 0 && tt.net == "ip4:icmp" {
    177 			t.Log("skipping test; must be root")
    178 			continue
    179 		}
    180 		testFilePacketConnListen(t, tt.net, tt.addr)
    181 		switch tt.net {
    182 		case "udp", "udp4", "udp6":
    183 			host, _, err := SplitHostPort(tt.addr)
    184 			if err != nil {
    185 				t.Error(err)
    186 				continue
    187 			}
    188 			testFilePacketConnDial(t, tt.net, JoinHostPort(host, "12345"))
    189 		case "ip4:icmp":
    190 			testFilePacketConnDial(t, tt.net, tt.addr)
    191 		}
    192 	}
    193 }
    194