mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-04-25 04:16:22 +02:00
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package peer
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestAnomalyDetector_NormalPattern(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
|
|
// Simulate normal sync: mostly "sync" requests with some "ping".
|
|
for i := 0; i < 20; i++ {
|
|
d.RecordRequest("peer-1", "sync")
|
|
}
|
|
for i := 0; i < 3; i++ {
|
|
d.RecordRequest("peer-1", "ping")
|
|
}
|
|
|
|
result := d.Analyze("peer-1")
|
|
assert.Equal(t, 23, result.RequestCount)
|
|
assert.True(t, result.Entropy > 0)
|
|
// Low entropy with 2 types, dominated by one → should be LOW or NONE.
|
|
assert.NotEqual(t, AnomalyCritical, result.Level)
|
|
}
|
|
|
|
func TestAnomalyDetector_ChaoticPattern(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
|
|
// Simulate chaotic pattern: many diverse request types equally distributed.
|
|
types := []string{"sync", "ping", "handshake", "delta_sync", "status", "genome", "unknown1", "unknown2", "brute1", "brute2"}
|
|
for _, rt := range types {
|
|
for i := 0; i < 5; i++ {
|
|
d.RecordRequest("attacker", rt)
|
|
}
|
|
}
|
|
|
|
result := d.Analyze("attacker")
|
|
assert.Equal(t, 50, result.RequestCount)
|
|
// Uniform distribution → max entropy → CRITICAL.
|
|
assert.Equal(t, AnomalyCritical, result.Level)
|
|
}
|
|
|
|
func TestAnomalyDetector_UnknownPeer(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
result := d.Analyze("nonexistent")
|
|
assert.Equal(t, AnomalyNone, result.Level)
|
|
assert.Equal(t, 0, result.RequestCount)
|
|
}
|
|
|
|
func TestAnomalyDetector_InsufficientData(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
d.RecordRequest("peer-new", "sync")
|
|
d.RecordRequest("peer-new", "ping")
|
|
|
|
result := d.Analyze("peer-new")
|
|
assert.Equal(t, AnomalyNone, result.Level)
|
|
assert.Contains(t, result.Details, "insufficient data")
|
|
}
|
|
|
|
func TestAnomalyDetector_Reset(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
d.RecordRequest("peer-x", "sync")
|
|
d.RecordRequest("peer-x", "sync")
|
|
d.Reset("peer-x")
|
|
|
|
result := d.Analyze("peer-x")
|
|
assert.Equal(t, AnomalyNone, result.Level)
|
|
assert.Equal(t, 0, result.RequestCount)
|
|
}
|
|
|
|
func TestAnomalyDetector_AnalyzeAll(t *testing.T) {
|
|
d := NewAnomalyDetector()
|
|
d.RecordRequest("peer-a", "sync")
|
|
d.RecordRequest("peer-b", "ping")
|
|
|
|
results := d.AnalyzeAll()
|
|
assert.Len(t, results, 2)
|
|
}
|
|
|
|
func TestShannonEntropy_Uniform(t *testing.T) {
|
|
// Uniform distribution over 4 types → H = log2(4) = 2.0.
|
|
types := map[string]int{"a": 10, "b": 10, "c": 10, "d": 10}
|
|
h := shannonEntropy(types, 40)
|
|
assert.InDelta(t, 2.0, h, 0.01)
|
|
}
|
|
|
|
func TestShannonEntropy_SingleType(t *testing.T) {
|
|
// Single type → H = 0.
|
|
types := map[string]int{"sync": 100}
|
|
h := shannonEntropy(types, 100)
|
|
assert.Equal(t, 0.0, h)
|
|
}
|