AdGuardHome/internal/filtering/safesearch/safesearch_test.go

197 lines
4.7 KiB
Go

package safesearch_test
import (
"context"
"net"
"net/netip"
"testing"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
"github.com/AdguardTeam/golibs/testutil"
"github.com/miekg/dns"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMain(m *testing.M) {
testutil.DiscardLogOutput(m)
}
// Common test constants.
const (
// TODO(a.garipov): Add IPv6 tests.
testQType = dns.TypeA
testCacheSize = 5000
testCacheTTL = 30 * time.Minute
)
// testConf is the default safe search configuration for tests.
var testConf = filtering.SafeSearchConfig{
Enabled: true,
Bing: true,
DuckDuckGo: true,
Google: true,
Pixabay: true,
Yandex: true,
YouTube: true,
}
// yandexIP is the expected IP address of Yandex safe search results. Keep in
// sync with the rules data.
var yandexIP = netip.AddrFrom4([4]byte{213, 180, 193, 56})
func TestDefault_CheckHost_yandex(t *testing.T) {
conf := testConf
ss, err := safesearch.NewDefault(conf, "", testCacheSize, testCacheTTL)
require.NoError(t, err)
hosts := []string{
"yandex.ru",
"yAndeX.ru",
"YANdex.COM",
"yandex.by",
"yandex.kz",
"www.yandex.com",
}
testCases := []struct {
want netip.Addr
name string
qt uint16
}{{
want: yandexIP,
name: "a",
qt: dns.TypeA,
}, {
want: netip.Addr{},
name: "aaaa",
qt: dns.TypeAAAA,
}, {
want: netip.Addr{},
name: "https",
qt: dns.TypeHTTPS,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
for _, host := range hosts {
// Check host for each domain.
var res filtering.Result
res, err = ss.CheckHost(host, tc.qt)
require.NoError(t, err)
assert.True(t, res.IsFiltered)
assert.Equal(t, filtering.FilteredSafeSearch, res.Reason)
if tc.want == (netip.Addr{}) {
assert.Empty(t, res.Rules)
} else {
require.Len(t, res.Rules, 1)
assert.Equal(t, tc.want, res.Rules[0].IP)
assert.Equal(t, rulelist.URLFilterIDSafeSearch, res.Rules[0].FilterListID)
}
}
})
}
}
func TestDefault_CheckHost_google(t *testing.T) {
ss, err := safesearch.NewDefault(testConf, "", testCacheSize, testCacheTTL)
require.NoError(t, err)
// Check host for each domain.
for _, host := range []string{
"www.google.com",
"www.google.im",
"www.google.co.in",
"www.google.iq",
"www.google.is",
"www.google.it",
"www.google.je",
} {
t.Run(host, func(t *testing.T) {
var res filtering.Result
res, err = ss.CheckHost(host, testQType)
require.NoError(t, err)
assert.True(t, res.IsFiltered)
assert.Equal(t, filtering.FilteredSafeSearch, res.Reason)
assert.Equal(t, "forcesafesearch.google.com", res.CanonName)
assert.Empty(t, res.Rules)
})
}
}
// testResolver is a [filtering.Resolver] for tests.
//
// TODO(a.garipov): Move to aghtest and use everywhere.
type testResolver struct {
OnLookupIP func(ctx context.Context, network, host string) (ips []net.IP, err error)
}
// type check
var _ filtering.Resolver = (*testResolver)(nil)
// LookupIP implements the [filtering.Resolver] interface for *testResolver.
func (r *testResolver) LookupIP(
ctx context.Context,
network string,
host string,
) (ips []net.IP, err error) {
return r.OnLookupIP(ctx, network, host)
}
func TestDefault_CheckHost_duckduckgoAAAA(t *testing.T) {
ss, err := safesearch.NewDefault(testConf, "", testCacheSize, testCacheTTL)
require.NoError(t, err)
// The DuckDuckGo safe-search addresses are resolved through CNAMEs, but
// DuckDuckGo doesn't have a safe-search IPv6 address. The result should be
// the same as the one for Yandex IPv6. That is, a NODATA response.
res, err := ss.CheckHost("www.duckduckgo.com", dns.TypeAAAA)
require.NoError(t, err)
assert.True(t, res.IsFiltered)
assert.Equal(t, filtering.FilteredSafeSearch, res.Reason)
assert.Equal(t, "safe.duckduckgo.com", res.CanonName)
assert.Empty(t, res.Rules)
}
func TestDefault_Update(t *testing.T) {
conf := testConf
ss, err := safesearch.NewDefault(conf, "", testCacheSize, testCacheTTL)
require.NoError(t, err)
res, err := ss.CheckHost("www.yandex.com", testQType)
require.NoError(t, err)
assert.True(t, res.IsFiltered)
err = ss.Update(filtering.SafeSearchConfig{
Enabled: true,
Google: false,
})
require.NoError(t, err)
res, err = ss.CheckHost("www.yandex.com", testQType)
require.NoError(t, err)
assert.False(t, res.IsFiltered)
err = ss.Update(filtering.SafeSearchConfig{
Enabled: false,
Google: true,
})
require.NoError(t, err)
res, err = ss.CheckHost("www.yandex.com", testQType)
require.NoError(t, err)
assert.False(t, res.IsFiltered)
}