github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/resolvconf/resolvconf_unix_test.go (about)

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