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 			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