use super::*;
#[test]
fn a_durable_console_channel_is_refused_in_config() -> Result<(), Box<dyn std::error::Error>> {
let console = |durable| ChannelDef {
name: "console.topology".to_owned(),
schema_ref: None,
durable,
loaded_schema: None,
};
let mut config = sample_config()?;
config.channels.push(console(true));
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("console channel 'console.topology' must not be durable"));
let mut config = sample_config()?;
config.channels.push(console(false));
validate(&mut config, None)?;
Ok(())
}
#[test]
fn valid_config_passes_validation() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
validate(&mut config, None)?;
Ok(())
}
#[test]
fn invalid_listen_address_reports_field_name() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.listen_address = socket("127.0.0.1:0")?;
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("listen_address"));
assert!(message.contains("port"));
Ok(())
}
#[test]
fn invalid_health_listen_address_reports_field_name() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.health_listen_address = socket("127.0.0.1:0")?;
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("health_listen_address"));
assert!(message.contains("port"));
Ok(())
}
#[test]
fn matching_health_and_main_listen_addresses_are_rejected() -> Result<(), Box<dyn std::error::Error>>
{
let mut config = sample_config()?;
config.health_listen_address = config.listen_address;
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("health_listen_address"));
assert!(message.contains("listen_address"));
Ok(())
}
#[test]
fn matching_health_and_main_listen_ports_are_rejected() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.health_listen_address = socket("0.0.0.0:8080")?;
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("health_listen_address"));
assert!(message.contains("port"));
Ok(())
}
#[test]
fn zero_drain_timeout_is_accepted_because_the_field_is_ignored()
-> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.drain_timeout_ms = 0;
validate(&mut config, None)?;
assert_eq!(config.drain_timeout_ms, 0);
Ok(())
}
#[test]
fn duplicate_channel_names_are_listed() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.channels.push(ChannelDef {
name: "orders".to_owned(),
schema_ref: None,
durable: false,
loaded_schema: None,
});
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("duplicate"));
assert!(message.contains("orders"));
Ok(())
}
#[test]
fn unreachable_persistence_path_reports_path() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
let path = unique_temp_dir("missing");
config.persistence_path = Some(path.clone());
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("persistence_path"));
assert!(message.contains(&path.display().to_string()));
Ok(())
}
#[test]
fn file_persistence_path_is_rejected() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
let path = unique_temp_dir("file");
fs::write(&path, "not a directory")?;
config.persistence_path = Some(path.clone());
let message = config_validation_message(validate(&mut config, None));
fs::remove_file(&path)?;
assert!(message.contains("persistence_path"));
assert!(message.contains("directory"));
Ok(())
}
#[test]
fn multiple_validation_errors_are_reported_together() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
let missing_path = unique_temp_dir("multi-missing");
config.listen_address = socket("127.0.0.1:0")?;
config.channels.push(ChannelDef {
name: "orders".to_owned(),
schema_ref: None,
durable: false,
loaded_schema: None,
});
config.persistence_path = Some(missing_path.clone());
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("listen_address"));
assert!(message.contains("duplicate channel names: orders"));
assert!(message.contains(&missing_path.display().to_string()));
Ok(())
}
#[test]
fn routing_rules_reference_configured_channels() -> Result<(), Box<dyn std::error::Error>> {
let mut config = sample_config()?;
config.routing_rules[0].target_channel = "unknown".to_owned();
let message = config_validation_message(validate(&mut config, None));
assert!(message.contains("routing_rules[0].target_channel"));
assert!(message.contains("unknown"));
Ok(())
}