Home | History | Annotate | Download | only in net
      1 // Copyright 2011 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 	"reflect"
     10 	"runtime"
     11 	"sync"
     12 	"testing"
     13 )
     14 
     15 // The full stack test cases for IPConn have been moved to the
     16 // following:
     17 //      golang.org/x/net/ipv4
     18 //      golang.org/x/net/ipv6
     19 //      golang.org/x/net/icmp
     20 
     21 var fileConnTests = []struct {
     22 	network string
     23 }{
     24 	{"tcp"},
     25 	{"udp"},
     26 	{"unix"},
     27 	{"unixpacket"},
     28 }
     29 
     30 func TestFileConn(t *testing.T) {
     31 	switch runtime.GOOS {
     32 	case "nacl", "plan9", "windows":
     33 		t.Skipf("not supported on %s", runtime.GOOS)
     34 	}
     35 
     36 	for _, tt := range fileConnTests {
     37 		if !testableNetwork(tt.network) {
     38 			t.Logf("skipping %s test", tt.network)
     39 			continue
     40 		}
     41 
     42 		var network, address string
     43 		switch tt.network {
     44 		case "udp":
     45 			c, err := newLocalPacketListener(tt.network)
     46 			if err != nil {
     47 				t.Fatal(err)
     48 			}
     49 			defer c.Close()
     50 			network = c.LocalAddr().Network()
     51 			address = c.LocalAddr().String()
     52 		default:
     53 			handler := func(ls *localServer, ln Listener) {
     54 				c, err := ln.Accept()
     55 				if err != nil {
     56 					return
     57 				}
     58 				defer c.Close()
     59 				var b [1]byte
     60 				c.Read(b[:])
     61 			}
     62 			ls, err := newLocalServer(tt.network)
     63 			if err != nil {
     64 				t.Fatal(err)
     65 			}
     66 			defer ls.teardown()
     67 			if err := ls.buildup(handler); err != nil {
     68 				t.Fatal(err)
     69 			}
     70 			network = ls.Listener.Addr().Network()
     71 			address = ls.Listener.Addr().String()
     72 		}
     73 
     74 		c1, err := Dial(network, address)
     75 		if err != nil {
     76 			if perr := parseDialError(err); perr != nil {
     77 				t.Error(perr)
     78 			}
     79 			t.Fatal(err)
     80 		}
     81 		addr := c1.LocalAddr()
     82 
     83 		var f *os.File
     84 		switch c1 := c1.(type) {
     85 		case *TCPConn:
     86 			f, err = c1.File()
     87 		case *UDPConn:
     88 			f, err = c1.File()
     89 		case *UnixConn:
     90 			f, err = c1.File()
     91 		}
     92 		if err := c1.Close(); err != nil {
     93 			if perr := parseCloseError(err, false); perr != nil {
     94 				t.Error(perr)
     95 			}
     96 			t.Error(err)
     97 		}
     98 		if err != nil {
     99 			if perr := parseCommonError(err); perr != nil {
    100 				t.Error(perr)
    101 			}
    102 			t.Fatal(err)
    103 		}
    104 
    105 		c2, err := FileConn(f)
    106 		if err := f.Close(); err != nil {
    107 			t.Error(err)
    108 		}
    109 		if err != nil {
    110 			if perr := parseCommonError(err); perr != nil {
    111 				t.Error(perr)
    112 			}
    113 			t.Fatal(err)
    114 		}
    115 		defer c2.Close()
    116 
    117 		if _, err := c2.Write([]byte("FILECONN TEST")); err != nil {
    118 			if perr := parseWriteError(err); perr != nil {
    119 				t.Error(perr)
    120 			}
    121 			t.Fatal(err)
    122 		}
    123 		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
    124 			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
    125 		}
    126 	}
    127 }
    128 
    129 var fileListenerTests = []struct {
    130 	network string
    131 }{
    132 	{"tcp"},
    133 	{"unix"},
    134 	{"unixpacket"},
    135 }
    136 
    137 func TestFileListener(t *testing.T) {
    138 	switch runtime.GOOS {
    139 	case "nacl", "plan9", "windows":
    140 		t.Skipf("not supported on %s", runtime.GOOS)
    141 	}
    142 
    143 	for _, tt := range fileListenerTests {
    144 		if !testableNetwork(tt.network) {
    145 			t.Logf("skipping %s test", tt.network)
    146 			continue
    147 		}
    148 
    149 		ln1, err := newLocalListener(tt.network)
    150 		if err != nil {
    151 			t.Fatal(err)
    152 		}
    153 		switch tt.network {
    154 		case "unix", "unixpacket":
    155 			defer os.Remove(ln1.Addr().String())
    156 		}
    157 		addr := ln1.Addr()
    158 
    159 		var f *os.File
    160 		switch ln1 := ln1.(type) {
    161 		case *TCPListener:
    162 			f, err = ln1.File()
    163 		case *UnixListener:
    164 			f, err = ln1.File()
    165 		}
    166 		switch tt.network {
    167 		case "unix", "unixpacket":
    168 			defer ln1.Close() // UnixListener.Close calls syscall.Unlink internally
    169 		default:
    170 			if err := ln1.Close(); err != nil {
    171 				t.Error(err)
    172 			}
    173 		}
    174 		if err != nil {
    175 			if perr := parseCommonError(err); perr != nil {
    176 				t.Error(perr)
    177 			}
    178 			t.Fatal(err)
    179 		}
    180 
    181 		ln2, err := FileListener(f)
    182 		if err := f.Close(); err != nil {
    183 			t.Error(err)
    184 		}
    185 		if err != nil {
    186 			if perr := parseCommonError(err); perr != nil {
    187 				t.Error(perr)
    188 			}
    189 			t.Fatal(err)
    190 		}
    191 		defer ln2.Close()
    192 
    193 		var wg sync.WaitGroup
    194 		wg.Add(1)
    195 		go func() {
    196 			defer wg.Done()
    197 			c, err := Dial(ln2.Addr().Network(), ln2.Addr().String())
    198 			if err != nil {
    199 				if perr := parseDialError(err); perr != nil {
    200 					t.Error(perr)
    201 				}
    202 				t.Error(err)
    203 				return
    204 			}
    205 			c.Close()
    206 		}()
    207 		c, err := ln2.Accept()
    208 		if err != nil {
    209 			if perr := parseAcceptError(err); perr != nil {
    210 				t.Error(perr)
    211 			}
    212 			t.Fatal(err)
    213 		}
    214 		c.Close()
    215 		wg.Wait()
    216 		if !reflect.DeepEqual(ln2.Addr(), addr) {
    217 			t.Fatalf("got %#v; want %#v", ln2.Addr(), addr)
    218 		}
    219 	}
    220 }
    221 
    222 var filePacketConnTests = []struct {
    223 	network string
    224 }{
    225 	{"udp"},
    226 	{"unixgram"},
    227 }
    228 
    229 func TestFilePacketConn(t *testing.T) {
    230 	switch runtime.GOOS {
    231 	case "nacl", "plan9", "windows":
    232 		t.Skipf("not supported on %s", runtime.GOOS)
    233 	}
    234 
    235 	for _, tt := range filePacketConnTests {
    236 		if !testableNetwork(tt.network) {
    237 			t.Logf("skipping %s test", tt.network)
    238 			continue
    239 		}
    240 
    241 		c1, err := newLocalPacketListener(tt.network)
    242 		if err != nil {
    243 			t.Fatal(err)
    244 		}
    245 		switch tt.network {
    246 		case "unixgram":
    247 			defer os.Remove(c1.LocalAddr().String())
    248 		}
    249 		addr := c1.LocalAddr()
    250 
    251 		var f *os.File
    252 		switch c1 := c1.(type) {
    253 		case *UDPConn:
    254 			f, err = c1.File()
    255 		case *UnixConn:
    256 			f, err = c1.File()
    257 		}
    258 		if err := c1.Close(); err != nil {
    259 			if perr := parseCloseError(err, false); perr != nil {
    260 				t.Error(perr)
    261 			}
    262 			t.Error(err)
    263 		}
    264 		if err != nil {
    265 			if perr := parseCommonError(err); perr != nil {
    266 				t.Error(perr)
    267 			}
    268 			t.Fatal(err)
    269 		}
    270 
    271 		c2, err := FilePacketConn(f)
    272 		if err := f.Close(); err != nil {
    273 			t.Error(err)
    274 		}
    275 		if err != nil {
    276 			if perr := parseCommonError(err); perr != nil {
    277 				t.Error(perr)
    278 			}
    279 			t.Fatal(err)
    280 		}
    281 		defer c2.Close()
    282 
    283 		if _, err := c2.WriteTo([]byte("FILEPACKETCONN TEST"), addr); err != nil {
    284 			if perr := parseWriteError(err); perr != nil {
    285 				t.Error(perr)
    286 			}
    287 			t.Fatal(err)
    288 		}
    289 		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
    290 			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
    291 		}
    292 	}
    293 }
    294