package services import ( "testing" "github.com/stretchr/testify/assert" "go.uber.org/zap/zaptest" ) func TestNewBitrateStrategyService(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) assert.NotNil(t, service) assert.NotNil(t, service.logger) } func TestNewBitrateStrategyService_NilLogger(t *testing.T) { service := NewBitrateStrategyService(nil) assert.NotNil(t, service) assert.NotNil(t, service.logger) } func TestBitrateStrategyService_GetThresholds_Conservative(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) thresholds := service.GetThresholds(StrategyConservative) assert.Equal(t, 0.3, thresholds.BufferLevelThreshold) assert.Equal(t, 0.7, thresholds.BandwidthRatioThreshold) assert.False(t, thresholds.UseOrCondition) } func TestBitrateStrategyService_GetThresholds_Aggressive(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) thresholds := service.GetThresholds(StrategyAggressive) assert.Equal(t, 0.15, thresholds.BufferLevelThreshold) assert.Equal(t, 0.5, thresholds.BandwidthRatioThreshold) assert.True(t, thresholds.UseOrCondition) } func TestBitrateStrategyService_GetThresholds_Balanced(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) thresholds := service.GetThresholds(StrategyBalanced) assert.Equal(t, 0.2, thresholds.BufferLevelThreshold) assert.Equal(t, 0.6, thresholds.BandwidthRatioThreshold) assert.False(t, thresholds.UseOrCondition) } func TestBitrateStrategyService_GetThresholds_Default(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Tester avec une stratégie invalide (devrait retourner Balanced par défaut) thresholds := service.GetThresholds(BitrateStrategy("invalid")) assert.Equal(t, 0.2, thresholds.BufferLevelThreshold) assert.Equal(t, 0.6, thresholds.BandwidthRatioThreshold) assert.False(t, thresholds.UseOrCondition) } func TestBitrateStrategyService_ShouldAdapt_Conservative(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) tests := []struct { name string bufferLevel float64 bandwidthRatio float64 expected bool }{ { name: "both low - should adapt", bufferLevel: 0.25, // < 0.3 bandwidthRatio: 0.6, // < 0.7 expected: true, }, { name: "buffer low but bandwidth ok - should not adapt", bufferLevel: 0.25, // < 0.3 bandwidthRatio: 0.8, // >= 0.7 expected: false, }, { name: "bandwidth low but buffer ok - should not adapt", bufferLevel: 0.4, // >= 0.3 bandwidthRatio: 0.6, // < 0.7 expected: false, }, { name: "both ok - should not adapt", bufferLevel: 0.4, // >= 0.3 bandwidthRatio: 0.8, // >= 0.7 expected: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := service.ShouldAdapt(StrategyConservative, tt.bufferLevel, tt.bandwidthRatio) assert.Equal(t, tt.expected, result, "ShouldAdapt failed for %s", tt.name) }) } } func TestBitrateStrategyService_ShouldAdapt_Aggressive(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) tests := []struct { name string bufferLevel float64 bandwidthRatio float64 expected bool }{ { name: "buffer low - should adapt", bufferLevel: 0.1, // < 0.15 bandwidthRatio: 0.8, // >= 0.5 expected: true, }, { name: "bandwidth low - should adapt", bufferLevel: 0.3, // >= 0.15 bandwidthRatio: 0.4, // < 0.5 expected: true, }, { name: "both low - should adapt", bufferLevel: 0.1, // < 0.15 bandwidthRatio: 0.4, // < 0.5 expected: true, }, { name: "both ok - should not adapt", bufferLevel: 0.2, // >= 0.15 bandwidthRatio: 0.6, // >= 0.5 expected: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := service.ShouldAdapt(StrategyAggressive, tt.bufferLevel, tt.bandwidthRatio) assert.Equal(t, tt.expected, result, "ShouldAdapt failed for %s", tt.name) }) } } func TestBitrateStrategyService_ShouldAdapt_Balanced(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) tests := []struct { name string bufferLevel float64 bandwidthRatio float64 expected bool }{ { name: "both low - should adapt", bufferLevel: 0.15, // < 0.2 bandwidthRatio: 0.5, // < 0.6 expected: true, }, { name: "buffer low but bandwidth ok - should not adapt", bufferLevel: 0.15, // < 0.2 bandwidthRatio: 0.7, // >= 0.6 expected: false, }, { name: "bandwidth low but buffer ok - should not adapt", bufferLevel: 0.3, // >= 0.2 bandwidthRatio: 0.5, // < 0.6 expected: false, }, { name: "both ok - should not adapt", bufferLevel: 0.3, // >= 0.2 bandwidthRatio: 0.7, // >= 0.6 expected: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := service.ShouldAdapt(StrategyBalanced, tt.bufferLevel, tt.bandwidthRatio) assert.Equal(t, tt.expected, result, "ShouldAdapt failed for %s", tt.name) }) } } func TestBitrateStrategyService_ShouldAdapt_InvalidBufferLevel(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Buffer level négatif result := service.ShouldAdapt(StrategyBalanced, -0.1, 0.5) assert.False(t, result) // Buffer level > 1.0 result = service.ShouldAdapt(StrategyBalanced, 1.5, 0.5) assert.False(t, result) } func TestBitrateStrategyService_ShouldAdapt_InvalidBandwidthRatio(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Bandwidth ratio négatif result := service.ShouldAdapt(StrategyBalanced, 0.5, -0.1) assert.False(t, result) } func TestBitrateStrategyService_ShouldAdapt_EdgeCases(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Buffer level exactement au seuil result := service.ShouldAdapt(StrategyBalanced, 0.2, 0.5) assert.False(t, result) // 0.2 n'est pas < 0.2 // Buffer level juste en dessous du seuil result = service.ShouldAdapt(StrategyBalanced, 0.199, 0.5) assert.True(t, result) // Bandwidth ratio exactement au seuil result = service.ShouldAdapt(StrategyBalanced, 0.15, 0.6) assert.False(t, result) // 0.6 n'est pas < 0.6 // Bandwidth ratio juste en dessous du seuil result = service.ShouldAdapt(StrategyBalanced, 0.15, 0.599) assert.True(t, result) } func TestBitrateStrategyService_SelectStrategy_WithUserPreference(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) preference := StrategyAggressive result := service.SelectStrategy(0.5, &preference) assert.Equal(t, StrategyAggressive, result) } func TestBitrateStrategyService_SelectStrategy_UnstableNetwork(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Réseau instable (< 0.3) result := service.SelectStrategy(0.2, nil) assert.Equal(t, StrategyConservative, result) result = service.SelectStrategy(0.0, nil) assert.Equal(t, StrategyConservative, result) } func TestBitrateStrategyService_SelectStrategy_StableNetwork(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Réseau stable (> 0.7) result := service.SelectStrategy(0.8, nil) assert.Equal(t, StrategyAggressive, result) result = service.SelectStrategy(1.0, nil) assert.Equal(t, StrategyAggressive, result) } func TestBitrateStrategyService_SelectStrategy_ModerateNetwork(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) // Réseau modéré (0.3 à 0.7) result := service.SelectStrategy(0.5, nil) assert.Equal(t, StrategyBalanced, result) result = service.SelectStrategy(0.3, nil) assert.Equal(t, StrategyBalanced, result) result = service.SelectStrategy(0.7, nil) assert.Equal(t, StrategyBalanced, result) } func TestBitrateStrategyService_IsValidStrategy(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) assert.True(t, service.IsValidStrategy(StrategyConservative)) assert.True(t, service.IsValidStrategy(StrategyAggressive)) assert.True(t, service.IsValidStrategy(StrategyBalanced)) assert.False(t, service.IsValidStrategy(BitrateStrategy("invalid"))) assert.False(t, service.IsValidStrategy(BitrateStrategy(""))) } func TestBitrateStrategyService_RealWorldScenarios(t *testing.T) { logger := zaptest.NewLogger(t) service := NewBitrateStrategyService(logger) tests := []struct { name string strategy BitrateStrategy bufferLevel float64 bandwidthRatio float64 expected bool description string }{ { name: "conservative - good conditions", strategy: StrategyConservative, bufferLevel: 0.5, bandwidthRatio: 0.9, expected: false, description: "Should not adapt with good buffer and bandwidth", }, { name: "aggressive - buffer dropping", strategy: StrategyAggressive, bufferLevel: 0.1, bandwidthRatio: 0.8, expected: true, description: "Should adapt when buffer is dropping even with good bandwidth", }, { name: "balanced - moderate conditions", strategy: StrategyBalanced, bufferLevel: 0.18, bandwidthRatio: 0.55, expected: true, description: "Should adapt when both are moderately low", }, { name: "conservative - critical buffer", strategy: StrategyConservative, bufferLevel: 0.25, bandwidthRatio: 0.65, expected: true, description: "Should adapt when both are below conservative thresholds", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := service.ShouldAdapt(tt.strategy, tt.bufferLevel, tt.bandwidthRatio) assert.Equal(t, tt.expected, result, tt.description) }) } }