use super::*;
#[test]
fn parse_family_revision_with_revision() {
assert_eq!(parse_family_revision("web:3"), ("web".to_string(), Some(3)));
}
#[test]
fn parse_family_revision_without_revision() {
assert_eq!(parse_family_revision("web"), ("web".to_string(), None));
}
#[test]
fn parse_family_revision_non_numeric_treated_as_no_revision() {
assert_eq!(
parse_family_revision("web:latest"),
("web:latest".to_string(), None)
);
}
#[test]
fn decode_ecs_arn_cluster() {
let (account, rtype, tail) =
decode_ecs_arn("arn:aws:ecs:us-east-1:111122223333:cluster/prod").unwrap();
assert_eq!(account, "111122223333");
assert_eq!(rtype, "cluster");
assert_eq!(tail, "prod");
}
#[test]
fn decode_ecs_arn_task_definition() {
let (account, rtype, tail) =
decode_ecs_arn("arn:aws:ecs:us-east-1:111122223333:task-definition/web:5").unwrap();
assert_eq!(account, "111122223333");
assert_eq!(rtype, "task-definition");
assert_eq!(tail, "web:5");
}
#[test]
fn decode_ecs_arn_rejects_non_ecs() {
assert!(decode_ecs_arn("arn:aws:s3:::bucket").is_err());
}
#[test]
fn resolve_service_key_handles_short_and_long() {
let mut state = EcsState::new("123456789012", "us-east-1");
state.services.insert(
"default/api".to_string(),
Service {
service_name: "api".into(),
service_arn: "arn".into(),
cluster_name: "default".into(),
cluster_arn: "arn".into(),
task_definition_arn: "td-arn".into(),
family: "td".into(),
revision: 1,
desired_count: 0,
running_count: 0,
pending_count: 0,
launch_type: "FARGATE".into(),
status: "ACTIVE".into(),
scheduling_strategy: "REPLICA".into(),
deployment_controller: "ECS".into(),
minimum_healthy_percent: None,
maximum_percent: None,
circuit_breaker: None,
deployments: vec![],
load_balancers: vec![],
service_registries: vec![],
placement_constraints: vec![],
placement_strategy: vec![],
network_configuration: None,
tags: vec![],
created_at: chrono::Utc::now(),
created_by: None,
role_arn: None,
platform_version: None,
health_check_grace_period_seconds: None,
enable_execute_command: false,
enable_ecs_managed_tags: false,
propagate_tags: None,
capacity_provider_strategy: vec![],
availability_zone_rebalancing: None,
volume_configurations: vec![],
},
);
assert_eq!(
resolve_service_key(&state, "default/api"),
Some("default/api".to_string())
);
assert_eq!(
resolve_service_key(&state, "api"),
Some("default/api".to_string())
);
assert_eq!(resolve_service_key(&state, "nope"), None);
}
#[test]
fn resolve_container_instance_key_handles_short_and_long() {
let mut state = EcsState::new("123456789012", "us-east-1");
state.container_instances.insert(
"default/abc-123".to_string(),
ContainerInstance {
container_instance_arn: "arn".into(),
ec2_instance_id: Some("i-x".into()),
cluster_name: "default".into(),
cluster_arn: "arn".into(),
status: "ACTIVE".into(),
version: 0,
version_info: None,
agent_connected: true,
agent_update_status: None,
remaining_resources: vec![],
registered_resources: vec![],
running_tasks_count: 0,
pending_tasks_count: 0,
registered_at: chrono::Utc::now(),
attributes: vec![],
tags: vec![],
capacity_provider_name: None,
health_status: None,
},
);
assert_eq!(
resolve_container_instance_key(&state, "default/abc-123"),
Some("default/abc-123".to_string())
);
assert_eq!(
resolve_container_instance_key(&state, "abc-123"),
Some("default/abc-123".to_string())
);
assert_eq!(resolve_container_instance_key(&state, "nope"), None);
}
#[test]
fn validate_family_name_accepts_hyphen_underscore() {
assert!(validate_family_name("web_server-2").is_ok());
}
#[test]
fn validate_family_name_rejects_empty() {
assert!(validate_family_name("").is_err());
}
#[test]
fn validate_family_name_rejects_slash() {
assert!(validate_family_name("web/server").is_err());
}
#[test]
fn resolve_task_definition_ref_bare_family() {
let (account, family, rev) = resolve_task_definition_ref("web").unwrap();
assert_eq!(account, None);
assert_eq!(family, "web");
assert_eq!(rev, None);
}
#[test]
fn resolve_task_definition_ref_family_revision() {
let (account, family, rev) = resolve_task_definition_ref("web:3").unwrap();
assert_eq!(account, None);
assert_eq!(family, "web");
assert_eq!(rev, Some(3));
}
#[test]
fn resolve_task_definition_ref_full_arn() {
let (account, family, rev) =
resolve_task_definition_ref("arn:aws:ecs:us-east-1:111122223333:task-definition/web:3")
.unwrap();
assert_eq!(account, Some("111122223333".to_string()));
assert_eq!(family, "web");
assert_eq!(rev, Some(3));
}
#[test]
fn merge_tags_replaces_existing_value() {
let mut current = vec![TagEntry {
key: "env".into(),
value: "dev".into(),
}];
merge_tags(
&mut current,
vec![TagEntry {
key: "env".into(),
value: "prod".into(),
}],
);
assert_eq!(current.len(), 1);
assert_eq!(current[0].value, "prod");
}
#[test]
fn merge_tags_adds_new() {
let mut current = vec![TagEntry {
key: "env".into(),
value: "dev".into(),
}];
merge_tags(
&mut current,
vec![TagEntry {
key: "team".into(),
value: "platform".into(),
}],
);
assert_eq!(current.len(), 2);
}
#[test]
fn parse_tags_reads_lowercase_keys() {
let body = json!({
"tags": [
{"key": "env", "value": "prod"},
{"key": "team", "value": "platform"},
]
});
let tags = parse_tags(&body);
assert_eq!(tags.len(), 2);
assert_eq!(tags[0].key, "env");
assert_eq!(tags[0].value, "prod");
}
#[test]
fn matches_filter_respects_none() {
assert!(matches_filter(None, "anything"));
assert!(matches_filter(Some("x"), "x"));
assert!(!matches_filter(Some("x"), "y"));
}