test(05-02): update tests for new NewBank signature and dynamic gain
- All NewBank calls updated to two-argument form passing ClassFreqConfigs - TestMixerNoClip iterates ClassFreqConfigs keys instead of classify.AllClasses() - TestNewBankDynamicGain verifies gainPerLayer=1/N for 3-class custom config - TestNewBankCustomConfigNoClip verifies no-clip guarantee with 2-class config - TestNumLayersMatchesAllClasses now asserts len(ClassFreqConfigs) == len(AllClasses())
This commit is contained in:
+47
-9
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewBankHas14Layers(t *testing.T) {
|
func TestNewBankHas14Layers(t *testing.T) {
|
||||||
b := NewBank(1.0)
|
b := NewBank(1.0, ClassFreqConfigs)
|
||||||
if len(b.layers) != 14 {
|
if len(b.layers) != 14 {
|
||||||
t.Errorf("NewBank() has %d layers, want 14", len(b.layers))
|
t.Errorf("NewBank() has %d layers, want 14", len(b.layers))
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ func TestNewBankHas14Layers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderWindowOutputLength(t *testing.T) {
|
func TestRenderWindowOutputLength(t *testing.T) {
|
||||||
b := NewBank(1.0)
|
b := NewBank(1.0, ClassFreqConfigs)
|
||||||
snap := classify.WindowSnapshot{
|
snap := classify.WindowSnapshot{
|
||||||
Counts: make(map[classify.TrafficClass]int64),
|
Counts: make(map[classify.TrafficClass]int64),
|
||||||
TotalPackets: 0,
|
TotalPackets: 0,
|
||||||
@@ -34,7 +34,7 @@ func TestRenderWindowOutputLength(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderWindowSilentWhenNoTraffic(t *testing.T) {
|
func TestRenderWindowSilentWhenNoTraffic(t *testing.T) {
|
||||||
b := NewBank(1.0)
|
b := NewBank(1.0, ClassFreqConfigs)
|
||||||
// Empty counts — no class ever seen — all layers should stay at zero amplitude
|
// Empty counts — no class ever seen — all layers should stay at zero amplitude
|
||||||
snap := classify.WindowSnapshot{
|
snap := classify.WindowSnapshot{
|
||||||
Counts: make(map[classify.TrafficClass]int64),
|
Counts: make(map[classify.TrafficClass]int64),
|
||||||
@@ -51,7 +51,7 @@ func TestRenderWindowSilentWhenNoTraffic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRenderWindowNonZeroWithTraffic(t *testing.T) {
|
func TestRenderWindowNonZeroWithTraffic(t *testing.T) {
|
||||||
b := NewBank(1.0)
|
b := NewBank(1.0, ClassFreqConfigs)
|
||||||
counts := make(map[classify.TrafficClass]int64)
|
counts := make(map[classify.TrafficClass]int64)
|
||||||
counts[classify.ClassICMP] = 100
|
counts[classify.ClassICMP] = 100
|
||||||
snap := classify.WindowSnapshot{
|
snap := classify.WindowSnapshot{
|
||||||
@@ -74,15 +74,15 @@ func TestRenderWindowNonZeroWithTraffic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMixerNoClip(t *testing.T) {
|
func TestMixerNoClip(t *testing.T) {
|
||||||
b := NewBank(0.01) // fast EMA to quickly ramp up to near-max amplitude
|
b := NewBank(0.01, ClassFreqConfigs) // fast EMA to quickly ramp up to near-max amplitude
|
||||||
counts := make(map[classify.TrafficClass]int64)
|
counts := make(map[classify.TrafficClass]int64)
|
||||||
// All 14 classes at max count — worst-case mixing scenario
|
// All 14 classes at max count — worst-case mixing scenario
|
||||||
for _, class := range classify.AllClasses() {
|
for class := range ClassFreqConfigs {
|
||||||
counts[class] = 1000
|
counts[class] = 1000
|
||||||
}
|
}
|
||||||
snap := classify.WindowSnapshot{
|
snap := classify.WindowSnapshot{
|
||||||
Counts: counts,
|
Counts: counts,
|
||||||
TotalPackets: 14000,
|
TotalPackets: int64(len(ClassFreqConfigs)) * 1000,
|
||||||
WindowIndex: 0,
|
WindowIndex: 0,
|
||||||
}
|
}
|
||||||
// Render multiple windows to let EMA converge
|
// Render multiple windows to let EMA converge
|
||||||
@@ -102,7 +102,7 @@ func TestMixerNoClip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStereoPan(t *testing.T) {
|
func TestStereoPan(t *testing.T) {
|
||||||
b := NewBank(0.01) // fast EMA
|
b := NewBank(0.01, ClassFreqConfigs) // fast EMA
|
||||||
counts := make(map[classify.TrafficClass]int64)
|
counts := make(map[classify.TrafficClass]int64)
|
||||||
// ClassDHCP has pan=-0.75 (wide-left in config.go)
|
// ClassDHCP has pan=-0.75 (wide-left in config.go)
|
||||||
counts[classify.ClassDHCP] = 1000
|
counts[classify.ClassDHCP] = 1000
|
||||||
@@ -130,7 +130,7 @@ func TestStereoPan(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMultipleWindowsEMAConvergence(t *testing.T) {
|
func TestMultipleWindowsEMAConvergence(t *testing.T) {
|
||||||
b := NewBank(1.0)
|
b := NewBank(1.0, ClassFreqConfigs)
|
||||||
counts := make(map[classify.TrafficClass]int64)
|
counts := make(map[classify.TrafficClass]int64)
|
||||||
counts[classify.ClassICMP] = 100
|
counts[classify.ClassICMP] = 100
|
||||||
snap := classify.WindowSnapshot{
|
snap := classify.WindowSnapshot{
|
||||||
@@ -150,6 +150,44 @@ func TestMultipleWindowsEMAConvergence(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewBankDynamicGain(t *testing.T) {
|
||||||
|
// Create a config map with only 3 classes
|
||||||
|
cfgs := map[classify.TrafficClass]FreqConfig{
|
||||||
|
classify.ClassICMP: ClassFreqConfigs[classify.ClassICMP],
|
||||||
|
classify.ClassDNS: ClassFreqConfigs[classify.ClassDNS],
|
||||||
|
classify.ClassHTTPS: ClassFreqConfigs[classify.ClassHTTPS],
|
||||||
|
}
|
||||||
|
b := NewBank(0.01, cfgs)
|
||||||
|
if len(b.layers) != 3 {
|
||||||
|
t.Errorf("NewBank with 3 configs has %d layers, want 3", len(b.layers))
|
||||||
|
}
|
||||||
|
// Verify gainPerLayer is 1/3
|
||||||
|
expected := 1.0 / 3.0
|
||||||
|
if b.gainPerLayer != expected {
|
||||||
|
t.Errorf("gainPerLayer = %v, want %v", b.gainPerLayer, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewBankCustomConfigNoClip(t *testing.T) {
|
||||||
|
cfgs := map[classify.TrafficClass]FreqConfig{
|
||||||
|
classify.ClassICMP: ClassFreqConfigs[classify.ClassICMP],
|
||||||
|
classify.ClassDNS: ClassFreqConfigs[classify.ClassDNS],
|
||||||
|
}
|
||||||
|
b := NewBank(0.01, cfgs)
|
||||||
|
counts := map[classify.TrafficClass]int64{
|
||||||
|
classify.ClassICMP: 1000,
|
||||||
|
classify.ClassDNS: 1000,
|
||||||
|
}
|
||||||
|
snap := classify.WindowSnapshot{Counts: counts, TotalPackets: 2000, WindowIndex: 0}
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
for _, frame := range b.RenderWindow(snap) {
|
||||||
|
if frame[0] > 1.0 || frame[0] < -1.0 || frame[1] > 1.0 || frame[1] < -1.0 {
|
||||||
|
t.Fatalf("clipped with 2-class config: L=%v R=%v", frame[0], frame[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// windowRMS computes the root mean square amplitude across all stereo frames.
|
// windowRMS computes the root mean square amplitude across all stereo frames.
|
||||||
func windowRMS(frames [][2]float64) float64 {
|
func windowRMS(frames [][2]float64) float64 {
|
||||||
var sum float64
|
var sum float64
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ func TestClassFreqConfigsComplete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNumLayersMatchesAllClasses(t *testing.T) {
|
func TestNumLayersMatchesAllClasses(t *testing.T) {
|
||||||
if synth.NumLayers != len(classify.AllClasses()) {
|
if len(synth.ClassFreqConfigs) != len(classify.AllClasses()) {
|
||||||
t.Errorf("NumLayers=%d but AllClasses() has %d entries", synth.NumLayers, len(classify.AllClasses()))
|
t.Errorf("ClassFreqConfigs has %d entries but AllClasses() has %d entries",
|
||||||
|
len(synth.ClassFreqConfigs), len(classify.AllClasses()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user