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