Home | History | Annotate | Download | only in net
      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 			return false
     47 		case "netbsd":
     48 			// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
     49 			if runtime.GOARCH == "386" {
     50 				return false
     51 			}
     52 		}
     53 	}
     54 	switch ss[0] {
     55 	case "tcp4", "udp4", "ip4":
     56 		if !supportsIPv4() {
     57 			return false
     58 		}
     59 	case "tcp6", "udp6", "ip6":
     60 		if !supportsIPv6() {
     61 			return false
     62 		}
     63 	}
     64 	return true
     65 }
     66 
     67 // testableAddress reports whether address of network is testable on
     68 // the current platform configuration.
     69 func testableAddress(network, address string) bool {
     70 	switch ss := strings.Split(network, ":"); ss[0] {
     71 	case "unix", "unixgram", "unixpacket":
     72 		// Abstract unix domain sockets, a Linux-ism.
     73 		if address[0] == '@' && runtime.GOOS != "linux" {
     74 			return false
     75 		}
     76 	}
     77 	return true
     78 }
     79 
     80 // testableListenArgs reports whether arguments are testable on the
     81 // current platform configuration.
     82 func testableListenArgs(network, address, client string) bool {
     83 	if !testableNetwork(network) || !testableAddress(network, address) {
     84 		return false
     85 	}
     86 
     87 	var err error
     88 	var addr Addr
     89 	switch ss := strings.Split(network, ":"); ss[0] {
     90 	case "tcp", "tcp4", "tcp6":
     91 		addr, err = ResolveTCPAddr("tcp", address)
     92 	case "udp", "udp4", "udp6":
     93 		addr, err = ResolveUDPAddr("udp", address)
     94 	case "ip", "ip4", "ip6":
     95 		addr, err = ResolveIPAddr("ip", address)
     96 	default:
     97 		return true
     98 	}
     99 	if err != nil {
    100 		return false
    101 	}
    102 	var ip IP
    103 	var wildcard bool
    104 	switch addr := addr.(type) {
    105 	case *TCPAddr:
    106 		ip = addr.IP
    107 		wildcard = addr.isWildcard()
    108 	case *UDPAddr:
    109 		ip = addr.IP
    110 		wildcard = addr.isWildcard()
    111 	case *IPAddr:
    112 		ip = addr.IP
    113 		wildcard = addr.isWildcard()
    114 	}
    115 
    116 	// Test wildcard IP addresses.
    117 	if wildcard && !testenv.HasExternalNetwork() {
    118 		return false
    119 	}
    120 
    121 	// Test functionality of IPv4 communication using AF_INET and
    122 	// IPv6 communication using AF_INET6 sockets.
    123 	if !supportsIPv4() && ip.To4() != nil {
    124 		return false
    125 	}
    126 	if !supportsIPv6() && ip.To16() != nil && ip.To4() == nil {
    127 		return false
    128 	}
    129 	cip := ParseIP(client)
    130 	if cip != nil {
    131 		if !supportsIPv4() && cip.To4() != nil {
    132 			return false
    133 		}
    134 		if !supportsIPv6() && cip.To16() != nil && cip.To4() == nil {
    135 			return false
    136 		}
    137 	}
    138 
    139 	// Test functionality of IPv4 communication using AF_INET6
    140 	// sockets.
    141 	if !supportsIPv4map() && supportsIPv4() && (network == "tcp" || network == "udp" || network == "ip") && wildcard {
    142 		// At this point, we prefer IPv4 when ip is nil.
    143 		// See favoriteAddrFamily for further information.
    144 		if ip.To16() != nil && ip.To4() == nil && cip.To4() != nil { // a pair of IPv6 server and IPv4 client
    145 			return false
    146 		}
    147 		if (ip.To4() != nil || ip == nil) && cip.To16() != nil && cip.To4() == nil { // a pair of IPv4 server and IPv6 client
    148 			return false
    149 		}
    150 	}
    151 
    152 	return true
    153 }
    154 
    155 func condFatalf(t *testing.T, network string, format string, args ...interface{}) {
    156 	t.Helper()
    157 	// A few APIs like File and Read/WriteMsg{UDP,IP} are not
    158 	// fully implemented yet on Plan 9 and Windows.
    159 	switch runtime.GOOS {
    160 	case "windows":
    161 		if network == "file+net" {
    162 			t.Logf(format, args...)
    163 			return
    164 		}
    165 	case "plan9":
    166 		t.Logf(format, args...)
    167 		return
    168 	}
    169 	t.Fatalf(format, args...)
    170 }
    171