mirror of
https://github.com/golang/go
synced 2024-11-26 12:37:57 -07:00
b55cbbb9e7
Passing in an explicit testing.TB gives two benefits: 1. It allows the helper to fail the test itself, instead of returning an error to the caller. A non-nil error invariably fails the calling test, and none of these callers bother to add detail to the error when logging it anyway so returning the error just added noise to the test bodies. 2. It allows the helper to use t.Cleanup to perform any needed cleanup tasks, which will be used in CL 370695 to clean up temp directories used as namespaces for unix socket paths. For #34611 Change-Id: I805e701687c12de2caca955649369294229c10b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/370696 Trust: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
212 lines
4.3 KiB
Go
212 lines
4.3 KiB
Go
// 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.
|
|
|
|
//go: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 := newLocalServer(t, "tcp")
|
|
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 := newLocalListener(t, "tcp")
|
|
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 := newLocalListener(t, "tcp")
|
|
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")
|
|
}
|
|
})
|
|
}
|