106 lines
3.2 KiB
Go
106 lines
3.2 KiB
Go
package transform
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"codeberg.org/pata1704/guenther/internal/config"
|
|
"codeberg.org/pata1704/guenther/pkg/types"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestTransformEngine_Fusion(t *testing.T) {
|
|
logChan := make(chan types.LogEvent, 100)
|
|
metricChan := make(chan types.MetricSnapshot, 100)
|
|
serviceStatusChan := make(chan types.ServiceStatus, 100)
|
|
featureChan := make(chan types.FeatureVector, 100)
|
|
healthChan := make(chan types.StageHealth, 10)
|
|
|
|
cfg := &config.Config{}
|
|
cfg.Transformation.WindowSize = 1 * time.Second
|
|
cfg.Transformation.DbPath = ":memory:"
|
|
|
|
engine, err := NewTransformEngine(cfg, logChan, metricChan, serviceStatusChan, featureChan, healthChan)
|
|
assert.NoError(t, err)
|
|
|
|
baseTime := time.Date(2026, 1, 1, 12, 0, 0, 0, time.Local)
|
|
|
|
// 1. Send data for first window
|
|
metricChan <- types.MetricSnapshot{
|
|
Timestamp: baseTime,
|
|
CPUPercent: 50.0,
|
|
MemoryUsedMB: 1000,
|
|
MemoryDirtyMB: 100,
|
|
NetworkInMBps: 10.0,
|
|
NetworkOutMBps: 20.0,
|
|
TCPRetransPerS: 5,
|
|
NetPacketsInPerS: 100,
|
|
NetPacketsOutPerS: 200,
|
|
}
|
|
|
|
// 2. Start engine and wait for first window
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
engine.Start(ctx)
|
|
defer func() {
|
|
cancel()
|
|
engine.Wait()
|
|
}()
|
|
|
|
select {
|
|
case fv := <-featureChan:
|
|
assert.Equal(t, 50.0, fv.AvgCPUPercent)
|
|
// Deltas are absolute value on first window because tracker starts at 0
|
|
assert.Equal(t, 10.0, fv.DeltaNetIn)
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("Timeout waiting for first FeatureVector")
|
|
}
|
|
|
|
// 3. Send data for second window (triggers deltas)
|
|
secondTime := baseTime.Add(cfg.Transformation.WindowSize)
|
|
metricChan <- types.MetricSnapshot{
|
|
Timestamp: secondTime,
|
|
CPUPercent: 60.0,
|
|
MemoryUsedMB: 1000,
|
|
MemoryDirtyMB: 200,
|
|
NetworkInMBps: 15.0, // DeltaNetIn = 15.0 - 10.0 = 5.0
|
|
NetworkOutMBps: 20.0,
|
|
TCPRetransPerS: 10, // DeltaTCPRetrans = 10.0 - 5.0 = 5.0
|
|
NetPacketsInPerS: 150,
|
|
NetPacketsOutPerS: 200,
|
|
}
|
|
|
|
select {
|
|
case fv := <-featureChan:
|
|
// Check original logic
|
|
assert.Equal(t, 60.0, fv.AvgCPUPercent)
|
|
|
|
// Check new delta features
|
|
assert.Equal(t, 5.0, fv.DeltaNetIn)
|
|
assert.Equal(t, 5.0, fv.DeltaTCPRetrans)
|
|
|
|
// Check ratio features
|
|
// MemPressure = dirty / (used + 1) = 200/1001
|
|
expectedPressure := 200.0 / 1001.0
|
|
assert.InDelta(t, expectedPressure, fv.MemPressure, 1e-9)
|
|
// NetAsymmetry = in / (out + 1e-3) = 15/20.001
|
|
expectedAsym := 15.0 / 20.001
|
|
assert.InDelta(t, expectedAsym, fv.NetAsymmetry, 1e-9)
|
|
|
|
// Check NormalizedVector length (should be 45 base + params)
|
|
assert.GreaterOrEqual(t, len(fv.NormalizedVector), 45)
|
|
|
|
// Verify slots 39-44 (Engineered Features tail)
|
|
nv := fv.NormalizedVector
|
|
assert.Equal(t, 5.0, nv[39]) // DeltaNetIn
|
|
assert.Equal(t, 5.0, nv[40]) // DeltaTCPRetrans
|
|
// TcpRollStd and NetRollStd will have values (even if just 2 pts)
|
|
assert.Greater(t, nv[41], 0.0) // TcpRollStd (10 and 5)
|
|
assert.Equal(t, 0.0, nv[42]) // NetRollStd (20 and 20 -> std=0)
|
|
assert.InDelta(t, expectedPressure, nv[43], 1e-9) // MemPressure
|
|
assert.InDelta(t, expectedAsym, nv[44], 1e-9) // NetAsymmetry
|
|
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("Timeout waiting for second FeatureVector")
|
|
}
|
|
}
|