2022-09-29 15:36:01 +01:00
|
|
|
package filtering
|
2019-09-04 12:12:00 +01:00
|
|
|
|
|
|
|
import (
|
2020-04-07 21:29:03 +01:00
|
|
|
"net"
|
2019-09-04 12:12:00 +01:00
|
|
|
"net/http"
|
2021-09-15 18:09:32 +01:00
|
|
|
"net/url"
|
2019-09-04 12:12:00 +01:00
|
|
|
"os"
|
2021-09-15 18:09:32 +01:00
|
|
|
"path/filepath"
|
2019-09-04 12:12:00 +01:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2023-01-19 12:04:46 +00:00
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
2021-10-22 09:58:18 +01:00
|
|
|
"github.com/AdguardTeam/golibs/testutil"
|
2019-09-04 12:12:00 +01:00
|
|
|
"github.com/stretchr/testify/assert"
|
2021-03-11 14:32:58 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2019-09-04 12:12:00 +01:00
|
|
|
)
|
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
// testTimeout is the common timeout for tests.
|
|
|
|
const testTimeout = 5 * time.Second
|
|
|
|
|
2023-01-19 12:04:46 +00:00
|
|
|
// serveHTTPLocally starts a new HTTP server, that handles its index with h. It
|
|
|
|
// also gracefully closes the listener when the test under t finishes.
|
|
|
|
func serveHTTPLocally(t *testing.T, h http.Handler) (urlStr string) {
|
2021-09-15 18:09:32 +01:00
|
|
|
t.Helper()
|
2021-03-11 14:32:58 +00:00
|
|
|
|
2022-11-02 13:18:02 +00:00
|
|
|
l, err := net.Listen("tcp", ":0")
|
2021-09-15 18:09:32 +01:00
|
|
|
require.NoError(t, err)
|
2021-03-11 14:32:58 +00:00
|
|
|
|
2022-11-02 13:18:02 +00:00
|
|
|
go func() { _ = http.Serve(l, h) }()
|
2021-10-22 09:58:18 +01:00
|
|
|
testutil.CleanupAndRequireSuccess(t, l.Close)
|
2020-04-07 21:29:03 +01:00
|
|
|
|
2022-11-02 13:18:02 +00:00
|
|
|
addr := l.Addr()
|
2023-01-19 12:04:46 +00:00
|
|
|
require.IsType(t, (*net.TCPAddr)(nil), addr)
|
|
|
|
|
|
|
|
return (&url.URL{
|
|
|
|
Scheme: aghhttp.SchemeHTTP,
|
|
|
|
Host: addr.String(),
|
|
|
|
}).String()
|
|
|
|
}
|
2022-11-02 13:18:02 +00:00
|
|
|
|
2023-01-19 12:04:46 +00:00
|
|
|
// serveFiltersLocally is a helper that concurrently listens on a free port to
|
|
|
|
// respond with fltContent.
|
|
|
|
func serveFiltersLocally(t *testing.T, fltContent []byte) (urlStr string) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
return serveHTTPLocally(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
|
|
pt := testutil.PanicT{}
|
|
|
|
|
|
|
|
n, werr := w.Write(fltContent)
|
|
|
|
require.NoError(pt, werr)
|
|
|
|
require.Equal(pt, len(fltContent), n)
|
|
|
|
}))
|
2020-04-07 21:29:03 +01:00
|
|
|
}
|
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
// updateAndAssert loads filter content from its URL and then asserts rules
|
|
|
|
// count.
|
|
|
|
func updateAndAssert(
|
|
|
|
t *testing.T,
|
|
|
|
dnsFilter *DNSFilter,
|
|
|
|
f *FilterYAML,
|
|
|
|
wantUpd require.BoolAssertionFunc,
|
|
|
|
wantRulesCount int,
|
|
|
|
) {
|
|
|
|
t.Helper()
|
2021-09-15 18:09:32 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
ok, err := dnsFilter.update(f)
|
|
|
|
require.NoError(t, err)
|
|
|
|
wantUpd(t, ok)
|
2021-03-11 14:32:58 +00:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
assert.Equal(t, wantRulesCount, f.RulesCount)
|
2022-09-29 15:36:01 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
dir, err := os.ReadDir(filepath.Join(dnsFilter.conf.DataDir, filterDir))
|
2022-09-29 15:36:01 +01:00
|
|
|
require.NoError(t, err)
|
2023-09-07 15:13:48 +01:00
|
|
|
require.FileExists(t, f.Path(dnsFilter.conf.DataDir))
|
2019-09-04 12:12:00 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
assert.Len(t, dir, 1)
|
2019-09-04 12:12:00 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
err = dnsFilter.load(f)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
2019-09-04 12:12:00 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
// newDNSFilter returns a new properly initialized DNS filter instance.
|
|
|
|
func newDNSFilter(t *testing.T) (d *DNSFilter) {
|
|
|
|
t.Helper()
|
2019-09-04 12:12:00 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
dnsFilter, err := New(&Config{
|
|
|
|
DataDir: t.TempDir(),
|
|
|
|
HTTPClient: &http.Client{
|
|
|
|
Timeout: testTimeout,
|
|
|
|
},
|
|
|
|
}, nil)
|
|
|
|
require.NoError(t, err)
|
2021-09-15 18:09:32 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
return dnsFilter
|
|
|
|
}
|
2021-09-15 18:09:32 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
func TestDNSFilter_Update(t *testing.T) {
|
|
|
|
const content = `||example.org^$third-party
|
|
|
|
# Inline comment example
|
|
|
|
||example.com^$third-party
|
|
|
|
0.0.0.0 example.com
|
|
|
|
`
|
2021-09-15 18:09:32 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
fltContent := []byte(content)
|
|
|
|
addr := serveFiltersLocally(t, fltContent)
|
|
|
|
f := &FilterYAML{
|
|
|
|
URL: addr,
|
|
|
|
Name: "test-filter",
|
2021-09-15 18:09:32 +01:00
|
|
|
}
|
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
dnsFilter := newDNSFilter(t)
|
|
|
|
|
2021-09-15 18:09:32 +01:00
|
|
|
t.Run("download", func(t *testing.T) {
|
2023-09-07 15:13:48 +01:00
|
|
|
updateAndAssert(t, dnsFilter, f, require.True, 3)
|
2021-09-15 18:09:32 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("refresh_idle", func(t *testing.T) {
|
2023-09-07 15:13:48 +01:00
|
|
|
updateAndAssert(t, dnsFilter, f, require.False, 3)
|
2021-09-15 18:09:32 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("refresh_actually", func(t *testing.T) {
|
2022-11-02 13:18:02 +00:00
|
|
|
anotherContent := []byte(`||example.com^`)
|
|
|
|
oldURL := f.URL
|
|
|
|
|
2023-01-19 12:04:46 +00:00
|
|
|
f.URL = serveFiltersLocally(t, anotherContent)
|
2022-11-02 13:18:02 +00:00
|
|
|
t.Cleanup(func() { f.URL = oldURL })
|
2021-09-15 18:09:32 +01:00
|
|
|
|
2023-09-07 15:13:48 +01:00
|
|
|
updateAndAssert(t, dnsFilter, f, require.True, 1)
|
2021-09-15 18:09:32 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("load_unload", func(t *testing.T) {
|
2023-09-07 15:13:48 +01:00
|
|
|
err := dnsFilter.load(f)
|
2021-09-15 18:09:32 +01:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
f.unload()
|
|
|
|
})
|
2019-09-04 12:12:00 +01:00
|
|
|
}
|
2023-09-07 15:13:48 +01:00
|
|
|
|
|
|
|
func TestFilterYAML_EnsureName(t *testing.T) {
|
|
|
|
dnsFilter := newDNSFilter(t)
|
|
|
|
|
|
|
|
t.Run("title_custom", func(t *testing.T) {
|
|
|
|
content := []byte("! Title: src-title\n||example.com^")
|
|
|
|
|
|
|
|
f := &FilterYAML{
|
|
|
|
URL: serveFiltersLocally(t, content),
|
|
|
|
Name: "user-custom",
|
|
|
|
}
|
|
|
|
|
|
|
|
updateAndAssert(t, dnsFilter, f, require.True, 1)
|
|
|
|
assert.Equal(t, "user-custom", f.Name)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("title_from_src", func(t *testing.T) {
|
|
|
|
content := []byte("! Title: src-title\n||example.com^")
|
|
|
|
|
|
|
|
f := &FilterYAML{
|
|
|
|
URL: serveFiltersLocally(t, content),
|
|
|
|
}
|
|
|
|
|
|
|
|
updateAndAssert(t, dnsFilter, f, require.True, 1)
|
|
|
|
assert.Equal(t, "src-title", f.Name)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("title_default", func(t *testing.T) {
|
|
|
|
content := []byte("||example.com^")
|
|
|
|
|
|
|
|
f := &FilterYAML{
|
|
|
|
URL: serveFiltersLocally(t, content),
|
|
|
|
}
|
|
|
|
|
|
|
|
updateAndAssert(t, dnsFilter, f, require.True, 1)
|
|
|
|
assert.Equal(t, "List 0", f.Name)
|
|
|
|
})
|
|
|
|
}
|