github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/net/rawconn_test.go (about)

     1  // Copyright 2018 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  // +build !js
     6  
     7  package net
     8  
     9  import (
    10  	"github.com/x04/go/src/bytes"
    11  	"github.com/x04/go/src/runtime"
    12  	"github.com/x04/go/src/testing"
    13  	"github.com/x04/go/src/time"
    14  )
    15  
    16  func TestRawConnReadWrite(t *testing.T) {
    17  	switch runtime.GOOS {
    18  	case "plan9":
    19  		t.Skipf("not supported on %s", runtime.GOOS)
    20  	}
    21  
    22  	t.Run("TCP", func(t *testing.T) {
    23  		handler := func(ls *localServer, ln Listener) {
    24  			c, err := ln.Accept()
    25  			if err != nil {
    26  				t.Error(err)
    27  				return
    28  			}
    29  			defer c.Close()
    30  
    31  			cc, err := ln.(*TCPListener).SyscallConn()
    32  			if err != nil {
    33  				t.Fatal(err)
    34  			}
    35  			called := false
    36  			op := func(uintptr) bool {
    37  				called = true
    38  				return true
    39  			}
    40  			err = cc.Write(op)
    41  			if err == nil {
    42  				t.Error("Write should return an error")
    43  			}
    44  			if called {
    45  				t.Error("Write shouldn't call op")
    46  			}
    47  			called = false
    48  			err = cc.Read(op)
    49  			if err == nil {
    50  				t.Error("Read should return an error")
    51  			}
    52  			if called {
    53  				t.Error("Read shouldn't call op")
    54  			}
    55  
    56  			var b [32]byte
    57  			n, err := c.Read(b[:])
    58  			if err != nil {
    59  				t.Error(err)
    60  				return
    61  			}
    62  			if _, err := c.Write(b[:n]); err != nil {
    63  				t.Error(err)
    64  				return
    65  			}
    66  		}
    67  		ls, err := newLocalServer("tcp")
    68  		if err != nil {
    69  			t.Fatal(err)
    70  		}
    71  		defer ls.teardown()
    72  		if err := ls.buildup(handler); err != nil {
    73  			t.Fatal(err)
    74  		}
    75  
    76  		c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
    77  		if err != nil {
    78  			t.Fatal(err)
    79  		}
    80  		defer c.Close()
    81  
    82  		cc, err := c.(*TCPConn).SyscallConn()
    83  		if err != nil {
    84  			t.Fatal(err)
    85  		}
    86  		data := []byte("HELLO-R-U-THERE")
    87  		if err := writeRawConn(cc, data); err != nil {
    88  			t.Fatal(err)
    89  		}
    90  		var b [32]byte
    91  		n, err := readRawConn(cc, b[:])
    92  		if err != nil {
    93  			t.Fatal(err)
    94  		}
    95  		if bytes.Compare(b[:n], data) != 0 {
    96  			t.Fatalf("got %q; want %q", b[:n], data)
    97  		}
    98  	})
    99  	t.Run("Deadline", func(t *testing.T) {
   100  		switch runtime.GOOS {
   101  		case "windows":
   102  			t.Skipf("not supported on %s", runtime.GOOS)
   103  		}
   104  
   105  		ln, err := newLocalListener("tcp")
   106  		if err != nil {
   107  			t.Fatal(err)
   108  		}
   109  		defer ln.Close()
   110  
   111  		c, err := Dial(ln.Addr().Network(), ln.Addr().String())
   112  		if err != nil {
   113  			t.Fatal(err)
   114  		}
   115  		defer c.Close()
   116  
   117  		cc, err := c.(*TCPConn).SyscallConn()
   118  		if err != nil {
   119  			t.Fatal(err)
   120  		}
   121  		var b [1]byte
   122  
   123  		c.SetDeadline(noDeadline)
   124  		if err := c.SetDeadline(time.Now().Add(-1)); err != nil {
   125  			t.Fatal(err)
   126  		}
   127  		if err = writeRawConn(cc, b[:]); err == nil {
   128  			t.Fatal("Write should fail")
   129  		}
   130  		if perr := parseWriteError(err); perr != nil {
   131  			t.Error(perr)
   132  		}
   133  		if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
   134  			t.Errorf("got %v; want timeout", err)
   135  		}
   136  		if _, err = readRawConn(cc, b[:]); err == nil {
   137  			t.Fatal("Read should fail")
   138  		}
   139  		if perr := parseReadError(err); perr != nil {
   140  			t.Error(perr)
   141  		}
   142  		if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
   143  			t.Errorf("got %v; want timeout", err)
   144  		}
   145  
   146  		c.SetReadDeadline(noDeadline)
   147  		if err := c.SetReadDeadline(time.Now().Add(-1)); err != nil {
   148  			t.Fatal(err)
   149  		}
   150  		if _, err = readRawConn(cc, b[:]); err == nil {
   151  			t.Fatal("Read should fail")
   152  		}
   153  		if perr := parseReadError(err); perr != nil {
   154  			t.Error(perr)
   155  		}
   156  		if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
   157  			t.Errorf("got %v; want timeout", err)
   158  		}
   159  
   160  		c.SetWriteDeadline(noDeadline)
   161  		if err := c.SetWriteDeadline(time.Now().Add(-1)); err != nil {
   162  			t.Fatal(err)
   163  		}
   164  		if err = writeRawConn(cc, b[:]); err == nil {
   165  			t.Fatal("Write should fail")
   166  		}
   167  		if perr := parseWriteError(err); perr != nil {
   168  			t.Error(perr)
   169  		}
   170  		if nerr, ok := err.(Error); !ok || !nerr.Timeout() {
   171  			t.Errorf("got %v; want timeout", err)
   172  		}
   173  	})
   174  }
   175  
   176  func TestRawConnControl(t *testing.T) {
   177  	switch runtime.GOOS {
   178  	case "plan9":
   179  		t.Skipf("not supported on %s", runtime.GOOS)
   180  	}
   181  
   182  	t.Run("TCP", func(t *testing.T) {
   183  		ln, err := newLocalListener("tcp")
   184  		if err != nil {
   185  			t.Fatal(err)
   186  		}
   187  		defer ln.Close()
   188  
   189  		cc1, err := ln.(*TCPListener).SyscallConn()
   190  		if err != nil {
   191  			t.Fatal(err)
   192  		}
   193  		if err := controlRawConn(cc1, ln.Addr()); err != nil {
   194  			t.Fatal(err)
   195  		}
   196  
   197  		c, err := Dial(ln.Addr().Network(), ln.Addr().String())
   198  		if err != nil {
   199  			t.Fatal(err)
   200  		}
   201  		defer c.Close()
   202  
   203  		cc2, err := c.(*TCPConn).SyscallConn()
   204  		if err != nil {
   205  			t.Fatal(err)
   206  		}
   207  		if err := controlRawConn(cc2, c.LocalAddr()); err != nil {
   208  			t.Fatal(err)
   209  		}
   210  
   211  		ln.Close()
   212  		if err := controlRawConn(cc1, ln.Addr()); err == nil {
   213  			t.Fatal("Control after Close should fail")
   214  		}
   215  		c.Close()
   216  		if err := controlRawConn(cc2, c.LocalAddr()); err == nil {
   217  			t.Fatal("Control after Close should fail")
   218  		}
   219  	})
   220  }