AdGuardDNS/internal/profiledb/profiledb_test.go

722 lines
19 KiB
Go
Raw Normal View History

2023-06-11 12:58:40 +03:00
package profiledb_test
import (
"context"
"net/netip"
"path/filepath"
"testing"
"time"
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
"github.com/AdguardTeam/AdGuardDNS/internal/agdtest"
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb"
2023-09-06 08:22:07 +03:00
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal"
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal/filecachepb"
2023-06-11 12:58:40 +03:00
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal/profiledbtest"
"github.com/AdguardTeam/golibs/errors"
2024-10-14 17:44:24 +03:00
"github.com/AdguardTeam/golibs/logutil/slogutil"
2023-06-11 12:58:40 +03:00
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Common IPs for tests
var (
2024-07-10 19:49:07 +03:00
testClientIPv4 = netip.MustParseAddr("192.0.2.1")
testOtherClientIPv4 = netip.MustParseAddr("192.0.2.2")
2023-06-11 12:58:40 +03:00
2024-07-10 19:49:07 +03:00
testDedicatedIPv4 = netip.MustParseAddr("192.0.2.3")
testOtherDedicatedIPv4 = netip.MustParseAddr("192.0.2.4")
2023-06-11 12:58:40 +03:00
)
// testTimeout is the common timeout for tests.
const testTimeout = 1 * time.Second
// newDefaultProfileDB returns a new default profile database for tests.
// devicesCh receives the devices that the storage should return in its
// response.
func newDefaultProfileDB(tb testing.TB, devices <-chan []*agd.Device) (db *profiledb.Default) {
tb.Helper()
onProfiles := func(
_ context.Context,
2024-07-10 19:49:07 +03:00
_ *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
2023-06-11 12:58:40 +03:00
devices, _ := testutil.RequireReceive(tb, devices, testTimeout)
devIDs := make([]agd.DeviceID, 0, len(devices))
for _, d := range devices {
devIDs = append(devIDs, d.ID)
}
2024-07-10 19:49:07 +03:00
return &profiledb.StorageProfilesResponse{
2023-06-11 12:58:40 +03:00
Profiles: []*agd.Profile{{
2024-01-04 19:22:32 +03:00
BlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
DeviceIDs: devIDs,
2023-06-11 12:58:40 +03:00
}},
Devices: devices,
}, nil
}
ps := &agdtest.ProfileStorage{
2024-07-10 19:49:07 +03:00
OnCreateAutoDevice: func(
_ context.Context,
_ *profiledb.StorageCreateAutoDeviceRequest,
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
panic("not implemented")
},
2023-06-11 12:58:40 +03:00
OnProfiles: onProfiles,
}
2024-01-04 19:22:32 +03:00
db, err := profiledb.New(&profiledb.Config{
2024-10-14 17:44:24 +03:00
Logger: slogutil.NewDiscardLogger(),
Storage: ps,
ErrColl: agdtest.NewErrorCollector(),
Metrics: profiledb.EmptyMetrics{},
CacheFilePath: "none",
FullSyncIvl: 1 * time.Minute,
FullSyncRetryIvl: 1 * time.Minute,
ResponseSizeEstimate: profiledbtest.RespSzEst,
2024-01-04 19:22:32 +03:00
})
2023-06-11 12:58:40 +03:00
require.NoError(tb, err)
2024-07-10 19:49:07 +03:00
ctx := testutil.ContextWithTimeout(tb, testTimeout)
require.NoError(tb, db.Refresh(ctx))
2023-06-11 12:58:40 +03:00
return db
}
func TestDefaultProfileDB(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
const (
devIdxDefault = iota
devIdxAuto
)
devices := []*agd.Device{
devIdxDefault: {
ID: profiledbtest.DeviceID,
LinkedIP: testClientIPv4,
DedicatedIPs: []netip.Addr{
testDedicatedIPv4,
},
},
devIdxAuto: {
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
2023-06-11 12:58:40 +03:00
},
}
2024-07-10 19:49:07 +03:00
devicesCh := make(chan []*agd.Device, 2)
devicesCh <- devices
2023-06-11 12:58:40 +03:00
db := newDefaultProfileDB(t, devicesCh)
2024-07-10 19:49:07 +03:00
t.Run("by_dedicated_ip", func(t *testing.T) {
t.Parallel()
ctx := testutil.ContextWithTimeout(t, testTimeout)
p, d, err := db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
require.NoError(t, err)
assert.Equal(t, profiledbtest.ProfileID, p.ID)
assert.Equal(t, d, devices[devIdxDefault])
})
2023-06-11 12:58:40 +03:00
t.Run("by_device_id", func(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2024-06-07 14:27:46 +03:00
ctx := testutil.ContextWithTimeout(t, testTimeout)
2023-06-11 12:58:40 +03:00
p, d, err := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
require.NoError(t, err)
assert.Equal(t, profiledbtest.ProfileID, p.ID)
2024-07-10 19:49:07 +03:00
assert.Equal(t, d, devices[devIdxDefault])
2023-06-11 12:58:40 +03:00
})
2024-07-10 19:49:07 +03:00
t.Run("by_human_id", func(t *testing.T) {
t.Parallel()
2024-06-07 14:27:46 +03:00
ctx := testutil.ContextWithTimeout(t, testTimeout)
2024-07-10 19:49:07 +03:00
p, d, err := db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
2023-06-11 12:58:40 +03:00
require.NoError(t, err)
assert.Equal(t, profiledbtest.ProfileID, p.ID)
2024-07-10 19:49:07 +03:00
assert.Equal(t, d, devices[devIdxAuto])
2023-06-11 12:58:40 +03:00
})
t.Run("by_linked_ip", func(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2024-06-07 14:27:46 +03:00
ctx := testutil.ContextWithTimeout(t, testTimeout)
2023-06-11 12:58:40 +03:00
p, d, err := db.ProfileByLinkedIP(ctx, testClientIPv4)
require.NoError(t, err)
assert.Equal(t, profiledbtest.ProfileID, p.ID)
2024-07-10 19:49:07 +03:00
assert.Equal(t, d, devices[devIdxDefault])
2023-06-11 12:58:40 +03:00
})
}
func TestDefaultProfileDB_ProfileByDedicatedIP_removedDevice(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
dev := &agd.Device{
ID: profiledbtest.DeviceID,
DedicatedIPs: []netip.Addr{
testDedicatedIPv4,
},
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
2024-06-07 14:27:46 +03:00
ctx := testutil.ContextWithTimeout(t, testTimeout)
2023-06-11 12:58:40 +03:00
_, d, err := db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device is removed.
devicesCh <- nil
2024-06-07 14:27:46 +03:00
ctx = testutil.ContextWithTimeout(t, testTimeout)
2023-06-11 12:58:40 +03:00
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
2024-06-07 14:27:46 +03:00
ctx = testutil.ContextWithTimeout(t, testTimeout)
2023-06-11 12:58:40 +03:00
_, d, err = db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, testTimeout, testTimeout/10)
}
func TestDefaultProfileDB_ProfileByDedicatedIP_deviceNewIP(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
dev := &agd.Device{
ID: profiledbtest.DeviceID,
DedicatedIPs: []netip.Addr{
testDedicatedIPv4,
},
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
ctx := context.Background()
_, d, err := db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device has a new IP.
dev.DedicatedIPs[0] = testOtherDedicatedIPv4
devicesCh <- []*agd.Device{dev}
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
_, _, err = db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
if !errors.Is(err, profiledb.ErrDeviceNotFound) {
return false
}
_, d, err = db.ProfileByDedicatedIP(ctx, testOtherDedicatedIPv4)
if err != nil {
return false
}
return d != nil && d.ID == dev.ID
}, testTimeout, testTimeout/10)
}
2024-07-10 19:49:07 +03:00
func TestDefaultProfileDB_ProfileByHumanID_removedDevice(t *testing.T) {
t.Parallel()
dev := &agd.Device{
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
ctx := context.Background()
_, d, err := db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device is removed.
devicesCh <- nil
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
_, d, err = db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, testTimeout, testTimeout/10)
}
func TestDefaultProfileDB_ProfileByHumanID_deviceNotAuto(t *testing.T) {
t.Parallel()
dev := &agd.Device{
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
ctx := testutil.ContextWithTimeout(t, testTimeout)
_, d, err := db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device is now a non-auto device.
devicesCh <- []*agd.Device{{
ID: profiledbtest.DeviceIDAuto,
}}
ctx = testutil.ContextWithTimeout(t, testTimeout)
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
ctx = testutil.ContextWithTimeout(t, testTimeout)
_, d, err = db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, testTimeout, testTimeout/10)
}
2023-06-11 12:58:40 +03:00
func TestDefaultProfileDB_ProfileByLinkedIP_removedDevice(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
dev := &agd.Device{
ID: profiledbtest.DeviceID,
LinkedIP: testClientIPv4,
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
ctx := context.Background()
_, d, err := db.ProfileByLinkedIP(ctx, testClientIPv4)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device is removed.
devicesCh <- nil
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
_, d, err = db.ProfileByLinkedIP(ctx, testClientIPv4)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, testTimeout, testTimeout/10)
}
func TestDefaultProfileDB_ProfileByLinkedIP_deviceNewIP(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
dev := &agd.Device{
ID: profiledbtest.DeviceID,
LinkedIP: testClientIPv4,
}
devicesCh := make(chan []*agd.Device, 2)
// The first response, the device is still there.
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(t, devicesCh)
ctx := context.Background()
_, d, err := db.ProfileByLinkedIP(ctx, testClientIPv4)
require.NoError(t, err)
assert.Equal(t, d, dev)
// The second response, the device has a new IP.
dev.LinkedIP = testOtherClientIPv4
devicesCh <- []*agd.Device{dev}
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
_, _, err = db.ProfileByLinkedIP(ctx, testClientIPv4)
if !errors.Is(err, profiledb.ErrDeviceNotFound) {
return false
}
_, d, err = db.ProfileByLinkedIP(ctx, testOtherClientIPv4)
if err != nil {
return false
}
return d != nil && d.ID == dev.ID
}, testTimeout, testTimeout/10)
}
func TestDefaultProfileDB_fileCache_success(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
var gotSyncTime time.Time
onProfiles := func(
_ context.Context,
2024-07-10 19:49:07 +03:00
req *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
2023-06-11 12:58:40 +03:00
gotSyncTime = req.SyncTime
2024-07-10 19:49:07 +03:00
return &profiledb.StorageProfilesResponse{}, nil
2023-06-11 12:58:40 +03:00
}
ps := &agdtest.ProfileStorage{
2024-07-10 19:49:07 +03:00
OnCreateAutoDevice: func(
_ context.Context,
_ *profiledb.StorageCreateAutoDeviceRequest,
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
panic("not implemented")
},
2023-06-11 12:58:40 +03:00
OnProfiles: onProfiles,
}
// Use the time with monotonic clocks stripped down.
wantSyncTime := time.Now().Round(0).UTC()
2023-09-06 08:22:07 +03:00
prof, dev := profiledbtest.NewProfile(t)
cacheFilePath := filepath.Join(t.TempDir(), "profiles.pb")
2024-10-14 17:44:24 +03:00
logger := slogutil.NewDiscardLogger()
pbCache := filecachepb.New(logger, cacheFilePath, profiledbtest.RespSzEst)
ctx := testutil.ContextWithTimeout(t, testTimeout)
err := pbCache.Store(ctx, &internal.FileCache{
2023-09-06 08:22:07 +03:00
SyncTime: wantSyncTime,
Profiles: []*agd.Profile{prof},
Devices: []*agd.Device{dev},
Version: internal.FileCacheVersion,
})
2023-06-11 12:58:40 +03:00
require.NoError(t, err)
2024-01-04 19:22:32 +03:00
db, err := profiledb.New(&profiledb.Config{
2024-10-14 17:44:24 +03:00
Logger: logger,
Storage: ps,
ErrColl: agdtest.NewErrorCollector(),
Metrics: profiledb.EmptyMetrics{},
CacheFilePath: cacheFilePath,
FullSyncIvl: 1 * time.Minute,
FullSyncRetryIvl: 1 * time.Minute,
ResponseSizeEstimate: profiledbtest.RespSzEst,
2024-01-04 19:22:32 +03:00
})
2023-06-11 12:58:40 +03:00
require.NoError(t, err)
require.NotNil(t, db)
2024-10-14 17:44:24 +03:00
ctx = testutil.ContextWithTimeout(t, testTimeout)
2024-07-10 19:49:07 +03:00
require.NoError(t, db.Refresh(ctx))
2023-06-11 12:58:40 +03:00
assert.Equal(t, wantSyncTime, gotSyncTime)
p, d, err := db.ProfileByDeviceID(context.Background(), dev.ID)
require.NoError(t, err)
assert.Equal(t, dev, d)
assert.Equal(t, prof, p)
}
func TestDefaultProfileDB_fileCache_badVersion(t *testing.T) {
2024-07-10 19:49:07 +03:00
t.Parallel()
2023-06-11 12:58:40 +03:00
storageCalled := false
ps := &agdtest.ProfileStorage{
2024-07-10 19:49:07 +03:00
OnCreateAutoDevice: func(
_ context.Context,
_ *profiledb.StorageCreateAutoDeviceRequest,
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
panic("not implemented")
},
2023-06-11 12:58:40 +03:00
OnProfiles: func(
_ context.Context,
2024-07-10 19:49:07 +03:00
_ *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
2023-06-11 12:58:40 +03:00
storageCalled = true
2024-07-10 19:49:07 +03:00
return &profiledb.StorageProfilesResponse{}, nil
2023-06-11 12:58:40 +03:00
},
}
2023-09-06 08:22:07 +03:00
cacheFilePath := filepath.Join(t.TempDir(), "profiles.pb")
2024-10-14 17:44:24 +03:00
logger := slogutil.NewDiscardLogger()
pbCache := filecachepb.New(logger, cacheFilePath, profiledbtest.RespSzEst)
ctx := testutil.ContextWithTimeout(t, testTimeout)
err := pbCache.Store(ctx, &internal.FileCache{
2023-09-06 08:22:07 +03:00
Version: 10000,
})
2023-06-11 12:58:40 +03:00
require.NoError(t, err)
2024-01-04 19:22:32 +03:00
db, err := profiledb.New(&profiledb.Config{
2024-10-14 17:44:24 +03:00
Logger: logger,
Storage: ps,
ErrColl: agdtest.NewErrorCollector(),
Metrics: profiledb.EmptyMetrics{},
CacheFilePath: cacheFilePath,
FullSyncIvl: 1 * time.Minute,
FullSyncRetryIvl: 1 * time.Minute,
ResponseSizeEstimate: profiledbtest.RespSzEst,
2024-01-04 19:22:32 +03:00
})
2023-06-11 12:58:40 +03:00
assert.NoError(t, err)
assert.NotNil(t, db)
2024-07-10 19:49:07 +03:00
2024-10-14 17:44:24 +03:00
ctx = testutil.ContextWithTimeout(t, testTimeout)
2024-07-10 19:49:07 +03:00
require.NoError(t, db.Refresh(ctx))
2023-06-11 12:58:40 +03:00
assert.True(t, storageCalled)
}
2024-07-10 19:49:07 +03:00
func TestDefaultProfileDB_CreateAutoDevice(t *testing.T) {
t.Parallel()
wantDev := &agd.Device{
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
}
wantProf := &agd.Profile{
BlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
DeviceIDs: nil,
AutoDevicesEnabled: true,
}
ps := &agdtest.ProfileStorage{
OnCreateAutoDevice: func(
_ context.Context,
_ *profiledb.StorageCreateAutoDeviceRequest,
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
return &profiledb.StorageCreateAutoDeviceResponse{
Device: wantDev,
}, nil
},
OnProfiles: func(
_ context.Context,
_ *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
return &profiledb.StorageProfilesResponse{
Profiles: []*agd.Profile{wantProf},
Devices: nil,
}, nil
},
}
db, err := profiledb.New(&profiledb.Config{
2024-10-14 17:44:24 +03:00
Logger: slogutil.NewDiscardLogger(),
Storage: ps,
ErrColl: agdtest.NewErrorCollector(),
Metrics: profiledb.EmptyMetrics{},
CacheFilePath: "none",
FullSyncIvl: 1 * time.Minute,
FullSyncRetryIvl: 1 * time.Minute,
ResponseSizeEstimate: profiledbtest.RespSzEst,
2024-07-10 19:49:07 +03:00
})
require.NoError(t, err)
require.NotNil(t, db)
ctx := testutil.ContextWithTimeout(t, testTimeout)
require.NoError(t, db.Refresh(ctx))
p, d, err := db.CreateAutoDevice(
ctx,
profiledbtest.ProfileID,
profiledbtest.HumanID,
agd.DeviceTypeOther,
)
require.NoError(t, err)
assert.Equal(t, wantDev, d)
assert.Equal(t, wantProf, p)
}
2023-06-11 12:58:40 +03:00
// Sinks for benchmarks.
var (
profSink *agd.Profile
devSink *agd.Device
errSink error
)
func BenchmarkDefaultProfileDB_ProfileByDeviceID(b *testing.B) {
dev := &agd.Device{
ID: profiledbtest.DeviceID,
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
}
assert.NotNil(b, profSink)
assert.NotNil(b, devSink)
assert.NoError(b, errSink)
})
const wrongDevID = profiledbtest.DeviceID + "_bad"
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByDeviceID(ctx, wrongDevID)
}
assert.Nil(b, profSink)
assert.Nil(b, devSink)
assert.ErrorIs(b, errSink, profiledb.ErrDeviceNotFound)
})
// Most recent results, as of 2023-04-10, on a ThinkPad X13 with a Ryzen Pro
// 7 CPU:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
2024-07-10 19:49:07 +03:00
// BenchmarkDefaultProfileDB_ProfileByDeviceID/success-16 55459413 23.43 ns/op 0 B/op 0 allocs/op
// BenchmarkDefaultProfileDB_ProfileByDeviceID/not_found-16 61798608 17.87 ns/op 0 B/op 0 allocs/op
2023-06-11 12:58:40 +03:00
}
func BenchmarkDefaultProfileDB_ProfileByLinkedIP(b *testing.B) {
dev := &agd.Device{
ID: profiledbtest.DeviceID,
LinkedIP: testClientIPv4,
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByLinkedIP(ctx, testClientIPv4)
}
assert.NotNil(b, profSink)
assert.NotNil(b, devSink)
assert.NoError(b, errSink)
})
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByLinkedIP(ctx, testOtherClientIPv4)
}
assert.Nil(b, profSink)
assert.Nil(b, devSink)
assert.ErrorIs(b, errSink, profiledb.ErrDeviceNotFound)
})
// Most recent results, as of 2023-04-10, on a ThinkPad X13 with a Ryzen Pro
// 7 CPU:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
2024-07-10 19:49:07 +03:00
// BenchmarkDefaultProfileDB_ProfileByLinkedIP/success-16 26068507 44.23 ns/op 0 B/op 0 allocs/op
// BenchmarkDefaultProfileDB_ProfileByLinkedIP/not_found-16 53764724 22.63 ns/op 0 B/op 0 allocs/op
2023-06-11 12:58:40 +03:00
}
func BenchmarkDefaultProfileDB_ProfileByDedicatedIP(b *testing.B) {
dev := &agd.Device{
ID: profiledbtest.DeviceID,
DedicatedIPs: []netip.Addr{
testClientIPv4,
},
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{dev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByDedicatedIP(ctx, testClientIPv4)
}
assert.NotNil(b, profSink)
assert.NotNil(b, devSink)
assert.NoError(b, errSink)
})
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
2024-06-07 14:27:46 +03:00
for range b.N {
2023-06-11 12:58:40 +03:00
profSink, devSink, errSink = db.ProfileByDedicatedIP(ctx, testOtherClientIPv4)
}
assert.Nil(b, profSink)
assert.Nil(b, devSink)
assert.ErrorIs(b, errSink, profiledb.ErrDeviceNotFound)
})
// Most recent results, as of 2023-04-10, on a ThinkPad X13 with a Ryzen Pro
// 7 CPU:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
2024-07-10 19:49:07 +03:00
// BenchmarkDefaultProfileDB_ProfileByDedicatedIP/success-16 26034816 48.21 ns/op 0 B/op 0 allocs/op
// BenchmarkDefaultProfileDB_ProfileByDedicatedIP/not_found-16 54165615 22.38 ns/op 0 B/op 0 allocs/op
2023-06-11 12:58:40 +03:00
}