Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 1 | // Copyright 2015 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 | "runtime" |
| 10 | "strings" |
| 11 | "testing" |
| 12 | ) |
| 13 | |
| 14 | // testableNetwork reports whether network is testable on the current |
| 15 | // platform configuration. |
| 16 | func testableNetwork(network string) bool { |
Mikio Hara | 3b38626 | 2015-05-12 23:11:28 +0900 | [diff] [blame] | 17 | ss := strings.Split(network, ":") |
| 18 | switch ss[0] { |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 19 | case "ip+nopriv": |
| 20 | switch runtime.GOOS { |
| 21 | case "nacl": |
| 22 | return false |
| 23 | } |
| 24 | case "ip", "ip4", "ip6": |
| 25 | switch runtime.GOOS { |
| 26 | case "nacl", "plan9": |
| 27 | return false |
| 28 | default: |
| 29 | if os.Getuid() != 0 { |
| 30 | return false |
| 31 | } |
| 32 | } |
| 33 | case "unix", "unixgram": |
| 34 | switch runtime.GOOS { |
| 35 | case "nacl", "plan9", "windows": |
| 36 | return false |
| 37 | } |
| 38 | // iOS does not support unix, unixgram. |
| 39 | if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { |
| 40 | return false |
| 41 | } |
| 42 | case "unixpacket": |
| 43 | switch runtime.GOOS { |
Mikio Hara | 087d5c0 | 2015-05-03 23:29:34 +0900 | [diff] [blame] | 44 | case "android", "darwin", "nacl", "plan9", "windows": |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 45 | fallthrough |
| 46 | case "freebsd": // FreeBSD 8 and below don't support unixpacket |
| 47 | return false |
| 48 | } |
| 49 | } |
Mikio Hara | 3b38626 | 2015-05-12 23:11:28 +0900 | [diff] [blame] | 50 | switch ss[0] { |
| 51 | case "tcp4", "udp4", "ip4": |
| 52 | if !supportsIPv4 { |
| 53 | return false |
| 54 | } |
| 55 | case "tcp6", "udp6", "ip6": |
| 56 | if !supportsIPv6 { |
| 57 | return false |
| 58 | } |
| 59 | } |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 60 | return true |
| 61 | } |
| 62 | |
| 63 | // testableAddress reports whether address of network is testable on |
| 64 | // the current platform configuration. |
| 65 | func testableAddress(network, address string) bool { |
| 66 | switch ss := strings.Split(network, ":"); ss[0] { |
| 67 | case "unix", "unixgram", "unixpacket": |
| 68 | // Abstract unix domain sockets, a Linux-ism. |
| 69 | if address[0] == '@' && runtime.GOOS != "linux" { |
| 70 | return false |
| 71 | } |
| 72 | } |
| 73 | return true |
| 74 | } |
| 75 | |
| 76 | // testableListenArgs reports whether arguments are testable on the |
| 77 | // current platform configuration. |
| 78 | func testableListenArgs(network, address, client string) bool { |
| 79 | if !testableNetwork(network) || !testableAddress(network, address) { |
| 80 | return false |
| 81 | } |
| 82 | |
| 83 | var err error |
| 84 | var addr Addr |
| 85 | switch ss := strings.Split(network, ":"); ss[0] { |
| 86 | case "tcp", "tcp4", "tcp6": |
| 87 | addr, err = ResolveTCPAddr("tcp", address) |
| 88 | case "udp", "udp4", "udp6": |
| 89 | addr, err = ResolveUDPAddr("udp", address) |
| 90 | case "ip", "ip4", "ip6": |
| 91 | addr, err = ResolveIPAddr("ip", address) |
| 92 | default: |
| 93 | return true |
| 94 | } |
| 95 | if err != nil { |
| 96 | return false |
| 97 | } |
| 98 | var ip IP |
| 99 | var wildcard bool |
| 100 | switch addr := addr.(type) { |
| 101 | case *TCPAddr: |
| 102 | ip = addr.IP |
| 103 | wildcard = addr.isWildcard() |
| 104 | case *UDPAddr: |
| 105 | ip = addr.IP |
| 106 | wildcard = addr.isWildcard() |
| 107 | case *IPAddr: |
| 108 | ip = addr.IP |
| 109 | wildcard = addr.isWildcard() |
| 110 | } |
| 111 | |
| 112 | // Test wildcard IP addresses. |
| 113 | if wildcard && (testing.Short() || !*testExternal) { |
| 114 | return false |
| 115 | } |
| 116 | |
Mikio Hara | f963cb7 | 2015-05-07 08:20:42 +0900 | [diff] [blame] | 117 | // Test functionality of IPv4 communication using AF_INET and |
| 118 | // IPv6 communication using AF_INET6 sockets. |
| 119 | if !supportsIPv4 && ip.To4() != nil { |
| 120 | return false |
| 121 | } |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 122 | if !supportsIPv6 && ip.To16() != nil && ip.To4() == nil { |
| 123 | return false |
| 124 | } |
Mikio Hara | f963cb7 | 2015-05-07 08:20:42 +0900 | [diff] [blame] | 125 | cip := ParseIP(client) |
| 126 | if cip != nil { |
| 127 | if !supportsIPv4 && cip.To4() != nil { |
| 128 | return false |
| 129 | } |
| 130 | if !supportsIPv6 && cip.To16() != nil && cip.To4() == nil { |
| 131 | return false |
| 132 | } |
| 133 | } |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 134 | |
| 135 | // Test functionality of IPv4 communication using AF_INET6 |
| 136 | // sockets. |
Mikio Hara | 7b2b45e | 2015-03-26 23:26:45 +0900 | [diff] [blame] | 137 | if !supportsIPv4map && (network == "tcp" || network == "udp" || network == "ip") && wildcard { |
| 138 | // At this point, we prefer IPv4 when ip is nil. |
| 139 | // See favoriteAddrFamily for further information. |
| 140 | if ip.To16() != nil && ip.To4() == nil && cip.To4() != nil { // a pair of IPv6 server and IPv4 client |
| 141 | return false |
| 142 | } |
| 143 | if (ip.To4() != nil || ip == nil) && cip.To16() != nil && cip.To4() == nil { // a pair of IPv4 server and IPv6 client |
| 144 | return false |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | return true |
| 149 | } |
| 150 | |
| 151 | var condFatalf = func() func(*testing.T, string, ...interface{}) { |
| 152 | // A few APIs, File, Read/WriteMsg{UDP,IP}, are not |
| 153 | // implemented yet on both Plan 9 and Windows. |
| 154 | switch runtime.GOOS { |
| 155 | case "plan9", "windows": |
| 156 | return (*testing.T).Logf |
| 157 | } |
| 158 | return (*testing.T).Fatalf |
| 159 | }() |