mirror of
https://github.com/AdguardTeam/dnsproxy.git
synced 2026-10-12 02:01:26 +00:00
Merge in GO/dnsproxy from AGDNS-2744-close-listeners-on-err to master Squashed commit of the following: commit e19682135682e8ea48110e05e58c62190e9be1ab Author: Eugene Burkov <[email protected]> Date: Thu Jun 5 20:16:40 2025 +0300 all: upd go, deps commit 3bc328054291232673547bbd7cc7955a25c17287 Author: Eugene Burkov <[email protected]> Date: Thu Jun 5 20:13:07 2025 +0300 proxy: fix doc commit 6f4ae4c6402e6d214c4f720f2224fda960e62c5a Author: Eugene Burkov <[email protected]> Date: Thu Jun 5 20:09:49 2025 +0300 proxy: imp code commit e25567a28e0d82a41a9c8f39d68cef6cdbae546a Author: Eugene Burkov <[email protected]> Date: Thu Jun 5 19:36:40 2025 +0300 proxy: add test commit 4a9a677f9ca60b6e6bd1e9b766994040f8feecc4 Author: Eugene Burkov <[email protected]> Date: Thu Jun 5 19:12:09 2025 +0300 all: close active listeners on error
196 lines
5.3 KiB
Go
196 lines
5.3 KiB
Go
package proxy_test
|
|
|
|
import (
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/AdguardTeam/dnsproxy/internal/bootstrap"
|
|
"github.com/AdguardTeam/dnsproxy/internal/dnsproxytest"
|
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
|
"github.com/AdguardTeam/golibs/testutil"
|
|
"github.com/miekg/dns"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// newCustomUpstreamConfig is a helper function that returns an initialized
|
|
// [*proxy.CustomUpstreamConfig].
|
|
func newCustomUpstreamConfig(ups upstream.Upstream, enabled bool) (c *proxy.CustomUpstreamConfig) {
|
|
return proxy.NewCustomUpstreamConfig(
|
|
&proxy.UpstreamConfig{Upstreams: []upstream.Upstream{ups}},
|
|
enabled,
|
|
0,
|
|
false,
|
|
)
|
|
}
|
|
|
|
// isCachedWithCustomConfig is a helper function that returns the caching
|
|
// results of a constructed request using the provided custom upstream
|
|
// configuration and FQDN.
|
|
func isCachedWithCustomConfig(
|
|
tb testing.TB,
|
|
p *proxy.Proxy,
|
|
conf *proxy.CustomUpstreamConfig,
|
|
fqdn string,
|
|
) (isCached bool) {
|
|
tb.Helper()
|
|
|
|
d := &proxy.DNSContext{
|
|
CustomUpstreamConfig: conf,
|
|
Req: (&dns.Msg{}).SetQuestion(fqdn, dns.TypeA),
|
|
}
|
|
|
|
err := p.Resolve(d)
|
|
require.NoError(tb, err)
|
|
|
|
qs := d.QueryStatistics()
|
|
require.NotNil(tb, qs)
|
|
|
|
s := qs.Main()
|
|
require.Len(tb, s, 1)
|
|
|
|
return s[0].IsCached
|
|
}
|
|
|
|
func TestProxy_Resolve_cache(t *testing.T) {
|
|
const host = "example.test."
|
|
|
|
ups := &dnsproxytest.FakeUpstream{
|
|
OnAddress: func() (addr string) { return "stub" },
|
|
OnClose: func() (err error) { return nil },
|
|
}
|
|
ups.OnExchange = func(req *dns.Msg) (resp *dns.Msg, err error) {
|
|
resp = (&dns.Msg{}).SetReply(req)
|
|
resp.Answer = append(resp.Answer, &dns.A{
|
|
Hdr: dns.RR_Header{
|
|
Name: req.Question[0].Name,
|
|
Rrtype: dns.TypeA,
|
|
Class: dns.ClassINET,
|
|
Ttl: 60,
|
|
},
|
|
A: net.IP{192, 0, 2, 0},
|
|
})
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
upsConf := &proxy.UpstreamConfig{
|
|
Upstreams: []upstream.Upstream{ups},
|
|
}
|
|
|
|
testCases := []struct {
|
|
customUpstreamConf *proxy.CustomUpstreamConfig
|
|
wantCachedWithConf assert.BoolAssertionFunc
|
|
wantCachedGlobal assert.BoolAssertionFunc
|
|
name string
|
|
prxCacheEnabled bool
|
|
}{{
|
|
customUpstreamConf: nil,
|
|
wantCachedWithConf: assert.True,
|
|
wantCachedGlobal: assert.True,
|
|
name: "global_cache",
|
|
prxCacheEnabled: true,
|
|
}, {
|
|
customUpstreamConf: newCustomUpstreamConfig(ups, true),
|
|
wantCachedWithConf: assert.True,
|
|
wantCachedGlobal: assert.False,
|
|
name: "custom_cache",
|
|
prxCacheEnabled: false,
|
|
}, {
|
|
customUpstreamConf: newCustomUpstreamConfig(ups, false),
|
|
wantCachedWithConf: assert.False,
|
|
wantCachedGlobal: assert.False,
|
|
name: "custom_cache_only_upstreams",
|
|
prxCacheEnabled: false,
|
|
}, {
|
|
customUpstreamConf: newCustomUpstreamConfig(ups, true),
|
|
wantCachedWithConf: assert.True,
|
|
wantCachedGlobal: assert.False,
|
|
name: "two_caches_enabled",
|
|
prxCacheEnabled: true,
|
|
}, {
|
|
customUpstreamConf: nil,
|
|
wantCachedWithConf: assert.False,
|
|
wantCachedGlobal: assert.False,
|
|
name: "two_caches_disabled",
|
|
prxCacheEnabled: false,
|
|
}}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p, err := proxy.New(&proxy.Config{
|
|
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(localhostAnyPort)},
|
|
UpstreamConfig: upsConf,
|
|
CacheEnabled: tc.prxCacheEnabled,
|
|
})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, p)
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
err = p.Start(ctx)
|
|
require.NoError(t, err)
|
|
|
|
testutil.CleanupAndRequireSuccess(t, func() (err error) { return p.Shutdown(ctx) })
|
|
|
|
res := isCachedWithCustomConfig(t, p, tc.customUpstreamConf, host)
|
|
assert.False(t, res)
|
|
|
|
res = isCachedWithCustomConfig(t, p, tc.customUpstreamConf, host)
|
|
tc.wantCachedWithConf(t, res)
|
|
|
|
res = isCachedWithCustomConfig(t, p, nil, host)
|
|
tc.wantCachedGlobal(t, res)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProxy_Start_closeOnFail(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
l, err := net.ListenTCP(bootstrap.NetworkTCP, net.TCPAddrFromAddrPort(localhostAnyPort))
|
|
require.NoError(t, err)
|
|
|
|
tcpAddr := testutil.RequireTypeAssert[*net.TCPAddr](t, l.Addr())
|
|
|
|
ups := &dnsproxytest.FakeUpstream{
|
|
OnExchange: func(_ *dns.Msg) (_ *dns.Msg, _ error) { panic("not implemented") },
|
|
OnAddress: func() (_ string) { panic("not implemented") },
|
|
OnClose: func() (_ error) { panic("not implemented") },
|
|
}
|
|
|
|
p, err := proxy.New(&proxy.Config{
|
|
// Add a free address.
|
|
UDPListenAddr: []*net.UDPAddr{net.UDPAddrFromAddrPort(localhostAnyPort)},
|
|
// Add a bound address.
|
|
TCPListenAddr: []*net.TCPAddr{tcpAddr},
|
|
UpstreamConfig: &proxy.UpstreamConfig{Upstreams: []upstream.Upstream{ups}},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, t.Run("start_fail", func(t *testing.T) {
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
err = p.Start(ctx)
|
|
|
|
var netErr net.Error
|
|
require.ErrorAs(t, err, &netErr)
|
|
}))
|
|
|
|
// Don't panic anymore.
|
|
ups.OnClose = func() (err error) { return nil }
|
|
|
|
require.True(t, t.Run("restart_success", func(t *testing.T) {
|
|
require.NoError(t, l.Close())
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
err = p.Start(ctx)
|
|
require.NoError(t, err)
|
|
|
|
testutil.CleanupAndRequireSuccess(t, func() (err error) {
|
|
ctx = testutil.ContextWithTimeout(t, testTimeout)
|
|
|
|
return p.Shutdown(ctx)
|
|
})
|
|
}))
|
|
}
|