|  | // Copyright 2012 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. | 
|  |  | 
|  | // This file implements API tests across platforms and will never have a build | 
|  | // tag. | 
|  |  | 
|  | package net | 
|  |  | 
|  | import ( | 
|  | "os" | 
|  | "runtime" | 
|  | "testing" | 
|  | "time" | 
|  | ) | 
|  |  | 
|  | var connTests = []struct { | 
|  | net  string | 
|  | addr string | 
|  | }{ | 
|  | {"tcp", "127.0.0.1:0"}, | 
|  | {"unix", testUnixAddr()}, | 
|  | {"unixpacket", testUnixAddr()}, | 
|  | } | 
|  |  | 
|  | // someTimeout is used just to test that net.Conn implementations | 
|  | // don't explode when their SetFooDeadline methods are called. | 
|  | // It isn't actually used for testing timeouts. | 
|  | const someTimeout = 10 * time.Second | 
|  |  | 
|  | func TestConnAndListener(t *testing.T) { | 
|  | for _, tt := range connTests { | 
|  | switch tt.net { | 
|  | case "unix": | 
|  | switch runtime.GOOS { | 
|  | case "nacl", "plan9", "windows": | 
|  | continue | 
|  | } | 
|  | case "unixpacket": | 
|  | switch runtime.GOOS { | 
|  | case "android", "darwin", "nacl", "openbsd", "plan9", "windows": | 
|  | continue | 
|  | case "freebsd": // FreeBSD 8 doesn't support unixpacket | 
|  | continue | 
|  | } | 
|  | } | 
|  |  | 
|  | ln, err := Listen(tt.net, tt.addr) | 
|  | if err != nil { | 
|  | t.Fatalf("Listen failed: %v", err) | 
|  | } | 
|  | defer func(ln Listener, net, addr string) { | 
|  | ln.Close() | 
|  | switch net { | 
|  | case "unix", "unixpacket": | 
|  | os.Remove(addr) | 
|  | } | 
|  | }(ln, tt.net, tt.addr) | 
|  | if ln.Addr().Network() != tt.net { | 
|  | t.Fatalf("got %v; expected %v", ln.Addr().Network(), tt.net) | 
|  | } | 
|  |  | 
|  | done := make(chan int) | 
|  | go transponder(t, ln, done) | 
|  |  | 
|  | c, err := Dial(tt.net, ln.Addr().String()) | 
|  | if err != nil { | 
|  | t.Fatalf("Dial failed: %v", err) | 
|  | } | 
|  | defer c.Close() | 
|  | if c.LocalAddr().Network() != tt.net || c.LocalAddr().Network() != tt.net { | 
|  | t.Fatalf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), tt.net, tt.net) | 
|  | } | 
|  | c.SetDeadline(time.Now().Add(someTimeout)) | 
|  | c.SetReadDeadline(time.Now().Add(someTimeout)) | 
|  | c.SetWriteDeadline(time.Now().Add(someTimeout)) | 
|  |  | 
|  | if _, err := c.Write([]byte("CONN TEST")); err != nil { | 
|  | t.Fatalf("Conn.Write failed: %v", err) | 
|  | } | 
|  | rb := make([]byte, 128) | 
|  | if _, err := c.Read(rb); err != nil { | 
|  | t.Fatalf("Conn.Read failed: %v", err) | 
|  | } | 
|  |  | 
|  | <-done | 
|  | } | 
|  | } | 
|  |  | 
|  | func transponder(t *testing.T, ln Listener, done chan<- int) { | 
|  | defer func() { done <- 1 }() | 
|  |  | 
|  | switch ln := ln.(type) { | 
|  | case *TCPListener: | 
|  | ln.SetDeadline(time.Now().Add(someTimeout)) | 
|  | case *UnixListener: | 
|  | ln.SetDeadline(time.Now().Add(someTimeout)) | 
|  | } | 
|  | c, err := ln.Accept() | 
|  | if err != nil { | 
|  | t.Errorf("Listener.Accept failed: %v", err) | 
|  | return | 
|  | } | 
|  | defer c.Close() | 
|  | network := ln.Addr().Network() | 
|  | if c.LocalAddr().Network() != network || c.LocalAddr().Network() != network { | 
|  | t.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network) | 
|  | return | 
|  | } | 
|  | c.SetDeadline(time.Now().Add(someTimeout)) | 
|  | c.SetReadDeadline(time.Now().Add(someTimeout)) | 
|  | c.SetWriteDeadline(time.Now().Add(someTimeout)) | 
|  |  | 
|  | b := make([]byte, 128) | 
|  | n, err := c.Read(b) | 
|  | if err != nil { | 
|  | t.Errorf("Conn.Read failed: %v", err) | 
|  | return | 
|  | } | 
|  | if _, err := c.Write(b[:n]); err != nil { | 
|  | t.Errorf("Conn.Write failed: %v", err) | 
|  | return | 
|  | } | 
|  | } |