mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
722 lines
19 KiB
Go
722 lines
19 KiB
Go
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"
|
|
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal"
|
|
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal/filecachepb"
|
|
"github.com/AdguardTeam/AdGuardDNS/internal/profiledb/internal/profiledbtest"
|
|
"github.com/AdguardTeam/golibs/errors"
|
|
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
|
"github.com/AdguardTeam/golibs/testutil"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// Common IPs for tests
|
|
var (
|
|
testClientIPv4 = netip.MustParseAddr("192.0.2.1")
|
|
testOtherClientIPv4 = netip.MustParseAddr("192.0.2.2")
|
|
|
|
testDedicatedIPv4 = netip.MustParseAddr("192.0.2.3")
|
|
testOtherDedicatedIPv4 = netip.MustParseAddr("192.0.2.4")
|
|
)
|
|
|
|
// 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,
|
|
_ *profiledb.StorageProfilesRequest,
|
|
) (resp *profiledb.StorageProfilesResponse, err error) {
|
|
devices, _ := testutil.RequireReceive(tb, devices, testTimeout)
|
|
devIDs := make([]agd.DeviceID, 0, len(devices))
|
|
for _, d := range devices {
|
|
devIDs = append(devIDs, d.ID)
|
|
}
|
|
|
|
return &profiledb.StorageProfilesResponse{
|
|
Profiles: []*agd.Profile{{
|
|
BlockingMode: &dnsmsg.BlockingModeNullIP{},
|
|
ID: profiledbtest.ProfileID,
|
|
DeviceIDs: devIDs,
|
|
}},
|
|
Devices: devices,
|
|
}, nil
|
|
}
|
|
|
|
ps := &agdtest.ProfileStorage{
|
|
OnCreateAutoDevice: func(
|
|
_ context.Context,
|
|
_ *profiledb.StorageCreateAutoDeviceRequest,
|
|
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
|
|
panic("not implemented")
|
|
},
|
|
OnProfiles: onProfiles,
|
|
}
|
|
|
|
db, err := profiledb.New(&profiledb.Config{
|
|
Logger: slogutil.NewDiscardLogger(),
|
|
Storage: ps,
|
|
ErrColl: agdtest.NewErrorCollector(),
|
|
Metrics: profiledb.EmptyMetrics{},
|
|
CacheFilePath: "none",
|
|
FullSyncIvl: 1 * time.Minute,
|
|
FullSyncRetryIvl: 1 * time.Minute,
|
|
ResponseSizeEstimate: profiledbtest.RespSzEst,
|
|
})
|
|
require.NoError(tb, err)
|
|
|
|
ctx := testutil.ContextWithTimeout(tb, testTimeout)
|
|
require.NoError(tb, db.Refresh(ctx))
|
|
|
|
return db
|
|
}
|
|
|
|
func TestDefaultProfileDB(t *testing.T) {
|
|
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,
|
|
},
|
|
}
|
|
|
|
devicesCh := make(chan []*agd.Device, 2)
|
|
devicesCh <- devices
|
|
db := newDefaultProfileDB(t, devicesCh)
|
|
|
|
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])
|
|
})
|
|
|
|
t.Run("by_device_id", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
p, d, err := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, profiledbtest.ProfileID, p.ID)
|
|
assert.Equal(t, d, devices[devIdxDefault])
|
|
})
|
|
|
|
t.Run("by_human_id", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
p, d, err := db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, profiledbtest.ProfileID, p.ID)
|
|
assert.Equal(t, d, devices[devIdxAuto])
|
|
})
|
|
|
|
t.Run("by_linked_ip", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
p, d, err := db.ProfileByLinkedIP(ctx, testClientIPv4)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, profiledbtest.ProfileID, p.ID)
|
|
assert.Equal(t, d, devices[devIdxDefault])
|
|
})
|
|
}
|
|
|
|
func TestDefaultProfileDB_ProfileByDedicatedIP_removedDevice(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
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 := testutil.ContextWithTimeout(t, testTimeout)
|
|
_, d, err := db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, d, dev)
|
|
|
|
// The second response, the device is removed.
|
|
devicesCh <- nil
|
|
|
|
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.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
|
|
|
|
return errors.Is(err, profiledb.ErrDeviceNotFound)
|
|
}, testTimeout, testTimeout/10)
|
|
}
|
|
|
|
func TestDefaultProfileDB_ProfileByDedicatedIP_deviceNewIP(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
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)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
func TestDefaultProfileDB_ProfileByLinkedIP_removedDevice(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
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) {
|
|
t.Parallel()
|
|
|
|
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) {
|
|
t.Parallel()
|
|
|
|
var gotSyncTime time.Time
|
|
onProfiles := func(
|
|
_ context.Context,
|
|
req *profiledb.StorageProfilesRequest,
|
|
) (resp *profiledb.StorageProfilesResponse, err error) {
|
|
gotSyncTime = req.SyncTime
|
|
|
|
return &profiledb.StorageProfilesResponse{}, nil
|
|
}
|
|
|
|
ps := &agdtest.ProfileStorage{
|
|
OnCreateAutoDevice: func(
|
|
_ context.Context,
|
|
_ *profiledb.StorageCreateAutoDeviceRequest,
|
|
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
|
|
panic("not implemented")
|
|
},
|
|
OnProfiles: onProfiles,
|
|
}
|
|
|
|
// Use the time with monotonic clocks stripped down.
|
|
wantSyncTime := time.Now().Round(0).UTC()
|
|
|
|
prof, dev := profiledbtest.NewProfile(t)
|
|
|
|
cacheFilePath := filepath.Join(t.TempDir(), "profiles.pb")
|
|
logger := slogutil.NewDiscardLogger()
|
|
pbCache := filecachepb.New(logger, cacheFilePath, profiledbtest.RespSzEst)
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
err := pbCache.Store(ctx, &internal.FileCache{
|
|
SyncTime: wantSyncTime,
|
|
Profiles: []*agd.Profile{prof},
|
|
Devices: []*agd.Device{dev},
|
|
Version: internal.FileCacheVersion,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
db, err := profiledb.New(&profiledb.Config{
|
|
Logger: logger,
|
|
Storage: ps,
|
|
ErrColl: agdtest.NewErrorCollector(),
|
|
Metrics: profiledb.EmptyMetrics{},
|
|
CacheFilePath: cacheFilePath,
|
|
FullSyncIvl: 1 * time.Minute,
|
|
FullSyncRetryIvl: 1 * time.Minute,
|
|
ResponseSizeEstimate: profiledbtest.RespSzEst,
|
|
})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, db)
|
|
|
|
ctx = testutil.ContextWithTimeout(t, testTimeout)
|
|
require.NoError(t, db.Refresh(ctx))
|
|
|
|
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) {
|
|
t.Parallel()
|
|
|
|
storageCalled := false
|
|
ps := &agdtest.ProfileStorage{
|
|
OnCreateAutoDevice: func(
|
|
_ context.Context,
|
|
_ *profiledb.StorageCreateAutoDeviceRequest,
|
|
) (resp *profiledb.StorageCreateAutoDeviceResponse, err error) {
|
|
panic("not implemented")
|
|
},
|
|
OnProfiles: func(
|
|
_ context.Context,
|
|
_ *profiledb.StorageProfilesRequest,
|
|
) (resp *profiledb.StorageProfilesResponse, err error) {
|
|
storageCalled = true
|
|
|
|
return &profiledb.StorageProfilesResponse{}, nil
|
|
},
|
|
}
|
|
|
|
cacheFilePath := filepath.Join(t.TempDir(), "profiles.pb")
|
|
logger := slogutil.NewDiscardLogger()
|
|
pbCache := filecachepb.New(logger, cacheFilePath, profiledbtest.RespSzEst)
|
|
|
|
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
|
err := pbCache.Store(ctx, &internal.FileCache{
|
|
Version: 10000,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
db, err := profiledb.New(&profiledb.Config{
|
|
Logger: logger,
|
|
Storage: ps,
|
|
ErrColl: agdtest.NewErrorCollector(),
|
|
Metrics: profiledb.EmptyMetrics{},
|
|
CacheFilePath: cacheFilePath,
|
|
FullSyncIvl: 1 * time.Minute,
|
|
FullSyncRetryIvl: 1 * time.Minute,
|
|
ResponseSizeEstimate: profiledbtest.RespSzEst,
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, db)
|
|
|
|
ctx = testutil.ContextWithTimeout(t, testTimeout)
|
|
require.NoError(t, db.Refresh(ctx))
|
|
|
|
assert.True(t, storageCalled)
|
|
}
|
|
|
|
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{
|
|
Logger: slogutil.NewDiscardLogger(),
|
|
Storage: ps,
|
|
ErrColl: agdtest.NewErrorCollector(),
|
|
Metrics: profiledb.EmptyMetrics{},
|
|
CacheFilePath: "none",
|
|
FullSyncIvl: 1 * time.Minute,
|
|
FullSyncRetryIvl: 1 * time.Minute,
|
|
ResponseSizeEstimate: profiledbtest.RespSzEst,
|
|
})
|
|
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)
|
|
}
|
|
|
|
// 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()
|
|
for range b.N {
|
|
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()
|
|
for range b.N {
|
|
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
|
|
// 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
|
|
}
|
|
|
|
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()
|
|
for range b.N {
|
|
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()
|
|
for range b.N {
|
|
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
|
|
// 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
|
|
}
|
|
|
|
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()
|
|
for range b.N {
|
|
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()
|
|
for range b.N {
|
|
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
|
|
// 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
|
|
}
|