Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/interface_unix_test.go

Documentation: net

     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  //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
     6  // +build darwin dragonfly freebsd linux netbsd openbsd
     7  
     8  package net
     9  
    10  import (
    11  	"fmt"
    12  	"os"
    13  	"os/exec"
    14  	"runtime"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  type testInterface struct {
    21  	name         string
    22  	local        string
    23  	remote       string
    24  	setupCmds    []*exec.Cmd
    25  	teardownCmds []*exec.Cmd
    26  }
    27  
    28  func (ti *testInterface) setup() error {
    29  	for _, cmd := range ti.setupCmds {
    30  		if out, err := cmd.CombinedOutput(); err != nil {
    31  			return fmt.Errorf("args=%v out=%q err=%v", cmd.Args, string(out), err)
    32  		}
    33  	}
    34  	return nil
    35  }
    36  
    37  func (ti *testInterface) teardown() error {
    38  	for _, cmd := range ti.teardownCmds {
    39  		if out, err := cmd.CombinedOutput(); err != nil {
    40  			return fmt.Errorf("args=%v out=%q err=%v ", cmd.Args, string(out), err)
    41  		}
    42  	}
    43  	return nil
    44  }
    45  
    46  func TestPointToPointInterface(t *testing.T) {
    47  	if testing.Short() {
    48  		t.Skip("avoid external network")
    49  	}
    50  	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
    51  		t.Skipf("not supported on %s", runtime.GOOS)
    52  	}
    53  	if os.Getuid() != 0 {
    54  		t.Skip("must be root")
    55  	}
    56  
    57  	// We suppose that using IPv4 link-local addresses doesn't
    58  	// harm anyone.
    59  	local, remote := "169.254.0.1", "169.254.0.254"
    60  	ip := ParseIP(remote)
    61  	for i := 0; i < 3; i++ {
    62  		ti := &testInterface{local: local, remote: remote}
    63  		if err := ti.setPointToPoint(5963 + i); err != nil {
    64  			t.Skipf("test requires external command: %v", err)
    65  		}
    66  		if err := ti.setup(); err != nil {
    67  			if e := err.Error(); strings.Contains(e, "No such device") && strings.Contains(e, "gre0") {
    68  				t.Skip("skipping test; no gre0 device. likely running in container?")
    69  			}
    70  			t.Fatal(err)
    71  		} else {
    72  			time.Sleep(3 * time.Millisecond)
    73  		}
    74  		ift, err := Interfaces()
    75  		if err != nil {
    76  			ti.teardown()
    77  			t.Fatal(err)
    78  		}
    79  		for _, ifi := range ift {
    80  			if ti.name != ifi.Name {
    81  				continue
    82  			}
    83  			ifat, err := ifi.Addrs()
    84  			if err != nil {
    85  				ti.teardown()
    86  				t.Fatal(err)
    87  			}
    88  			for _, ifa := range ifat {
    89  				if ip.Equal(ifa.(*IPNet).IP) {
    90  					ti.teardown()
    91  					t.Fatalf("got %v", ifa)
    92  				}
    93  			}
    94  		}
    95  		if err := ti.teardown(); err != nil {
    96  			t.Fatal(err)
    97  		} else {
    98  			time.Sleep(3 * time.Millisecond)
    99  		}
   100  	}
   101  }
   102  
   103  func TestInterfaceArrivalAndDeparture(t *testing.T) {
   104  	if testing.Short() {
   105  		t.Skip("avoid external network")
   106  	}
   107  	if os.Getuid() != 0 {
   108  		t.Skip("must be root")
   109  	}
   110  
   111  	// We suppose that using IPv4 link-local addresses and the
   112  	// dot1Q ID for Token Ring and FDDI doesn't harm anyone.
   113  	local, remote := "169.254.0.1", "169.254.0.254"
   114  	ip := ParseIP(remote)
   115  	for _, vid := range []int{1002, 1003, 1004, 1005} {
   116  		ift1, err := Interfaces()
   117  		if err != nil {
   118  			t.Fatal(err)
   119  		}
   120  		ti := &testInterface{local: local, remote: remote}
   121  		if err := ti.setBroadcast(vid); err != nil {
   122  			t.Skipf("test requires external command: %v", err)
   123  		}
   124  		if err := ti.setup(); err != nil {
   125  			t.Fatal(err)
   126  		} else {
   127  			time.Sleep(3 * time.Millisecond)
   128  		}
   129  		ift2, err := Interfaces()
   130  		if err != nil {
   131  			ti.teardown()
   132  			t.Fatal(err)
   133  		}
   134  		if len(ift2) <= len(ift1) {
   135  			for _, ifi := range ift1 {
   136  				t.Logf("before: %v", ifi)
   137  			}
   138  			for _, ifi := range ift2 {
   139  				t.Logf("after: %v", ifi)
   140  			}
   141  			ti.teardown()
   142  			t.Fatalf("got %v; want gt %v", len(ift2), len(ift1))
   143  		}
   144  		for _, ifi := range ift2 {
   145  			if ti.name != ifi.Name {
   146  				continue
   147  			}
   148  			ifat, err := ifi.Addrs()
   149  			if err != nil {
   150  				ti.teardown()
   151  				t.Fatal(err)
   152  			}
   153  			for _, ifa := range ifat {
   154  				if ip.Equal(ifa.(*IPNet).IP) {
   155  					ti.teardown()
   156  					t.Fatalf("got %v", ifa)
   157  				}
   158  			}
   159  		}
   160  		if err := ti.teardown(); err != nil {
   161  			t.Fatal(err)
   162  		} else {
   163  			time.Sleep(3 * time.Millisecond)
   164  		}
   165  		ift3, err := Interfaces()
   166  		if err != nil {
   167  			t.Fatal(err)
   168  		}
   169  		if len(ift3) >= len(ift2) {
   170  			for _, ifi := range ift2 {
   171  				t.Logf("before: %v", ifi)
   172  			}
   173  			for _, ifi := range ift3 {
   174  				t.Logf("after: %v", ifi)
   175  			}
   176  			t.Fatalf("got %v; want lt %v", len(ift3), len(ift2))
   177  		}
   178  	}
   179  }
   180  
   181  func TestInterfaceArrivalAndDepartureZoneCache(t *testing.T) {
   182  	if testing.Short() {
   183  		t.Skip("avoid external network")
   184  	}
   185  	if os.Getuid() != 0 {
   186  		t.Skip("must be root")
   187  	}
   188  
   189  	// Ensure zoneCache is filled:
   190  	_, _ = Listen("tcp", "[fe80::1%nonexistent]:0")
   191  
   192  	ti := &testInterface{local: "fe80::1"}
   193  	if err := ti.setLinkLocal(0); err != nil {
   194  		t.Skipf("test requires external command: %v", err)
   195  	}
   196  	if err := ti.setup(); err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	defer ti.teardown()
   200  
   201  	time.Sleep(3 * time.Millisecond)
   202  
   203  	// If Listen fails (on Linux with “bind: invalid argument”), zoneCache was
   204  	// not updated when encountering a nonexistent interface:
   205  	ln, err := Listen("tcp", "[fe80::1%"+ti.name+"]:0")
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	ln.Close()
   210  	if err := ti.teardown(); err != nil {
   211  		t.Fatal(err)
   212  	}
   213  }
   214  

View as plain text