rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/net/server_test.go (about)

     1  // Copyright 2009 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  	"io"
     9  	"os"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  var streamConnServerTests = []struct {
    15  	snet  string // server side
    16  	saddr string
    17  	cnet  string // client side
    18  	caddr string
    19  	empty bool // test with empty data
    20  }{
    21  	{snet: "tcp", saddr: ":0", cnet: "tcp", caddr: "127.0.0.1"},
    22  	{snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp", caddr: "127.0.0.1"},
    23  	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp", caddr: "127.0.0.1"},
    24  	{snet: "tcp", saddr: "[::]:0", cnet: "tcp", caddr: "::1"},
    25  
    26  	{snet: "tcp", saddr: ":0", cnet: "tcp", caddr: "::1"},
    27  	{snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp", caddr: "::1"},
    28  	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp", caddr: "::1"},
    29  	{snet: "tcp", saddr: "[::]:0", cnet: "tcp", caddr: "127.0.0.1"},
    30  
    31  	{snet: "tcp", saddr: ":0", cnet: "tcp4", caddr: "127.0.0.1"},
    32  	{snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp4", caddr: "127.0.0.1"},
    33  	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp4", caddr: "127.0.0.1"},
    34  	{snet: "tcp", saddr: "[::]:0", cnet: "tcp6", caddr: "::1"},
    35  
    36  	{snet: "tcp", saddr: ":0", cnet: "tcp6", caddr: "::1"},
    37  	{snet: "tcp", saddr: "0.0.0.0:0", cnet: "tcp6", caddr: "::1"},
    38  	{snet: "tcp", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp6", caddr: "::1"},
    39  	{snet: "tcp", saddr: "[::]:0", cnet: "tcp4", caddr: "127.0.0.1"},
    40  
    41  	{snet: "tcp", saddr: "127.0.0.1:0", cnet: "tcp", caddr: "127.0.0.1"},
    42  	{snet: "tcp", saddr: "[::ffff:127.0.0.1]:0", cnet: "tcp", caddr: "127.0.0.1"},
    43  	{snet: "tcp", saddr: "[::1]:0", cnet: "tcp", caddr: "::1"},
    44  
    45  	{snet: "tcp4", saddr: ":0", cnet: "tcp4", caddr: "127.0.0.1"},
    46  	{snet: "tcp4", saddr: "0.0.0.0:0", cnet: "tcp4", caddr: "127.0.0.1"},
    47  	{snet: "tcp4", saddr: "[::ffff:0.0.0.0]:0", cnet: "tcp4", caddr: "127.0.0.1"},
    48  
    49  	{snet: "tcp4", saddr: "127.0.0.1:0", cnet: "tcp4", caddr: "127.0.0.1"},
    50  
    51  	{snet: "tcp6", saddr: ":0", cnet: "tcp6", caddr: "::1"},
    52  	{snet: "tcp6", saddr: "[::]:0", cnet: "tcp6", caddr: "::1"},
    53  
    54  	{snet: "tcp6", saddr: "[::1]:0", cnet: "tcp6", caddr: "::1"},
    55  
    56  	{snet: "unix", saddr: testUnixAddr(), cnet: "unix", caddr: testUnixAddr()},
    57  	{snet: "unix", saddr: "@gotest2/net", cnet: "unix", caddr: "@gotest2/net.local"},
    58  }
    59  
    60  func TestStreamConnServer(t *testing.T) {
    61  	for _, tt := range streamConnServerTests {
    62  		if !testableListenArgs(tt.snet, tt.saddr, tt.caddr) {
    63  			t.Logf("skipping %s test", tt.snet+":"+tt.saddr+"->"+tt.caddr)
    64  			continue
    65  		}
    66  
    67  		listening := make(chan string)
    68  		done := make(chan int)
    69  		switch tt.snet {
    70  		case "unix":
    71  			os.Remove(tt.saddr)
    72  			os.Remove(tt.caddr)
    73  		}
    74  
    75  		go runStreamConnServer(t, tt.snet, tt.saddr, listening, done)
    76  		taddr := <-listening // wait for server to start
    77  
    78  		switch tt.cnet {
    79  		case "tcp", "tcp4", "tcp6":
    80  			_, port, err := SplitHostPort(taddr)
    81  			if err != nil {
    82  				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
    83  			}
    84  			taddr = JoinHostPort(tt.caddr, port)
    85  		}
    86  
    87  		runStreamConnClient(t, tt.cnet, taddr, tt.empty)
    88  		<-done // make sure server stopped
    89  
    90  		switch tt.snet {
    91  		case "unix":
    92  			os.Remove(tt.saddr)
    93  			os.Remove(tt.caddr)
    94  		}
    95  	}
    96  }
    97  
    98  var seqpacketConnServerTests = []struct {
    99  	net   string
   100  	saddr string // server address
   101  	caddr string // client address
   102  	empty bool   // test with empty data
   103  }{
   104  	{net: "unixpacket", saddr: testUnixAddr(), caddr: testUnixAddr()},
   105  	{net: "unixpacket", saddr: "@gotest4/net", caddr: "@gotest4/net.local"},
   106  }
   107  
   108  func TestSeqpacketConnServer(t *testing.T) {
   109  	for _, tt := range seqpacketConnServerTests {
   110  		if !testableListenArgs(tt.net, tt.saddr, tt.caddr) {
   111  			t.Logf("skipping %s test", tt.net+":"+tt.saddr+"->"+tt.caddr)
   112  			continue
   113  		}
   114  		listening := make(chan string)
   115  		done := make(chan int)
   116  		switch tt.net {
   117  		case "unixpacket":
   118  			os.Remove(tt.saddr)
   119  			os.Remove(tt.caddr)
   120  		}
   121  
   122  		go runStreamConnServer(t, tt.net, tt.saddr, listening, done)
   123  		taddr := <-listening // wait for server to start
   124  
   125  		runStreamConnClient(t, tt.net, taddr, tt.empty)
   126  		<-done // make sure server stopped
   127  
   128  		switch tt.net {
   129  		case "unixpacket":
   130  			os.Remove(tt.saddr)
   131  			os.Remove(tt.caddr)
   132  		}
   133  	}
   134  }
   135  
   136  func runStreamConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
   137  	defer close(done)
   138  	l, err := Listen(net, laddr)
   139  	if err != nil {
   140  		t.Errorf("Listen(%q, %q) failed: %v", net, laddr, err)
   141  		listening <- "<nil>"
   142  		return
   143  	}
   144  	defer l.Close()
   145  	listening <- l.Addr().String()
   146  
   147  	echo := func(rw io.ReadWriter, done chan<- int) {
   148  		buf := make([]byte, 1024)
   149  		for {
   150  			n, err := rw.Read(buf[0:])
   151  			if err != nil || n == 0 || string(buf[:n]) == "END" {
   152  				break
   153  			}
   154  			rw.Write(buf[0:n])
   155  		}
   156  		close(done)
   157  	}
   158  
   159  run:
   160  	for {
   161  		c, err := l.Accept()
   162  		if err != nil {
   163  			t.Logf("Accept failed: %v", err)
   164  			continue run
   165  		}
   166  		echodone := make(chan int)
   167  		go echo(c, echodone)
   168  		<-echodone // make sure echo stopped
   169  		c.Close()
   170  		break run
   171  	}
   172  }
   173  
   174  func runStreamConnClient(t *testing.T, net, taddr string, isEmpty bool) {
   175  	c, err := Dial(net, taddr)
   176  	if err != nil {
   177  		t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
   178  	}
   179  	defer c.Close()
   180  	c.SetReadDeadline(time.Now().Add(1 * time.Second))
   181  
   182  	var wb []byte
   183  	if !isEmpty {
   184  		wb = []byte("StreamConnClient by Dial\n")
   185  	}
   186  	if n, err := c.Write(wb); err != nil || n != len(wb) {
   187  		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
   188  	}
   189  
   190  	rb := make([]byte, 1024)
   191  	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
   192  		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
   193  	}
   194  
   195  	// Send explicit ending for unixpacket.
   196  	// Older Linux kernels do not stop reads on close.
   197  	switch net {
   198  	case "unixpacket":
   199  		c.Write([]byte("END"))
   200  	}
   201  }
   202  
   203  var datagramPacketConnServerTests = []struct {
   204  	snet  string // server side
   205  	saddr string
   206  	cnet  string // client side
   207  	caddr string
   208  	dial  bool // test with Dial or DialUnix
   209  	empty bool // test with empty data
   210  }{
   211  	{snet: "udp", saddr: ":0", cnet: "udp", caddr: "127.0.0.1"},
   212  	{snet: "udp", saddr: "0.0.0.0:0", cnet: "udp", caddr: "127.0.0.1"},
   213  	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp", caddr: "127.0.0.1"},
   214  	{snet: "udp", saddr: "[::]:0", cnet: "udp", caddr: "::1"},
   215  
   216  	{snet: "udp", saddr: ":0", cnet: "udp", caddr: "::1"},
   217  	{snet: "udp", saddr: "0.0.0.0:0", cnet: "udp", caddr: "::1"},
   218  	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp", caddr: "::1"},
   219  	{snet: "udp", saddr: "[::]:0", cnet: "udp", caddr: "127.0.0.1"},
   220  
   221  	{snet: "udp", saddr: ":0", cnet: "udp4", caddr: "127.0.0.1"},
   222  	{snet: "udp", saddr: "0.0.0.0:0", cnet: "udp4", caddr: "127.0.0.1"},
   223  	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp4", caddr: "127.0.0.1"},
   224  	{snet: "udp", saddr: "[::]:0", cnet: "udp6", caddr: "::1"},
   225  
   226  	{snet: "udp", saddr: ":0", cnet: "udp6", caddr: "::1"},
   227  	{snet: "udp", saddr: "0.0.0.0:0", cnet: "udp6", caddr: "::1"},
   228  	{snet: "udp", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp6", caddr: "::1"},
   229  	{snet: "udp", saddr: "[::]:0", cnet: "udp4", caddr: "127.0.0.1"},
   230  
   231  	{snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1"},
   232  	{snet: "udp", saddr: "[::ffff:127.0.0.1]:0", cnet: "udp", caddr: "127.0.0.1"},
   233  	{snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1"},
   234  
   235  	{snet: "udp4", saddr: ":0", cnet: "udp4", caddr: "127.0.0.1"},
   236  	{snet: "udp4", saddr: "0.0.0.0:0", cnet: "udp4", caddr: "127.0.0.1"},
   237  	{snet: "udp4", saddr: "[::ffff:0.0.0.0]:0", cnet: "udp4", caddr: "127.0.0.1"},
   238  
   239  	{snet: "udp4", saddr: "127.0.0.1:0", cnet: "udp4", caddr: "127.0.0.1"},
   240  
   241  	{snet: "udp6", saddr: ":0", cnet: "udp6", caddr: "::1"},
   242  	{snet: "udp6", saddr: "[::]:0", cnet: "udp6", caddr: "::1"},
   243  
   244  	{snet: "udp6", saddr: "[::1]:0", cnet: "udp6", caddr: "::1"},
   245  
   246  	{snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", dial: true},
   247  	{snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", empty: true},
   248  	{snet: "udp", saddr: "127.0.0.1:0", cnet: "udp", caddr: "127.0.0.1", dial: true, empty: true},
   249  
   250  	{snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", dial: true},
   251  	{snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", empty: true},
   252  	{snet: "udp", saddr: "[::1]:0", cnet: "udp", caddr: "::1", dial: true, empty: true},
   253  
   254  	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr()},
   255  	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true},
   256  	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), empty: true},
   257  	{snet: "unixgram", saddr: testUnixAddr(), cnet: "unixgram", caddr: testUnixAddr(), dial: true, empty: true},
   258  
   259  	{snet: "unixgram", saddr: "@gotest6/net", cnet: "unixgram", caddr: "@gotest6/net.local"},
   260  }
   261  
   262  func TestDatagramPacketConnServer(t *testing.T) {
   263  	if !*testDatagram {
   264  		return
   265  	}
   266  
   267  	for _, tt := range datagramPacketConnServerTests {
   268  		if !testableListenArgs(tt.snet, tt.saddr, tt.caddr) {
   269  			t.Logf("skipping %s test", tt.snet+":"+tt.saddr+"->"+tt.caddr)
   270  			continue
   271  		}
   272  
   273  		listening := make(chan string)
   274  		done := make(chan int)
   275  		switch tt.snet {
   276  		case "unixgram":
   277  			os.Remove(tt.saddr)
   278  			os.Remove(tt.caddr)
   279  		}
   280  
   281  		go runDatagramPacketConnServer(t, tt.snet, tt.saddr, listening, done)
   282  		taddr := <-listening // wait for server to start
   283  
   284  		switch tt.cnet {
   285  		case "udp", "udp4", "udp6":
   286  			_, port, err := SplitHostPort(taddr)
   287  			if err != nil {
   288  				t.Fatalf("SplitHostPort(%q) failed: %v", taddr, err)
   289  			}
   290  			taddr = JoinHostPort(tt.caddr, port)
   291  			tt.caddr = JoinHostPort(tt.caddr, "0")
   292  		}
   293  		if tt.dial {
   294  			runDatagramConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
   295  		} else {
   296  			runDatagramPacketConnClient(t, tt.cnet, tt.caddr, taddr, tt.empty)
   297  		}
   298  		<-done // tell server to stop
   299  		<-done // make sure server stopped
   300  
   301  		switch tt.snet {
   302  		case "unixgram":
   303  			os.Remove(tt.saddr)
   304  			os.Remove(tt.caddr)
   305  		}
   306  	}
   307  }
   308  
   309  func runDatagramPacketConnServer(t *testing.T, net, laddr string, listening chan<- string, done chan<- int) {
   310  	c, err := ListenPacket(net, laddr)
   311  	if err != nil {
   312  		t.Errorf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
   313  		listening <- "<nil>"
   314  		done <- 1
   315  		return
   316  	}
   317  	defer c.Close()
   318  	listening <- c.LocalAddr().String()
   319  
   320  	buf := make([]byte, 1024)
   321  run:
   322  	for {
   323  		c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
   324  		n, ra, err := c.ReadFrom(buf[0:])
   325  		if nerr, ok := err.(Error); ok && nerr.Timeout() {
   326  			select {
   327  			case done <- 1:
   328  				break run
   329  			default:
   330  				continue run
   331  			}
   332  		}
   333  		if err != nil {
   334  			break run
   335  		}
   336  		if _, err = c.WriteTo(buf[0:n], ra); err != nil {
   337  			t.Errorf("WriteTo(%v) failed: %v", ra, err)
   338  			break run
   339  		}
   340  	}
   341  	done <- 1
   342  }
   343  
   344  func runDatagramConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
   345  	var c Conn
   346  	var err error
   347  	switch net {
   348  	case "udp", "udp4", "udp6":
   349  		c, err = Dial(net, taddr)
   350  		if err != nil {
   351  			t.Fatalf("Dial(%q, %q) failed: %v", net, taddr, err)
   352  		}
   353  	case "unixgram":
   354  		c, err = DialUnix(net, &UnixAddr{Name: laddr, Net: net}, &UnixAddr{Name: taddr, Net: net})
   355  		if err != nil {
   356  			t.Fatalf("DialUnix(%q, {%q, %q}) failed: %v", net, laddr, taddr, err)
   357  		}
   358  	}
   359  	defer c.Close()
   360  	c.SetReadDeadline(time.Now().Add(1 * time.Second))
   361  
   362  	var wb []byte
   363  	if !isEmpty {
   364  		wb = []byte("DatagramConnClient by Dial\n")
   365  	}
   366  	if n, err := c.Write(wb[0:]); err != nil || n != len(wb) {
   367  		t.Fatalf("Write failed: %v, %v; want %v, <nil>", n, err, len(wb))
   368  	}
   369  
   370  	rb := make([]byte, 1024)
   371  	if n, err := c.Read(rb[0:]); err != nil || n != len(wb) {
   372  		t.Fatalf("Read failed: %v, %v; want %v, <nil>", n, err, len(wb))
   373  	}
   374  }
   375  
   376  func runDatagramPacketConnClient(t *testing.T, net, laddr, taddr string, isEmpty bool) {
   377  	var ra Addr
   378  	var err error
   379  	switch net {
   380  	case "udp", "udp4", "udp6":
   381  		ra, err = ResolveUDPAddr(net, taddr)
   382  		if err != nil {
   383  			t.Fatalf("ResolveUDPAddr(%q, %q) failed: %v", net, taddr, err)
   384  		}
   385  	case "unixgram":
   386  		ra, err = ResolveUnixAddr(net, taddr)
   387  		if err != nil {
   388  			t.Fatalf("ResolveUxixAddr(%q, %q) failed: %v", net, taddr, err)
   389  		}
   390  	}
   391  	c, err := ListenPacket(net, laddr)
   392  	if err != nil {
   393  		t.Fatalf("ListenPacket(%q, %q) failed: %v", net, laddr, err)
   394  	}
   395  	defer c.Close()
   396  	c.SetReadDeadline(time.Now().Add(1 * time.Second))
   397  
   398  	var wb []byte
   399  	if !isEmpty {
   400  		wb = []byte("DatagramPacketConnClient by ListenPacket\n")
   401  	}
   402  	if n, err := c.WriteTo(wb[0:], ra); err != nil || n != len(wb) {
   403  		t.Fatalf("WriteTo(%v) failed: %v, %v; want %v, <nil>", ra, n, err, len(wb))
   404  	}
   405  
   406  	rb := make([]byte, 1024)
   407  	if n, _, err := c.ReadFrom(rb[0:]); err != nil || n != len(wb) {
   408  		t.Fatalf("ReadFrom failed: %v, %v; want %v, <nil>", n, err, len(wb))
   409  	}
   410  }