浏览代码

Merge pull request #2 from songgao/songgao/add_tests

Add TAP test (ipv4 broadcast)
Song Gao 9 年之前
父节点
当前提交
e7338c341f
共有 4 个文件被更改,包括 113 次插入2 次删除
  1. 81 0
      ipv4_test.go
  2. 16 0
      ipv4_test_linux.go
  3. 12 0
      ipv4_test_other.go
  4. 4 2
      syscalls_other.go

+ 81 - 0
ipv4_test.go

@@ -0,0 +1,81 @@
+package water
+
+import (
+	"net"
+	"os/exec"
+	"testing"
+	"time"
+
+	"github.com/songgao/water/waterutil"
+)
+
+const BUFFERSIZE = 1522
+
+func startRead(ch chan<- []byte, ifce *Interface) {
+	go func() {
+		for {
+			buffer := make([]byte, BUFFERSIZE)
+			_, err := ifce.Read(buffer)
+			if err == nil {
+				ch <- buffer
+			}
+		}
+	}()
+}
+
+func startBroadcast(t *testing.T, dst net.IP) {
+	if err := exec.Command("ping", "-b", "-c", "2", dst.String()).Start(); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestBroadcast(t *testing.T) {
+	var (
+		self = net.IPv4(10, 0, 42, 1)
+		mask = net.IPv4Mask(255, 255, 255, 0)
+		brd  = net.IPv4(10, 0, 42, 255)
+	)
+
+	ifce, err := NewTAP("test")
+	if err != nil {
+		t.Fatalf("creating TAP error: %v\n", err)
+	}
+
+	setupIfce(t, net.IPNet{IP: self, Mask: mask}, ifce.Name())
+	startBroadcast(t, brd)
+
+	dataCh := make(chan []byte, 8)
+	startRead(dataCh, ifce)
+
+	timeout := time.NewTimer(8 * time.Second).C
+
+readFrame:
+	for {
+		select {
+		case buffer := <-dataCh:
+			ethertype := waterutil.MACEthertype(buffer)
+			if ethertype != waterutil.IPv4 {
+				continue readFrame
+			}
+			if !waterutil.IsBroadcast(waterutil.MACDestination(buffer)) {
+				continue readFrame
+			}
+			packet := waterutil.MACPayload(buffer)
+			if !waterutil.IsIPv4(packet) {
+				continue readFrame
+			}
+			if !waterutil.IPv4Source(packet).Equal(self) {
+				continue readFrame
+			}
+			if !waterutil.IPv4Destination(packet).Equal(brd) {
+				continue readFrame
+			}
+			if waterutil.IPv4Protocol(packet) != waterutil.ICMP {
+				continue readFrame
+			}
+			break readFrame
+		case <-timeout:
+			t.Fatal("Waiting for broadcast packet timeout")
+		}
+	}
+}

+ 16 - 0
ipv4_test_linux.go

@@ -0,0 +1,16 @@
+package water
+
+import (
+	"net"
+	"os/exec"
+	"testing"
+)
+
+func setupIfce(t *testing.T, ipNet net.IPNet, dev string) {
+	if err := exec.Command("ip", "link", "set", dev, "up").Run(); err != nil {
+		t.Fatal(err)
+	}
+	if err := exec.Command("ip", "addr", "add", ipNet.String(), "dev", dev).Run(); err != nil {
+		t.Fatal(err)
+	}
+}

+ 12 - 0
ipv4_test_other.go

@@ -0,0 +1,12 @@
+// +build !linux
+
+package water
+
+import (
+	"net"
+	"testing"
+)
+
+func setupIfce(t *testing.T, ipNet net.IPNet, dev string) {
+	t.Fatal("unsupported platform")
+}

+ 4 - 2
syscalls_other.go

@@ -2,10 +2,12 @@
 
 package water
 
+import "errors"
+
 func newTAP(ifName string) (ifce *Interface, err error) {
-	panic("water: tap interface not implemented on this platform")
+	return nil, errors.New("tap interface not implemented on this platform")
 }
 
 func newTUN(ifName string) (ifce *Interface, err error) {
-	panic("water: tap interface not implemented on this platform")
+	return nil, errors.New("tap interface not implemented on this platform")
 }