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