Files
AdGuardDNS/internal/profiledb/default_test.go
Andrey Meshkov c1ba1c877a Sync v2.17.0
2025-11-07 13:47:40 +03:00

842 lines
21 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/container"
"github.com/AdguardTeam/golibs/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDefault(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 := profiledbtest.ContextWithTimeout(t)
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 := profiledbtest.ContextWithTimeout(t)
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 := profiledbtest.ContextWithTimeout(t)
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 := profiledbtest.ContextWithTimeout(t)
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 TestDefault_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 := profiledbtest.ContextWithTimeout(t)
_, 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 = profiledbtest.ContextWithTimeout(t)
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
ctx = profiledbtest.ContextWithTimeout(t)
_, d, err = db.ProfileByDedicatedIP(ctx, testDedicatedIPv4)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_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
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_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)
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_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 := profiledbtest.ContextWithTimeout(t)
_, 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 = profiledbtest.ContextWithTimeout(t)
err = db.Refresh(ctx)
require.NoError(t, err)
assert.Eventually(t, func() (ok bool) {
ctx = profiledbtest.ContextWithTimeout(t)
_, d, err = db.ProfileByHumanID(ctx, profiledbtest.ProfileID, profiledbtest.HumanIDLower)
return errors.Is(err, profiledb.ErrDeviceNotFound)
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_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)
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_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
}, profiledbtest.Timeout, profiledbtest.Timeout/10)
}
func TestDefault_fileCache_success(t *testing.T) {
t.Parallel()
var gotSyncTime time.Time
ps := agdtest.NewProfileStorage()
ps.OnProfiles = func(
_ context.Context,
req *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
gotSyncTime = req.SyncTime
return &profiledb.StorageProfilesResponse{}, nil
}
// 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")
pbCache := filecachepb.New(&filecachepb.Config{
Logger: profiledbtest.Logger,
BaseCustomLogger: profiledbtest.Logger,
ProfileAccessConstructor: profiledbtest.ProfileAccessConstructor,
CacheFilePath: cacheFilePath,
ResponseSizeEstimate: profiledbtest.RespSzEst,
})
ctx := profiledbtest.ContextWithTimeout(t)
err := pbCache.Store(ctx, &internal.FileCache{
SyncTime: wantSyncTime,
Profiles: []*agd.Profile{prof},
Devices: []*agd.Device{dev},
Version: internal.FileCacheVersion,
})
require.NoError(t, err)
db := newProfileDB(t, &profiledb.Config{
Storage: ps,
CacheFilePath: cacheFilePath,
})
ctx = profiledbtest.ContextWithTimeout(t)
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)
agdtest.AssertEqualProfile(t, prof, p)
}
func TestDefault_fileCache_badVersion(t *testing.T) {
t.Parallel()
storageCalled := false
ps := agdtest.NewProfileStorage()
ps.OnProfiles = func(
_ context.Context,
_ *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
storageCalled = true
return &profiledb.StorageProfilesResponse{}, nil
}
cacheFilePath := filepath.Join(t.TempDir(), "profiles.pb")
pbCache := filecachepb.New(&filecachepb.Config{
Logger: profiledbtest.Logger,
BaseCustomLogger: profiledbtest.Logger,
ProfileAccessConstructor: profiledbtest.ProfileAccessConstructor,
CacheFilePath: cacheFilePath,
ResponseSizeEstimate: profiledbtest.RespSzEst,
})
ctx := profiledbtest.ContextWithTimeout(t)
err := pbCache.Store(ctx, &internal.FileCache{
Version: 10000,
})
require.NoError(t, err)
db := newProfileDB(t, &profiledb.Config{
Storage: ps,
CacheFilePath: cacheFilePath,
})
ctx = profiledbtest.ContextWithTimeout(t)
require.NoError(t, db.Refresh(ctx))
assert.True(t, storageCalled)
}
func TestDefault_CreateAutoDevice(t *testing.T) {
t.Parallel()
wantDev := &agd.Device{
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
}
wantProf := &agd.Profile{
CustomDomains: &agd.AccountCustomDomains{},
AdultBlockingMode: &dnsmsg.BlockingModeNullIP{},
BlockingMode: &dnsmsg.BlockingModeNullIP{},
SafeBrowsingBlockingMode: &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 := newProfileDB(t, &profiledb.Config{
Storage: ps,
})
ctx := profiledbtest.ContextWithTimeout(t)
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)
}
func TestDefault_deviceChanges(t *testing.T) {
t.Parallel()
var (
devPrevName = &agd.Device{
ID: profiledbtest.DeviceID,
Name: "Name 1",
}
devNewName = &agd.Device{
ID: profiledbtest.DeviceID,
Name: "Name 2",
}
devAuto = &agd.Device{
ID: profiledbtest.DeviceIDAuto,
HumanIDLower: profiledbtest.HumanIDLower,
}
)
profBefore := &agd.Profile{
CustomDomains: &agd.AccountCustomDomains{},
AdultBlockingMode: &dnsmsg.BlockingModeNullIP{},
BlockingMode: &dnsmsg.BlockingModeNullIP{},
SafeBrowsingBlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
DeviceIDs: container.NewMapSet(
profiledbtest.DeviceID,
profiledbtest.DeviceIDAuto,
),
AutoDevicesEnabled: true,
}
profAfter := &agd.Profile{
CustomDomains: &agd.AccountCustomDomains{},
AdultBlockingMode: &dnsmsg.BlockingModeNullIP{},
BlockingMode: &dnsmsg.BlockingModeNullIP{},
SafeBrowsingBlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
DeviceIDs: container.NewMapSet(
profiledbtest.DeviceID,
),
AutoDevicesEnabled: true,
}
var (
strgRespFull = &profiledb.StorageProfilesResponse{
SyncTime: time.Now(),
Profiles: []*agd.Profile{profBefore},
Devices: []*agd.Device{devPrevName, devAuto},
}
strgRespChg = &profiledb.StorageDeviceChange{
DeletedDeviceIDs: []agd.DeviceID{profiledbtest.DeviceIDAuto},
IsPartial: true,
}
strgRespPartial = &profiledb.StorageProfilesResponse{
SyncTime: time.Now(),
DeviceChanges: map[agd.ProfileID]*profiledb.StorageDeviceChange{
profiledbtest.ProfileID: strgRespChg,
},
Profiles: []*agd.Profile{profAfter},
Devices: []*agd.Device{devNewName},
}
)
ps := agdtest.NewProfileStorage()
ps.OnProfiles = func(
_ context.Context,
req *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
if req.SyncTime.IsZero() {
return strgRespFull, nil
} else {
return strgRespPartial, nil
}
}
db := newProfileDB(t, &profiledb.Config{
Storage: ps,
})
require.True(t, t.Run("after_full", func(t *testing.T) {
ctx := profiledbtest.ContextWithTimeout(t)
require.NoError(t, db.RefreshFull(ctx))
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
require.NoError(t, dbErr)
assert.Equal(t, profBefore, p)
assert.Equal(t, devPrevName, d)
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr = db.ProfileByDeviceID(ctx, profiledbtest.DeviceIDAuto)
require.NoError(t, dbErr)
assert.Equal(t, profBefore, p)
assert.Equal(t, devAuto, d)
}))
require.True(t, t.Run("after_partial", func(t *testing.T) {
ctx := profiledbtest.ContextWithTimeout(t)
require.NoError(t, db.Refresh(ctx))
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
require.NoError(t, dbErr)
assert.Equal(t, profAfter, p)
assert.Equal(t, devNewName, d)
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr = db.ProfileByDeviceID(ctx, profiledbtest.DeviceIDAuto)
assert.ErrorIs(t, dbErr, profiledb.ErrDeviceNotFound)
assert.Nil(t, p)
assert.Nil(t, d)
}))
}
func TestDefault_noDeviceChanges(t *testing.T) {
t.Parallel()
dev := &agd.Device{
ID: profiledbtest.DeviceID,
}
profBefore := &agd.Profile{
CustomDomains: &agd.AccountCustomDomains{},
AdultBlockingMode: &dnsmsg.BlockingModeNullIP{},
BlockingMode: &dnsmsg.BlockingModeNullIP{},
SafeBrowsingBlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
FilteringEnabled: true,
DeviceIDs: container.NewMapSet(profiledbtest.DeviceID),
}
profAfter := &agd.Profile{
CustomDomains: &agd.AccountCustomDomains{},
AdultBlockingMode: &dnsmsg.BlockingModeNullIP{},
BlockingMode: &dnsmsg.BlockingModeNullIP{},
SafeBrowsingBlockingMode: &dnsmsg.BlockingModeNullIP{},
ID: profiledbtest.ProfileID,
FilteringEnabled: false,
DeviceIDs: container.NewMapSet(profiledbtest.DeviceID),
}
var (
strgRespFull = &profiledb.StorageProfilesResponse{
SyncTime: time.Now(),
Profiles: []*agd.Profile{profBefore},
Devices: []*agd.Device{dev},
}
strgRespChg = &profiledb.StorageDeviceChange{
DeletedDeviceIDs: []agd.DeviceID{},
IsPartial: true,
}
strgRespPartial = &profiledb.StorageProfilesResponse{
SyncTime: time.Now(),
DeviceChanges: map[agd.ProfileID]*profiledb.StorageDeviceChange{
profiledbtest.ProfileID: strgRespChg,
},
Profiles: []*agd.Profile{profAfter},
Devices: []*agd.Device{},
}
)
ps := agdtest.NewProfileStorage()
ps.OnProfiles = func(
_ context.Context,
req *profiledb.StorageProfilesRequest,
) (resp *profiledb.StorageProfilesResponse, err error) {
if req.SyncTime.IsZero() {
return strgRespFull, nil
} else {
return strgRespPartial, nil
}
}
db := newProfileDB(t, &profiledb.Config{
Storage: ps,
})
require.True(t, t.Run("after_full", func(t *testing.T) {
ctx := profiledbtest.ContextWithTimeout(t)
require.NoError(t, db.RefreshFull(ctx))
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
require.NoError(t, dbErr)
assert.Equal(t, profBefore, p)
assert.Equal(t, dev, d)
}))
require.True(t, t.Run("after_partial", func(t *testing.T) {
ctx := profiledbtest.ContextWithTimeout(t)
require.NoError(t, db.Refresh(ctx))
ctx = profiledbtest.ContextWithTimeout(t)
p, d, dbErr := db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
require.NoError(t, dbErr)
assert.Equal(t, profAfter, p)
assert.Equal(t, dev, d)
}))
}
func BenchmarkDefault_ProfileByDeviceID(b *testing.B) {
existingDev := &agd.Device{
ID: profiledbtest.DeviceID,
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{existingDev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
var (
prof *agd.Profile
dev *agd.Device
err error
)
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByDeviceID(ctx, profiledbtest.DeviceID)
}
assert.NotNil(b, prof)
assert.NotNil(b, dev)
assert.NoError(b, err)
})
const wrongDevID = profiledbtest.DeviceID + "_bad"
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByDeviceID(ctx, wrongDevID)
}
assert.Nil(b, prof)
assert.Nil(b, dev)
assert.ErrorIs(b, err, profiledb.ErrDeviceNotFound)
})
// Most recent results:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
// BenchmarkDefault_ProfileByDeviceID/success-16 31104525 37.61 ns/op 0 B/op 0 allocs/op
// BenchmarkDefault_ProfileByDeviceID/not_found-16 60978588 18.41 ns/op 0 B/op 0 allocs/op
}
func BenchmarkDefault_ProfileByLinkedIP(b *testing.B) {
existingDev := &agd.Device{
ID: profiledbtest.DeviceID,
LinkedIP: testClientIPv4,
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{existingDev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
var (
prof *agd.Profile
dev *agd.Device
err error
)
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByLinkedIP(ctx, testClientIPv4)
}
assert.NotNil(b, prof)
assert.NotNil(b, dev)
assert.NoError(b, err)
})
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByLinkedIP(ctx, testOtherClientIPv4)
}
assert.Nil(b, prof)
assert.Nil(b, dev)
assert.ErrorIs(b, err, profiledb.ErrDeviceNotFound)
})
// Most recent results:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
// BenchmarkDefault_ProfileByLinkedIP/success-16 18498074 63.25 ns/op 0 B/op 0 allocs/op
// BenchmarkDefault_ProfileByLinkedIP/not_found-16 46330509 23.94 ns/op 0 B/op 0 allocs/op
}
func BenchmarkDefault_ProfileByDedicatedIP(b *testing.B) {
existingDev := &agd.Device{
ID: profiledbtest.DeviceID,
DedicatedIPs: []netip.Addr{
testClientIPv4,
},
}
devicesCh := make(chan []*agd.Device, 1)
devicesCh <- []*agd.Device{existingDev}
db := newDefaultProfileDB(b, devicesCh)
ctx := context.Background()
var (
prof *agd.Profile
dev *agd.Device
err error
)
b.Run("success", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByDedicatedIP(ctx, testClientIPv4)
}
assert.NotNil(b, prof)
assert.NotNil(b, dev)
assert.NoError(b, err)
})
b.Run("not_found", func(b *testing.B) {
b.ReportAllocs()
for b.Loop() {
prof, dev, err = db.ProfileByDedicatedIP(ctx, testOtherClientIPv4)
}
assert.Nil(b, prof)
assert.Nil(b, dev)
assert.ErrorIs(b, err, profiledb.ErrDeviceNotFound)
})
// Most recent results:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardDNS/internal/profiledb
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
// BenchmarkDefault_ProfileByDedicatedIP/success-16 18668960 63.51 ns/op 0 B/op 0 allocs/op
// BenchmarkDefault_ProfileByDedicatedIP/not_found-16 57252513 19.94 ns/op 0 B/op 0 allocs/op
}