Path: blob/dev/pkg/protocols/common/honeypotdetector/honeypotdetector_test.go
4538 views
package honeypotdetector12import (3"fmt"4"sync"5"sync/atomic"6"testing"78"github.com/stretchr/testify/require"9)1011func TestThresholdBoundary(t *testing.T) {12t.Parallel()1314d := New(2)15host := "example.com"1617require.False(t, d.RecordMatch(host, "t1"), "flagging should not happen at N-1 matches")18require.True(t, d.RecordMatch(host, "t2"), "flagging should happen at exactly N distinct template IDs")19require.True(t, d.IsFlagged(host))2021// Once flagged, additional distinct matches should not re-trigger the boundary condition.22require.False(t, d.RecordMatch(host, "t3"))23}2425func TestDeduplication(t *testing.T) {26t.Parallel()2728d := New(2)29host := "example.com"3031require.False(t, d.RecordMatch(host, "t1"))32require.False(t, d.RecordMatch(host, "t1"), "same templateID on same host must count once")33require.True(t, d.RecordMatch(host, "t2"))34require.True(t, d.IsFlagged(host))35}3637func TestHostIsolation(t *testing.T) {38t.Parallel()3940d := New(2)4142require.False(t, d.RecordMatch("example-a.com", "t1"))43require.False(t, d.RecordMatch("example-b.com", "t1"))44require.True(t, d.RecordMatch("example-a.com", "t2"), "host A should be flagged independently")4546require.True(t, d.IsFlagged("example-a.com"))47require.False(t, d.IsFlagged("example-b.com"))48}4950func TestConcurrentAccess(t *testing.T) {51t.Parallel()5253const (54threshold = 1055goroutines = 10056)5758d := New(threshold)59host := "example.com"6061var justFlaggedCount atomic.Int3262var wg sync.WaitGroup63wg.Add(goroutines)6465for i := 0; i < goroutines; i++ {66i := i67go func() {68defer wg.Done()69if d.RecordMatch(host, fmt.Sprintf("t-%d", i)) {70justFlaggedCount.Add(1)71}72}()73}7475wg.Wait()7677require.True(t, d.IsFlagged(host))78require.Equal(t, int32(1), justFlaggedCount.Load(), "exactly one goroutine should trigger the boundary")79}8081func TestHostNormalization(t *testing.T) {82t.Parallel()8384d := New(2)8586// Scheme + trailing slash must be stripped so these map to the same normalized host.87require.False(t, d.RecordMatch("https://example.com/", "t1"))88require.True(t, d.RecordMatch("http://example.com", "t2"))89require.True(t, d.IsFlagged("example.com"))9091// Explicit port should keep it distinct (example.com and example.com:443 are different keys).92d2 := New(1)93require.True(t, d2.RecordMatch("example.com:443", "t1"))94require.True(t, d2.IsFlagged("example.com:443"))95require.False(t, d2.IsFlagged("example.com"), "host without explicit port must not share the same key")9697// IPv6 should be canonicalized, and bracketed host:port should keep bracketed form when port is present.98d3 := New(1)99require.True(t, d3.RecordMatch("http://[2001:db8::1]/", "t1"))100require.True(t, d3.IsFlagged("2001:db8::1"))101require.True(t, d3.IsFlagged("[2001:db8::1]"))102103d4 := New(1)104require.True(t, d4.RecordMatch("[2001:db8::1]:443", "t1"))105require.True(t, d4.IsFlagged("[2001:db8::1]:443"))106require.False(t, d4.IsFlagged("2001:db8::1"), "IPv6 with explicit port must not share the same key as IPv6 without port")107}108109110