summaryrefslogtreecommitdiffstats
path: root/src/net/rawconn_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/rawconn_test.go')
-rw-r--r--src/net/rawconn_test.go220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/net/rawconn_test.go b/src/net/rawconn_test.go
new file mode 100644
index 0000000..a08ff89
--- /dev/null
+++ b/src/net/rawconn_test.go
@@ -0,0 +1,220 @@
+// Copyright 2018 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 !js
+
+package net
+
+import (
+ "bytes"
+ "runtime"
+ "testing"
+ "time"
+)
+
+func TestRawConnReadWrite(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ t.Run("TCP", func(t *testing.T) {
+ handler := func(ls *localServer, ln Listener) {
+ c, err := ln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer c.Close()
+
+ cc, err := ln.(*TCPListener).SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+ called := false
+ op := func(uintptr) bool {
+ called = true
+ return true
+ }
+ err = cc.Write(op)
+ if err == nil {
+ t.Error("Write should return an error")
+ }
+ if called {
+ t.Error("Write shouldn't call op")
+ }
+ called = false
+ err = cc.Read(op)
+ if err == nil {
+ t.Error("Read should return an error")
+ }
+ if called {
+ t.Error("Read shouldn't call op")
+ }
+
+ 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)
+ }
+ data := []byte("HELLO-R-U-THERE")
+ if err := writeRawConn(cc, data); err != nil {
+ t.Fatal(err)
+ }
+ var b [32]byte
+ n, err := readRawConn(cc, b[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if bytes.Compare(b[:n], data) != 0 {
+ t.Fatalf("got %q; want %q", b[:n], data)
+ }
+ })
+ t.Run("Deadline", func(t *testing.T) {
+ switch runtime.GOOS {
+ case "windows":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ c, err := Dial(ln.Addr().Network(), ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ cc, err := c.(*TCPConn).SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+ var b [1]byte
+
+ c.SetDeadline(noDeadline)
+ if err := c.SetDeadline(time.Now().Add(-1)); err != nil {
+ t.Fatal(err)
+ }
+ if err = writeRawConn(cc, b[:]); err == nil {
+ t.Fatal("Write should fail")
+ }
+ if perr := parseWriteError(err); perr != nil {
+ t.Error(perr)
+ }
+ if !isDeadlineExceeded(err) {
+ t.Errorf("got %v; want timeout", err)
+ }
+ if _, err = readRawConn(cc, b[:]); err == nil {
+ t.Fatal("Read should fail")
+ }
+ if perr := parseReadError(err); perr != nil {
+ t.Error(perr)
+ }
+ if !isDeadlineExceeded(err) {
+ t.Errorf("got %v; want timeout", err)
+ }
+
+ c.SetReadDeadline(noDeadline)
+ if err := c.SetReadDeadline(time.Now().Add(-1)); err != nil {
+ t.Fatal(err)
+ }
+ if _, err = readRawConn(cc, b[:]); err == nil {
+ t.Fatal("Read should fail")
+ }
+ if perr := parseReadError(err); perr != nil {
+ t.Error(perr)
+ }
+ if !isDeadlineExceeded(err) {
+ t.Errorf("got %v; want timeout", err)
+ }
+
+ c.SetWriteDeadline(noDeadline)
+ if err := c.SetWriteDeadline(time.Now().Add(-1)); err != nil {
+ t.Fatal(err)
+ }
+ if err = writeRawConn(cc, b[:]); err == nil {
+ t.Fatal("Write should fail")
+ }
+ if perr := parseWriteError(err); perr != nil {
+ t.Error(perr)
+ }
+ if !isDeadlineExceeded(err) {
+ t.Errorf("got %v; want timeout", err)
+ }
+ })
+}
+
+func TestRawConnControl(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9":
+ t.Skipf("not supported on %s", runtime.GOOS)
+ }
+
+ t.Run("TCP", func(t *testing.T) {
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ cc1, err := ln.(*TCPListener).SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := controlRawConn(cc1, ln.Addr()); err != nil {
+ t.Fatal(err)
+ }
+
+ c, err := Dial(ln.Addr().Network(), ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+
+ cc2, err := c.(*TCPConn).SyscallConn()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := controlRawConn(cc2, c.LocalAddr()); err != nil {
+ t.Fatal(err)
+ }
+
+ ln.Close()
+ if err := controlRawConn(cc1, ln.Addr()); err == nil {
+ t.Fatal("Control after Close should fail")
+ }
+ c.Close()
+ if err := controlRawConn(cc2, c.LocalAddr()); err == nil {
+ t.Fatal("Control after Close should fail")
+ }
+ })
+}