vendor: add golang.org/x/net/nettest

Adds golang.org/x/net/nettest at revision 9773060888fba93b172cedcd70127db1ab739bd1.
This allows us to test net.Conn implementations for compliance.

Updates #18170

Change-Id: I8d3d3430b0a1abc83513180a677c39ee39303f5a
Reviewed-on: https://go-review.googlesource.com/37404
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/vendor/golang_org/x/net/nettest/conntest.go b/src/vendor/golang_org/x/net/nettest/conntest.go
new file mode 100644
index 0000000..c246bbe
--- /dev/null
+++ b/src/vendor/golang_org/x/net/nettest/conntest.go
@@ -0,0 +1,451 @@
+// Copyright 2016 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.
+
+// Package nettest provides utilities for network testing.
+package nettest
+
+import (
+	"bytes"
+	"encoding/binary"
+	"io"
+	"io/ioutil"
+	"math/rand"
+	"net"
+	"sync"
+	"testing"
+	"time"
+)
+
+var (
+	aLongTimeAgo = time.Unix(233431200, 0)
+	neverTimeout = time.Time{}
+)
+
+// MakePipe creates a connection between two endpoints and returns the pair
+// as c1 and c2, such that anything written to c1 is read by c2 and vice-versa.
+// The stop function closes all resources, including c1, c2, and the underlying
+// net.Listener (if there is one), and should not be nil.
+type MakePipe func() (c1, c2 net.Conn, stop func(), err error)
+
+// TestConn tests that a net.Conn implementation properly satisfies the interface.
+// The tests should not produce any false positives, but may experience
+// false negatives. Thus, some issues may only be detected when the test is
+// run multiple times. For maximal effectiveness, run the tests under the
+// race detector.
+func TestConn(t *testing.T, mp MakePipe) {
+	testConn(t, mp)
+}
+
+type connTester func(t *testing.T, c1, c2 net.Conn)
+
+func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) {
+	c1, c2, stop, err := mp()
+	if err != nil {
+		t.Fatalf("unable to make pipe: %v", err)
+	}
+	var once sync.Once
+	defer once.Do(func() { stop() })
+	timer := time.AfterFunc(time.Minute, func() {
+		once.Do(func() {
+			t.Error("test timed out; terminating pipe")
+			stop()
+		})
+	})
+	defer timer.Stop()
+	f(t, c1, c2)
+}
+
+// testBasicIO tests that the data sent on c1 is properly received on c2.
+func testBasicIO(t *testing.T, c1, c2 net.Conn) {
+	want := make([]byte, 1<<20)
+	rand.New(rand.NewSource(0)).Read(want)
+
+	dataCh := make(chan []byte)
+	go func() {
+		rd := bytes.NewReader(want)
+		if err := chunkedCopy(c1, rd); err != nil {
+			t.Errorf("unexpected c1.Write error: %v", err)
+		}
+		if err := c1.Close(); err != nil {
+			t.Errorf("unexpected c1.Close error: %v", err)
+		}
+	}()
+
+	go func() {
+		wr := new(bytes.Buffer)
+		if err := chunkedCopy(wr, c2); err != nil {
+			t.Errorf("unexpected c2.Read error: %v", err)
+		}
+		if err := c2.Close(); err != nil {
+			t.Errorf("unexpected c2.Close error: %v", err)
+		}
+		dataCh <- wr.Bytes()
+	}()
+
+	if got := <-dataCh; !bytes.Equal(got, want) {
+		t.Errorf("transmitted data differs")
+	}
+}
+
+// testPingPong tests that the two endpoints can synchronously send data to
+// each other in a typical request-response pattern.
+func testPingPong(t *testing.T, c1, c2 net.Conn) {
+	var wg sync.WaitGroup
+	defer wg.Wait()
+
+	pingPonger := func(c net.Conn) {
+		defer wg.Done()
+		buf := make([]byte, 8)
+		var prev uint64
+		for {
+			if _, err := io.ReadFull(c, buf); err != nil {
+				if err == io.EOF {
+					break
+				}
+				t.Errorf("unexpected Read error: %v", err)
+			}
+
+			v := binary.LittleEndian.Uint64(buf)
+			binary.LittleEndian.PutUint64(buf, v+1)
+			if prev != 0 && prev+2 != v {
+				t.Errorf("mismatching value: got %d, want %d", v, prev+2)
+			}
+			prev = v
+			if v == 1000 {
+				break
+			}
+
+			if _, err := c.Write(buf); err != nil {
+				t.Errorf("unexpected Write error: %v", err)
+				break
+			}
+		}
+		if err := c.Close(); err != nil {
+			t.Errorf("unexpected Close error: %v", err)
+		}
+	}
+
+	wg.Add(2)
+	go pingPonger(c1)
+	go pingPonger(c2)
+
+	// Start off the chain reaction.
+	if _, err := c1.Write(make([]byte, 8)); err != nil {
+		t.Errorf("unexpected c1.Write error: %v", err)
+	}
+}
+
+// testRacyRead tests that it is safe to mutate the input Read buffer
+// immediately after cancelation has occurred.
+func testRacyRead(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(c2, rand.New(rand.NewSource(0)))
+
+	var wg sync.WaitGroup
+	defer wg.Wait()
+
+	c1.SetReadDeadline(time.Now().Add(time.Millisecond))
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+
+			b1 := make([]byte, 1024)
+			b2 := make([]byte, 1024)
+			for j := 0; j < 100; j++ {
+				_, err := c1.Read(b1)
+				copy(b1, b2) // Mutate b1 to trigger potential race
+				if err != nil {
+					checkForTimeoutError(t, err)
+					c1.SetReadDeadline(time.Now().Add(time.Millisecond))
+				}
+			}
+		}()
+	}
+}
+
+// testRacyWrite tests that it is safe to mutate the input Write buffer
+// immediately after cancelation has occurred.
+func testRacyWrite(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(ioutil.Discard, c2)
+
+	var wg sync.WaitGroup
+	defer wg.Wait()
+
+	c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+
+			b1 := make([]byte, 1024)
+			b2 := make([]byte, 1024)
+			for j := 0; j < 100; j++ {
+				_, err := c1.Write(b1)
+				copy(b1, b2) // Mutate b1 to trigger potential race
+				if err != nil {
+					checkForTimeoutError(t, err)
+					c1.SetWriteDeadline(time.Now().Add(time.Millisecond))
+				}
+			}
+		}()
+	}
+}
+
+// testReadTimeout tests that Read timeouts do not affect Write.
+func testReadTimeout(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(ioutil.Discard, c2)
+
+	c1.SetReadDeadline(aLongTimeAgo)
+	_, err := c1.Read(make([]byte, 1024))
+	checkForTimeoutError(t, err)
+	if _, err := c1.Write(make([]byte, 1024)); err != nil {
+		t.Errorf("unexpected Write error: %v", err)
+	}
+}
+
+// testWriteTimeout tests that Write timeouts do not affect Read.
+func testWriteTimeout(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(c2, rand.New(rand.NewSource(0)))
+
+	c1.SetWriteDeadline(aLongTimeAgo)
+	_, err := c1.Write(make([]byte, 1024))
+	checkForTimeoutError(t, err)
+	if _, err := c1.Read(make([]byte, 1024)); err != nil {
+		t.Errorf("unexpected Read error: %v", err)
+	}
+}
+
+// testPastTimeout tests that a deadline set in the past immediately times out
+// Read and Write requests.
+func testPastTimeout(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(c2, c2)
+
+	testRoundtrip(t, c1)
+
+	c1.SetDeadline(aLongTimeAgo)
+	n, err := c1.Write(make([]byte, 1024))
+	if n != 0 {
+		t.Errorf("unexpected Write count: got %d, want 0", n)
+	}
+	checkForTimeoutError(t, err)
+	n, err = c1.Read(make([]byte, 1024))
+	if n != 0 {
+		t.Errorf("unexpected Read count: got %d, want 0", n)
+	}
+	checkForTimeoutError(t, err)
+
+	testRoundtrip(t, c1)
+}
+
+// testPresentTimeout tests that a deadline set while there are pending
+// Read and Write operations immediately times out those operations.
+func testPresentTimeout(t *testing.T, c1, c2 net.Conn) {
+	var wg sync.WaitGroup
+	defer wg.Wait()
+	wg.Add(3)
+
+	deadlineSet := make(chan bool, 1)
+	go func() {
+		defer wg.Done()
+		time.Sleep(100 * time.Millisecond)
+		deadlineSet <- true
+		c1.SetReadDeadline(aLongTimeAgo)
+		c1.SetWriteDeadline(aLongTimeAgo)
+	}()
+	go func() {
+		defer wg.Done()
+		n, err := c1.Read(make([]byte, 1024))
+		if n != 0 {
+			t.Errorf("unexpected Read count: got %d, want 0", n)
+		}
+		checkForTimeoutError(t, err)
+		if len(deadlineSet) == 0 {
+			t.Error("Read timed out before deadline is set")
+		}
+	}()
+	go func() {
+		defer wg.Done()
+		var err error
+		for err == nil {
+			_, err = c1.Write(make([]byte, 1024))
+		}
+		checkForTimeoutError(t, err)
+		if len(deadlineSet) == 0 {
+			t.Error("Write timed out before deadline is set")
+		}
+	}()
+}
+
+// testFutureTimeout tests that a future deadline will eventually time out
+// Read and Write operations.
+func testFutureTimeout(t *testing.T, c1, c2 net.Conn) {
+	var wg sync.WaitGroup
+	wg.Add(2)
+
+	c1.SetDeadline(time.Now().Add(100 * time.Millisecond))
+	go func() {
+		defer wg.Done()
+		_, err := c1.Read(make([]byte, 1024))
+		checkForTimeoutError(t, err)
+	}()
+	go func() {
+		defer wg.Done()
+		var err error
+		for err == nil {
+			_, err = c1.Write(make([]byte, 1024))
+		}
+		checkForTimeoutError(t, err)
+	}()
+	wg.Wait()
+
+	go chunkedCopy(c2, c2)
+	resyncConn(t, c1)
+	testRoundtrip(t, c1)
+}
+
+// testCloseTimeout tests that calling Close immediately times out pending
+// Read and Write operations.
+func testCloseTimeout(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(c2, c2)
+
+	var wg sync.WaitGroup
+	defer wg.Wait()
+	wg.Add(3)
+
+	// Test for cancelation upon connection closure.
+	c1.SetDeadline(neverTimeout)
+	go func() {
+		defer wg.Done()
+		time.Sleep(100 * time.Millisecond)
+		c1.Close()
+	}()
+	go func() {
+		defer wg.Done()
+		var err error
+		buf := make([]byte, 1024)
+		for err == nil {
+			_, err = c1.Read(buf)
+		}
+	}()
+	go func() {
+		defer wg.Done()
+		var err error
+		buf := make([]byte, 1024)
+		for err == nil {
+			_, err = c1.Write(buf)
+		}
+	}()
+}
+
+// testConcurrentMethods tests that the methods of net.Conn can safely
+// be called concurrently.
+func testConcurrentMethods(t *testing.T, c1, c2 net.Conn) {
+	go chunkedCopy(c2, c2)
+
+	// The results of the calls may be nonsensical, but this should
+	// not trigger a race detector warning.
+	var wg sync.WaitGroup
+	for i := 0; i < 100; i++ {
+		wg.Add(7)
+		go func() {
+			defer wg.Done()
+			c1.Read(make([]byte, 1024))
+		}()
+		go func() {
+			defer wg.Done()
+			c1.Write(make([]byte, 1024))
+		}()
+		go func() {
+			defer wg.Done()
+			c1.SetDeadline(time.Now().Add(10 * time.Millisecond))
+		}()
+		go func() {
+			defer wg.Done()
+			c1.SetReadDeadline(aLongTimeAgo)
+		}()
+		go func() {
+			defer wg.Done()
+			c1.SetWriteDeadline(aLongTimeAgo)
+		}()
+		go func() {
+			defer wg.Done()
+			c1.LocalAddr()
+		}()
+		go func() {
+			defer wg.Done()
+			c1.RemoteAddr()
+		}()
+	}
+	wg.Wait() // At worst, the deadline is set 10ms into the future
+
+	resyncConn(t, c1)
+	testRoundtrip(t, c1)
+}
+
+// checkForTimeoutError checks that the error satisfies the Error interface
+// and that Timeout returns true.
+func checkForTimeoutError(t *testing.T, err error) {
+	if nerr, ok := err.(net.Error); ok {
+		if !nerr.Timeout() {
+			t.Errorf("err.Timeout() = false, want true")
+		}
+	} else {
+		t.Errorf("got %T, want net.Error", err)
+	}
+}
+
+// testRoundtrip writes something into c and reads it back.
+// It assumes that everything written into c is echoed back to itself.
+func testRoundtrip(t *testing.T, c net.Conn) {
+	if err := c.SetDeadline(neverTimeout); err != nil {
+		t.Errorf("roundtrip SetDeadline error: %v", err)
+	}
+
+	const s = "Hello, world!"
+	buf := []byte(s)
+	if _, err := c.Write(buf); err != nil {
+		t.Errorf("roundtrip Write error: %v", err)
+	}
+	if _, err := io.ReadFull(c, buf); err != nil {
+		t.Errorf("roundtrip Read error: %v", err)
+	}
+	if string(buf) != s {
+		t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s)
+	}
+}
+
+// resyncConn resynchronizes the connection into a sane state.
+// It assumes that everything written into c is echoed back to itself.
+// It assumes that 0xff is not currently on the wire or in the read buffer.
+func resyncConn(t *testing.T, c net.Conn) {
+	c.SetDeadline(neverTimeout)
+	errCh := make(chan error)
+	go func() {
+		_, err := c.Write([]byte{0xff})
+		errCh <- err
+	}()
+	buf := make([]byte, 1024)
+	for {
+		n, err := c.Read(buf)
+		if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 {
+			break
+		}
+		if err != nil {
+			t.Errorf("unexpected Read error: %v", err)
+		}
+	}
+	if err := <-errCh; err != nil {
+		t.Errorf("unexpected Write error: %v", err)
+	}
+}
+
+// chunkedCopy copies from r to w in fixed-width chunks to avoid
+// causing a Write that exceeds the maximum packet size for packet-based
+// connections like "unixpacket".
+// We assume that the maximum packet size is at least 1024.
+func chunkedCopy(w io.Writer, r io.Reader) error {
+	b := make([]byte, 1024)
+	_, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b)
+	return err
+}
diff --git a/src/vendor/golang_org/x/net/nettest/conntest_go16.go b/src/vendor/golang_org/x/net/nettest/conntest_go16.go
new file mode 100644
index 0000000..4cbf48e
--- /dev/null
+++ b/src/vendor/golang_org/x/net/nettest/conntest_go16.go
@@ -0,0 +1,24 @@
+// Copyright 2016 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 !go1.7
+
+package nettest
+
+import "testing"
+
+func testConn(t *testing.T, mp MakePipe) {
+	// Avoid using subtests on Go 1.6 and below.
+	timeoutWrapper(t, mp, testBasicIO)
+	timeoutWrapper(t, mp, testPingPong)
+	timeoutWrapper(t, mp, testRacyRead)
+	timeoutWrapper(t, mp, testRacyWrite)
+	timeoutWrapper(t, mp, testReadTimeout)
+	timeoutWrapper(t, mp, testWriteTimeout)
+	timeoutWrapper(t, mp, testPastTimeout)
+	timeoutWrapper(t, mp, testPresentTimeout)
+	timeoutWrapper(t, mp, testFutureTimeout)
+	timeoutWrapper(t, mp, testCloseTimeout)
+	timeoutWrapper(t, mp, testConcurrentMethods)
+}
diff --git a/src/vendor/golang_org/x/net/nettest/conntest_go17.go b/src/vendor/golang_org/x/net/nettest/conntest_go17.go
new file mode 100644
index 0000000..fa039f0
--- /dev/null
+++ b/src/vendor/golang_org/x/net/nettest/conntest_go17.go
@@ -0,0 +1,24 @@
+// Copyright 2016 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 go1.7
+
+package nettest
+
+import "testing"
+
+func testConn(t *testing.T, mp MakePipe) {
+	// Use subtests on Go 1.7 and above since it is better organized.
+	t.Run("BasicIO", func(t *testing.T) { timeoutWrapper(t, mp, testBasicIO) })
+	t.Run("PingPong", func(t *testing.T) { timeoutWrapper(t, mp, testPingPong) })
+	t.Run("RacyRead", func(t *testing.T) { timeoutWrapper(t, mp, testRacyRead) })
+	t.Run("RacyWrite", func(t *testing.T) { timeoutWrapper(t, mp, testRacyWrite) })
+	t.Run("ReadTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testReadTimeout) })
+	t.Run("WriteTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testWriteTimeout) })
+	t.Run("PastTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPastTimeout) })
+	t.Run("PresentTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPresentTimeout) })
+	t.Run("FutureTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testFutureTimeout) })
+	t.Run("CloseTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testCloseTimeout) })
+	t.Run("ConcurrentMethods", func(t *testing.T) { timeoutWrapper(t, mp, testConcurrentMethods) })
+}
diff --git a/src/vendor/golang_org/x/net/nettest/conntest_test.go b/src/vendor/golang_org/x/net/nettest/conntest_test.go
new file mode 100644
index 0000000..23bd69f
--- /dev/null
+++ b/src/vendor/golang_org/x/net/nettest/conntest_test.go
@@ -0,0 +1,126 @@
+// Copyright 2016 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 go1.8
+
+package nettest
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net"
+	"os"
+	"runtime"
+	"testing"
+)
+
+// testUnixAddr uses ioutil.TempFile to get a name that is unique.
+// It also uses /tmp directory in case it is prohibited to create UNIX
+// sockets in TMPDIR.
+func testUnixAddr() string {
+	f, err := ioutil.TempFile("", "go-nettest")
+	if err != nil {
+		panic(err)
+	}
+	addr := f.Name()
+	f.Close()
+	os.Remove(addr)
+	return addr
+}
+
+// testableNetwork reports whether network is testable on the current
+// platform configuration.
+// This is based on logic from standard library's net/platform_test.go.
+func testableNetwork(network string) bool {
+	switch network {
+	case "unix":
+		switch runtime.GOOS {
+		case "android", "nacl", "plan9", "windows":
+			return false
+		}
+		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
+			return false
+		}
+	case "unixpacket":
+		switch runtime.GOOS {
+		case "android", "darwin", "nacl", "plan9", "windows", "freebsd":
+			return false
+		}
+	}
+	return true
+}
+
+func newLocalListener(network string) (net.Listener, error) {
+	switch network {
+	case "tcp":
+		ln, err := net.Listen("tcp", "127.0.0.1:0")
+		if err != nil {
+			ln, err = net.Listen("tcp6", "[::1]:0")
+		}
+		return ln, err
+	case "unix", "unixpacket":
+		return net.Listen(network, testUnixAddr())
+	}
+	return nil, fmt.Errorf("%s is not supported", network)
+}
+
+func TestTestConn(t *testing.T) {
+	tests := []struct{ name, network string }{
+		{"TCP", "tcp"},
+		{"UnixPipe", "unix"},
+		{"UnixPacketPipe", "unixpacket"},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if !testableNetwork(tt.network) {
+				t.Skipf("not supported on %s", runtime.GOOS)
+			}
+
+			mp := func() (c1, c2 net.Conn, stop func(), err error) {
+				ln, err := newLocalListener(tt.network)
+				if err != nil {
+					return nil, nil, nil, err
+				}
+
+				// Start a connection between two endpoints.
+				var err1, err2 error
+				done := make(chan bool)
+				go func() {
+					c2, err2 = ln.Accept()
+					close(done)
+				}()
+				c1, err1 = net.Dial(ln.Addr().Network(), ln.Addr().String())
+				<-done
+
+				stop = func() {
+					if err1 == nil {
+						c1.Close()
+					}
+					if err2 == nil {
+						c2.Close()
+					}
+					ln.Close()
+					switch tt.network {
+					case "unix", "unixpacket":
+						os.Remove(ln.Addr().String())
+					}
+				}
+
+				switch {
+				case err1 != nil:
+					stop()
+					return nil, nil, nil, err1
+				case err2 != nil:
+					stop()
+					return nil, nil, nil, err2
+				default:
+					return c1, c2, stop, nil
+				}
+			}
+
+			TestConn(t, mp)
+		})
+	}
+}