diff options
Diffstat (limited to 'src/net/rawconn_test.go')
-rw-r--r-- | src/net/rawconn_test.go | 220 |
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") + } + }) +} |