123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // 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")
- }
- })
- }
|