github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/net/dnsconfig_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 //go:build unix 6 7 package net 8 9 import ( 10 "errors" 11 "io/fs" 12 "os" 13 "reflect" 14 "strings" 15 "testing" 16 "time" 17 ) 18 19 var dnsReadConfigTests = []struct { 20 name string 21 want *dnsConfig 22 }{ 23 { 24 name: "testdata/resolv.conf", 25 want: &dnsConfig{ 26 servers: []string{"8.8.8.8:53", "[2001:4860:4860::8888]:53", "[fe80::1%lo0]:53"}, 27 search: []string{"localdomain."}, 28 ndots: 5, 29 timeout: 10 * time.Second, 30 attempts: 3, 31 rotate: true, 32 unknownOpt: true, // the "options attempts 3" line 33 }, 34 }, 35 { 36 name: "testdata/domain-resolv.conf", 37 want: &dnsConfig{ 38 servers: []string{"8.8.8.8:53"}, 39 search: []string{"localdomain."}, 40 ndots: 1, 41 timeout: 5 * time.Second, 42 attempts: 2, 43 }, 44 }, 45 { 46 name: "testdata/search-resolv.conf", 47 want: &dnsConfig{ 48 servers: []string{"8.8.8.8:53"}, 49 search: []string{"test.", "invalid."}, 50 ndots: 1, 51 timeout: 5 * time.Second, 52 attempts: 2, 53 }, 54 }, 55 { 56 name: "testdata/search-single-dot-resolv.conf", 57 want: &dnsConfig{ 58 servers: []string{"8.8.8.8:53"}, 59 search: []string{}, 60 ndots: 1, 61 timeout: 5 * time.Second, 62 attempts: 2, 63 }, 64 }, 65 { 66 name: "testdata/empty-resolv.conf", 67 want: &dnsConfig{ 68 servers: defaultNS, 69 ndots: 1, 70 timeout: 5 * time.Second, 71 attempts: 2, 72 search: []string{"domain.local."}, 73 }, 74 }, 75 { 76 name: "testdata/invalid-ndots-resolv.conf", 77 want: &dnsConfig{ 78 servers: defaultNS, 79 ndots: 0, 80 timeout: 5 * time.Second, 81 attempts: 2, 82 search: []string{"domain.local."}, 83 }, 84 }, 85 { 86 name: "testdata/large-ndots-resolv.conf", 87 want: &dnsConfig{ 88 servers: defaultNS, 89 ndots: 15, 90 timeout: 5 * time.Second, 91 attempts: 2, 92 search: []string{"domain.local."}, 93 }, 94 }, 95 { 96 name: "testdata/negative-ndots-resolv.conf", 97 want: &dnsConfig{ 98 servers: defaultNS, 99 ndots: 0, 100 timeout: 5 * time.Second, 101 attempts: 2, 102 search: []string{"domain.local."}, 103 }, 104 }, 105 { 106 name: "testdata/openbsd-resolv.conf", 107 want: &dnsConfig{ 108 ndots: 1, 109 timeout: 5 * time.Second, 110 attempts: 2, 111 lookup: []string{"file", "bind"}, 112 servers: []string{"169.254.169.254:53", "10.240.0.1:53"}, 113 search: []string{"c.symbolic-datum-552.internal."}, 114 }, 115 }, 116 { 117 name: "testdata/single-request-resolv.conf", 118 want: &dnsConfig{ 119 servers: defaultNS, 120 ndots: 1, 121 singleRequest: true, 122 timeout: 5 * time.Second, 123 attempts: 2, 124 search: []string{"domain.local."}, 125 }, 126 }, 127 { 128 name: "testdata/single-request-reopen-resolv.conf", 129 want: &dnsConfig{ 130 servers: defaultNS, 131 ndots: 1, 132 singleRequest: true, 133 timeout: 5 * time.Second, 134 attempts: 2, 135 search: []string{"domain.local."}, 136 }, 137 }, 138 { 139 name: "testdata/linux-use-vc-resolv.conf", 140 want: &dnsConfig{ 141 servers: defaultNS, 142 ndots: 1, 143 useTCP: true, 144 timeout: 5 * time.Second, 145 attempts: 2, 146 search: []string{"domain.local."}, 147 }, 148 }, 149 { 150 name: "testdata/freebsd-usevc-resolv.conf", 151 want: &dnsConfig{ 152 servers: defaultNS, 153 ndots: 1, 154 useTCP: true, 155 timeout: 5 * time.Second, 156 attempts: 2, 157 search: []string{"domain.local."}, 158 }, 159 }, 160 { 161 name: "testdata/openbsd-tcp-resolv.conf", 162 want: &dnsConfig{ 163 servers: defaultNS, 164 ndots: 1, 165 useTCP: true, 166 timeout: 5 * time.Second, 167 attempts: 2, 168 search: []string{"domain.local."}, 169 }, 170 }, 171 } 172 173 func TestDNSReadConfig(t *testing.T) { 174 origGetHostname := getHostname 175 defer func() { getHostname = origGetHostname }() 176 getHostname = func() (string, error) { return "host.domain.local", nil } 177 178 for _, tt := range dnsReadConfigTests { 179 want := *tt.want 180 if len(want.search) == 0 { 181 want.search = dnsDefaultSearch() 182 } 183 conf := dnsReadConfig(tt.name) 184 if conf.err != nil { 185 t.Fatal(conf.err) 186 } 187 conf.mtime = time.Time{} 188 if !reflect.DeepEqual(conf, &want) { 189 t.Errorf("%s:\ngot: %+v\nwant: %+v", tt.name, conf, want) 190 } 191 } 192 } 193 194 func TestDNSReadMissingFile(t *testing.T) { 195 origGetHostname := getHostname 196 defer func() { getHostname = origGetHostname }() 197 getHostname = func() (string, error) { return "host.domain.local", nil } 198 199 conf := dnsReadConfig("a-nonexistent-file") 200 if !os.IsNotExist(conf.err) { 201 t.Errorf("missing resolv.conf:\ngot: %v\nwant: %v", conf.err, fs.ErrNotExist) 202 } 203 conf.err = nil 204 want := &dnsConfig{ 205 servers: defaultNS, 206 ndots: 1, 207 timeout: 5 * time.Second, 208 attempts: 2, 209 search: []string{"domain.local."}, 210 } 211 if !reflect.DeepEqual(conf, want) { 212 t.Errorf("missing resolv.conf:\ngot: %+v\nwant: %+v", conf, want) 213 } 214 } 215 216 var dnsDefaultSearchTests = []struct { 217 name string 218 err error 219 want []string 220 }{ 221 { 222 name: "host.long.domain.local", 223 want: []string{"long.domain.local."}, 224 }, 225 { 226 name: "host.local", 227 want: []string{"local."}, 228 }, 229 { 230 name: "host", 231 want: nil, 232 }, 233 { 234 name: "host.domain.local", 235 err: errors.New("errored"), 236 want: nil, 237 }, 238 { 239 // ensures we don't return []string{""} 240 // which causes duplicate lookups 241 name: "foo.", 242 want: nil, 243 }, 244 } 245 246 func TestDNSDefaultSearch(t *testing.T) { 247 origGetHostname := getHostname 248 defer func() { getHostname = origGetHostname }() 249 250 for _, tt := range dnsDefaultSearchTests { 251 getHostname = func() (string, error) { return tt.name, tt.err } 252 got := dnsDefaultSearch() 253 if !reflect.DeepEqual(got, tt.want) { 254 t.Errorf("dnsDefaultSearch with hostname %q and error %+v = %q, wanted %q", tt.name, tt.err, got, tt.want) 255 } 256 } 257 } 258 259 func TestDNSNameLength(t *testing.T) { 260 origGetHostname := getHostname 261 defer func() { getHostname = origGetHostname }() 262 getHostname = func() (string, error) { return "host.domain.local", nil } 263 264 var char63 = "" 265 for i := 0; i < 63; i++ { 266 char63 += "a" 267 } 268 longDomain := strings.Repeat(char63+".", 5) + "example" 269 270 for _, tt := range dnsReadConfigTests { 271 conf := dnsReadConfig(tt.name) 272 if conf.err != nil { 273 t.Fatal(conf.err) 274 } 275 276 suffixList := tt.want.search 277 if len(suffixList) == 0 { 278 suffixList = dnsDefaultSearch() 279 } 280 281 var shortestSuffix int 282 for _, suffix := range suffixList { 283 if shortestSuffix == 0 || len(suffix) < shortestSuffix { 284 shortestSuffix = len(suffix) 285 } 286 } 287 288 // Test a name that will be maximally long when prefixing the shortest 289 // suffix (accounting for the intervening dot). 290 longName := longDomain[len(longDomain)-254+1+shortestSuffix:] 291 if longName[0] == '.' || longName[1] == '.' { 292 longName = "aa." + longName[3:] 293 } 294 for _, fqdn := range conf.nameList(longName) { 295 if len(fqdn) > 254 { 296 t.Errorf("got %d; want less than or equal to 254", len(fqdn)) 297 } 298 } 299 300 // Now test a name that's too long for suffixing. 301 unsuffixable := "a." + longName[1:] 302 unsuffixableResults := conf.nameList(unsuffixable) 303 if len(unsuffixableResults) != 1 { 304 t.Errorf("suffixed names %v; want []", unsuffixableResults[1:]) 305 } 306 307 // Now test a name that's too long for DNS. 308 tooLong := "a." + longDomain 309 tooLongResults := conf.nameList(tooLong) 310 if tooLongResults != nil { 311 t.Errorf("suffixed names %v; want nil", tooLongResults) 312 } 313 } 314 }