// 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" "strings" "testing" "time" ) func packetConnTestData(t *testing.T, net string, i int) ([]byte, func()) { switch net { case "udp": return []byte("UDP PACKETCONN TEST"), nil case "ip": if skip, skipmsg := skipRawSocketTest(t); skip { return nil, func() { t.Logf(skipmsg) } } b, err := (&icmpMessage{ Type: icmpv4EchoRequest, Code: 0, Body: &icmpEcho{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("IP PACKETCONN TEST"), }, }).Marshal() if err != nil { return nil, func() { t.Fatalf("icmpMessage.Marshal failed: %v", err) } } return b, nil case "unixgram": switch runtime.GOOS { case "nacl", "plan9", "windows": return nil, func() { t.Logf("skipping %q test on %q", net, runtime.GOOS) } default: return []byte("UNIXGRAM PACKETCONN TEST"), nil } default: return nil, func() { t.Logf("skipping %q test", net) } } } var packetConnTests = []struct { net string addr1 string addr2 string }{ {"udp", "127.0.0.1:0", "127.0.0.1:0"}, {"ip:icmp", "127.0.0.1", "127.0.0.1"}, {"unixgram", testUnixAddr(), testUnixAddr()}, } func TestPacketConn(t *testing.T) { closer := func(c PacketConn, net, addr1, addr2 string) { c.Close() switch net { case "unixgram": os.Remove(addr1) os.Remove(addr2) } } for i, tt := range packetConnTests { netstr := strings.Split(tt.net, ":") wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i) if skipOrFatalFn != nil { skipOrFatalFn() continue } c1, err := ListenPacket(tt.net, tt.addr1) if err != nil { t.Fatalf("ListenPacket failed: %v", err) } defer closer(c1, netstr[0], tt.addr1, tt.addr2) c1.LocalAddr() c1.SetDeadline(time.Now().Add(100 * time.Millisecond)) c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) c2, err := ListenPacket(tt.net, tt.addr2) if err != nil { t.Fatalf("ListenPacket failed: %v", err) } defer closer(c2, netstr[0], tt.addr1, tt.addr2) c2.LocalAddr() c2.SetDeadline(time.Now().Add(100 * time.Millisecond)) c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) if _, err := c1.WriteTo(wb, c2.LocalAddr()); err != nil { t.Fatalf("PacketConn.WriteTo failed: %v", err) } rb2 := make([]byte, 128) if _, _, err := c2.ReadFrom(rb2); err != nil { t.Fatalf("PacketConn.ReadFrom failed: %v", err) } if _, err := c2.WriteTo(wb, c1.LocalAddr()); err != nil { t.Fatalf("PacketConn.WriteTo failed: %v", err) } rb1 := make([]byte, 128) if _, _, err := c1.ReadFrom(rb1); err != nil { t.Fatalf("PacketConn.ReadFrom failed: %v", err) } } } func TestConnAndPacketConn(t *testing.T) { closer := func(c PacketConn, net, addr1, addr2 string) { c.Close() switch net { case "unixgram": os.Remove(addr1) os.Remove(addr2) } } for i, tt := range packetConnTests { var wb []byte netstr := strings.Split(tt.net, ":") wb, skipOrFatalFn := packetConnTestData(t, netstr[0], i) if skipOrFatalFn != nil { skipOrFatalFn() continue } c1, err := ListenPacket(tt.net, tt.addr1) if err != nil { t.Fatalf("ListenPacket failed: %v", err) } defer closer(c1, netstr[0], tt.addr1, tt.addr2) c1.LocalAddr() c1.SetDeadline(time.Now().Add(100 * time.Millisecond)) c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c1.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) c2, err := Dial(tt.net, c1.LocalAddr().String()) if err != nil { t.Fatalf("Dial failed: %v", err) } defer c2.Close() c2.LocalAddr() c2.RemoteAddr() c2.SetDeadline(time.Now().Add(100 * time.Millisecond)) c2.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) c2.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) if _, err := c2.Write(wb); err != nil { t.Fatalf("Conn.Write failed: %v", err) } rb1 := make([]byte, 128) if _, _, err := c1.ReadFrom(rb1); err != nil { t.Fatalf("PacketConn.ReadFrom failed: %v", err) } var dst Addr switch netstr[0] { case "ip": dst = &IPAddr{IP: IPv4(127, 0, 0, 1)} case "unixgram": continue default: dst = c2.LocalAddr() } if _, err := c1.WriteTo(wb, dst); err != nil { t.Fatalf("PacketConn.WriteTo failed: %v", err) } rb2 := make([]byte, 128) if _, err := c2.Read(rb2); err != nil { t.Fatalf("Conn.Read failed: %v", err) } } }