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