platform_test.go 4.06 KB
Newer Older
Mikio Hara's avatar
Mikio Hara committed
1 2 3 4 5 6 7
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package net

import (
8
	"internal/testenv"
Mikio Hara's avatar
Mikio Hara committed
9 10 11 12 13 14 15 16 17
	"os"
	"runtime"
	"strings"
	"testing"
)

// testableNetwork reports whether network is testable on the current
// platform configuration.
func testableNetwork(network string) bool {
18 19
	ss := strings.Split(network, ":")
	switch ss[0] {
Mikio Hara's avatar
Mikio Hara committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
	case "ip+nopriv":
		switch runtime.GOOS {
		case "nacl":
			return false
		}
	case "ip", "ip4", "ip6":
		switch runtime.GOOS {
		case "nacl", "plan9":
			return false
		default:
			if os.Getuid() != 0 {
				return false
			}
		}
	case "unix", "unixgram":
		switch runtime.GOOS {
36
		case "android", "nacl", "plan9", "windows":
Mikio Hara's avatar
Mikio Hara committed
37 38 39 40 41 42 43 44
			return false
		}
		// iOS does not support unix, unixgram.
		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
			return false
		}
	case "unixpacket":
		switch runtime.GOOS {
45
		case "aix", "android", "darwin", "nacl", "plan9", "windows":
Mikio Hara's avatar
Mikio Hara committed
46
			return false
47 48 49 50 51
		case "netbsd":
			// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
			if runtime.GOARCH == "386" {
				return false
			}
Mikio Hara's avatar
Mikio Hara committed
52 53
		}
	}
54 55
	switch ss[0] {
	case "tcp4", "udp4", "ip4":
56
		if !supportsIPv4() {
57 58 59
			return false
		}
	case "tcp6", "udp6", "ip6":
60
		if !supportsIPv6() {
61 62 63
			return false
		}
	}
Mikio Hara's avatar
Mikio Hara committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
	return true
}

// testableAddress reports whether address of network is testable on
// the current platform configuration.
func testableAddress(network, address string) bool {
	switch ss := strings.Split(network, ":"); ss[0] {
	case "unix", "unixgram", "unixpacket":
		// Abstract unix domain sockets, a Linux-ism.
		if address[0] == '@' && runtime.GOOS != "linux" {
			return false
		}
	}
	return true
}

// testableListenArgs reports whether arguments are testable on the
// current platform configuration.
func testableListenArgs(network, address, client string) bool {
	if !testableNetwork(network) || !testableAddress(network, address) {
		return false
	}

	var err error
	var addr Addr
	switch ss := strings.Split(network, ":"); ss[0] {
	case "tcp", "tcp4", "tcp6":
		addr, err = ResolveTCPAddr("tcp", address)
	case "udp", "udp4", "udp6":
		addr, err = ResolveUDPAddr("udp", address)
	case "ip", "ip4", "ip6":
		addr, err = ResolveIPAddr("ip", address)
	default:
		return true
	}
	if err != nil {
		return false
	}
	var ip IP
	var wildcard bool
	switch addr := addr.(type) {
	case *TCPAddr:
		ip = addr.IP
		wildcard = addr.isWildcard()
	case *UDPAddr:
		ip = addr.IP
		wildcard = addr.isWildcard()
	case *IPAddr:
		ip = addr.IP
		wildcard = addr.isWildcard()
	}

	// Test wildcard IP addresses.
117
	if wildcard && !testenv.HasExternalNetwork() {
Mikio Hara's avatar
Mikio Hara committed
118 119 120
		return false
	}

121 122
	// Test functionality of IPv4 communication using AF_INET and
	// IPv6 communication using AF_INET6 sockets.
123
	if !supportsIPv4() && ip.To4() != nil {
124 125
		return false
	}
126
	if !supportsIPv6() && ip.To16() != nil && ip.To4() == nil {
Mikio Hara's avatar
Mikio Hara committed
127 128
		return false
	}
129 130
	cip := ParseIP(client)
	if cip != nil {
131
		if !supportsIPv4() && cip.To4() != nil {
132 133
			return false
		}
134
		if !supportsIPv6() && cip.To16() != nil && cip.To4() == nil {
135 136 137
			return false
		}
	}
Mikio Hara's avatar
Mikio Hara committed
138 139 140

	// Test functionality of IPv4 communication using AF_INET6
	// sockets.
141
	if !supportsIPv4map() && supportsIPv4() && (network == "tcp" || network == "udp" || network == "ip") && wildcard {
Mikio Hara's avatar
Mikio Hara committed
142 143 144 145 146 147 148 149 150 151 152 153 154
		// At this point, we prefer IPv4 when ip is nil.
		// See favoriteAddrFamily for further information.
		if ip.To16() != nil && ip.To4() == nil && cip.To4() != nil { // a pair of IPv6 server and IPv4 client
			return false
		}
		if (ip.To4() != nil || ip == nil) && cip.To16() != nil && cip.To4() == nil { // a pair of IPv4 server and IPv6 client
			return false
		}
	}

	return true
}

155 156
func condFatalf(t *testing.T, network string, format string, args ...interface{}) {
	t.Helper()
157 158
	// A few APIs like File and Read/WriteMsg{UDP,IP} are not
	// fully implemented yet on Plan 9 and Windows.
Mikio Hara's avatar
Mikio Hara committed
159
	switch runtime.GOOS {
160
	case "windows":
161
		if network == "file+net" {
162 163 164 165 166 167
			t.Logf(format, args...)
			return
		}
	case "plan9":
		t.Logf(format, args...)
		return
Mikio Hara's avatar
Mikio Hara committed
168
	}
169 170
	t.Fatalf(format, args...)
}