use crate::lighting::effects::*;
use crate::lighting::engine::tests::common::create_test_fixture;
use crate::lighting::engine::EffectEngine;
use std::collections::HashMap;
use std::time::Duration;
#[test]
fn test_validate_fixture_capabilities_rgb_missing_red() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("green".to_string(), 2);
channels.insert("blue".to_string(), 3);
let fixture = FixtureInfo::new(
"rgb_fixture".to_string(),
1,
1,
"RGB".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_fixture_capabilities_rgb_missing_green() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("red".to_string(), 1);
channels.insert("blue".to_string(), 3);
let fixture = FixtureInfo::new(
"rgb_fixture".to_string(),
1,
1,
"RGB".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_fixture_capabilities_rgb_missing_blue() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("red".to_string(), 1);
channels.insert("green".to_string(), 2);
let fixture = FixtureInfo::new(
"rgb_fixture".to_string(),
1,
1,
"RGB".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_fixture_capabilities_strobe_missing() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("dimmer".to_string(), 1);
let fixture = FixtureInfo::new(
"strobe_fixture".to_string(),
1,
1,
"Strobe".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_fixture_capabilities_moving_head_missing_pan() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("tilt".to_string(), 2);
channels.insert("dimmer".to_string(), 3);
let fixture = FixtureInfo::new(
"moving_head".to_string(),
1,
1,
"MovingHead".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_fixture_capabilities_moving_head_missing_tilt() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("pan".to_string(), 1);
channels.insert("dimmer".to_string(), 3);
let fixture = FixtureInfo::new(
"moving_head".to_string(),
1,
1,
"MovingHead".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
}
#[test]
fn test_validate_effect_nonexistent_fixture() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let mut params = HashMap::new();
params.insert("dimmer".to_string(), 0.5);
let effect = EffectInstance::new(
"test_effect".to_string(),
EffectType::Static {
parameters: params,
duration: Duration::from_secs(5),
},
vec!["nonexistent_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Fixture(msg)) = result {
assert!(msg.contains("nonexistent_fixture"));
} else {
panic!("Expected Fixture error");
}
}
#[test]
fn test_validate_effect_static_parameter_out_of_range() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let mut params_high = HashMap::new();
params_high.insert("dimmer".to_string(), 1.5);
let effect_high = EffectInstance::new(
"test_effect_high".to_string(),
EffectType::Static {
parameters: params_high,
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect_high);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("must be between 0.0 and 1.0"));
} else {
panic!("Expected Parameter error for value > 1.0");
}
let mut params_low = HashMap::new();
params_low.insert("dimmer".to_string(), -0.5);
let effect_low = EffectInstance::new(
"test_effect_low".to_string(),
EffectType::Static {
parameters: params_low,
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect_low);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("must be between 0.0 and 1.0"));
} else {
panic!("Expected Parameter error for value < 0.0");
}
}
#[test]
fn test_validate_effect_static_parameter_valid_range() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let mut params_min = HashMap::new();
params_min.insert("dimmer".to_string(), 0.0);
let effect_min = EffectInstance::new(
"test_effect_min".to_string(),
EffectType::Static {
parameters: params_min,
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
assert!(engine.start_effect(effect_min).is_ok());
let mut params_max = HashMap::new();
params_max.insert("dimmer".to_string(), 1.0);
let effect_max = EffectInstance::new(
"test_effect_max".to_string(),
EffectType::Static {
parameters: params_max,
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
assert!(engine.start_effect(effect_max).is_ok());
}
#[test]
fn test_validate_effect_strobe_negative_frequency() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"strobe".to_string(),
EffectType::Strobe {
frequency: TempoAwareFrequency::Fixed(-1.0),
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("frequency") && msg.contains("non-negative"));
} else {
panic!("Expected Parameter error for negative frequency");
}
}
#[test]
fn test_validate_effect_strobe_zero_frequency() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"strobe".to_string(),
EffectType::Strobe {
frequency: TempoAwareFrequency::Fixed(0.0),
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
assert!(engine.start_effect(effect).is_ok());
}
#[test]
fn test_validate_effect_pulse_zero_frequency() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"pulse".to_string(),
EffectType::Pulse {
base_level: 0.5,
pulse_amplitude: 0.5,
frequency: TempoAwareFrequency::Fixed(0.0),
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("frequency") && msg.contains("positive"));
} else {
panic!("Expected Parameter error for zero frequency");
}
}
#[test]
fn test_validate_effect_pulse_negative_frequency() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"pulse".to_string(),
EffectType::Pulse {
base_level: 0.5,
pulse_amplitude: 0.5,
frequency: TempoAwareFrequency::Fixed(-1.0),
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("frequency") && msg.contains("positive"));
} else {
panic!("Expected Parameter error for negative frequency");
}
}
#[test]
fn test_validate_effect_compatibility_color_cycle_no_rgb() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("dimmer".to_string(), 1);
let fixture = FixtureInfo::new(
"dimmer_only".to_string(),
1,
1,
"Dimmer".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
let colors = vec![Color::new(255, 0, 0)];
let effect = EffectInstance::new(
"cycle".to_string(),
EffectType::ColorCycle {
colors,
speed: TempoAwareSpeed::Fixed(1.0),
direction: CycleDirection::Forward,
transition: CycleTransition::Snap,
duration: Duration::from_secs(10),
},
vec!["dimmer_only".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("Color cycle") && msg.contains("RGB capability"));
} else {
panic!("Expected Parameter error for incompatible effect");
}
}
#[test]
fn test_validate_effect_compatibility_rainbow_no_rgb() {
let mut engine = EffectEngine::new();
let mut channels = HashMap::new();
channels.insert("dimmer".to_string(), 1);
let fixture = FixtureInfo::new(
"dimmer_only".to_string(),
1,
1,
"Dimmer".to_string(),
channels,
None,
);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"rainbow".to_string(),
EffectType::Rainbow {
speed: TempoAwareSpeed::Fixed(1.0),
saturation: 1.0,
brightness: 1.0,
duration: Duration::from_secs(10),
},
vec!["dimmer_only".to_string()],
None,
None,
None,
);
let result = engine.start_effect(effect);
assert!(result.is_err());
if let Err(EffectError::Parameter(msg)) = result {
assert!(msg.contains("Rainbow") && msg.contains("RGB capability"));
} else {
panic!("Expected Parameter error for incompatible effect");
}
}
#[test]
fn test_validate_effect_compatibility_strobe_with_dimmer() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"strobe".to_string(),
EffectType::Strobe {
frequency: TempoAwareFrequency::Fixed(5.0),
duration: Duration::from_secs(5),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
assert!(engine.start_effect(effect).is_ok());
}
#[test]
fn test_validate_effect_compatibility_chase_with_rgb() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let effect = EffectInstance::new(
"chase".to_string(),
EffectType::Chase {
pattern: ChasePattern::Linear,
speed: TempoAwareSpeed::Fixed(1.0),
direction: ChaseDirection::LeftToRight,
transition: CycleTransition::Snap,
duration: Duration::from_secs(10),
},
vec!["test_fixture".to_string()],
None,
None,
None,
);
assert!(engine.start_effect(effect).is_ok());
}
#[test]
fn test_validate_effect_timing_negative_duration() {
let mut engine = EffectEngine::new();
let fixture = create_test_fixture("test_fixture", 1, 1);
engine.register_fixture(fixture);
let mut params = HashMap::new();
params.insert("dimmer".to_string(), 0.5);
let effect = EffectInstance::new(
"test".to_string(),
EffectType::Static {
parameters: params,
duration: Duration::from_secs(1),
},
vec!["test_fixture".to_string()],
None,
Some(Duration::from_secs(1)),
None,
);
assert!(engine.start_effect(effect).is_ok());
}