github.com/rawahars/moby@v24.0.4+incompatible/libnetwork/resolvconf/resolvconf_unix_test.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  package resolvconf
     5  
     6  import (
     7  	"bytes"
     8  	"os"
     9  	"testing"
    10  )
    11  
    12  func TestGet(t *testing.T) {
    13  	actual, err := Get()
    14  	if err != nil {
    15  		t.Fatal(err)
    16  	}
    17  	expected, err := os.ReadFile(Path())
    18  	if err != nil {
    19  		t.Fatal(err)
    20  	}
    21  	if !bytes.Equal(actual.Content, expected) {
    22  		t.Errorf("%s and GetResolvConf have different content.", Path())
    23  	}
    24  	if !bytes.Equal(actual.Hash, hashData(expected)) {
    25  		t.Errorf("%s and GetResolvConf have different hashes.", Path())
    26  	}
    27  }
    28  
    29  func TestGetNameservers(t *testing.T) {
    30  	for _, tc := range []struct {
    31  		input  string
    32  		result []string
    33  	}{
    34  		{
    35  			input: ``,
    36  		},
    37  		{
    38  			input: `search example.com`,
    39  		},
    40  		{
    41  			input:  `  nameserver 1.2.3.4   `,
    42  			result: []string{"1.2.3.4"},
    43  		},
    44  		{
    45  			input: `
    46  nameserver 1.2.3.4
    47  nameserver 40.3.200.10
    48  search example.com`,
    49  			result: []string{"1.2.3.4", "40.3.200.10"},
    50  		},
    51  		{
    52  			input: `nameserver 1.2.3.4
    53  search example.com
    54  nameserver 4.30.20.100`,
    55  			result: []string{"1.2.3.4", "4.30.20.100"},
    56  		},
    57  		{
    58  			input: `search example.com
    59  nameserver 1.2.3.4
    60  #nameserver 4.3.2.1`,
    61  			result: []string{"1.2.3.4"},
    62  		},
    63  		{
    64  			input: `search example.com
    65  nameserver 1.2.3.4 # not 4.3.2.1`,
    66  			result: []string{"1.2.3.4"},
    67  		},
    68  	} {
    69  		test := GetNameservers([]byte(tc.input), IP)
    70  		if !strSlicesEqual(test, tc.result) {
    71  			t.Errorf("Wrong nameserver string {%s} should be %v. Input: %s", test, tc.result, tc.input)
    72  		}
    73  	}
    74  }
    75  
    76  func TestGetNameserversAsCIDR(t *testing.T) {
    77  	for _, tc := range []struct {
    78  		input  string
    79  		result []string
    80  	}{
    81  		{
    82  			input: ``,
    83  		},
    84  		{
    85  			input: `search example.com`,
    86  		},
    87  		{
    88  			input:  `  nameserver 1.2.3.4   `,
    89  			result: []string{"1.2.3.4/32"},
    90  		},
    91  		{
    92  			input: `
    93  nameserver 1.2.3.4
    94  nameserver 40.3.200.10
    95  search example.com`,
    96  			result: []string{"1.2.3.4/32", "40.3.200.10/32"},
    97  		},
    98  		{
    99  			input: `nameserver 1.2.3.4
   100  search example.com
   101  nameserver 4.30.20.100`,
   102  			result: []string{"1.2.3.4/32", "4.30.20.100/32"},
   103  		},
   104  		{
   105  			input: `search example.com
   106  nameserver 1.2.3.4
   107  #nameserver 4.3.2.1`,
   108  			result: []string{"1.2.3.4/32"},
   109  		},
   110  		{
   111  			input: `search example.com
   112  nameserver 1.2.3.4 # not 4.3.2.1`,
   113  			result: []string{"1.2.3.4/32"},
   114  		},
   115  	} {
   116  		test := GetNameserversAsCIDR([]byte(tc.input))
   117  		if !strSlicesEqual(test, tc.result) {
   118  			t.Errorf("Wrong nameserver string {%s} should be %v. Input: %s", test, tc.result, tc.input)
   119  		}
   120  	}
   121  }
   122  
   123  func TestGetSearchDomains(t *testing.T) {
   124  	for _, tc := range []struct {
   125  		input  string
   126  		result []string
   127  	}{
   128  		{
   129  			input: ``,
   130  		},
   131  		{
   132  			input: `# ignored`,
   133  		},
   134  		{
   135  			input:  `search example.com`,
   136  			result: []string{"example.com"},
   137  		},
   138  		{
   139  			input:  `search example.com # ignored`,
   140  			result: []string{"example.com"},
   141  		},
   142  		{
   143  			input:  `	  search	 example.com	  `,
   144  			result: []string{"example.com"},
   145  		},
   146  		{
   147  			input:  `	  search	 example.com	  # ignored`,
   148  			result: []string{"example.com"},
   149  		},
   150  		{
   151  			input:  `search foo.example.com example.com`,
   152  			result: []string{"foo.example.com", "example.com"},
   153  		},
   154  		{
   155  			input:  `	   search	   foo.example.com	 example.com	`,
   156  			result: []string{"foo.example.com", "example.com"},
   157  		},
   158  		{
   159  			input:  `	   search	   foo.example.com	 example.com	# ignored`,
   160  			result: []string{"foo.example.com", "example.com"},
   161  		},
   162  		{
   163  			input: `nameserver 1.2.3.4
   164  search foo.example.com example.com`,
   165  			result: []string{"foo.example.com", "example.com"},
   166  		},
   167  		{
   168  			input: `nameserver 1.2.3.4
   169  search dup1.example.com dup2.example.com
   170  search foo.example.com example.com`,
   171  			result: []string{"foo.example.com", "example.com"},
   172  		},
   173  		{
   174  			input: `nameserver 1.2.3.4
   175  search foo.example.com example.com
   176  nameserver 4.30.20.100`,
   177  			result: []string{"foo.example.com", "example.com"},
   178  		},
   179  	} {
   180  		test := GetSearchDomains([]byte(tc.input))
   181  		if !strSlicesEqual(test, tc.result) {
   182  			t.Errorf("Wrong search domain string {%s} should be %v. Input: %s", test, tc.result, tc.input)
   183  		}
   184  	}
   185  }
   186  
   187  func TestGetOptions(t *testing.T) {
   188  	for _, tc := range []struct {
   189  		input  string
   190  		result []string
   191  	}{
   192  		{
   193  			input: ``,
   194  		},
   195  		{
   196  			input: `# ignored`,
   197  		},
   198  		{
   199  			input: `nameserver 1.2.3.4`,
   200  		},
   201  		{
   202  			input:  `options opt1`,
   203  			result: []string{"opt1"},
   204  		},
   205  		{
   206  			input:  `options opt1 # ignored`,
   207  			result: []string{"opt1"},
   208  		},
   209  		{
   210  			input:  `	  options	 opt1	  `,
   211  			result: []string{"opt1"},
   212  		},
   213  		{
   214  			input:  `	  options	 opt1	  # ignored`,
   215  			result: []string{"opt1"},
   216  		},
   217  		{
   218  			input:  `options opt1 opt2 opt3`,
   219  			result: []string{"opt1", "opt2", "opt3"},
   220  		},
   221  		{
   222  			input:  `options opt1 opt2 opt3 # ignored`,
   223  			result: []string{"opt1", "opt2", "opt3"},
   224  		},
   225  		{
   226  			input:  `	   options	 opt1	 opt2	 opt3	`,
   227  			result: []string{"opt1", "opt2", "opt3"},
   228  		},
   229  		{
   230  			input:  `	   options	 opt1	 opt2	 opt3	# ignored`,
   231  			result: []string{"opt1", "opt2", "opt3"},
   232  		},
   233  		{
   234  			input: `nameserver 1.2.3.4
   235  options opt1 opt2 opt3`,
   236  			result: []string{"opt1", "opt2", "opt3"},
   237  		},
   238  		{
   239  			input: `nameserver 1.2.3.4
   240  options opt1 opt2
   241  options opt3 opt4`,
   242  			result: []string{"opt3", "opt4"},
   243  		},
   244  	} {
   245  		test := GetOptions([]byte(tc.input))
   246  		if !strSlicesEqual(test, tc.result) {
   247  			t.Errorf("Wrong options string {%s} should be %v. Input: %s", test, tc.result, tc.input)
   248  		}
   249  	}
   250  }
   251  
   252  func strSlicesEqual(a, b []string) bool {
   253  	if len(a) != len(b) {
   254  		return false
   255  	}
   256  
   257  	for i, v := range a {
   258  		if v != b[i] {
   259  			return false
   260  		}
   261  	}
   262  
   263  	return true
   264  }
   265  
   266  func TestBuild(t *testing.T) {
   267  	tmpDir := t.TempDir()
   268  	file, err := os.CreateTemp(tmpDir, "")
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	f, err := Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"search1"}, []string{"opt1"})
   274  	if err != nil {
   275  		t.Fatal(err)
   276  	}
   277  
   278  	const expected = "search search1\nnameserver ns1\nnameserver ns2\nnameserver ns3\noptions opt1\n"
   279  	if !bytes.Equal(f.Content, []byte(expected)) {
   280  		t.Errorf("Expected to find '%s' got '%s'", expected, f.Content)
   281  	}
   282  	content, err := os.ReadFile(file.Name())
   283  	if err != nil {
   284  		t.Fatal(err)
   285  	}
   286  	if !bytes.Equal(content, []byte(expected)) {
   287  		t.Errorf("Expected to find '%s' got '%s'", expected, content)
   288  	}
   289  }
   290  
   291  func TestBuildWithZeroLengthDomainSearch(t *testing.T) {
   292  	tmpDir := t.TempDir()
   293  	file, err := os.CreateTemp(tmpDir, "")
   294  	if err != nil {
   295  		t.Fatal(err)
   296  	}
   297  
   298  	f, err := Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"."}, []string{"opt1"})
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  
   303  	const expected = "nameserver ns1\nnameserver ns2\nnameserver ns3\noptions opt1\n"
   304  	if !bytes.Equal(f.Content, []byte(expected)) {
   305  		t.Errorf("Expected to find '%s' got '%s'", expected, f.Content)
   306  	}
   307  	content, err := os.ReadFile(file.Name())
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  	if !bytes.Equal(content, []byte(expected)) {
   312  		t.Errorf("Expected to find '%s' got '%s'", expected, content)
   313  	}
   314  }
   315  
   316  func TestBuildWithNoOptions(t *testing.T) {
   317  	tmpDir := t.TempDir()
   318  	file, err := os.CreateTemp(tmpDir, "")
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  
   323  	f, err := Build(file.Name(), []string{"ns1", "ns2", "ns3"}, []string{"search1"}, []string{})
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  
   328  	const expected = "search search1\nnameserver ns1\nnameserver ns2\nnameserver ns3\n"
   329  	if !bytes.Equal(f.Content, []byte(expected)) {
   330  		t.Errorf("Expected to find '%s' got '%s'", expected, f.Content)
   331  	}
   332  	content, err := os.ReadFile(file.Name())
   333  	if err != nil {
   334  		t.Fatal(err)
   335  	}
   336  	if !bytes.Equal(content, []byte(expected)) {
   337  		t.Errorf("Expected to find '%s' got '%s'", expected, content)
   338  	}
   339  }
   340  
   341  func TestFilterResolvDNS(t *testing.T) {
   342  	ns0 := "nameserver 10.16.60.14\nnameserver 10.16.60.21\n"
   343  
   344  	if result, _ := FilterResolvDNS([]byte(ns0), false); result != nil {
   345  		if ns0 != string(result.Content) {
   346  			t.Errorf("Failed No Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   347  		}
   348  	}
   349  
   350  	ns1 := "nameserver 10.16.60.14\nnameserver 10.16.60.21\nnameserver 127.0.0.1\n"
   351  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   352  		if ns0 != string(result.Content) {
   353  			t.Errorf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   354  		}
   355  	}
   356  
   357  	ns1 = "nameserver 10.16.60.14\nnameserver 127.0.0.1\nnameserver 10.16.60.21\n"
   358  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   359  		if ns0 != string(result.Content) {
   360  			t.Errorf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   361  		}
   362  	}
   363  
   364  	ns1 = "nameserver 127.0.1.1\nnameserver 10.16.60.14\nnameserver 10.16.60.21\n"
   365  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   366  		if ns0 != string(result.Content) {
   367  			t.Errorf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   368  		}
   369  	}
   370  
   371  	ns1 = "nameserver ::1\nnameserver 10.16.60.14\nnameserver 127.0.2.1\nnameserver 10.16.60.21\n"
   372  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   373  		if ns0 != string(result.Content) {
   374  			t.Errorf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   375  		}
   376  	}
   377  
   378  	ns1 = "nameserver 10.16.60.14\nnameserver ::1\nnameserver 10.16.60.21\nnameserver ::1"
   379  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   380  		if ns0 != string(result.Content) {
   381  			t.Errorf("Failed Localhost: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   382  		}
   383  	}
   384  
   385  	// with IPv6 disabled (false param), the IPv6 nameserver should be removed
   386  	ns1 = "nameserver 10.16.60.14\nnameserver 2002:dead:beef::1\nnameserver 10.16.60.21\nnameserver ::1"
   387  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   388  		if ns0 != string(result.Content) {
   389  			t.Errorf("Failed Localhost+IPv6 off: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   390  		}
   391  	}
   392  
   393  	// with IPv6 disabled (false param), the IPv6 link-local nameserver with zone ID should be removed
   394  	ns1 = "nameserver 10.16.60.14\nnameserver FE80::BB1%1\nnameserver FE80::BB1%eth0\nnameserver 10.16.60.21\n"
   395  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   396  		if ns0 != string(result.Content) {
   397  			t.Errorf("Failed Localhost+IPv6 off: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   398  		}
   399  	}
   400  
   401  	// with IPv6 enabled, the IPv6 nameserver should be preserved
   402  	ns0 = "nameserver 10.16.60.14\nnameserver 2002:dead:beef::1\nnameserver 10.16.60.21\n"
   403  	ns1 = "nameserver 10.16.60.14\nnameserver 2002:dead:beef::1\nnameserver 10.16.60.21\nnameserver ::1"
   404  	if result, _ := FilterResolvDNS([]byte(ns1), true); result != nil {
   405  		if ns0 != string(result.Content) {
   406  			t.Errorf("Failed Localhost+IPv6 on: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   407  		}
   408  	}
   409  
   410  	// with IPv6 enabled, and no non-localhost servers, Google defaults (both IPv4+IPv6) should be added
   411  	ns0 = "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\nnameserver 2001:4860:4860::8888\nnameserver 2001:4860:4860::8844"
   412  	ns1 = "nameserver 127.0.0.1\nnameserver ::1\nnameserver 127.0.2.1"
   413  	if result, _ := FilterResolvDNS([]byte(ns1), true); result != nil {
   414  		if ns0 != string(result.Content) {
   415  			t.Errorf("Failed no Localhost+IPv6 enabled: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   416  		}
   417  	}
   418  
   419  	// with IPv6 disabled, and no non-localhost servers, Google defaults (only IPv4) should be added
   420  	ns0 = "\nnameserver 8.8.8.8\nnameserver 8.8.4.4"
   421  	ns1 = "nameserver 127.0.0.1\nnameserver ::1\nnameserver 127.0.2.1"
   422  	if result, _ := FilterResolvDNS([]byte(ns1), false); result != nil {
   423  		if ns0 != string(result.Content) {
   424  			t.Errorf("Failed no Localhost+IPv6 enabled: expected \n<%s> got \n<%s>", ns0, string(result.Content))
   425  		}
   426  	}
   427  }