Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/rawconn_test.go

Documentation: net

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

View as plain text