github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/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 if len(tt.want.search) == 0 { 180 tt.want.search = append(tt.want.search, dnsDefaultSearch()...) 181 } 182 conf := dnsReadConfig(tt.name) 183 if conf.err != nil { 184 t.Fatal(conf.err) 185 } 186 conf.mtime = time.Time{} 187 if !reflect.DeepEqual(conf, tt.want) { 188 t.Errorf("%s:\ngot: %+v\nwant: %+v", tt.name, conf, tt.want) 189 } 190 } 191 } 192 193 func TestDNSReadMissingFile(t *testing.T) { 194 origGetHostname := getHostname 195 defer func() { getHostname = origGetHostname }() 196 getHostname = func() (string, error) { return "host.domain.local", nil } 197 198 conf := dnsReadConfig("a-nonexistent-file") 199 if !os.IsNotExist(conf.err) { 200 t.Errorf("missing resolv.conf:\ngot: %v\nwant: %v", conf.err, fs.ErrNotExist) 201 } 202 conf.err = nil 203 want := &dnsConfig{ 204 servers: defaultNS, 205 ndots: 1, 206 timeout: 5 * time.Second, 207 attempts: 2, 208 search: []string{"domain.local."}, 209 } 210 if !reflect.DeepEqual(conf, want) { 211 t.Errorf("missing resolv.conf:\ngot: %+v\nwant: %+v", conf, want) 212 } 213 } 214 215 var dnsDefaultSearchTests = []struct { 216 name string 217 err error 218 want []string 219 }{ 220 { 221 name: "host.long.domain.local", 222 want: []string{"long.domain.local."}, 223 }, 224 { 225 name: "host.local", 226 want: []string{"local."}, 227 }, 228 { 229 name: "host", 230 want: nil, 231 }, 232 { 233 name: "host.domain.local", 234 err: errors.New("errored"), 235 want: nil, 236 }, 237 { 238 // ensures we don't return []string{""} 239 // which causes duplicate lookups 240 name: "foo.", 241 want: nil, 242 }, 243 } 244 245 func TestDNSDefaultSearch(t *testing.T) { 246 origGetHostname := getHostname 247 defer func() { getHostname = origGetHostname }() 248 249 for _, tt := range dnsDefaultSearchTests { 250 getHostname = func() (string, error) { return tt.name, tt.err } 251 got := dnsDefaultSearch() 252 if !reflect.DeepEqual(got, tt.want) { 253 t.Errorf("dnsDefaultSearch with hostname %q and error %+v = %q, wanted %q", tt.name, tt.err, got, tt.want) 254 } 255 } 256 } 257 258 func TestDNSNameLength(t *testing.T) { 259 origGetHostname := getHostname 260 defer func() { getHostname = origGetHostname }() 261 getHostname = func() (string, error) { return "host.domain.local", nil } 262 263 var char63 = "" 264 for i := 0; i < 63; i++ { 265 char63 += "a" 266 } 267 longDomain := strings.Repeat(char63+".", 5) + "example" 268 269 for _, tt := range dnsReadConfigTests { 270 conf := dnsReadConfig(tt.name) 271 if conf.err != nil { 272 t.Fatal(conf.err) 273 } 274 275 var shortestSuffix int 276 for _, suffix := range tt.want.search { 277 if shortestSuffix == 0 || len(suffix) < shortestSuffix { 278 shortestSuffix = len(suffix) 279 } 280 } 281 282 // Test a name that will be maximally long when prefixing the shortest 283 // suffix (accounting for the intervening dot). 284 longName := longDomain[len(longDomain)-254+1+shortestSuffix:] 285 if longName[0] == '.' || longName[1] == '.' { 286 longName = "aa." + longName[3:] 287 } 288 for _, fqdn := range conf.nameList(longName) { 289 if len(fqdn) > 254 { 290 t.Errorf("got %d; want less than or equal to 254", len(fqdn)) 291 } 292 } 293 294 // Now test a name that's too long for suffixing. 295 unsuffixable := "a." + longName[1:] 296 unsuffixableResults := conf.nameList(unsuffixable) 297 if len(unsuffixableResults) != 1 { 298 t.Errorf("suffixed names %v; want []", unsuffixableResults[1:]) 299 } 300 301 // Now test a name that's too long for DNS. 302 tooLong := "a." + longDomain 303 tooLongResults := conf.nameList(tooLong) 304 if tooLongResults != nil { 305 t.Errorf("suffixed names %v; want nil", tooLongResults) 306 } 307 } 308 }