AdGuardHome/internal/dnsforward/upstreams_internal_test.go

210 lines
5.5 KiB
Go
Raw Normal View History

Pull request 2080: AG-27539 imp upstream test Squashed commit of the following: commit 5a9e8c0c2e4b68c0ff6508c47fbd8abde0d05e95 Merge: 85820c173 c4e69cd96 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Nov 28 16:09:53 2023 +0300 Merge branch 'master' into AG-27539-imp-upstream-test commit 85820c173dddb6391dabe9615b821b585b1ecdef Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Nov 28 15:48:53 2023 +0300 dnsforward: split code commit dac0148a4d4780bea19fb7622b46ac08fbf1ee74 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Fri Nov 24 15:47:05 2023 +0300 dnsforward: fix docs commit 9f0015b255d547f31d34513aa6bb2faf65a39e0e Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Fri Nov 24 14:45:43 2023 +0300 dnsforward: imp code commit 49fefc373972b7c8991abcb46d7730288b92c24c Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Thu Nov 23 14:12:02 2023 +0300 dnsforward: imp code commit 120ba4b1f727bba537471c4a8aa4b412eac30f85 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Nov 22 17:02:01 2023 +0300 dnsforward: add tests commit 70775975ced46191a6ba64504c7bac0e3d1eed7f Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Nov 22 15:48:05 2023 +0300 dnsforward: imp code commit 9487f1fd62b821efb242267d9972f3ae3785ad19 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Nov 21 18:06:00 2023 +0300 dnsforward: imp code commit e2612e0e6fd1c9116872939edd0e86f2e9af07d7 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Nov 21 16:12:20 2023 +0300 dnsforward: add ups checker commit 09db7d2a604809669affbeef2f0536fa6605a39b Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Nov 14 17:31:04 2023 +0300 dnsforward: separate upstream code
2023-11-28 13:40:52 +00:00
package dnsforward
import (
"net"
"net/url"
"strings"
"sync/atomic"
"testing"
"time"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/testutil"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUpstreamConfigValidator(t *testing.T) {
goodHandler := dns.HandlerFunc(func(w dns.ResponseWriter, m *dns.Msg) {
err := w.WriteMsg(new(dns.Msg).SetReply(m))
require.NoError(testutil.PanicT{}, err)
})
badHandler := dns.HandlerFunc(func(w dns.ResponseWriter, _ *dns.Msg) {
err := w.WriteMsg(new(dns.Msg))
require.NoError(testutil.PanicT{}, err)
})
goodUps := (&url.URL{
Scheme: "tcp",
Host: newLocalUpstreamListener(t, 0, goodHandler).String(),
}).String()
badUps := (&url.URL{
Scheme: "tcp",
Host: newLocalUpstreamListener(t, 0, badHandler).String(),
}).String()
goodAndBadUps := strings.Join([]string{goodUps, badUps}, " ")
// upsTimeout restricts the checking process to prevent the test from
// hanging.
const upsTimeout = 100 * time.Millisecond
testCases := []struct {
want map[string]string
name string
general []string
fallback []string
private []string
}{{
name: "success",
general: []string{goodUps},
want: map[string]string{
goodUps: "OK",
},
}, {
name: "broken",
general: []string{badUps},
want: map[string]string{
badUps: `couldn't communicate with upstream: exchanging with ` +
badUps + ` over tcp: dns: id mismatch`,
},
}, {
name: "both",
general: []string{goodUps, badUps, goodUps},
want: map[string]string{
goodUps: "OK",
badUps: `couldn't communicate with upstream: exchanging with ` +
badUps + ` over tcp: dns: id mismatch`,
},
}, {
name: "domain_specific_error",
general: []string{"[/domain.example/]" + badUps},
want: map[string]string{
badUps: `WARNING: couldn't communicate ` +
`with upstream: exchanging with ` + badUps + ` over tcp: ` +
`dns: id mismatch`,
},
}, {
name: "fallback_success",
fallback: []string{goodUps},
want: map[string]string{
goodUps: "OK",
},
}, {
name: "fallback_broken",
fallback: []string{badUps},
want: map[string]string{
badUps: `couldn't communicate with upstream: exchanging with ` +
badUps + ` over tcp: dns: id mismatch`,
},
}, {
name: "multiple_domain_specific_upstreams",
general: []string{"[/domain.example/]" + goodAndBadUps},
want: map[string]string{
goodUps: "OK",
badUps: `WARNING: couldn't communicate ` +
`with upstream: exchanging with ` + badUps + ` over tcp: ` +
`dns: id mismatch`,
},
}, {
name: "bad_specification",
general: []string{"[/domain.example/]/]1.2.3.4"},
want: map[string]string{
"[/domain.example/]/]1.2.3.4": `splitting upstream line ` +
`"[/domain.example/]/]1.2.3.4": duplicated separator`,
},
}, {
name: "all_different",
general: []string{"[/domain.example/]" + goodAndBadUps},
fallback: []string{"[/domain.example/]" + goodAndBadUps},
private: []string{"[/domain.example/]" + goodAndBadUps},
want: map[string]string{
goodUps: "OK",
badUps: `WARNING: couldn't communicate ` +
`with upstream: exchanging with ` + badUps + ` over tcp: ` +
`dns: id mismatch`,
},
}, {
name: "bad_specific_domains",
general: []string{"[/example/]/]" + goodUps},
fallback: []string{"[/example/" + goodUps},
private: []string{"[/example//bad.123/]" + goodUps},
want: map[string]string{
`[/example/]/]` + goodUps: `splitting upstream line ` +
`"[/example/]/]` + goodUps + `": duplicated separator`,
`[/example/` + goodUps: `splitting upstream line ` +
`"[/example/` + goodUps + `": missing separator`,
`[/example//bad.123/]` + goodUps: `splitting upstream line ` +
`"[/example//bad.123/]` + goodUps + `": domain at index 2: ` +
`bad domain name "bad.123": ` +
`bad top-level domain name label "123": all octets are numeric`,
},
}, {
name: "non-specific_default",
general: []string{
"#",
"[/example/]#",
},
want: map[string]string{
"#": "not a domain-specific upstream",
},
}, {
name: "bad_proto",
general: []string{
"bad://1.2.3.4",
},
want: map[string]string{
"bad://1.2.3.4": `bad protocol "bad"`,
},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cv := newUpstreamConfigValidator(tc.general, tc.fallback, tc.private, &upstream.Options{
Timeout: upsTimeout,
Bootstrap: net.DefaultResolver,
})
cv.check()
cv.close()
assert.Equal(t, tc.want, cv.status())
})
}
}
func TestUpstreamConfigValidator_Check_once(t *testing.T) {
reqs := atomic.Int32{}
reset := func() { reqs.Store(0) }
hdlr := dns.HandlerFunc(func(w dns.ResponseWriter, m *dns.Msg) {
err := w.WriteMsg(new(dns.Msg).SetReply(m))
require.NoError(testutil.PanicT{}, err)
reqs.Add(1)
})
addr := (&url.URL{
Scheme: "tcp",
Host: newLocalUpstreamListener(t, 0, hdlr).String(),
}).String()
twoAddrs := strings.Join([]string{addr, addr}, " ")
testCases := []struct {
name string
ups []string
}{{
name: "common",
ups: []string{addr, addr, addr},
}, {
name: "domain-specific",
ups: []string{"[/one.example/]" + addr, "[/two.example/]" + twoAddrs},
}, {
name: "both",
ups: []string{addr, "[/one.example/]" + addr, addr, "[/two.example/]" + twoAddrs},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Cleanup(reset)
cv := newUpstreamConfigValidator(tc.ups, nil, nil, &upstream.Options{
Timeout: 100 * time.Millisecond,
})
cv.check()
cv.close()
assert.Equal(t, int32(1), reqs.Load())
})
}
}