github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/net/rawconn_unix_test.go (about)

     1  // Copyright 2017 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 darwin dragonfly freebsd linux netbsd openbsd solaris
     6  
     7  package net
     8  
     9  import (
    10  	"bytes"
    11  	"syscall"
    12  	"testing"
    13  )
    14  
    15  func TestRawConn(t *testing.T) {
    16  	handler := func(ls *localServer, ln Listener) {
    17  		c, err := ln.Accept()
    18  		if err != nil {
    19  			t.Error(err)
    20  			return
    21  		}
    22  		defer c.Close()
    23  		var b [32]byte
    24  		n, err := c.Read(b[:])
    25  		if err != nil {
    26  			t.Error(err)
    27  			return
    28  		}
    29  		if _, err := c.Write(b[:n]); err != nil {
    30  			t.Error(err)
    31  			return
    32  		}
    33  	}
    34  	ls, err := newLocalServer("tcp")
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  	defer ls.teardown()
    39  	if err := ls.buildup(handler); err != nil {
    40  		t.Fatal(err)
    41  	}
    42  
    43  	c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	defer c.Close()
    48  	cc, err := c.(*TCPConn).SyscallConn()
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	var operr error
    54  	data := []byte("HELLO-R-U-THERE")
    55  	err = cc.Write(func(s uintptr) bool {
    56  		_, operr = syscall.Write(int(s), data)
    57  		if operr == syscall.EAGAIN {
    58  			return false
    59  		}
    60  		return true
    61  	})
    62  	if err != nil || operr != nil {
    63  		t.Fatal(err, operr)
    64  	}
    65  
    66  	var nr int
    67  	var b [32]byte
    68  	err = cc.Read(func(s uintptr) bool {
    69  		nr, operr = syscall.Read(int(s), b[:])
    70  		if operr == syscall.EAGAIN {
    71  			return false
    72  		}
    73  		return true
    74  	})
    75  	if err != nil || operr != nil {
    76  		t.Fatal(err, operr)
    77  	}
    78  	if bytes.Compare(b[:nr], data) != 0 {
    79  		t.Fatalf("got %#v; want %#v", b[:nr], data)
    80  	}
    81  
    82  	fn := func(s uintptr) {
    83  		operr = syscall.SetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
    84  	}
    85  	err = cc.Control(fn)
    86  	if err != nil || operr != nil {
    87  		t.Fatal(err, operr)
    88  	}
    89  	c.Close()
    90  	err = cc.Control(fn)
    91  	if err == nil {
    92  		t.Fatal("should fail")
    93  	}
    94  }