LEFT | RIGHT |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
| 8 "fmt" |
8 "reflect" | 9 "reflect" |
9 "runtime" | 10 "runtime" |
10 "testing" | 11 "testing" |
11 "time" | 12 "time" |
12 ) | 13 ) |
13 | 14 |
14 func BenchmarkTCPOneShot(b *testing.B) { | 15 func BenchmarkTCP4OneShot(b *testing.B) { |
15 » benchmarkTCP(b, false, false) | 16 » benchmarkTCP(b, false, false, "127.0.0.1:0") |
16 } | 17 } |
17 | 18 |
18 func BenchmarkTCPOneShotTimeout(b *testing.B) { | 19 func BenchmarkTCP4OneShotTimeout(b *testing.B) { |
19 » benchmarkTCP(b, false, true) | 20 » benchmarkTCP(b, false, true, "127.0.0.1:0") |
20 } | 21 } |
21 | 22 |
22 func BenchmarkTCPPersistent(b *testing.B) { | 23 func BenchmarkTCP4Persistent(b *testing.B) { |
23 » benchmarkTCP(b, true, false) | 24 » benchmarkTCP(b, true, false, "127.0.0.1:0") |
24 } | 25 } |
25 | 26 |
26 func BenchmarkTCPPersistentTimeout(b *testing.B) { | 27 func BenchmarkTCP4PersistentTimeout(b *testing.B) { |
27 » benchmarkTCP(b, true, true) | 28 » benchmarkTCP(b, true, true, "127.0.0.1:0") |
28 } | 29 } |
29 | 30 |
30 func benchmarkTCP(b *testing.B, persistent, timeout bool) { | 31 func BenchmarkTCP6OneShot(b *testing.B) { |
| 32 » if !supportsIPv6 { |
| 33 » » b.Skip("ipv6 is not supported") |
| 34 » } |
| 35 » benchmarkTCP(b, false, false, "[::1]:0") |
| 36 } |
| 37 |
| 38 func BenchmarkTCP6OneShotTimeout(b *testing.B) { |
| 39 » if !supportsIPv6 { |
| 40 » » b.Skip("ipv6 is not supported") |
| 41 » } |
| 42 » benchmarkTCP(b, false, true, "[::1]:0") |
| 43 } |
| 44 |
| 45 func BenchmarkTCP6Persistent(b *testing.B) { |
| 46 » if !supportsIPv6 { |
| 47 » » b.Skip("ipv6 is not supported") |
| 48 » } |
| 49 » benchmarkTCP(b, true, false, "[::1]:0") |
| 50 } |
| 51 |
| 52 func BenchmarkTCP6PersistentTimeout(b *testing.B) { |
| 53 » if !supportsIPv6 { |
| 54 » » b.Skip("ipv6 is not supported") |
| 55 » } |
| 56 » benchmarkTCP(b, true, true, "[::1]:0") |
| 57 } |
| 58 |
| 59 func benchmarkTCP(b *testing.B, persistent, timeout bool, laddr string) { |
31 const msgLen = 512 | 60 const msgLen = 512 |
32 conns := b.N | 61 conns := b.N |
33 numConcurrent := runtime.GOMAXPROCS(-1) * 16 | 62 numConcurrent := runtime.GOMAXPROCS(-1) * 16 |
34 msgs := 1 | 63 msgs := 1 |
35 if persistent { | 64 if persistent { |
36 conns = numConcurrent | 65 conns = numConcurrent |
37 msgs = b.N / conns | 66 msgs = b.N / conns |
38 if msgs == 0 { | 67 if msgs == 0 { |
39 msgs = 1 | 68 msgs = 1 |
40 } | 69 } |
(...skipping 13 matching lines...) Expand all Loading... |
54 for read := 0; read != len(buf); { | 83 for read := 0; read != len(buf); { |
55 n, err := c.Read(buf) | 84 n, err := c.Read(buf) |
56 read += n | 85 read += n |
57 if err != nil { | 86 if err != nil { |
58 b.Logf("Read failed: %v", err) | 87 b.Logf("Read failed: %v", err) |
59 return false | 88 return false |
60 } | 89 } |
61 } | 90 } |
62 return true | 91 return true |
63 } | 92 } |
64 » ln, err := Listen("tcp", "127.0.0.1:0") | 93 » ln, err := Listen("tcp", laddr) |
65 if err != nil { | 94 if err != nil { |
66 b.Fatalf("Listen failed: %v", err) | 95 b.Fatalf("Listen failed: %v", err) |
67 } | 96 } |
68 defer ln.Close() | 97 defer ln.Close() |
69 // Acceptor. | 98 // Acceptor. |
70 go func() { | 99 go func() { |
71 for { | 100 for { |
72 c, err := ln.Accept() | 101 c, err := ln.Accept() |
73 if err != nil { | 102 if err != nil { |
74 break | 103 break |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 } | 144 } |
116 for i := 0; i < cap(sem); i++ { | 145 for i := 0; i < cap(sem); i++ { |
117 sem <- true | 146 sem <- true |
118 } | 147 } |
119 } | 148 } |
120 | 149 |
121 var resolveTCPAddrTests = []struct { | 150 var resolveTCPAddrTests = []struct { |
122 net string | 151 net string |
123 litAddr string | 152 litAddr string |
124 addr *TCPAddr | 153 addr *TCPAddr |
| 154 err error |
125 }{ | 155 }{ |
126 » {"tcp", "127.0.0.1:1", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}}, | 156 » {"tcp", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, |
127 » {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535
}}, | 157 » {"tcp4", "127.0.0.1:65535", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535
}, nil}, |
128 | 158 |
129 » {"tcp", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}}, | 159 » {"tcp", "[::1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1}, nil}, |
130 » {"tcp", "[::1%1]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, zoneId: 1}}, | 160 » {"tcp6", "[::1]:65534", &TCPAddr{IP: ParseIP("::1"), Port: 65534}, nil}, |
131 » {"tcp6", "[::1]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2}}, | 161 |
132 » {"tcp6", "[::1%2]:3", &TCPAddr{IP: ParseIP("::1"), Port: 3, zoneId: 2}}, | 162 » {"tcp", "[::1%en0]:1", &TCPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"
}, nil}, |
133 » {"tcp6", "[::1]:4", &TCPAddr{IP: ParseIP("::1"), Port: 4, zoneId: -1}}, | 163 » {"tcp6", "[::1%911]:2", &TCPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911
"}, nil}, |
| 164 » {"tcp6", "[fe80::1]:3", &TCPAddr{IP: ParseIP("fe80::1"), Port: 3, Zone:
"name"}, nil}, |
| 165 » {"tcp6", "[fe80::1]:4", &TCPAddr{IP: ParseIP("fe80::1"), Port: 4, Zone:
"index"}, nil}, |
| 166 |
| 167 » {"", "127.0.0.1:0", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil}, //
Go 1.0 behavior |
| 168 » {"", "[::1]:0", &TCPAddr{IP: ParseIP("::1"), Port: 0}, nil}, //
Go 1.0 behavior |
| 169 |
| 170 » {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")}, |
134 } | 171 } |
135 | 172 |
136 func TestResolveTCPAddr(t *testing.T) { | 173 func TestResolveTCPAddr(t *testing.T) { |
137 for _, tt := range resolveTCPAddrTests { | 174 for _, tt := range resolveTCPAddrTests { |
138 » » if tt.addr.zoneId == -1 { | 175 » » if tt.addr != nil && (tt.addr.Zone == "name" || tt.addr.Zone ==
"index") { |
139 ifi := loopbackInterface() | 176 ifi := loopbackInterface() |
140 if ifi == nil { | 177 if ifi == nil { |
141 continue | 178 continue |
142 } | 179 } |
143 i := last(tt.litAddr, ']') | 180 i := last(tt.litAddr, ']') |
144 if i > 0 { | 181 if i > 0 { |
145 » » » » tt.litAddr = tt.litAddr[:i] + "%" + ifi.Name + t
t.litAddr[i:] | 182 » » » » switch tt.addr.Zone { |
146 » » » » tt.addr.zoneId = ifi.Index | 183 » » » » case "name": |
| 184 » » » » » tt.litAddr = tt.litAddr[:i] + "%" + ifi.
Name + tt.litAddr[i:] |
| 185 » » » » » tt.addr.Zone = zoneToString(ifi.Index) |
| 186 » » » » case "index": |
| 187 » » » » » index := fmt.Sprintf("%v", ifi.Index) |
| 188 » » » » » tt.litAddr = tt.litAddr[:i] + "%" + inde
x + tt.litAddr[i:] |
| 189 » » » » » tt.addr.Zone = index |
| 190 » » » » } |
147 } | 191 } |
148 } | 192 } |
149 addr, err := ResolveTCPAddr(tt.net, tt.litAddr) | 193 addr, err := ResolveTCPAddr(tt.net, tt.litAddr) |
150 » » if err != nil { | 194 » » if err != tt.err { |
151 t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt
.litAddr, err) | 195 t.Fatalf("ResolveTCPAddr(%v, %v) failed: %v", tt.net, tt
.litAddr, err) |
152 } | 196 } |
153 if !reflect.DeepEqual(addr, tt.addr) { | 197 if !reflect.DeepEqual(addr, tt.addr) { |
154 t.Fatalf("got %#v; expected %#v", addr, tt.addr) | 198 t.Fatalf("got %#v; expected %#v", addr, tt.addr) |
155 } | 199 } |
156 } | 200 } |
157 } | 201 } |
| 202 |
| 203 var tcpListenerNameTests = []struct { |
| 204 net string |
| 205 laddr *TCPAddr |
| 206 }{ |
| 207 {"tcp4", &TCPAddr{IP: IPv4(127, 0, 0, 1)}}, |
| 208 {"tcp4", &TCPAddr{}}, |
| 209 {"tcp4", nil}, |
| 210 } |
| 211 |
| 212 func TestTCPListenerName(t *testing.T) { |
| 213 if testing.Short() || !*testExternal { |
| 214 t.Skip("skipping test to avoid external network") |
| 215 } |
| 216 |
| 217 for _, tt := range tcpListenerNameTests { |
| 218 ln, err := ListenTCP(tt.net, tt.laddr) |
| 219 if err != nil { |
| 220 t.Errorf("ListenTCP failed: %v", err) |
| 221 return |
| 222 } |
| 223 defer ln.Close() |
| 224 la := ln.Addr() |
| 225 if a, ok := la.(*TCPAddr); !ok || a.Port == 0 { |
| 226 t.Errorf("got %v; expected a proper address with non-zer
o port number", la) |
| 227 return |
| 228 } |
| 229 } |
| 230 } |
| 231 |
| 232 func TestIPv6LinkLocalUnicastTCP(t *testing.T) { |
| 233 if testing.Short() || !*testExternal { |
| 234 t.Skip("skipping test to avoid external network") |
| 235 } |
| 236 if !supportsIPv6 { |
| 237 t.Skip("ipv6 is not supported") |
| 238 } |
| 239 ifi := loopbackInterface() |
| 240 if ifi == nil { |
| 241 t.Skip("loopback interface not found") |
| 242 } |
| 243 laddr := ipv6LinkLocalUnicastAddr(ifi) |
| 244 if laddr == "" { |
| 245 t.Skip("ipv6 unicast address on loopback not found") |
| 246 } |
| 247 |
| 248 type test struct { |
| 249 net, addr string |
| 250 nameLookup bool |
| 251 } |
| 252 var tests = []test{ |
| 253 {"tcp", "[" + laddr + "%" + ifi.Name + "]:0", false}, |
| 254 {"tcp6", "[" + laddr + "%" + ifi.Name + "]:0", false}, |
| 255 } |
| 256 switch runtime.GOOS { |
| 257 case "darwin", "freebsd", "opensbd", "netbsd": |
| 258 tests = append(tests, []test{ |
| 259 {"tcp", "[localhost%" + ifi.Name + "]:0", true}, |
| 260 {"tcp6", "[localhost%" + ifi.Name + "]:0", true}, |
| 261 }...) |
| 262 case "linux": |
| 263 tests = append(tests, []test{ |
| 264 {"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true}, |
| 265 {"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true}, |
| 266 }...) |
| 267 } |
| 268 for _, tt := range tests { |
| 269 ln, err := Listen(tt.net, tt.addr) |
| 270 if err != nil { |
| 271 // It might return "LookupHost returned no |
| 272 // suitable address" error on some platforms. |
| 273 t.Logf("Listen failed: %v", err) |
| 274 continue |
| 275 } |
| 276 defer ln.Close() |
| 277 if la, ok := ln.Addr().(*TCPAddr); !ok || !tt.nameLookup && la.Z
one == "" { |
| 278 t.Fatalf("got %v; expected a proper address with zone id
entifier", la) |
| 279 } |
| 280 |
| 281 done := make(chan int) |
| 282 go transponder(t, ln, done) |
| 283 |
| 284 c, err := Dial(tt.net, ln.Addr().String()) |
| 285 if err != nil { |
| 286 t.Fatalf("Dial failed: %v", err) |
| 287 } |
| 288 defer c.Close() |
| 289 if la, ok := c.LocalAddr().(*TCPAddr); !ok || !tt.nameLookup &&
la.Zone == "" { |
| 290 t.Fatalf("got %v; expected a proper address with zone id
entifier", la) |
| 291 } |
| 292 if ra, ok := c.RemoteAddr().(*TCPAddr); !ok || !tt.nameLookup &&
ra.Zone == "" { |
| 293 t.Fatalf("got %v; expected a proper address with zone id
entifier", ra) |
| 294 } |
| 295 |
| 296 if _, err := c.Write([]byte("TCP OVER IPV6 LINKLOCAL TEST")); er
r != nil { |
| 297 t.Fatalf("Conn.Write failed: %v", err) |
| 298 } |
| 299 b := make([]byte, 32) |
| 300 if _, err := c.Read(b); err != nil { |
| 301 t.Fatalf("Conn.Read failed: %v", err) |
| 302 } |
| 303 |
| 304 <-done |
| 305 } |
| 306 } |
LEFT | RIGHT |