| 
									
										
										
										
											2013-08-13 09:44:12 -07:00
										 |  |  | // Copyright 2013 The Go Authors. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 15:50:01 +02:00
										 |  |  | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris | 
					
						
							| 
									
										
										
										
											2013-08-14 00:44:57 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-13 09:44:12 -07:00
										 |  |  | package net | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-04-14 17:47:25 -07:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-02-10 14:59:38 -08:00
										 |  |  | 	"internal/poll" | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path" | 
					
						
							|  |  |  | 	"reflect" | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2013-08-13 09:44:12 -07:00
										 |  |  | 	"testing" | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-05 15:01:53 -05:00
										 |  |  | 	"internal/x/net/dns/dnsmessage" | 
					
						
							| 
									
										
										
										
											2013-08-13 09:44:12 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | var goResolver = Resolver{PreferGo: true} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | // Test address from 192.0.2.0/24 block, reserved by RFC 5737 for documentation. | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | var TestAddr = [4]byte{0xc0, 0x00, 0x02, 0x01} | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | // Test address from 2001:db8::/32 block, reserved by RFC 3849 for documentation. | 
					
						
							|  |  |  | var TestAddr6 = [16]byte{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | func mustNewName(name string) dnsmessage.Name { | 
					
						
							|  |  |  | 	nn, err := dnsmessage.NewName(name) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		panic(fmt.Sprint("creating name: ", err)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nn | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func mustQuestion(name string, qtype dnsmessage.Type, class dnsmessage.Class) dnsmessage.Question { | 
					
						
							|  |  |  | 	return dnsmessage.Question{ | 
					
						
							|  |  |  | 		Name:  mustNewName(name), | 
					
						
							|  |  |  | 		Type:  qtype, | 
					
						
							|  |  |  | 		Class: class, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | var dnsTransportFallbackTests = []struct { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	server   string | 
					
						
							|  |  |  | 	question dnsmessage.Question | 
					
						
							|  |  |  | 	timeout  int | 
					
						
							|  |  |  | 	rcode    dnsmessage.RCode | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | }{ | 
					
						
							|  |  |  | 	// Querying "com." with qtype=255 usually makes an answer | 
					
						
							|  |  |  | 	// which requires more than 512 bytes. | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	{"8.8.8.8:53", mustQuestion("com.", dnsmessage.TypeALL, dnsmessage.ClassINET), 2, dnsmessage.RCodeSuccess}, | 
					
						
							|  |  |  | 	{"8.8.4.4:53", mustQuestion("com.", dnsmessage.TypeALL, dnsmessage.ClassINET), 4, dnsmessage.RCodeSuccess}, | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestDNSTransportFallback(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	fake := fakeDNSServer{ | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 			r := dnsmessage.Message{ | 
					
						
							|  |  |  | 				Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 					ID:       q.Header.ID, | 
					
						
							|  |  |  | 					Response: true, | 
					
						
							|  |  |  | 					RCode:    dnsmessage.RCodeSuccess, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if n == "udp" { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				r.Header.Truncated = true | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			return r, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 	for _, tt := range dnsTransportFallbackTests { | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 		ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							| 
									
										
											  
											
												net: fix plan9 after context change, propagate contexts more
My previous https://golang.org/cl/22101 to add context throughout the
net package broke Plan 9, which isn't currently tested (#15251).
It also broke some old unsupported version of Windows (Windows 2000?)
which doesn't have the ConnectEx function, but that was only found
visually, since our minimum supported Windows version has ConnectEx.
This change simplifies the Windows and deletes the non-ConnectEx code
path.  Windows 2000 will work even less now, if it even worked
before. Windows XP remains our minimum supported version.
Specifically, the previous CL stopped using the "dial" function, which
0intro noted:
https://github.com/golang/go/issues/15333#issuecomment-210842761
This CL removes the dial function instead and makes plan9's net
implementation respect contexts, which likely fixes a number of
t.Skipped tests. I'm leaving that to 0intro to investigate.
In the process of propagating and respecting contexts for plan9, I had
to change some signatures to add contexts to more places and ended up
pushing contexts down into the Go-based DNS resolution as well,
replacing the pure-Go DNS implementation's use of "timeout
time.Duration" with a context instead.
Updates #11932
Updates #15328
Fixes #15333
Change-Id: I6ad1e62f38271cdd86b3f40921f2d0f23374936a
Reviewed-on: https://go-review.googlesource.com/22144
Reviewed-by: David du Colombier <0intro@gmail.com>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
											
										 
											2016-04-16 14:17:40 -07:00
										 |  |  | 		defer cancel() | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		_, h, err := r.exchange(ctx, tt.server, tt.question, time.Second) | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		if h.RCode != tt.rcode { | 
					
						
							|  |  |  | 			t.Errorf("got %v from %v; want %v", h.RCode, tt.server, tt.rcode) | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // See RFC 6761 for further information about the reserved, pseudo | 
					
						
							|  |  |  | // domain names. | 
					
						
							|  |  |  | var specialDomainNameTests = []struct { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	question dnsmessage.Question | 
					
						
							|  |  |  | 	rcode    dnsmessage.RCode | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | }{ | 
					
						
							| 
									
										
										
										
											2015-01-14 21:25:26 -08:00
										 |  |  | 	// Name resolution APIs and libraries should not recognize the | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 	// followings as special. | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	{mustQuestion("1.0.168.192.in-addr.arpa.", dnsmessage.TypePTR, dnsmessage.ClassINET), dnsmessage.RCodeNameError}, | 
					
						
							|  |  |  | 	{mustQuestion("test.", dnsmessage.TypeALL, dnsmessage.ClassINET), dnsmessage.RCodeNameError}, | 
					
						
							|  |  |  | 	{mustQuestion("example.com.", dnsmessage.TypeALL, dnsmessage.ClassINET), dnsmessage.RCodeSuccess}, | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-14 21:25:26 -08:00
										 |  |  | 	// Name resolution APIs and libraries should recognize the | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 	// followings as special and should not send any queries. | 
					
						
							| 
									
										
										
										
											2016-02-24 11:55:20 +01:00
										 |  |  | 	// Though, we test those names here for verifying negative | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 	// answers at DNS query-response interaction level. | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	{mustQuestion("localhost.", dnsmessage.TypeALL, dnsmessage.ClassINET), dnsmessage.RCodeNameError}, | 
					
						
							|  |  |  | 	{mustQuestion("invalid.", dnsmessage.TypeALL, dnsmessage.ClassINET), dnsmessage.RCodeNameError}, | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestSpecialDomainName(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		r := dnsmessage.Message{ | 
					
						
							|  |  |  | 			Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 				ID:       q.ID, | 
					
						
							|  |  |  | 				Response: true, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		switch q.Questions[0].Name.String() { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		case "example.com.": | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r.Header.RCode = dnsmessage.RCodeSuccess | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r.Header.RCode = dnsmessage.RCodeNameError | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return r, nil | 
					
						
							|  |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 	server := "8.8.8.8:53" | 
					
						
							|  |  |  | 	for _, tt := range specialDomainNameTests { | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 		ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							| 
									
										
											  
											
												net: fix plan9 after context change, propagate contexts more
My previous https://golang.org/cl/22101 to add context throughout the
net package broke Plan 9, which isn't currently tested (#15251).
It also broke some old unsupported version of Windows (Windows 2000?)
which doesn't have the ConnectEx function, but that was only found
visually, since our minimum supported Windows version has ConnectEx.
This change simplifies the Windows and deletes the non-ConnectEx code
path.  Windows 2000 will work even less now, if it even worked
before. Windows XP remains our minimum supported version.
Specifically, the previous CL stopped using the "dial" function, which
0intro noted:
https://github.com/golang/go/issues/15333#issuecomment-210842761
This CL removes the dial function instead and makes plan9's net
implementation respect contexts, which likely fixes a number of
t.Skipped tests. I'm leaving that to 0intro to investigate.
In the process of propagating and respecting contexts for plan9, I had
to change some signatures to add contexts to more places and ended up
pushing contexts down into the Go-based DNS resolution as well,
replacing the pure-Go DNS implementation's use of "timeout
time.Duration" with a context instead.
Updates #11932
Updates #15328
Fixes #15333
Change-Id: I6ad1e62f38271cdd86b3f40921f2d0f23374936a
Reviewed-on: https://go-review.googlesource.com/22144
Reviewed-by: David du Colombier <0intro@gmail.com>
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
											
										 
											2016-04-16 14:17:40 -07:00
										 |  |  | 		defer cancel() | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		_, h, err := r.exchange(ctx, server, tt.question, 3*time.Second) | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		if h.RCode != tt.rcode { | 
					
						
							|  |  |  | 			t.Errorf("got %v from %v; want %v", h.RCode, server, tt.rcode) | 
					
						
							| 
									
										
										
										
											2014-08-06 09:58:47 +09:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-08-13 09:44:12 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-30 23:08:44 -07:00
										 |  |  | // Issue 13705: don't try to resolve onion addresses, etc | 
					
						
							|  |  |  | func TestAvoidDNSName(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name  string | 
					
						
							|  |  |  | 		avoid bool | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{"foo.com", false}, | 
					
						
							|  |  |  | 		{"foo.com.", false}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		{"foo.onion.", true}, | 
					
						
							|  |  |  | 		{"foo.onion", true}, | 
					
						
							|  |  |  | 		{"foo.ONION", true}, | 
					
						
							|  |  |  | 		{"foo.ONION.", true}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-17 10:13:03 +01:00
										 |  |  | 		// But do resolve *.local address; Issue 16739 | 
					
						
							|  |  |  | 		{"foo.local.", false}, | 
					
						
							|  |  |  | 		{"foo.local", false}, | 
					
						
							|  |  |  | 		{"foo.LOCAL", false}, | 
					
						
							|  |  |  | 		{"foo.LOCAL.", false}, | 
					
						
							| 
									
										
										
										
											2016-03-30 23:08:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		{"", true}, // will be rejected earlier too | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Without stuff before onion/local, they're fine to | 
					
						
							|  |  |  | 		// use DNS. With a search path, | 
					
						
							|  |  |  | 		// "onion.vegegtables.com" can use DNS. Without a | 
					
						
							|  |  |  | 		// search path (or with a trailing dot), the queries | 
					
						
							|  |  |  | 		// are just kinda useless, but don't reveal anything | 
					
						
							|  |  |  | 		// private. | 
					
						
							|  |  |  | 		{"local", false}, | 
					
						
							|  |  |  | 		{"onion", false}, | 
					
						
							|  |  |  | 		{"local.", false}, | 
					
						
							|  |  |  | 		{"onion.", false}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, tt := range tests { | 
					
						
							|  |  |  | 		got := avoidDNS(tt.name) | 
					
						
							|  |  |  | 		if got != tt.avoid { | 
					
						
							|  |  |  | 			t.Errorf("avoidDNS(%q) = %v; want %v", tt.name, got, tt.avoid) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | var fakeDNSServerSuccessful = fakeDNSServer{rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	r := dnsmessage.Message{ | 
					
						
							|  |  |  | 		Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 			ID:       q.ID, | 
					
						
							|  |  |  | 			Response: true, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		Questions: q.Questions, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(q.Questions) == 1 && q.Questions[0].Type == dnsmessage.TypeA { | 
					
						
							|  |  |  | 		r.Answers = []dnsmessage.Resource{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 					Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 					Type:   dnsmessage.TypeA, | 
					
						
							|  |  |  | 					Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 					Length: 4, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Body: &dnsmessage.AResource{ | 
					
						
							|  |  |  | 					A: TestAddr, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return r, nil | 
					
						
							|  |  |  | }} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-30 23:08:44 -07:00
										 |  |  | // Issue 13705: don't try to resolve onion addresses, etc | 
					
						
							|  |  |  | func TestLookupTorOnion(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	r := Resolver{PreferGo: true, Dial: fakeDNSServerSuccessful.DialContext} | 
					
						
							|  |  |  | 	addrs, err := r.LookupIPAddr(context.Background(), "foo.onion") | 
					
						
							| 
									
										
										
										
											2016-03-30 23:08:44 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("lookup = %v; want nil", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	if len(addrs) > 0 { | 
					
						
							|  |  |  | 		t.Errorf("unexpected addresses: %v", addrs) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-30 23:08:44 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | type resolvConfTest struct { | 
					
						
							| 
									
										
										
										
											2015-05-12 23:56:56 -04:00
										 |  |  | 	dir  string | 
					
						
							|  |  |  | 	path string | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	*resolverConfig | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | func newResolvConfTest() (*resolvConfTest, error) { | 
					
						
							| 
									
										
										
										
											2015-05-06 10:41:01 +09:00
										 |  |  | 	dir, err := ioutil.TempDir("", "go-resolvconftest") | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	conf := &resolvConfTest{ | 
					
						
							|  |  |  | 		dir:            dir, | 
					
						
							|  |  |  | 		path:           path.Join(dir, "resolv.conf"), | 
					
						
							|  |  |  | 		resolverConfig: &resolvConf, | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	conf.initOnce.Do(conf.init) | 
					
						
							|  |  |  | 	return conf, nil | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | func (conf *resolvConfTest) writeAndUpdate(lines []string) error { | 
					
						
							|  |  |  | 	f, err := os.OpenFile(conf.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	if _, err := f.WriteString(strings.Join(lines, "\n")); err != nil { | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 		f.Close() | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	f.Close() | 
					
						
							| 
									
										
										
										
											2016-02-20 20:33:34 -08:00
										 |  |  | 	if err := conf.forceUpdate(conf.path, time.Now().Add(time.Hour)); err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 20:33:34 -08:00
										 |  |  | func (conf *resolvConfTest) forceUpdate(name string, lastChecked time.Time) error { | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	dnsConf := dnsReadConfig(name) | 
					
						
							|  |  |  | 	conf.mu.Lock() | 
					
						
							|  |  |  | 	conf.dnsConfig = dnsConf | 
					
						
							|  |  |  | 	conf.mu.Unlock() | 
					
						
							|  |  |  | 	for i := 0; i < 5; i++ { | 
					
						
							|  |  |  | 		if conf.tryAcquireSema() { | 
					
						
							| 
									
										
										
										
											2016-02-20 20:33:34 -08:00
										 |  |  | 			conf.lastChecked = lastChecked | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 			conf.releaseSema() | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	return fmt.Errorf("tryAcquireSema for %s failed", name) | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | func (conf *resolvConfTest) servers() []string { | 
					
						
							|  |  |  | 	conf.mu.RLock() | 
					
						
							|  |  |  | 	servers := conf.dnsConfig.servers | 
					
						
							|  |  |  | 	conf.mu.RUnlock() | 
					
						
							|  |  |  | 	return servers | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-25 20:50:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | func (conf *resolvConfTest) teardown() error { | 
					
						
							| 
									
										
										
										
											2016-02-20 20:33:34 -08:00
										 |  |  | 	err := conf.forceUpdate("/etc/resolv.conf", time.Time{}) | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	os.RemoveAll(conf.dir) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-25 20:50:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | var updateResolvConfTests = []struct { | 
					
						
							|  |  |  | 	name    string   // query name | 
					
						
							|  |  |  | 	lines   []string // resolver configuration lines | 
					
						
							|  |  |  | 	servers []string // expected name servers | 
					
						
							|  |  |  | }{ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		name:    "golang.org", | 
					
						
							|  |  |  | 		lines:   []string{"nameserver 8.8.8.8"}, | 
					
						
							| 
									
										
										
										
											2016-04-28 11:15:44 -07:00
										 |  |  | 		servers: []string{"8.8.8.8:53"}, | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		name:    "", | 
					
						
							|  |  |  | 		lines:   nil, // an empty resolv.conf should use defaultNS as name servers | 
					
						
							|  |  |  | 		servers: defaultNS, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		name:    "www.example.com", | 
					
						
							|  |  |  | 		lines:   []string{"nameserver 8.8.4.4"}, | 
					
						
							| 
									
										
										
										
											2016-04-28 11:15:44 -07:00
										 |  |  | 		servers: []string{"8.8.4.4:53"}, | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | func TestUpdateResolvConf(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	r := Resolver{PreferGo: true, Dial: fakeDNSServerSuccessful.DialContext} | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2015-05-01 12:38:42 +09:00
										 |  |  | 		t.Fatal(err) | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	defer conf.teardown() | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	for i, tt := range updateResolvConfTests { | 
					
						
							|  |  |  | 		if err := conf.writeAndUpdate(tt.lines); err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if tt.name != "" { | 
					
						
							|  |  |  | 			var wg sync.WaitGroup | 
					
						
							|  |  |  | 			const N = 10 | 
					
						
							|  |  |  | 			wg.Add(N) | 
					
						
							|  |  |  | 			for j := 0; j < N; j++ { | 
					
						
							|  |  |  | 				go func(name string) { | 
					
						
							|  |  |  | 					defer wg.Done() | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 					ips, err := r.LookupIPAddr(context.Background(), name) | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 					if err != nil { | 
					
						
							|  |  |  | 						t.Error(err) | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					if len(ips) == 0 { | 
					
						
							|  |  |  | 						t.Errorf("no records for %s", name) | 
					
						
							|  |  |  | 						return | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}(tt.name) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			wg.Wait() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		servers := conf.servers() | 
					
						
							|  |  |  | 		if !reflect.DeepEqual(servers, tt.servers) { | 
					
						
							|  |  |  | 			t.Errorf("#%d: got %v; want %v", i, servers, tt.servers) | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2015-04-25 20:50:21 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-05-14 17:11:00 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-08-30 07:50:50 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-09 17:30:00 +09:00
										 |  |  | var goLookupIPWithResolverConfigTests = []struct { | 
					
						
							|  |  |  | 	name  string | 
					
						
							|  |  |  | 	lines []string // resolver configuration lines | 
					
						
							|  |  |  | 	error | 
					
						
							|  |  |  | 	a, aaaa bool // whether response contains A, AAAA-record | 
					
						
							|  |  |  | }{ | 
					
						
							|  |  |  | 	// no records, transport timeout | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"options timeout:1 attempts:1", | 
					
						
							|  |  |  | 			"nameserver 255.255.255.255", // please forgive us for abuse of limited broadcast address | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		&DNSError{Name: "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", Server: "255.255.255.255:53", IsTimeout: true}, | 
					
						
							|  |  |  | 		false, false, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// no records, non-existent domain | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"options timeout:3 attempts:1", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		&DNSError{Name: "jgahvsekduiv9bw4b3qhn4ykdfgj0493iohkrjfhdvhjiu4j", Server: "8.8.8.8:53", IsTimeout: false}, | 
					
						
							|  |  |  | 		false, false, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// a few A records, no AAAA records | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv4.google.com.", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		true, false, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv4.google.com", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"domain golang.org", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		true, false, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv4.google.com", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"search x.golang.org y.golang.org", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		true, false, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// no A records, a few AAAA records | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv6.google.com.", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		false, true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv6.google.com", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"domain golang.org", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		false, true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"ipv6.google.com", | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"search x.golang.org y.golang.org", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		false, true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// both A and AAAA records | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"hostname.as112.net", // see RFC 7534 | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"domain golang.org", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		true, true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"hostname.as112.net", // see RFC 7534 | 
					
						
							|  |  |  | 		[]string{ | 
					
						
							|  |  |  | 			"search x.golang.org y.golang.org", | 
					
						
							|  |  |  | 			"nameserver 2001:4860:4860::8888", | 
					
						
							|  |  |  | 			"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 		true, true, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGoLookupIPWithResolverConfig(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(n, s string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		switch s { | 
					
						
							|  |  |  | 		case "[2001:4860:4860::8888]:53", "8.8.8.8:53": | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			time.Sleep(10 * time.Millisecond) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			return dnsmessage.Message{}, poll.ErrTimeout | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		r := dnsmessage.Message{ | 
					
						
							|  |  |  | 			Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 				ID:       q.ID, | 
					
						
							|  |  |  | 				Response: true, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		for _, question := range q.Questions { | 
					
						
							|  |  |  | 			switch question.Type { | 
					
						
							|  |  |  | 			case dnsmessage.TypeA: | 
					
						
							|  |  |  | 				switch question.Name.String() { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 				case "hostname.as112.net.": | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				case "ipv4.google.com.": | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 					r.Answers = append(r.Answers, dnsmessage.Resource{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:   dnsmessage.TypeA, | 
					
						
							|  |  |  | 							Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 							Length: 4, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.AResource{ | 
					
						
							|  |  |  | 							A: TestAddr, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			case dnsmessage.TypeAAAA: | 
					
						
							|  |  |  | 				switch question.Name.String() { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 				case "hostname.as112.net.": | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				case "ipv6.google.com.": | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 					r.Answers = append(r.Answers, dnsmessage.Resource{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:   dnsmessage.TypeAAAA, | 
					
						
							|  |  |  | 							Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 							Length: 16, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.AAAAResource{ | 
					
						
							|  |  |  | 							AAAA: TestAddr6, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return r, nil | 
					
						
							|  |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2015-06-09 17:30:00 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tt := range goLookupIPWithResolverConfigTests { | 
					
						
							|  |  |  | 		if err := conf.writeAndUpdate(tt.lines); err != nil { | 
					
						
							|  |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		addrs, err := r.LookupIPAddr(context.Background(), tt.name) | 
					
						
							| 
									
										
										
										
											2015-06-09 17:30:00 +09:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-02-24 11:59:49 +09:00
										 |  |  | 			if err, ok := err.(*DNSError); !ok || tt.error != nil && (err.Name != tt.error.(*DNSError).Name || err.Server != tt.error.(*DNSError).Server || err.IsTimeout != tt.error.(*DNSError).IsTimeout) { | 
					
						
							| 
									
										
										
										
											2015-06-09 17:30:00 +09:00
										 |  |  | 				t.Errorf("got %v; want %v", err, tt.error) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(addrs) == 0 { | 
					
						
							|  |  |  | 			t.Errorf("no records for %s", tt.name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !tt.a && !tt.aaaa && len(addrs) > 0 { | 
					
						
							|  |  |  | 			t.Errorf("unexpected %v for %s", addrs, tt.name) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, addr := range addrs { | 
					
						
							|  |  |  | 			if !tt.a && addr.IP.To4() != nil { | 
					
						
							|  |  |  | 				t.Errorf("got %v; must not be IPv4 address", addr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !tt.aaaa && addr.IP.To16() != nil && addr.IP.To4() == nil { | 
					
						
							|  |  |  | 				t.Errorf("got %v; must not be IPv6 address", addr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-30 13:08:46 +08:00
										 |  |  | // Test that goLookupIPOrder falls back to the host file when no DNS servers are available. | 
					
						
							|  |  |  | func TestGoLookupIPOrderFallbackToFile(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(n, s string, q dnsmessage.Message, tm time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		r := dnsmessage.Message{ | 
					
						
							|  |  |  | 			Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 				ID:       q.ID, | 
					
						
							|  |  |  | 				Response: true, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return r, nil | 
					
						
							|  |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2015-11-30 13:08:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Add a config that simulates no dns servers being available. | 
					
						
							|  |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate([]string{}); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Redirect host file lookups. | 
					
						
							|  |  |  | 	defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath) | 
					
						
							|  |  |  | 	testHookHostsPath = "testdata/hosts" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, order := range []hostLookupOrder{hostLookupFilesDNS, hostLookupDNSFiles} { | 
					
						
							|  |  |  | 		name := fmt.Sprintf("order %v", order) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-24 11:55:20 +01:00
										 |  |  | 		// First ensure that we get an error when contacting a non-existent host. | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		_, _, err := r.goLookupIPCNAMEOrder(context.Background(), "notarealhost", order) | 
					
						
							| 
									
										
										
										
											2015-11-30 13:08:46 +08:00
										 |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			t.Errorf("%s: expected error while looking up name not in hosts file", name) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Now check that we get an address when the name appears in the hosts file. | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		addrs, _, err := r.goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts" | 
					
						
							| 
									
										
										
										
											2015-11-30 13:08:46 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Errorf("%s: expected to successfully lookup host entry", name) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-02 11:02:04 +08:00
										 |  |  | 		if len(addrs) != 1 { | 
					
						
							|  |  |  | 			t.Errorf("%s: expected exactly one result, but got %v", name, addrs) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if got, want := addrs[0].String(), "127.1.1.1"; got != want { | 
					
						
							| 
									
										
										
										
											2015-11-30 13:08:46 +08:00
										 |  |  | 			t.Errorf("%s: address doesn't match expectation. got %v, want %v", name, got, want) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | // Issue 12712. | 
					
						
							|  |  |  | // When using search domains, return the error encountered | 
					
						
							|  |  |  | // querying the original name instead of an error encountered | 
					
						
							|  |  |  | // querying a generated name. | 
					
						
							|  |  |  | func TestErrorForOriginalNameWhenSearching(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 	const fqdn = "doesnotexist.domain" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate([]string{"search servfail"}); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		r := dnsmessage.Message{ | 
					
						
							|  |  |  | 			Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 				ID:       q.ID, | 
					
						
							|  |  |  | 				Response: true, | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		switch q.Questions[0].Name.String() { | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 		case fqdn + ".servfail.": | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r.Header.RCode = dnsmessage.RCodeServerFailure | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r.Header.RCode = dnsmessage.RCodeNameError | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return r, nil | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	}} | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	cases := []struct { | 
					
						
							|  |  |  | 		strictErrors bool | 
					
						
							|  |  |  | 		wantErr      *DNSError | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{true, &DNSError{Name: fqdn, Err: "server misbehaving", IsTemporary: true}}, | 
					
						
							|  |  |  | 		{false, &DNSError{Name: fqdn, Err: errNoSuchHost.Error()}}, | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	for _, tt := range cases { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		r := Resolver{PreferGo: true, StrictErrors: tt.strictErrors, Dial: fake.DialContext} | 
					
						
							|  |  |  | 		_, err = r.LookupIPAddr(context.Background(), fqdn) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			t.Fatal("expected an error") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		want := tt.wantErr | 
					
						
							|  |  |  | 		if err, ok := err.(*DNSError); !ok || err.Name != want.Name || err.Err != want.Err || err.IsTemporary != want.IsTemporary { | 
					
						
							|  |  |  | 			t.Errorf("got %v; want %v", err, want) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | // Issue 15434. If a name server gives a lame referral, continue to the next. | 
					
						
							|  |  |  | func TestIgnoreLameReferrals(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 	if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", // the one that will give a lame referral | 
					
						
							|  |  |  | 		"nameserver 192.0.2.2"}); err != nil { | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, s string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 		t.Log(s, q) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		r := dnsmessage.Message{ | 
					
						
							|  |  |  | 			Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 				ID:       q.ID, | 
					
						
							|  |  |  | 				Response: true, | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if s == "192.0.2.2:53" { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r.Header.RecursionAvailable = true | 
					
						
							|  |  |  | 			if q.Questions[0].Type == dnsmessage.TypeA { | 
					
						
							|  |  |  | 				r.Answers = []dnsmessage.Resource{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:   dnsmessage.TypeA, | 
					
						
							|  |  |  | 							Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 							Length: 4, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.AResource{ | 
					
						
							|  |  |  | 							A: TestAddr, | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return r, nil | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	addrs, err := r.LookupIPAddr(context.Background(), "www.golang.org") | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if got := len(addrs); got != 1 { | 
					
						
							| 
									
										
										
										
											2016-05-11 13:04:22 +09:00
										 |  |  | 		t.Fatalf("got %d addresses, want 1", got) | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if got, want := addrs[0].String(), "192.0.2.1"; got != want { | 
					
						
							| 
									
										
										
										
											2016-05-11 13:04:22 +09:00
										 |  |  | 		t.Fatalf("got address %v, want %v", got, want) | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | func BenchmarkGoLookupIP(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2015-05-14 09:25:24 +09:00
										 |  |  | 	testHookUninstaller.Do(uninstallTestHooks) | 
					
						
							| 
									
										
										
										
											2016-04-14 17:47:25 -07:00
										 |  |  | 	ctx := context.Background() | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | 	b.ReportAllocs() | 
					
						
							| 
									
										
											  
											
												net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
	/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
	/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
	/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
	/go/src/net/timeout_test.go:247 +0xc9
	(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
											
										 
											2015-03-01 12:27:01 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		goResolver.LookupIPAddr(ctx, "www.example.com") | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 07:50:50 +09:00
										 |  |  | func BenchmarkGoLookupIPNoSuchHost(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2015-05-14 09:25:24 +09:00
										 |  |  | 	testHookUninstaller.Do(uninstallTestHooks) | 
					
						
							| 
									
										
										
										
											2016-04-14 17:47:25 -07:00
										 |  |  | 	ctx := context.Background() | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | 	b.ReportAllocs() | 
					
						
							| 
									
										
											  
											
												net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
	/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
	/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
	/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
	/go/src/net/timeout_test.go:247 +0xc9
	(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
											
										 
											2015-03-01 12:27:01 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 07:50:50 +09:00
										 |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		goResolver.LookupIPAddr(ctx, "some.nonexistent") | 
					
						
							| 
									
										
										
										
											2014-08-30 07:50:50 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) { | 
					
						
							| 
									
										
										
										
											2015-05-14 09:25:24 +09:00
										 |  |  | 	testHookUninstaller.Do(uninstallTestHooks) | 
					
						
							| 
									
										
											  
											
												net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
	/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
	/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
	/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
	/go/src/net/timeout_test.go:247 +0xc9
	(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
											
										 
											2015-03-01 12:27:01 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		b.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lines := []string{ | 
					
						
							|  |  |  | 		"nameserver 203.0.113.254", // use TEST-NET-3 block, see RFC 5737 | 
					
						
							|  |  |  | 		"nameserver 8.8.8.8", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate(lines); err != nil { | 
					
						
							|  |  |  | 		b.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-14 17:47:25 -07:00
										 |  |  | 	ctx := context.Background() | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | 	b.ReportAllocs() | 
					
						
							| 
									
										
										
										
											2015-06-11 12:46:01 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | 	for i := 0; i < b.N; i++ { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		goResolver.LookupIPAddr(ctx, "www.example.com") | 
					
						
							| 
									
										
										
										
											2014-08-30 13:12:28 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | type fakeDNSServer struct { | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	rh        func(n, s string, q dnsmessage.Message, t time.Time) (dnsmessage.Message, error) | 
					
						
							|  |  |  | 	alwaysTCP bool | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | func (server *fakeDNSServer) DialContext(_ context.Context, n, s string) (Conn, error) { | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	if server.alwaysTCP || n == "tcp" || n == "tcp4" || n == "tcp6" { | 
					
						
							|  |  |  | 		return &fakeDNSConn{tcp: true, server: server, n: n, s: s}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return &fakeDNSPacketConn{fakeDNSConn: fakeDNSConn{tcp: false, server: server, n: n, s: s}}, nil | 
					
						
							| 
									
										
										
										
											2016-04-25 13:09:11 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type fakeDNSConn struct { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	Conn | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	tcp    bool | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	server *fakeDNSServer | 
					
						
							|  |  |  | 	n      string | 
					
						
							|  |  |  | 	s      string | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	q      dnsmessage.Message | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	t      time.Time | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	buf    []byte | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *fakeDNSConn) Close() error { | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | func (f *fakeDNSConn) Read(b []byte) (int, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	if len(f.buf) > 0 { | 
					
						
							|  |  |  | 		n := copy(b, f.buf) | 
					
						
							|  |  |  | 		f.buf = f.buf[n:] | 
					
						
							|  |  |  | 		return n, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 	resp, err := f.server.rh(f.n, f.s, f.q, f.t) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	bb := make([]byte, 2, 514) | 
					
						
							|  |  |  | 	bb, err = resp.AppendPack(bb) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return 0, fmt.Errorf("cannot marshal DNS message: %v", err) | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if f.tcp { | 
					
						
							|  |  |  | 		l := len(bb) - 2 | 
					
						
							|  |  |  | 		bb[0] = byte(l >> 8) | 
					
						
							|  |  |  | 		bb[1] = byte(l) | 
					
						
							|  |  |  | 		f.buf = bb | 
					
						
							|  |  |  | 		return f.Read(b) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bb = bb[2:] | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 	if len(b) < len(bb) { | 
					
						
							|  |  |  | 		return 0, errors.New("read would fragment DNS message") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	copy(b, bb) | 
					
						
							|  |  |  | 	return len(bb), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *fakeDNSConn) Write(b []byte) (int, error) { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	if f.tcp && len(b) >= 2 { | 
					
						
							|  |  |  | 		b = b[2:] | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if f.q.Unpack(b) != nil { | 
					
						
							|  |  |  | 		return 0, fmt.Errorf("cannot unmarshal DNS message fake %s (%d)", f.n, len(b)) | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return len(b), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | func (f *fakeDNSConn) SetDeadline(t time.Time) error { | 
					
						
							|  |  |  | 	f.t = t | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | type fakeDNSPacketConn struct { | 
					
						
							|  |  |  | 	PacketConn | 
					
						
							|  |  |  | 	fakeDNSConn | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *fakeDNSPacketConn) SetDeadline(t time.Time) error { | 
					
						
							|  |  |  | 	return f.fakeDNSConn.SetDeadline(t) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (f *fakeDNSPacketConn) Close() error { | 
					
						
							|  |  |  | 	return f.fakeDNSConn.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | // UDP round-tripper algorithm should ignore invalid DNS responses (issue 13281). | 
					
						
							|  |  |  | func TestIgnoreDNSForgeries(t *testing.T) { | 
					
						
							|  |  |  | 	c, s := Pipe() | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		b := make([]byte, 512) | 
					
						
							|  |  |  | 		n, err := s.Read(b) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2016-11-14 21:34:58 -08:00
										 |  |  | 			t.Error(err) | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		var msg dnsmessage.Message | 
					
						
							|  |  |  | 		if msg.Unpack(b[:n]) != nil { | 
					
						
							|  |  |  | 			t.Error("invalid DNS query:", err) | 
					
						
							| 
									
										
										
										
											2016-11-14 21:34:58 -08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		s.Write([]byte("garbage DNS response packet")) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		msg.Header.Response = true | 
					
						
							|  |  |  | 		msg.Header.ID++ // make invalid ID | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if b, err = msg.Pack(); err != nil { | 
					
						
							|  |  |  | 			t.Error("failed to pack DNS response:", err) | 
					
						
							| 
									
										
										
										
											2016-11-14 21:34:58 -08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		s.Write(b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		msg.Header.ID-- // restore original ID | 
					
						
							|  |  |  | 		msg.Answers = []dnsmessage.Resource{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 					Name:   mustNewName("www.example.com."), | 
					
						
							|  |  |  | 					Type:   dnsmessage.TypeA, | 
					
						
							|  |  |  | 					Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 					Length: 4, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Body: &dnsmessage.AResource{ | 
					
						
							|  |  |  | 					A: TestAddr, | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		b, err = msg.Pack() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			t.Error("failed to pack DNS response:", err) | 
					
						
							| 
									
										
										
										
											2016-11-14 21:34:58 -08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		s.Write(b) | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	msg := dnsmessage.Message{ | 
					
						
							|  |  |  | 		Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 			ID: 42, | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		Questions: []dnsmessage.Question{ | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				Name:  mustNewName("www.example.com."), | 
					
						
							|  |  |  | 				Type:  dnsmessage.TypeA, | 
					
						
							|  |  |  | 				Class: dnsmessage.ClassINET, | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	b, err := msg.Pack() | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		t.Fatal("Pack failed:", err) | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	p, _, err := dnsPacketRoundTrip(c, 42, msg.Questions[0], b) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatalf("dnsPacketRoundTrip failed: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p.SkipAllQuestions() | 
					
						
							|  |  |  | 	as, err := p.AllAnswers() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("AllAnswers failed:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if got := as[0].Body.(*dnsmessage.AResource).A; got != TestAddr { | 
					
						
							| 
									
										
										
										
											2016-05-11 13:04:22 +09:00
										 |  |  | 		t.Errorf("got address %v, want %v", got, TestAddr) | 
					
						
							| 
									
										
										
										
											2016-04-15 19:19:58 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-19 15:24:42 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Issue 16865. If a name server times out, continue to the next. | 
					
						
							|  |  |  | func TestRetryTimeout(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 	testConf := []string{ | 
					
						
							|  |  |  | 		"nameserver 192.0.2.1", // the one that will timeout | 
					
						
							|  |  |  | 		"nameserver 192.0.2.2", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate(testConf); err != nil { | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var deadline0 time.Time | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, s string, q dnsmessage.Message, deadline time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 		t.Log(s, q, deadline) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if deadline.IsZero() { | 
					
						
							|  |  |  | 			t.Error("zero deadline") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if s == "192.0.2.1:53" { | 
					
						
							|  |  |  | 			deadline0 = deadline | 
					
						
							|  |  |  | 			time.Sleep(10 * time.Millisecond) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			return dnsmessage.Message{}, poll.ErrTimeout | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-04 15:05:33 +00:00
										 |  |  | 		if deadline.Equal(deadline0) { | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 			t.Error("deadline didn't change") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 		return mockTXTResponse(q), nil | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	}} | 
					
						
							|  |  |  | 	r := &Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	_, err = r.LookupTXT(context.Background(), "www.golang.org") | 
					
						
							| 
									
										
										
										
											2016-08-29 13:53:32 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if deadline0.IsZero() { | 
					
						
							|  |  |  | 		t.Error("deadline0 still zero", deadline0) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestRotate(t *testing.T) { | 
					
						
							|  |  |  | 	// without rotation, always uses the first server | 
					
						
							|  |  |  | 	testRotate(t, false, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.1:53", "192.0.2.1:53"}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// with rotation, rotates through back to first | 
					
						
							|  |  |  | 	testRotate(t, true, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.2:53", "192.0.2.1:53"}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func testRotate(t *testing.T, rotate bool, nameservers, wantServers []string) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var confLines []string | 
					
						
							|  |  |  | 	for _, ns := range nameservers { | 
					
						
							|  |  |  | 		confLines = append(confLines, "nameserver "+ns) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if rotate { | 
					
						
							|  |  |  | 		confLines = append(confLines, "options rotate") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate(confLines); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var usedServers []string | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, s string, q dnsmessage.Message, deadline time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 		usedServers = append(usedServers, s) | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 		return mockTXTResponse(q), nil | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// len(nameservers) + 1 to allow rotation to get back to start | 
					
						
							|  |  |  | 	for i := 0; i < len(nameservers)+1; i++ { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		if _, err := r.LookupTXT(context.Background(), "www.golang.org"); err != nil { | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 			t.Fatal(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !reflect.DeepEqual(usedServers, wantServers) { | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 		t.Errorf("rotate=%t got used servers:\n%v\nwant:\n%v", rotate, usedServers, wantServers) | 
					
						
							| 
									
										
										
										
											2016-09-15 17:24:42 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | func mockTXTResponse(q dnsmessage.Message) dnsmessage.Message { | 
					
						
							|  |  |  | 	r := dnsmessage.Message{ | 
					
						
							|  |  |  | 		Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 			ID:                 q.ID, | 
					
						
							|  |  |  | 			Response:           true, | 
					
						
							|  |  |  | 			RecursionAvailable: true, | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		Questions: q.Questions, | 
					
						
							|  |  |  | 		Answers: []dnsmessage.Resource{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 					Name:  q.Questions[0].Name, | 
					
						
							|  |  |  | 					Type:  dnsmessage.TypeTXT, | 
					
						
							|  |  |  | 					Class: dnsmessage.ClassINET, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Body: &dnsmessage.TXTResource{ | 
					
						
							|  |  |  | 					TXT: []string{"ok"}, | 
					
						
							| 
									
										
										
										
											2016-12-19 13:05:53 -08:00
										 |  |  | 				}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return r | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Issue 17448. With StrictErrors enabled, temporary errors should make | 
					
						
							|  |  |  | // LookupIP fail rather than return a partial result. | 
					
						
							|  |  |  | func TestStrictErrorsLookupIP(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	confData := []string{ | 
					
						
							|  |  |  | 		"nameserver 192.0.2.53", | 
					
						
							|  |  |  | 		"search x.golang.org y.golang.org", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate(confData); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-17 13:34:56 -07:00
										 |  |  | 	const name = "test-issue19592" | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	const server = "192.0.2.53:53" | 
					
						
							| 
									
										
										
										
											2017-03-17 13:34:56 -07:00
										 |  |  | 	const searchX = "test-issue19592.x.golang.org." | 
					
						
							|  |  |  | 	const searchY = "test-issue19592.y.golang.org." | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	const ip4 = "192.0.2.1" | 
					
						
							|  |  |  | 	const ip6 = "2001:db8::1" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	type resolveWhichEnum int | 
					
						
							|  |  |  | 	const ( | 
					
						
							|  |  |  | 		resolveOK resolveWhichEnum = iota | 
					
						
							|  |  |  | 		resolveOpError | 
					
						
							|  |  |  | 		resolveServfail | 
					
						
							|  |  |  | 		resolveTimeout | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	makeTempError := func(err string) error { | 
					
						
							|  |  |  | 		return &DNSError{ | 
					
						
							|  |  |  | 			Err:         err, | 
					
						
							|  |  |  | 			Name:        name, | 
					
						
							|  |  |  | 			Server:      server, | 
					
						
							|  |  |  | 			IsTemporary: true, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	makeTimeout := func() error { | 
					
						
							|  |  |  | 		return &DNSError{ | 
					
						
							|  |  |  | 			Err:       poll.ErrTimeout.Error(), | 
					
						
							|  |  |  | 			Name:      name, | 
					
						
							|  |  |  | 			Server:    server, | 
					
						
							|  |  |  | 			IsTimeout: true, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	makeNxDomain := func() error { | 
					
						
							|  |  |  | 		return &DNSError{ | 
					
						
							|  |  |  | 			Err:    errNoSuchHost.Error(), | 
					
						
							|  |  |  | 			Name:   name, | 
					
						
							|  |  |  | 			Server: server, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cases := []struct { | 
					
						
							|  |  |  | 		desc          string | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		resolveWhich  func(quest dnsmessage.Question) resolveWhichEnum | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		wantStrictErr error | 
					
						
							|  |  |  | 		wantLaxErr    error | 
					
						
							|  |  |  | 		wantIPs       []string | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "No errors", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantIPs: []string{ip4, ip6}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchX error fails in strict mode", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchX { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveTimeout | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTimeout(), | 
					
						
							|  |  |  | 			wantIPs:       []string{ip4, ip6}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchX IPv4-only timeout fails in strict mode", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchX && quest.Type == dnsmessage.TypeA { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveTimeout | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTimeout(), | 
					
						
							|  |  |  | 			wantIPs:       []string{ip4, ip6}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchX IPv6-only servfail fails in strict mode", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchX && quest.Type == dnsmessage.TypeAAAA { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveServfail | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTempError("server misbehaving"), | 
					
						
							|  |  |  | 			wantIPs:       []string{ip4, ip6}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchY error always fails", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchY { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveTimeout | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTimeout(), | 
					
						
							|  |  |  | 			wantLaxErr:    makeNxDomain(), // This one reaches the "test." FQDN. | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchY IPv4-only socket error fails in strict mode", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchY && quest.Type == dnsmessage.TypeA { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveOpError | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTempError("write: socket on fire"), | 
					
						
							|  |  |  | 			wantIPs:       []string{ip6}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			desc: "searchY IPv6-only timeout fails in strict mode", | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			resolveWhich: func(quest dnsmessage.Question) resolveWhichEnum { | 
					
						
							|  |  |  | 				if quest.Name.String() == searchY && quest.Type == dnsmessage.TypeAAAA { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 					return resolveTimeout | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return resolveOK | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			wantStrictErr: makeTimeout(), | 
					
						
							|  |  |  | 			wantIPs:       []string{ip4}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, tt := range cases { | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 		fake := fakeDNSServer{rh: func(_, s string, q dnsmessage.Message, deadline time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			t.Log(s, q) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			switch tt.resolveWhich(q.Questions[0]) { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			case resolveOK: | 
					
						
							|  |  |  | 				// Handle below. | 
					
						
							|  |  |  | 			case resolveOpError: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{}, &OpError{Op: "write", Err: fmt.Errorf("socket on fire")} | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			case resolveServfail: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{ | 
					
						
							|  |  |  | 					Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 						ID:       q.ID, | 
					
						
							|  |  |  | 						Response: true, | 
					
						
							|  |  |  | 						RCode:    dnsmessage.RCodeServerFailure, | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 					}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 					Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 				}, nil | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			case resolveTimeout: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{}, poll.ErrTimeout | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				t.Fatal("Impossible resolveWhich") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			switch q.Questions[0].Name.String() { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			case searchX, name + ".": | 
					
						
							|  |  |  | 				// Return NXDOMAIN to utilize the search list. | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{ | 
					
						
							|  |  |  | 					Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 						ID:       q.ID, | 
					
						
							|  |  |  | 						Response: true, | 
					
						
							|  |  |  | 						RCode:    dnsmessage.RCodeNameError, | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 					}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 					Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2017-06-08 13:19:28 -07:00
										 |  |  | 				}, nil | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			case searchY: | 
					
						
							|  |  |  | 				// Return records below. | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{}, fmt.Errorf("Unexpected Name: %v", q.Questions[0].Name) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			r := dnsmessage.Message{ | 
					
						
							|  |  |  | 				Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 					ID:       q.ID, | 
					
						
							|  |  |  | 					Response: true, | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				Questions: q.Questions, | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			switch q.Questions[0].Type { | 
					
						
							|  |  |  | 			case dnsmessage.TypeA: | 
					
						
							|  |  |  | 				r.Answers = []dnsmessage.Resource{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:   dnsmessage.TypeA, | 
					
						
							|  |  |  | 							Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 							Length: 4, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.AResource{ | 
					
						
							|  |  |  | 							A: TestAddr, | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			case dnsmessage.TypeAAAA: | 
					
						
							|  |  |  | 				r.Answers = []dnsmessage.Resource{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:   q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:   dnsmessage.TypeAAAA, | 
					
						
							|  |  |  | 							Class:  dnsmessage.ClassINET, | 
					
						
							|  |  |  | 							Length: 16, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.AAAAResource{ | 
					
						
							|  |  |  | 							AAAA: TestAddr6, | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 				return dnsmessage.Message{}, fmt.Errorf("Unexpected Type: %v", q.Questions[0].Type) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			return r, nil | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		}} | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		for _, strict := range []bool{true, false} { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 			r := Resolver{PreferGo: true, StrictErrors: strict, Dial: fake.DialContext} | 
					
						
							|  |  |  | 			ips, err := r.LookupIPAddr(context.Background(), name) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var wantErr error | 
					
						
							|  |  |  | 			if strict { | 
					
						
							|  |  |  | 				wantErr = tt.wantStrictErr | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				wantErr = tt.wantLaxErr | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !reflect.DeepEqual(err, wantErr) { | 
					
						
							|  |  |  | 				t.Errorf("#%d (%s) strict=%v: got err %#v; want %#v", i, tt.desc, strict, err, wantErr) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			gotIPs := map[string]struct{}{} | 
					
						
							|  |  |  | 			for _, ip := range ips { | 
					
						
							|  |  |  | 				gotIPs[ip.String()] = struct{}{} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			wantIPs := map[string]struct{}{} | 
					
						
							|  |  |  | 			if wantErr == nil { | 
					
						
							|  |  |  | 				for _, ip := range tt.wantIPs { | 
					
						
							|  |  |  | 					wantIPs[ip] = struct{}{} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if !reflect.DeepEqual(gotIPs, wantIPs) { | 
					
						
							|  |  |  | 				t.Errorf("#%d (%s) strict=%v: got ips %v; want %v", i, tt.desc, strict, gotIPs, wantIPs) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Issue 17448. With StrictErrors enabled, temporary errors should make | 
					
						
							|  |  |  | // LookupTXT stop walking the search list. | 
					
						
							|  |  |  | func TestStrictErrorsLookupTXT(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 	conf, err := newResolvConfTest() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defer conf.teardown() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	confData := []string{ | 
					
						
							|  |  |  | 		"nameserver 192.0.2.53", | 
					
						
							|  |  |  | 		"search x.golang.org y.golang.org", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := conf.writeAndUpdate(confData); err != nil { | 
					
						
							|  |  |  | 		t.Fatal(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const name = "test" | 
					
						
							|  |  |  | 	const server = "192.0.2.53:53" | 
					
						
							|  |  |  | 	const searchX = "test.x.golang.org." | 
					
						
							|  |  |  | 	const searchY = "test.y.golang.org." | 
					
						
							|  |  |  | 	const txt = "Hello World" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(_, s string, q dnsmessage.Message, deadline time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		t.Log(s, q) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		switch q.Questions[0].Name.String() { | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		case searchX: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			return dnsmessage.Message{}, poll.ErrTimeout | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		case searchY: | 
					
						
							|  |  |  | 			return mockTXTResponse(q), nil | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 			return dnsmessage.Message{}, fmt.Errorf("Unexpected Name: %v", q.Questions[0].Name) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 	}} | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	for _, strict := range []bool{true, false} { | 
					
						
							| 
									
										
										
										
											2017-02-20 05:58:55 -08:00
										 |  |  | 		r := Resolver{StrictErrors: strict, Dial: fake.DialContext} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		p, _, err := r.lookup(context.Background(), name, dnsmessage.TypeTXT) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		var wantErr error | 
					
						
							|  |  |  | 		var wantRRs int | 
					
						
							|  |  |  | 		if strict { | 
					
						
							|  |  |  | 			wantErr = &DNSError{ | 
					
						
							|  |  |  | 				Err:       poll.ErrTimeout.Error(), | 
					
						
							|  |  |  | 				Name:      name, | 
					
						
							|  |  |  | 				Server:    server, | 
					
						
							|  |  |  | 				IsTimeout: true, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			wantRRs = 1 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !reflect.DeepEqual(err, wantErr) { | 
					
						
							|  |  |  | 			t.Errorf("strict=%v: got err %#v; want %#v", strict, err, wantErr) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		a, err := p.AllAnswers() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			a = nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(a) != wantRRs { | 
					
						
							|  |  |  | 			t.Errorf("strict=%v: got %v; want %v", strict, len(a), wantRRs) | 
					
						
							| 
									
										
										
										
											2016-11-01 21:01:08 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Test for a race between uninstalling the test hooks and closing a | 
					
						
							|  |  |  | // socket connection. This used to fail when testing with -race. | 
					
						
							|  |  |  | func TestDNSGoroutineRace(t *testing.T) { | 
					
						
							|  |  |  | 	defer dnsWaitGroup.Wait() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 	fake := fakeDNSServer{rh: func(n, s string, q dnsmessage.Message, t time.Time) (dnsmessage.Message, error) { | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 		time.Sleep(10 * time.Microsecond) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		return dnsmessage.Message{}, poll.ErrTimeout | 
					
						
							| 
									
										
										
										
											2017-12-07 20:30:28 -08:00
										 |  |  | 	}} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The timeout here is less than the timeout used by the server, | 
					
						
							|  |  |  | 	// so the goroutine started to query the (fake) server will hang | 
					
						
							|  |  |  | 	// around after this test is done if we don't call dnsWaitGroup.Wait. | 
					
						
							|  |  |  | 	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Microsecond) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 	_, err := r.LookupIPAddr(ctx, "where.are.they.now") | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatal("fake DNS lookup unexpectedly succeeded") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error { | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resolvConf.mu.RLock() | 
					
						
							|  |  |  | 	conf := resolvConf.dnsConfig | 
					
						
							|  |  |  | 	resolvConf.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx, cancel := context.WithCancel(context.Background()) | 
					
						
							|  |  |  | 	defer cancel() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, _, err := r.tryOneName(ctx, conf, name, typ) | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | // Issue 8434: verify that Temporary returns true on an error when rcode | 
					
						
							|  |  |  | // is SERVFAIL | 
					
						
							|  |  |  | func TestIssue8434(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | 	err := lookupWithFake(fakeDNSServer{ | 
					
						
							|  |  |  | 		rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 			return dnsmessage.Message{ | 
					
						
							|  |  |  | 				Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 					ID:       q.ID, | 
					
						
							|  |  |  | 					Response: true, | 
					
						
							|  |  |  | 					RCode:    dnsmessage.RCodeServerFailure, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Questions: q.Questions, | 
					
						
							|  |  |  | 			}, nil | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | 	}, "golang.org.", dnsmessage.TypeALL) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Fatal("expected an error") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ne, ok := err.(Error); !ok { | 
					
						
							|  |  |  | 		t.Fatalf("err = %#v; wanted something supporting net.Error", err) | 
					
						
							|  |  |  | 	} else if !ne.Temporary() { | 
					
						
							|  |  |  | 		t.Fatalf("Temporary = false for err = %#v; want Temporary == true", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if de, ok := err.(*DNSError); !ok { | 
					
						
							|  |  |  | 		t.Fatalf("err = %#v; wanted a *net.DNSError", err) | 
					
						
							|  |  |  | 	} else if !de.IsTemporary { | 
					
						
							|  |  |  | 		t.Fatalf("IsTemporary = false for err = %#v; want IsTemporary == true", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | // TestNoSuchHost verifies that tryOneName works correctly when the domain does | 
					
						
							|  |  |  | // not exist. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Issue 12778: verify that NXDOMAIN without RA bit errors as "no such host" | 
					
						
							|  |  |  | // and not "server misbehaving" | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | // | 
					
						
							|  |  |  | // Issue 25336: verify that NXDOMAIN errors fail fast. | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | // | 
					
						
							|  |  |  | // Issue 27525: verify that empty answers fail fast. | 
					
						
							|  |  |  | func TestNoSuchHost(t *testing.T) { | 
					
						
							|  |  |  | 	tests := []struct { | 
					
						
							|  |  |  | 		name string | 
					
						
							|  |  |  | 		f    func(string, string, dnsmessage.Message, time.Time) (dnsmessage.Message, error) | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"NXDOMAIN", | 
					
						
							|  |  |  | 			func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 				return dnsmessage.Message{ | 
					
						
							|  |  |  | 					Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 						ID:                 q.ID, | 
					
						
							|  |  |  | 						Response:           true, | 
					
						
							|  |  |  | 						RCode:              dnsmessage.RCodeNameError, | 
					
						
							|  |  |  | 						RecursionAvailable: false, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Questions: q.Questions, | 
					
						
							|  |  |  | 				}, nil | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			"no answers", | 
					
						
							|  |  |  | 			func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 				return dnsmessage.Message{ | 
					
						
							|  |  |  | 					Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 						ID:                 q.ID, | 
					
						
							|  |  |  | 						Response:           true, | 
					
						
							|  |  |  | 						RCode:              dnsmessage.RCodeSuccess, | 
					
						
							|  |  |  | 						RecursionAvailable: false, | 
					
						
							|  |  |  | 						Authoritative:      true, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					Questions: q.Questions, | 
					
						
							|  |  |  | 				}, nil | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | 	for _, test := range tests { | 
					
						
							|  |  |  | 		t.Run(test.name, func(t *testing.T) { | 
					
						
							|  |  |  | 			lookups := 0 | 
					
						
							|  |  |  | 			err := lookupWithFake(fakeDNSServer{ | 
					
						
							|  |  |  | 				rh: func(n, s string, q dnsmessage.Message, d time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 					lookups++ | 
					
						
							|  |  |  | 					return test.f(n, s, q, d) | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}, ".", dnsmessage.TypeALL) | 
					
						
							| 
									
										
										
										
											2018-05-18 12:43:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | 			if lookups != 1 { | 
					
						
							|  |  |  | 				t.Errorf("got %d lookups, wanted 1", lookups) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 23:53:36 -07:00
										 |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				t.Fatal("expected an error") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			de, ok := err.(*DNSError) | 
					
						
							|  |  |  | 			if !ok { | 
					
						
							|  |  |  | 				t.Fatalf("err = %#v; wanted a *net.DNSError", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if de.Err != errNoSuchHost.Error() { | 
					
						
							|  |  |  | 				t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error()) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2017-11-22 17:12:30 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-07-24 16:19:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Issue 26573: verify that Conns that don't implement PacketConn are treated | 
					
						
							|  |  |  | // as streams even when udp was requested. | 
					
						
							|  |  |  | func TestDNSDialTCP(t *testing.T) { | 
					
						
							|  |  |  | 	fake := fakeDNSServer{ | 
					
						
							|  |  |  | 		rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 			r := dnsmessage.Message{ | 
					
						
							|  |  |  | 				Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 					ID:       q.Header.ID, | 
					
						
							|  |  |  | 					Response: true, | 
					
						
							|  |  |  | 					RCode:    dnsmessage.RCodeSuccess, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Questions: q.Questions, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return r, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		alwaysTCP: true, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							|  |  |  | 	ctx := context.Background() | 
					
						
							|  |  |  | 	_, _, err := r.exchange(ctx, "0.0.0.0", mustQuestion("com.", dnsmessage.TypeALL, dnsmessage.ClassINET), time.Second) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("exhange failed:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-24 06:08:54 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Issue 27763: verify that two strings in one TXT record are concatenated. | 
					
						
							|  |  |  | func TestTXTRecordTwoStrings(t *testing.T) { | 
					
						
							|  |  |  | 	fake := fakeDNSServer{ | 
					
						
							|  |  |  | 		rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) { | 
					
						
							|  |  |  | 			r := dnsmessage.Message{ | 
					
						
							|  |  |  | 				Header: dnsmessage.Header{ | 
					
						
							|  |  |  | 					ID:       q.Header.ID, | 
					
						
							|  |  |  | 					Response: true, | 
					
						
							|  |  |  | 					RCode:    dnsmessage.RCodeSuccess, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				Questions: q.Questions, | 
					
						
							|  |  |  | 				Answers: []dnsmessage.Resource{ | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:  q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:  dnsmessage.TypeA, | 
					
						
							|  |  |  | 							Class: dnsmessage.ClassINET, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.TXTResource{ | 
					
						
							|  |  |  | 							TXT: []string{"string1 ", "string2"}, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						Header: dnsmessage.ResourceHeader{ | 
					
						
							|  |  |  | 							Name:  q.Questions[0].Name, | 
					
						
							|  |  |  | 							Type:  dnsmessage.TypeA, | 
					
						
							|  |  |  | 							Class: dnsmessage.ClassINET, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						Body: &dnsmessage.TXTResource{ | 
					
						
							|  |  |  | 							TXT: []string{"onestring"}, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return r, nil | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	r := Resolver{PreferGo: true, Dial: fake.DialContext} | 
					
						
							|  |  |  | 	txt, err := r.lookupTXT(context.Background(), "golang.org") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("LookupTXT failed:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if want := 2; len(txt) != want { | 
					
						
							|  |  |  | 		t.Fatalf("len(txt), got %d, want %d", len(txt), want) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if want := "string1 string2"; txt[0] != want { | 
					
						
							|  |  |  | 		t.Errorf("txt[0], got %q, want %q", txt[0], want) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if want := "onestring"; txt[1] != want { | 
					
						
							|  |  |  | 		t.Errorf("txt[1], got %q, want %q", txt[1], want) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |