github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/net/interface_unix_test.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin dragonfly freebsd linux netbsd openbsd
     6  
     7  package net
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"os/exec"
    13  	"runtime"
    14  	"testing"
    15  	"time"
    16  )
    17  
    18  type testInterface struct {
    19  	name         string
    20  	local        string
    21  	remote       string
    22  	setupCmds    []*exec.Cmd
    23  	teardownCmds []*exec.Cmd
    24  }
    25  
    26  func (ti *testInterface) setup() error {
    27  	for _, cmd := range ti.setupCmds {
    28  		if out, err := cmd.CombinedOutput(); err != nil {
    29  			return fmt.Errorf("args=%v out=%q err=%v", cmd.Args, string(out), err)
    30  		}
    31  	}
    32  	return nil
    33  }
    34  
    35  func (ti *testInterface) teardown() error {
    36  	for _, cmd := range ti.teardownCmds {
    37  		if out, err := cmd.CombinedOutput(); err != nil {
    38  			return fmt.Errorf("args=%v out=%q err=%v ", cmd.Args, string(out), err)
    39  		}
    40  	}
    41  	return nil
    42  }
    43  
    44  func TestPointToPointInterface(t *testing.T) {
    45  	if testing.Short() {
    46  		t.Skip("avoid external network")
    47  	}
    48  	if runtime.GOOS == "darwin" {
    49  		t.Skipf("not supported on %s", runtime.GOOS)
    50  	}
    51  	if os.Getuid() != 0 {
    52  		t.Skip("must be root")
    53  	}
    54  
    55  	// We suppose that using IPv4 link-local addresses doesn't
    56  	// harm anyone.
    57  	local, remote := "169.254.0.1", "169.254.0.254"
    58  	ip := ParseIP(remote)
    59  	for i := 0; i < 3; i++ {
    60  		ti := &testInterface{local: local, remote: remote}
    61  		if err := ti.setPointToPoint(5963 + i); err != nil {
    62  			t.Skipf("test requires external command: %v", err)
    63  		}
    64  		if err := ti.setup(); err != nil {
    65  			t.Fatal(err)
    66  		} else {
    67  			time.Sleep(3 * time.Millisecond)
    68  		}
    69  		ift, err := Interfaces()
    70  		if err != nil {
    71  			ti.teardown()
    72  			t.Fatal(err)
    73  		}
    74  		for _, ifi := range ift {
    75  			if ti.name != ifi.Name {
    76  				continue
    77  			}
    78  			ifat, err := ifi.Addrs()
    79  			if err != nil {
    80  				ti.teardown()
    81  				t.Fatal(err)
    82  			}
    83  			for _, ifa := range ifat {
    84  				if ip.Equal(ifa.(*IPNet).IP) {
    85  					ti.teardown()
    86  					t.Fatalf("got %v", ifa)
    87  				}
    88  			}
    89  		}
    90  		if err := ti.teardown(); err != nil {
    91  			t.Fatal(err)
    92  		} else {
    93  			time.Sleep(3 * time.Millisecond)
    94  		}
    95  	}
    96  }
    97  
    98  func TestInterfaceArrivalAndDeparture(t *testing.T) {
    99  	if testing.Short() {
   100  		t.Skip("avoid external network")
   101  	}
   102  	if os.Getuid() != 0 {
   103  		t.Skip("must be root")
   104  	}
   105  
   106  	// We suppose that using IPv4 link-local addresses and the
   107  	// dot1Q ID for Token Ring and FDDI doesn't harm anyone.
   108  	local, remote := "169.254.0.1", "169.254.0.254"
   109  	ip := ParseIP(remote)
   110  	for _, vid := range []int{1002, 1003, 1004, 1005} {
   111  		ift1, err := Interfaces()
   112  		if err != nil {
   113  			t.Fatal(err)
   114  		}
   115  		ti := &testInterface{local: local, remote: remote}
   116  		if err := ti.setBroadcast(vid); err != nil {
   117  			t.Skipf("test requires external command: %v", err)
   118  		}
   119  		if err := ti.setup(); err != nil {
   120  			t.Fatal(err)
   121  		} else {
   122  			time.Sleep(3 * time.Millisecond)
   123  		}
   124  		ift2, err := Interfaces()
   125  		if err != nil {
   126  			ti.teardown()
   127  			t.Fatal(err)
   128  		}
   129  		if len(ift2) <= len(ift1) {
   130  			for _, ifi := range ift1 {
   131  				t.Logf("before: %v", ifi)
   132  			}
   133  			for _, ifi := range ift2 {
   134  				t.Logf("after: %v", ifi)
   135  			}
   136  			ti.teardown()
   137  			t.Fatalf("got %v; want gt %v", len(ift2), len(ift1))
   138  		}
   139  		for _, ifi := range ift2 {
   140  			if ti.name != ifi.Name {
   141  				continue
   142  			}
   143  			ifat, err := ifi.Addrs()
   144  			if err != nil {
   145  				ti.teardown()
   146  				t.Fatal(err)
   147  			}
   148  			for _, ifa := range ifat {
   149  				if ip.Equal(ifa.(*IPNet).IP) {
   150  					ti.teardown()
   151  					t.Fatalf("got %v", ifa)
   152  				}
   153  			}
   154  		}
   155  		if err := ti.teardown(); err != nil {
   156  			t.Fatal(err)
   157  		} else {
   158  			time.Sleep(3 * time.Millisecond)
   159  		}
   160  		ift3, err := Interfaces()
   161  		if err != nil {
   162  			t.Fatal(err)
   163  		}
   164  		if len(ift3) >= len(ift2) {
   165  			for _, ifi := range ift2 {
   166  				t.Logf("before: %v", ifi)
   167  			}
   168  			for _, ifi := range ift3 {
   169  				t.Logf("after: %v", ifi)
   170  			}
   171  			t.Fatalf("got %v; want lt %v", len(ift3), len(ift2))
   172  		}
   173  	}
   174  }