Pull request: 2639 use testify require vol.1
Merge in DNS/adguard-home from 2639-testify-require-1 to master
Updates #2639.
Squashed commit of the following:
commit da7d283c6b20b4dbbc0af4689fa812d14f022b52
Merge: c4af71b0 63e4adc0
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Tue Feb 9 14:27:41 2021 +0300
Merge branch 'master' into 2639-testify-require-1
commit c4af71b002dc68785106328f60946d7fa73fb933
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Mon Feb 8 19:32:51 2021 +0300
querylog: fix tests for windows
commit b616ea5de88a38550ffd42253d3054ea6f90cff9
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Mon Feb 8 18:29:28 2021 +0300
querylog: imp tests again
commit 091a698df5fbe6c3e572fde12da395f527c88b95
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Mon Feb 8 15:49:38 2021 +0300
querylog: imp tests
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
package querylog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -14,226 +17,292 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
aghtest.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
func prepareTestDir() string {
|
||||
const dir = "./agh-test"
|
||||
_ = os.RemoveAll(dir)
|
||||
_ = os.MkdirAll(dir, 0o755)
|
||||
func prepareTestDir(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
wd, err := os.Getwd()
|
||||
require.Nil(t, err)
|
||||
|
||||
dir, err := ioutil.TempDir(wd, "agh-tests")
|
||||
require.Nil(t, err)
|
||||
require.NotEmpty(t, dir)
|
||||
|
||||
t.Cleanup(func() {
|
||||
// TODO(e.burkov): Replace with t.TempDir methods after updating
|
||||
// go version to 1.15.
|
||||
start := time.Now()
|
||||
for {
|
||||
err := os.RemoveAll(dir)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" || time.Since(start) >= 500*time.Millisecond {
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
return dir
|
||||
}
|
||||
|
||||
// Check adding and loading (with filtering) entries from disk and memory
|
||||
// TestQueryLog tests adding and loading (with filtering) entries from disk and
|
||||
// memory.
|
||||
func TestQueryLog(t *testing.T) {
|
||||
conf := Config{
|
||||
l := newQueryLog(Config{
|
||||
Enabled: true,
|
||||
FileEnabled: true,
|
||||
Interval: 1,
|
||||
MemSize: 100,
|
||||
}
|
||||
conf.BaseDir = prepareTestDir()
|
||||
defer func() { _ = os.RemoveAll(conf.BaseDir) }()
|
||||
l := newQueryLog(conf)
|
||||
BaseDir: prepareTestDir(t),
|
||||
})
|
||||
|
||||
// add disk entries
|
||||
// Add disk entries.
|
||||
addEntry(l, "example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
// write to disk (first file)
|
||||
_ = l.flushLogBuffer(true)
|
||||
// start writing to the second file
|
||||
_ = l.rotate()
|
||||
// add disk entries
|
||||
// Write to disk (first file).
|
||||
require.Nil(t, l.flushLogBuffer(true))
|
||||
// Start writing to the second file.
|
||||
require.Nil(t, l.rotate())
|
||||
// Add disk entries.
|
||||
addEntry(l, "example.org", net.IPv4(1, 1, 1, 2), net.IPv4(2, 2, 2, 2))
|
||||
// write to disk
|
||||
_ = l.flushLogBuffer(true)
|
||||
// add memory entries
|
||||
// Write to disk.
|
||||
require.Nil(t, l.flushLogBuffer(true))
|
||||
// Add memory entries.
|
||||
addEntry(l, "test.example.org", net.IPv4(1, 1, 1, 3), net.IPv4(2, 2, 2, 3))
|
||||
addEntry(l, "example.com", net.IPv4(1, 1, 1, 4), net.IPv4(2, 2, 2, 4))
|
||||
|
||||
// get all entries
|
||||
params := newSearchParams()
|
||||
entries, _ := l.search(params)
|
||||
assert.Len(t, entries, 4)
|
||||
assertLogEntry(t, entries[0], "example.com", net.IPv4(1, 1, 1, 4), net.IPv4(2, 2, 2, 4))
|
||||
assertLogEntry(t, entries[1], "test.example.org", net.IPv4(1, 1, 1, 3), net.IPv4(2, 2, 2, 3))
|
||||
assertLogEntry(t, entries[2], "example.org", net.IPv4(1, 1, 1, 2), net.IPv4(2, 2, 2, 2))
|
||||
assertLogEntry(t, entries[3], "example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
type tcAssertion struct {
|
||||
num int
|
||||
host string
|
||||
answer, client net.IP
|
||||
}
|
||||
|
||||
// search by domain (strict)
|
||||
params = newSearchParams()
|
||||
params.searchCriteria = append(params.searchCriteria, searchCriteria{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: true,
|
||||
value: "TEST.example.org",
|
||||
})
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 1)
|
||||
assertLogEntry(t, entries[0], "test.example.org", net.IPv4(1, 1, 1, 3), net.IPv4(2, 2, 2, 3))
|
||||
testCases := []struct {
|
||||
name string
|
||||
sCr []searchCriteria
|
||||
want []tcAssertion
|
||||
}{{
|
||||
name: "all",
|
||||
sCr: []searchCriteria{},
|
||||
want: []tcAssertion{
|
||||
{num: 0, host: "example.com", answer: net.IPv4(1, 1, 1, 4), client: net.IPv4(2, 2, 2, 4)},
|
||||
{num: 1, host: "test.example.org", answer: net.IPv4(1, 1, 1, 3), client: net.IPv4(2, 2, 2, 3)},
|
||||
{num: 2, host: "example.org", answer: net.IPv4(1, 1, 1, 2), client: net.IPv4(2, 2, 2, 2)},
|
||||
{num: 3, host: "example.org", answer: net.IPv4(1, 1, 1, 1), client: net.IPv4(2, 2, 2, 1)},
|
||||
},
|
||||
}, {
|
||||
name: "by_domain_strict",
|
||||
sCr: []searchCriteria{{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: true,
|
||||
value: "TEST.example.org",
|
||||
}},
|
||||
want: []tcAssertion{{
|
||||
num: 0, host: "test.example.org", answer: net.IPv4(1, 1, 1, 3), client: net.IPv4(2, 2, 2, 3),
|
||||
}},
|
||||
}, {
|
||||
name: "by_domain_non-strict",
|
||||
sCr: []searchCriteria{{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: false,
|
||||
value: "example.ORG",
|
||||
}},
|
||||
want: []tcAssertion{
|
||||
{num: 0, host: "test.example.org", answer: net.IPv4(1, 1, 1, 3), client: net.IPv4(2, 2, 2, 3)},
|
||||
{num: 1, host: "example.org", answer: net.IPv4(1, 1, 1, 2), client: net.IPv4(2, 2, 2, 2)},
|
||||
{num: 2, host: "example.org", answer: net.IPv4(1, 1, 1, 1), client: net.IPv4(2, 2, 2, 1)},
|
||||
},
|
||||
}, {
|
||||
name: "by_client_ip_strict",
|
||||
sCr: []searchCriteria{{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: true,
|
||||
value: "2.2.2.2",
|
||||
}},
|
||||
want: []tcAssertion{{
|
||||
num: 0, host: "example.org", answer: net.IPv4(1, 1, 1, 2), client: net.IPv4(2, 2, 2, 2),
|
||||
}},
|
||||
}, {
|
||||
name: "by_client_ip_non-strict",
|
||||
sCr: []searchCriteria{{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: false,
|
||||
value: "2.2.2",
|
||||
}},
|
||||
want: []tcAssertion{
|
||||
{num: 0, host: "example.com", answer: net.IPv4(1, 1, 1, 4), client: net.IPv4(2, 2, 2, 4)},
|
||||
{num: 1, host: "test.example.org", answer: net.IPv4(1, 1, 1, 3), client: net.IPv4(2, 2, 2, 3)},
|
||||
{num: 2, host: "example.org", answer: net.IPv4(1, 1, 1, 2), client: net.IPv4(2, 2, 2, 2)},
|
||||
{num: 3, host: "example.org", answer: net.IPv4(1, 1, 1, 1), client: net.IPv4(2, 2, 2, 1)},
|
||||
},
|
||||
}}
|
||||
|
||||
// search by domain (not strict)
|
||||
params = newSearchParams()
|
||||
params.searchCriteria = append(params.searchCriteria, searchCriteria{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: false,
|
||||
value: "example.ORG",
|
||||
})
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 3)
|
||||
assertLogEntry(t, entries[0], "test.example.org", net.IPv4(1, 1, 1, 3), net.IPv4(2, 2, 2, 3))
|
||||
assertLogEntry(t, entries[1], "example.org", net.IPv4(1, 1, 1, 2), net.IPv4(2, 2, 2, 2))
|
||||
assertLogEntry(t, entries[2], "example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
params := newSearchParams()
|
||||
params.searchCriteria = tc.sCr
|
||||
|
||||
// search by client IP (strict)
|
||||
params = newSearchParams()
|
||||
params.searchCriteria = append(params.searchCriteria, searchCriteria{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: true,
|
||||
value: "2.2.2.2",
|
||||
})
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 1)
|
||||
assertLogEntry(t, entries[0], "example.org", net.IPv4(1, 1, 1, 2), net.IPv4(2, 2, 2, 2))
|
||||
|
||||
// search by client IP (part of)
|
||||
params = newSearchParams()
|
||||
params.searchCriteria = append(params.searchCriteria, searchCriteria{
|
||||
criteriaType: ctDomainOrClient,
|
||||
strict: false,
|
||||
value: "2.2.2",
|
||||
})
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 4)
|
||||
assertLogEntry(t, entries[0], "example.com", net.IPv4(1, 1, 1, 4), net.IPv4(2, 2, 2, 4))
|
||||
assertLogEntry(t, entries[1], "test.example.org", net.IPv4(1, 1, 1, 3), net.IPv4(2, 2, 2, 3))
|
||||
assertLogEntry(t, entries[2], "example.org", net.IPv4(1, 1, 1, 2), net.IPv4(2, 2, 2, 2))
|
||||
assertLogEntry(t, entries[3], "example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
entries, _ := l.search(params)
|
||||
require.Len(t, entries, len(tc.want))
|
||||
for _, want := range tc.want {
|
||||
assertLogEntry(t, entries[want.num], want.host, want.answer, want.client)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryLogOffsetLimit(t *testing.T) {
|
||||
conf := Config{
|
||||
l := newQueryLog(Config{
|
||||
Enabled: true,
|
||||
Interval: 1,
|
||||
MemSize: 100,
|
||||
}
|
||||
conf.BaseDir = prepareTestDir()
|
||||
defer func() { _ = os.RemoveAll(conf.BaseDir) }()
|
||||
l := newQueryLog(conf)
|
||||
BaseDir: prepareTestDir(t),
|
||||
})
|
||||
|
||||
// add 10 entries to the log
|
||||
for i := 0; i < 10; i++ {
|
||||
addEntry(l, "second.example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
const (
|
||||
entNum = 10
|
||||
firstPageDomain = "first.example.org"
|
||||
secondPageDomain = "second.example.org"
|
||||
)
|
||||
// Add entries to the log.
|
||||
for i := 0; i < entNum; i++ {
|
||||
addEntry(l, secondPageDomain, net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
}
|
||||
// write them to disk (first file)
|
||||
_ = l.flushLogBuffer(true)
|
||||
// add 10 more entries to the log (memory)
|
||||
for i := 0; i < 10; i++ {
|
||||
addEntry(l, "first.example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
// Write them to the first file.
|
||||
require.Nil(t, l.flushLogBuffer(true))
|
||||
// Add more to the in-memory part of log.
|
||||
for i := 0; i < entNum; i++ {
|
||||
addEntry(l, firstPageDomain, net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
}
|
||||
|
||||
// First page
|
||||
params := newSearchParams()
|
||||
params.offset = 0
|
||||
params.limit = 10
|
||||
entries, _ := l.search(params)
|
||||
assert.Len(t, entries, 10)
|
||||
assert.Equal(t, entries[0].QHost, "first.example.org")
|
||||
assert.Equal(t, entries[9].QHost, "first.example.org")
|
||||
|
||||
// Second page
|
||||
params.offset = 10
|
||||
params.limit = 10
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 10)
|
||||
assert.Equal(t, entries[0].QHost, "second.example.org")
|
||||
assert.Equal(t, entries[9].QHost, "second.example.org")
|
||||
testCases := []struct {
|
||||
name string
|
||||
offset int
|
||||
limit int
|
||||
wantLen int
|
||||
want string
|
||||
}{{
|
||||
name: "page_1",
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
wantLen: 10,
|
||||
want: firstPageDomain,
|
||||
}, {
|
||||
name: "page_2",
|
||||
offset: 10,
|
||||
limit: 10,
|
||||
wantLen: 10,
|
||||
want: secondPageDomain,
|
||||
}, {
|
||||
name: "page_2.5",
|
||||
offset: 15,
|
||||
limit: 10,
|
||||
wantLen: 5,
|
||||
want: secondPageDomain,
|
||||
}, {
|
||||
name: "page_3",
|
||||
offset: 20,
|
||||
limit: 10,
|
||||
wantLen: 0,
|
||||
}}
|
||||
|
||||
// Second and a half page
|
||||
params.offset = 15
|
||||
params.limit = 10
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 5)
|
||||
assert.Equal(t, entries[0].QHost, "second.example.org")
|
||||
assert.Equal(t, entries[4].QHost, "second.example.org")
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
params.offset = tc.offset
|
||||
params.limit = tc.limit
|
||||
entries, _ := l.search(params)
|
||||
|
||||
// Third page
|
||||
params.offset = 20
|
||||
params.limit = 10
|
||||
entries, _ = l.search(params)
|
||||
assert.Empty(t, entries)
|
||||
require.Len(t, entries, tc.wantLen)
|
||||
|
||||
if tc.wantLen > 0 {
|
||||
assert.Equal(t, entries[0].QHost, tc.want)
|
||||
assert.Equal(t, entries[tc.wantLen-1].QHost, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryLogMaxFileScanEntries(t *testing.T) {
|
||||
conf := Config{
|
||||
l := newQueryLog(Config{
|
||||
Enabled: true,
|
||||
FileEnabled: true,
|
||||
Interval: 1,
|
||||
MemSize: 100,
|
||||
}
|
||||
conf.BaseDir = prepareTestDir()
|
||||
defer func() { _ = os.RemoveAll(conf.BaseDir) }()
|
||||
l := newQueryLog(conf)
|
||||
BaseDir: prepareTestDir(t),
|
||||
})
|
||||
|
||||
// add 10 entries to the log
|
||||
for i := 0; i < 10; i++ {
|
||||
const entNum = 10
|
||||
// Add entries to the log.
|
||||
for i := 0; i < entNum; i++ {
|
||||
addEntry(l, "example.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
}
|
||||
// write them to disk (first file)
|
||||
_ = l.flushLogBuffer(true)
|
||||
// Write them to disk.
|
||||
require.Nil(t, l.flushLogBuffer(true))
|
||||
|
||||
params := newSearchParams()
|
||||
params.maxFileScanEntries = 5 // do not scan more than 5 records
|
||||
entries, _ := l.search(params)
|
||||
assert.Len(t, entries, 5)
|
||||
|
||||
params.maxFileScanEntries = 0 // disable the limit
|
||||
entries, _ = l.search(params)
|
||||
assert.Len(t, entries, 10)
|
||||
for _, maxFileScanEntries := range []int{5, 0} {
|
||||
t.Run(fmt.Sprintf("limit_%d", maxFileScanEntries), func(t *testing.T) {
|
||||
params.maxFileScanEntries = maxFileScanEntries
|
||||
entries, _ := l.search(params)
|
||||
assert.Len(t, entries, entNum-maxFileScanEntries)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueryLogFileDisabled(t *testing.T) {
|
||||
conf := Config{
|
||||
l := newQueryLog(Config{
|
||||
Enabled: true,
|
||||
FileEnabled: false,
|
||||
Interval: 1,
|
||||
MemSize: 2,
|
||||
}
|
||||
conf.BaseDir = prepareTestDir()
|
||||
defer func() { _ = os.RemoveAll(conf.BaseDir) }()
|
||||
l := newQueryLog(conf)
|
||||
BaseDir: prepareTestDir(t),
|
||||
})
|
||||
|
||||
addEntry(l, "example1.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
addEntry(l, "example2.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
// The oldest entry is going to be removed from memory buffer.
|
||||
addEntry(l, "example3.org", net.IPv4(1, 1, 1, 1), net.IPv4(2, 2, 2, 1))
|
||||
// the oldest entry is now removed from mem buffer
|
||||
|
||||
params := newSearchParams()
|
||||
ll, _ := l.search(params)
|
||||
assert.Len(t, ll, 2)
|
||||
require.Len(t, ll, 2)
|
||||
assert.Equal(t, "example3.org", ll[0].QHost)
|
||||
assert.Equal(t, "example2.org", ll[1].QHost)
|
||||
}
|
||||
|
||||
func addEntry(l *queryLog, host string, answerStr, client net.IP) {
|
||||
q := dns.Msg{}
|
||||
q.Question = append(q.Question, dns.Question{
|
||||
Name: host + ".",
|
||||
Qtype: dns.TypeA,
|
||||
Qclass: dns.ClassINET,
|
||||
})
|
||||
|
||||
a := dns.Msg{}
|
||||
a.Question = append(a.Question, q.Question[0])
|
||||
answer := new(dns.A)
|
||||
answer.Hdr = dns.RR_Header{
|
||||
Name: q.Question[0].Name,
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
q := dns.Msg{
|
||||
Question: []dns.Question{{
|
||||
Name: host + ".",
|
||||
Qtype: dns.TypeA,
|
||||
Qclass: dns.ClassINET,
|
||||
}},
|
||||
}
|
||||
|
||||
a := dns.Msg{
|
||||
Question: q.Question,
|
||||
Answer: []dns.RR{&dns.A{
|
||||
Hdr: dns.RR_Header{
|
||||
Name: q.Question[0].Name,
|
||||
Rrtype: dns.TypeA,
|
||||
Class: dns.ClassINET,
|
||||
},
|
||||
A: answerStr,
|
||||
}},
|
||||
}
|
||||
answer.A = answerStr
|
||||
a.Answer = append(a.Answer, answer)
|
||||
res := dnsfilter.Result{
|
||||
IsFiltered: true,
|
||||
Reason: dnsfilter.Rewritten,
|
||||
@@ -254,19 +323,22 @@ func addEntry(l *queryLog, host string, answerStr, client net.IP) {
|
||||
l.Add(params)
|
||||
}
|
||||
|
||||
func assertLogEntry(t *testing.T, entry *logEntry, host string, answer, client net.IP) bool {
|
||||
func assertLogEntry(t *testing.T, entry *logEntry, host string, answer, client net.IP) {
|
||||
t.Helper()
|
||||
|
||||
require.NotNil(t, entry)
|
||||
|
||||
assert.Equal(t, host, entry.QHost)
|
||||
assert.Equal(t, client, entry.IP)
|
||||
assert.Equal(t, "A", entry.QType)
|
||||
assert.Equal(t, "IN", entry.QClass)
|
||||
|
||||
msg := new(dns.Msg)
|
||||
assert.Nil(t, msg.Unpack(entry.Answer))
|
||||
assert.Len(t, msg.Answer, 1)
|
||||
msg := &dns.Msg{}
|
||||
require.Nil(t, msg.Unpack(entry.Answer))
|
||||
require.Len(t, msg.Answer, 1)
|
||||
|
||||
ip := proxyutil.GetIPFromDNSRecord(msg.Answer[0]).To16()
|
||||
assert.NotNil(t, ip)
|
||||
assert.Equal(t, answer, ip)
|
||||
return true
|
||||
}
|
||||
|
||||
func testEntries() (entries []*logEntry) {
|
||||
@@ -332,8 +404,8 @@ func TestLogEntriesByTime_sort(t *testing.T) {
|
||||
entries := testEntries()
|
||||
sort.Sort(logEntriesByTimeDesc(entries))
|
||||
|
||||
for i := 1; i < len(entries); i++ {
|
||||
assert.False(t, entries[i].Time.After(entries[i-1].Time),
|
||||
"%s %s", entries[i].Time, entries[i-1].Time)
|
||||
for i := range entries[1:] {
|
||||
assert.False(t, entries[i+1].Time.After(entries[i].Time),
|
||||
"%s %s", entries[i+1].Time, entries[i].Time)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user