| // Copyright 2017 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // +build darwin dragonfly freebsd linux netbsd openbsd solaris |
| |
| package net |
| |
| import ( |
| "bytes" |
| "syscall" |
| "testing" |
| ) |
| |
| func TestRawConn(t *testing.T) { |
| handler := func(ls *localServer, ln Listener) { |
| c, err := ln.Accept() |
| if err != nil { |
| t.Error(err) |
| return |
| } |
| defer c.Close() |
| var b [32]byte |
| n, err := c.Read(b[:]) |
| if err != nil { |
| t.Error(err) |
| return |
| } |
| if _, err := c.Write(b[:n]); err != nil { |
| t.Error(err) |
| return |
| } |
| } |
| ls, err := newLocalServer("tcp") |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer ls.teardown() |
| if err := ls.buildup(handler); err != nil { |
| t.Fatal(err) |
| } |
| |
| c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer c.Close() |
| cc, err := c.(*TCPConn).SyscallConn() |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| var operr error |
| data := []byte("HELLO-R-U-THERE") |
| err = cc.Write(func(s uintptr) bool { |
| _, operr = syscall.Write(int(s), data) |
| if operr == syscall.EAGAIN { |
| return false |
| } |
| return true |
| }) |
| if err != nil || operr != nil { |
| t.Fatal(err, operr) |
| } |
| |
| var nr int |
| var b [32]byte |
| err = cc.Read(func(s uintptr) bool { |
| nr, operr = syscall.Read(int(s), b[:]) |
| if operr == syscall.EAGAIN { |
| return false |
| } |
| return true |
| }) |
| if err != nil || operr != nil { |
| t.Fatal(err, operr) |
| } |
| if bytes.Compare(b[:nr], data) != 0 { |
| t.Fatalf("got %#v; want %#v", b[:nr], data) |
| } |
| |
| fn := func(s uintptr) { |
| operr = syscall.SetsockoptInt(int(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) |
| } |
| err = cc.Control(fn) |
| if err != nil || operr != nil { |
| t.Fatal(err, operr) |
| } |
| c.Close() |
| err = cc.Control(fn) |
| if err == nil { |
| t.Fatal("should fail") |
| } |
| } |