github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/etchosts/etchosts_test.go (about)

     1  package etchosts
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"sync"
     9  	"testing"
    10  
    11  	_ "github.com/docker/libnetwork/testutils"
    12  )
    13  
    14  func TestBuildDefault(t *testing.T) {
    15  	file, err := ioutil.TempFile("", "")
    16  	if err != nil {
    17  		t.Fatal(err)
    18  	}
    19  	defer os.Remove(file.Name())
    20  
    21  	// check that /data/data/hilled.pwnterm/files/usr/etc/hosts has consistent ordering
    22  	for i := 0; i <= 5; i++ {
    23  		err = Build(file.Name(), "", "", "", nil)
    24  		if err != nil {
    25  			t.Fatal(err)
    26  		}
    27  
    28  		content, err := ioutil.ReadFile(file.Name())
    29  		if err != nil {
    30  			t.Fatal(err)
    31  		}
    32  		expected := "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n"
    33  
    34  		if expected != string(content) {
    35  			t.Fatalf("Expected to find '%s' got '%s'", expected, content)
    36  		}
    37  	}
    38  }
    39  
    40  func TestBuildHostnameDomainname(t *testing.T) {
    41  	file, err := ioutil.TempFile("", "")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	defer os.Remove(file.Name())
    46  
    47  	err = Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil)
    48  	if err != nil {
    49  		t.Fatal(err)
    50  	}
    51  
    52  	content, err := ioutil.ReadFile(file.Name())
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
    58  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
    59  	}
    60  }
    61  
    62  func TestBuildHostname(t *testing.T) {
    63  	file, err := ioutil.TempFile("", "")
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	defer os.Remove(file.Name())
    68  
    69  	err = Build(file.Name(), "10.11.12.13", "testhostname", "", nil)
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	content, err := ioutil.ReadFile(file.Name())
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	if expected := "10.11.12.13\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) {
    80  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
    81  	}
    82  }
    83  
    84  func TestBuildHostnameFQDN(t *testing.T) {
    85  	file, err := ioutil.TempFile("", "")
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	defer os.Remove(file.Name())
    90  
    91  	err = Build(file.Name(), "10.11.12.13", "testhostname.testdomainname.com", "", nil)
    92  	if err != nil {
    93  		t.Fatal(err)
    94  	}
    95  
    96  	content, err := ioutil.ReadFile(file.Name())
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	if expected := "10.11.12.13\ttesthostname.testdomainname.com testhostname\n"; !bytes.Contains(content, []byte(expected)) {
   102  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   103  	}
   104  }
   105  
   106  func TestBuildNoIP(t *testing.T) {
   107  	file, err := ioutil.TempFile("", "")
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	defer os.Remove(file.Name())
   112  
   113  	err = Build(file.Name(), "", "testhostname", "", nil)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	content, err := ioutil.ReadFile(file.Name())
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	if expected := ""; !bytes.Contains(content, []byte(expected)) {
   124  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   125  	}
   126  }
   127  
   128  func TestUpdate(t *testing.T) {
   129  	file, err := ioutil.TempFile("", "")
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	defer os.Remove(file.Name())
   134  
   135  	if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", nil); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	content, err := ioutil.ReadFile(file.Name())
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	if expected := "10.11.12.13\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
   145  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   146  	}
   147  
   148  	if err := Update(file.Name(), "1.1.1.1", "testhostname"); err != nil {
   149  		t.Fatal(err)
   150  	}
   151  
   152  	content, err = ioutil.ReadFile(file.Name())
   153  	if err != nil {
   154  		t.Fatal(err)
   155  	}
   156  
   157  	if expected := "1.1.1.1\ttesthostname.testdomainname testhostname\n"; !bytes.Contains(content, []byte(expected)) {
   158  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   159  	}
   160  }
   161  
   162  // This regression test ensures that when a host is given a new IP
   163  // via the Update function that other hosts which start with the
   164  // same name as the targeted host are not erroneously updated as well.
   165  // In the test example, if updating a host called "prefix", unrelated
   166  // hosts named "prefixAndMore" or "prefix2" or anything else starting
   167  // with "prefix" should not be changed. For more information see
   168  // GitHub issue #603.
   169  func TestUpdateIgnoresPrefixedHostname(t *testing.T) {
   170  	file, err := ioutil.TempFile("", "")
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	defer os.Remove(file.Name())
   175  
   176  	if err := Build(file.Name(), "10.11.12.13", "testhostname", "testdomainname", []Record{
   177  		{
   178  			Hosts: "prefix",
   179  			IP:    "2.2.2.2",
   180  		},
   181  		{
   182  			Hosts: "prefixAndMore",
   183  			IP:    "3.3.3.3",
   184  		},
   185  		{
   186  			Hosts: "unaffectedHost",
   187  			IP:    "4.4.4.4",
   188  		},
   189  	}); err != nil {
   190  		t.Fatal(err)
   191  	}
   192  
   193  	content, err := ioutil.ReadFile(file.Name())
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	if expected := "2.2.2.2\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) {
   199  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   200  	}
   201  
   202  	if err := Update(file.Name(), "5.5.5.5", "prefix"); err != nil {
   203  		t.Fatal(err)
   204  	}
   205  
   206  	content, err = ioutil.ReadFile(file.Name())
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  
   211  	if expected := "5.5.5.5\tprefix\n3.3.3.3\tprefixAndMore\n4.4.4.4\tunaffectedHost\n"; !bytes.Contains(content, []byte(expected)) {
   212  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   213  	}
   214  
   215  }
   216  
   217  // This regression test covers the host prefix issue for the
   218  // Delete function. In the test example, if deleting a host called
   219  // "prefix", an unrelated host called "prefixAndMore" should not
   220  // be deleted. For more information see GitHub issue #603.
   221  func TestDeleteIgnoresPrefixedHostname(t *testing.T) {
   222  	file, err := ioutil.TempFile("", "")
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  	defer os.Remove(file.Name())
   227  
   228  	err = Build(file.Name(), "", "", "", nil)
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	if err := Add(file.Name(), []Record{
   234  		{
   235  			Hosts: "prefix",
   236  			IP:    "1.1.1.1",
   237  		},
   238  		{
   239  			Hosts: "prefixAndMore",
   240  			IP:    "2.2.2.2",
   241  		},
   242  	}); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	if err := Delete(file.Name(), []Record{
   247  		{
   248  			Hosts: "prefix",
   249  			IP:    "1.1.1.1",
   250  		},
   251  	}); err != nil {
   252  		t.Fatal(err)
   253  	}
   254  
   255  	content, err := ioutil.ReadFile(file.Name())
   256  	if err != nil {
   257  		t.Fatal(err)
   258  	}
   259  
   260  	if expected := "2.2.2.2\tprefixAndMore\n"; !bytes.Contains(content, []byte(expected)) {
   261  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   262  	}
   263  
   264  	if expected := "1.1.1.1\tprefix\n"; bytes.Contains(content, []byte(expected)) {
   265  		t.Fatalf("Did not expect to find '%s' got '%s'", expected, content)
   266  	}
   267  }
   268  
   269  func TestAddEmpty(t *testing.T) {
   270  	file, err := ioutil.TempFile("", "")
   271  	if err != nil {
   272  		t.Fatal(err)
   273  	}
   274  	defer os.Remove(file.Name())
   275  
   276  	err = Build(file.Name(), "", "", "", nil)
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  
   281  	if err := Add(file.Name(), []Record{}); err != nil {
   282  		t.Fatal(err)
   283  	}
   284  }
   285  
   286  func TestAdd(t *testing.T) {
   287  	file, err := ioutil.TempFile("", "")
   288  	if err != nil {
   289  		t.Fatal(err)
   290  	}
   291  	defer os.Remove(file.Name())
   292  
   293  	err = Build(file.Name(), "", "", "", nil)
   294  	if err != nil {
   295  		t.Fatal(err)
   296  	}
   297  
   298  	if err := Add(file.Name(), []Record{
   299  		{
   300  			Hosts: "testhostname",
   301  			IP:    "2.2.2.2",
   302  		},
   303  	}); err != nil {
   304  		t.Fatal(err)
   305  	}
   306  
   307  	content, err := ioutil.ReadFile(file.Name())
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	if expected := "2.2.2.2\ttesthostname\n"; !bytes.Contains(content, []byte(expected)) {
   313  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   314  	}
   315  }
   316  
   317  func TestDeleteEmpty(t *testing.T) {
   318  	file, err := ioutil.TempFile("", "")
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  	defer os.Remove(file.Name())
   323  
   324  	err = Build(file.Name(), "", "", "", nil)
   325  	if err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	if err := Delete(file.Name(), []Record{}); err != nil {
   330  		t.Fatal(err)
   331  	}
   332  }
   333  
   334  func TestDeleteNewline(t *testing.T) {
   335  	file, err := ioutil.TempFile("", "")
   336  	if err != nil {
   337  		t.Fatal(err)
   338  	}
   339  	defer os.Remove(file.Name())
   340  
   341  	b := []byte("\n")
   342  	if _, err := file.Write(b); err != nil {
   343  		t.Fatal(err)
   344  	}
   345  
   346  	rec := []Record{
   347  		{
   348  			Hosts: "prefix",
   349  			IP:    "2.2.2.2",
   350  		},
   351  	}
   352  	if err := Delete(file.Name(), rec); err != nil {
   353  		t.Fatal(err)
   354  	}
   355  }
   356  
   357  func TestDelete(t *testing.T) {
   358  	file, err := ioutil.TempFile("", "")
   359  	if err != nil {
   360  		t.Fatal(err)
   361  	}
   362  	defer os.Remove(file.Name())
   363  
   364  	err = Build(file.Name(), "", "", "", nil)
   365  	if err != nil {
   366  		t.Fatal(err)
   367  	}
   368  
   369  	if err := Add(file.Name(), []Record{
   370  		{
   371  			Hosts: "testhostname1",
   372  			IP:    "1.1.1.1",
   373  		},
   374  		{
   375  			Hosts: "testhostname2",
   376  			IP:    "2.2.2.2",
   377  		},
   378  		{
   379  			Hosts: "testhostname3",
   380  			IP:    "3.3.3.3",
   381  		},
   382  	}); err != nil {
   383  		t.Fatal(err)
   384  	}
   385  
   386  	if err := Delete(file.Name(), []Record{
   387  		{
   388  			Hosts: "testhostname1",
   389  			IP:    "1.1.1.1",
   390  		},
   391  		{
   392  			Hosts: "testhostname3",
   393  			IP:    "3.3.3.3",
   394  		},
   395  	}); err != nil {
   396  		t.Fatal(err)
   397  	}
   398  
   399  	content, err := ioutil.ReadFile(file.Name())
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  
   404  	if expected := "2.2.2.2\ttesthostname2\n"; !bytes.Contains(content, []byte(expected)) {
   405  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   406  	}
   407  
   408  	if expected := "1.1.1.1\ttesthostname1\n"; bytes.Contains(content, []byte(expected)) {
   409  		t.Fatalf("Did not expect to find '%s' got '%s'", expected, content)
   410  	}
   411  }
   412  
   413  func TestConcurrentWrites(t *testing.T) {
   414  	file, err := ioutil.TempFile("", "")
   415  	if err != nil {
   416  		t.Fatal(err)
   417  	}
   418  	defer os.Remove(file.Name())
   419  
   420  	err = Build(file.Name(), "", "", "", nil)
   421  	if err != nil {
   422  		t.Fatal(err)
   423  	}
   424  
   425  	if err := Add(file.Name(), []Record{
   426  		{
   427  			Hosts: "inithostname",
   428  			IP:    "172.17.0.1",
   429  		},
   430  	}); err != nil {
   431  		t.Fatal(err)
   432  	}
   433  
   434  	var wg sync.WaitGroup
   435  	for i := 0; i < 10; i++ {
   436  		wg.Add(1)
   437  		go func(i int) {
   438  			defer wg.Done()
   439  
   440  			rec := []Record{
   441  				{
   442  					IP:    fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
   443  					Hosts: fmt.Sprintf("testhostname%d", i),
   444  				},
   445  			}
   446  
   447  			for j := 0; j < 25; j++ {
   448  				if err := Add(file.Name(), rec); err != nil {
   449  					t.Fatal(err)
   450  				}
   451  
   452  				if err := Delete(file.Name(), rec); err != nil {
   453  					t.Fatal(err)
   454  				}
   455  			}
   456  		}(i)
   457  	}
   458  
   459  	wg.Wait()
   460  
   461  	content, err := ioutil.ReadFile(file.Name())
   462  	if err != nil {
   463  		t.Fatal(err)
   464  	}
   465  
   466  	if expected := "172.17.0.1\tinithostname\n"; !bytes.Contains(content, []byte(expected)) {
   467  		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
   468  	}
   469  }
   470  
   471  func benchDelete(b *testing.B) {
   472  	b.StopTimer()
   473  	file, err := ioutil.TempFile("", "")
   474  	if err != nil {
   475  		b.Fatal(err)
   476  	}
   477  	defer func() {
   478  		b.StopTimer()
   479  		file.Close()
   480  		os.Remove(file.Name())
   481  		b.StartTimer()
   482  	}()
   483  
   484  	err = Build(file.Name(), "", "", "", nil)
   485  	if err != nil {
   486  		b.Fatal(err)
   487  	}
   488  
   489  	var records []Record
   490  	var toDelete []Record
   491  	for i := 0; i < 255; i++ {
   492  		record := Record{
   493  			Hosts: fmt.Sprintf("testhostname%d", i),
   494  			IP:    fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
   495  		}
   496  		records = append(records, record)
   497  		if i%2 == 0 {
   498  			toDelete = append(records, record)
   499  		}
   500  	}
   501  
   502  	if err := Add(file.Name(), records); err != nil {
   503  		b.Fatal(err)
   504  	}
   505  
   506  	b.StartTimer()
   507  	if err := Delete(file.Name(), toDelete); err != nil {
   508  		b.Fatal(err)
   509  	}
   510  }
   511  
   512  func BenchmarkDelete(b *testing.B) {
   513  	for i := 0; i < b.N; i++ {
   514  		benchDelete(b)
   515  	}
   516  }