use multi_index_container::multi_index_container;
#[derive(Debug, Clone, PartialEq)]
struct Person {
email: String,
age: u32,
department: String,
seniority: u32,
team: String,
}
multi_index_container! {
#[derive(Debug)]
PersonMap<Person> {
unique email: String => |p| p.email.clone(),
non_unique age: u32 => |p| p.age,
non_unique department: String => |p| p.department.clone(),
unique_ordered seniority: u32 => |p| p.seniority,
non_unique_ordered team: String => |p| p.team.clone(),
}
}
fn make_map() -> PersonMap {
let mut map = PersonMap::new();
map.insert(Person {
email: "alice@example.com".to_string(),
age: 30,
department: "engineering".to_string(),
seniority: 5,
team: "backend".to_string(),
})
.unwrap();
map.insert(Person {
email: "bob@example.com".to_string(),
age: 25,
department: "engineering".to_string(),
seniority: 2,
team: "backend".to_string(),
})
.unwrap();
map.insert(Person {
email: "carol@example.com".to_string(),
age: 30,
department: "design".to_string(),
seniority: 7,
team: "frontend".to_string(),
})
.unwrap();
map
}
#[test]
fn test_remove_by_email() {
let mut map = make_map();
let removed = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.remove();
assert_eq!(removed.email, "alice@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert!(
map.get_by_age(&30)
.all(|p| p.email != "alice@example.com")
);
assert!(
map.get_by_department(&"engineering".to_string())
.all(|p| p.email != "alice@example.com")
);
assert!(map.get_by_seniority(&5).is_none());
assert!(
map.get_by_team(&"backend".to_string())
.all(|p| p.email != "alice@example.com")
);
}
#[test]
fn test_remove_by_age() {
let mut map = make_map();
let removed = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.remove();
assert_eq!(removed.age, 30);
let by_age: Vec<_> = map.get_by_age(&30).collect();
assert_eq!(by_age.len(), 1);
assert_eq!(by_age[0].email, "carol@example.com");
}
#[test]
fn test_remove_by_seniority() {
let mut map = make_map();
let removed = map.get_mut_by_seniority(&7).unwrap().remove();
assert_eq!(removed.email, "carol@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_seniority(&7).is_none());
assert!(map.get_by_email(&"carol@example.com".to_string()).is_none());
}
#[test]
fn test_remove_by_team() {
let mut map = make_map();
let removed = map
.get_mut_by_email(&"bob@example.com".to_string())
.unwrap()
.remove();
assert_eq!(removed.team, "backend");
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert_eq!(backend.len(), 1);
assert_eq!(backend[0].email, "alice@example.com");
}
#[test]
fn test_remove_by_department() {
let mut map = make_map();
let removed = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.remove();
assert_eq!(removed.department, "engineering");
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert_eq!(eng.len(), 1);
assert_eq!(eng[0].email, "bob@example.com");
}
#[test]
fn test_clash_unique_email() {
let mut map = make_map();
let err = map.insert(Person {
email: "alice@example.com".to_string(),
age: 99,
department: "hr".to_string(),
seniority: 99,
team: "other".to_string(),
});
assert!(err.is_err());
assert_eq!(map.len(), 3);
}
#[test]
fn test_clash_unique_ordered_seniority() {
let mut map = make_map();
let err = map.insert(Person {
email: "dave@example.com".to_string(),
age: 28,
department: "engineering".to_string(),
seniority: 5, team: "backend".to_string(),
});
assert!(err.is_err());
assert_eq!(map.len(), 3);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_some());
assert!(map.get_by_email(&"dave@example.com".to_string()).is_none());
}
#[test]
fn test_no_clash_non_unique_age() {
let mut map = make_map();
let result = map.insert(Person {
email: "dave@example.com".to_string(),
age: 30,
department: "sales".to_string(),
seniority: 10,
team: "frontend".to_string(),
});
assert!(result.is_ok());
assert_eq!(map.len(), 4);
let by_age: Vec<_> = map.get_by_age(&30).collect();
assert_eq!(by_age.len(), 3);
}
#[test]
fn test_no_clash_non_unique_department() {
let mut map = make_map();
let result = map.insert(Person {
email: "dave@example.com".to_string(),
age: 22,
department: "engineering".to_string(),
seniority: 1,
team: "devops".to_string(),
});
assert!(result.is_ok());
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert_eq!(eng.len(), 3);
}
#[test]
fn test_no_clash_non_unique_ordered_team() {
let mut map = make_map();
let result = map.insert(Person {
email: "dave@example.com".to_string(),
age: 27,
department: "ops".to_string(),
seniority: 3,
team: "backend".to_string(),
});
assert!(result.is_ok());
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert_eq!(backend.len(), 3);
}
#[test]
fn test_extend() {
let mut map = make_map();
let people = vec![
Person {
email: "dave@example.com".to_string(),
age: 40,
department: "sales".to_string(),
seniority: 10,
team: "frontend".to_string(),
},
Person {
email: "eve@example.com".to_string(),
age: 35,
department: "design".to_string(),
seniority: 8,
team: "mobile".to_string(),
},
];
let errors = map.extend(people);
assert!(errors.is_empty());
assert_eq!(map.len(), 5);
}
#[test]
fn test_extend_clash_unique_email() {
let mut map = make_map();
let people = vec![
Person {
email: "alice@example.com".to_string(), age: 99,
department: "hr".to_string(),
seniority: 99,
team: "other".to_string(),
},
Person {
email: "dave@example.com".to_string(),
age: 28,
department: "sales".to_string(),
seniority: 10,
team: "mobile".to_string(),
},
];
let errors = map.extend(people);
assert_eq!(errors.len(), 1);
assert_eq!(map.len(), 4); assert!(map.get_by_email(&"dave@example.com".to_string()).is_some());
}
#[test]
fn test_extend_clash_unique_ordered_seniority() {
let mut map = make_map();
let people = vec![
Person {
email: "dave@example.com".to_string(),
age: 28,
department: "sales".to_string(),
seniority: 5, team: "mobile".to_string(),
},
Person {
email: "eve@example.com".to_string(),
age: 26,
department: "hr".to_string(),
seniority: 11,
team: "mobile".to_string(),
},
];
let errors = map.extend(people);
assert_eq!(errors.len(), 1);
assert_eq!(map.len(), 4); assert!(map.get_by_email(&"eve@example.com".to_string()).is_some());
assert!(map.get_by_email(&"dave@example.com".to_string()).is_none());
}
#[test]
fn test_get_by_unique_existing() {
let map = make_map();
let person = map.get_by_email(&"alice@example.com".to_string());
assert!(person.is_some());
assert_eq!(person.unwrap().email, "alice@example.com");
}
#[test]
fn test_get_by_unique_missing() {
let map = make_map();
let person = map.get_by_email(&"unknown@example.com".to_string());
assert!(person.is_none());
}
#[test]
fn test_get_mut_by_unique_existing() {
let mut map = make_map();
let entry = map.get_mut_by_email(&"alice@example.com".to_string());
assert!(entry.is_some());
}
#[test]
fn test_get_mut_by_unique_missing() {
let mut map = make_map();
let entry = map.get_mut_by_email(&"unknown@example.com".to_string());
assert!(entry.is_none());
}
#[test]
fn test_get_by_non_unique_multiple_results() {
let map = make_map();
let persons: Vec<_> = map.get_by_age(&30).collect();
assert_eq!(persons.len(), 2);
assert!(persons.iter().any(|p| p.email == "alice@example.com"));
assert!(persons.iter().any(|p| p.email == "carol@example.com"));
}
#[test]
fn test_get_by_non_unique_single_result() {
let map = make_map();
let persons: Vec<_> = map.get_by_age(&25).collect();
assert_eq!(persons.len(), 1);
assert_eq!(persons[0].email, "bob@example.com");
}
#[test]
fn test_get_by_non_unique_missing() {
let map = make_map();
let persons: Vec<_> = map.get_by_age(&99).collect();
assert!(persons.is_empty());
}
#[test]
fn test_get_mut_by_non_unique_existing() {
let mut map = make_map();
let entries = map.get_mut_by_department(&"engineering".to_string());
assert!(entries.is_not_empty());
}
#[test]
fn test_get_mut_by_non_unique_missing() {
let mut map = make_map();
let entries = map.get_mut_by_department(&"marketing".to_string());
assert!(entries.is_empty());
}
#[test]
fn test_get_by_unique_ordered_existing() {
let map = make_map();
let person = map.get_by_seniority(&5);
assert!(person.is_some());
assert_eq!(person.unwrap().email, "alice@example.com");
}
#[test]
fn test_get_by_unique_ordered_missing() {
let map = make_map();
let person = map.get_by_seniority(&99);
assert!(person.is_none());
}
#[test]
fn test_get_mut_by_unique_ordered_existing() {
let mut map = make_map();
let entry = map.get_mut_by_seniority(&5);
assert!(entry.is_some());
}
#[test]
fn test_get_mut_by_unique_ordered_missing() {
let mut map = make_map();
let entry = map.get_mut_by_seniority(&99);
assert!(entry.is_none());
}
#[test]
fn test_get_by_non_unique_ordered_multiple_results() {
let map = make_map();
let persons: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert_eq!(persons.len(), 2);
assert!(persons.iter().any(|p| p.email == "alice@example.com"));
assert!(persons.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_get_by_non_unique_ordered_single_result() {
let map = make_map();
let persons: Vec<_> = map.get_by_team(&"frontend".to_string()).collect();
assert_eq!(persons.len(), 1);
assert_eq!(persons[0].email, "carol@example.com");
}
#[test]
fn test_get_by_non_unique_ordered_missing() {
let map = make_map();
let persons: Vec<_> = map.get_by_team(&"infra".to_string()).collect();
assert!(persons.is_empty());
}
#[test]
fn test_get_mut_by_non_unique_ordered_existing() {
let mut map = make_map();
let entries = map.get_mut_by_team(&"backend".to_string());
assert!(entries.is_not_empty());
}
#[test]
fn test_get_mut_by_non_unique_ordered_missing() {
let mut map = make_map();
let entries = map.get_mut_by_team(&"infra".to_string());
assert!(entries.is_empty());
}
#[test]
fn test_insert_or_overwrite_same_email() {
let mut map = make_map();
map.insert_or_overwrite(Person {
email: "alice@example.com".to_string(),
age: 99,
department: "hr".to_string(),
seniority: 99,
team: "other".to_string(),
});
assert_eq!(map.len(), 3); let alice = map.get_by_email(&"alice@example.com".to_string()).unwrap();
assert_eq!(alice.age, 99);
assert_eq!(alice.seniority, 99);
assert!(map.get_by_seniority(&5).is_none());
assert!(map.get_by_seniority(&99).is_some());
}
#[test]
fn test_insert_or_overwrite_same_seniority() {
let mut map = make_map();
map.insert_or_overwrite(Person {
email: "dave@example.com".to_string(),
age: 28,
department: "sales".to_string(),
seniority: 5,
team: "mobile".to_string(),
});
assert_eq!(map.len(), 3); assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert!(map.get_by_email(&"dave@example.com".to_string()).is_some());
assert_eq!(map.get_by_seniority(&5).unwrap().email, "dave@example.com");
let age_30: Vec<_> = map.get_by_age(&30).collect();
assert!(age_30.iter().all(|p| p.email != "alice@example.com"));
}
#[test]
fn test_insert_or_overwrite_no_clash() {
let mut map = make_map();
map.insert_or_overwrite(Person {
email: "dave@example.com".to_string(),
age: 28,
department: "sales".to_string(),
seniority: 10,
team: "mobile".to_string(),
});
assert_eq!(map.len(), 4);
assert!(map.get_by_email(&"dave@example.com".to_string()).is_some());
assert!(map.get_by_seniority(&10).is_some());
let sales: Vec<_> = map.get_by_department(&"sales".to_string()).collect();
assert_eq!(sales.len(), 1);
}
#[test]
fn test_insert_or_overwrite_clears_all_indexes_of_evicted_entry() {
let mut map = make_map();
map.insert_or_overwrite(Person {
email: "bob@example.com".to_string(),
age: 50,
department: "legal".to_string(),
seniority: 20,
team: "compliance".to_string(),
});
assert_eq!(map.len(), 3);
let age_25: Vec<_> = map.get_by_age(&25).collect();
assert!(age_25.is_empty());
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert!(eng.iter().all(|p| p.email != "bob@example.com"));
assert!(map.get_by_seniority(&2).is_none());
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert!(backend.iter().all(|p| p.email != "bob@example.com"));
let age_50: Vec<_> = map.get_by_age(&50).collect();
assert_eq!(age_50.len(), 1);
assert_eq!(age_50[0].email, "bob@example.com");
assert_eq!(map.get_by_seniority(&20).unwrap().email, "bob@example.com");
let legal: Vec<_> = map.get_by_department(&"legal".to_string()).collect();
assert_eq!(legal.len(), 1);
let compliance: Vec<_> = map.get_by_team(&"compliance".to_string()).collect();
assert_eq!(compliance.len(), 1);
}
#[test]
fn test_insert_or_overwrite_multi_clash_removes_all() {
let mut map = make_map();
map.insert_or_overwrite(Person {
email: "alice@example.com".to_string(),
age: 40,
department: "product".to_string(),
seniority: 2, team: "strategy".to_string(),
});
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"bob@example.com".to_string()).is_none());
assert!(map.get_by_seniority(&5).is_none());
let new_alice = map.get_by_email(&"alice@example.com".to_string()).unwrap();
assert_eq!(new_alice.seniority, 2);
assert_eq!(new_alice.department, "product");
}
#[test]
fn test_insert_or_overwrite_idempotent() {
let mut map = make_map();
let carol = map
.get_by_email(&"carol@example.com".to_string())
.unwrap()
.clone();
map.insert_or_overwrite(carol.clone());
assert_eq!(map.len(), 3);
let fetched = map.get_by_email(&"carol@example.com".to_string()).unwrap();
assert_eq!(*fetched, carol);
assert_eq!(map.get_by_seniority(&7).unwrap().email, "carol@example.com");
let frontend: Vec<_> = map.get_by_team(&"frontend".to_string()).collect();
assert_eq!(frontend.len(), 1);
}
#[test]
fn test_get_by_department_team_match() {
let map = make_map();
let results: Vec<_> =
map.get_by_department_team(&"engineering".to_string(), &"backend".to_string()).collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_get_by_department_team_no_match() {
let map = make_map();
let results: Vec<_> =
map.get_by_department_team(&"engineering".to_string(), &"frontend".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_department_team_single_match() {
let map = make_map();
let results: Vec<_> =
map.get_by_department_team(&"design".to_string(), &"frontend".to_string()).collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0].email, "carol@example.com");
}
#[test]
fn test_get_by_department_team_unknown_department() {
let map = make_map();
let results: Vec<_> = map.get_by_department_team(&"hr".to_string(), &"backend".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_department_team_unknown_team() {
let map = make_map();
let results: Vec<_> =
map.get_by_department_team(&"engineering".to_string(), &"mobile".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_age_department_team_single_match() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string()).collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0].email, "alice@example.com");
}
#[test]
fn test_get_by_age_department_team_age_narrows_department_team() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string()).collect();
assert!(results.iter().all(|p| p.email != "bob@example.com"));
}
#[test]
fn test_get_by_age_department_team_no_match_wrong_age() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&99, &"engineering".to_string(), &"backend".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_age_department_team_no_match_wrong_department() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&30, &"sales".to_string(), &"backend".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_age_department_team_no_match_wrong_team() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&30, &"engineering".to_string(), &"mobile".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_age_department_team_all_unknown() {
let map = make_map();
let results: Vec<_> =
map.get_by_age_department_team(&0, &"unknown".to_string(), &"unknown".to_string()).collect();
assert!(results.is_empty());
}
#[test]
fn test_combined_subset_of_department_team() {
let map = make_map();
let by_dept_team: Vec<_> = map
.get_by_department_team(&"engineering".to_string(), &"backend".to_string())
.into_iter()
.map(|p| p.email.clone())
.collect();
let by_age_dept_team: Vec<_> = map
.get_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string())
.into_iter()
.map(|p| p.email.clone())
.collect();
for email in &by_age_dept_team {
assert!(by_dept_team.contains(email));
}
}
#[test]
fn test_remove_via_get_mut_by_department_team_single_match() {
let mut map = make_map();
let removed = map
.get_mut_by_department_team(&"design".to_string(), &"frontend".to_string())
.first()
.unwrap()
.remove();
assert_eq!(removed.email, "carol@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"carol@example.com".to_string()).is_none());
assert!(map.get_by_seniority(&7).is_none());
let age_30: Vec<_> = map.get_by_age(&30).collect();
assert!(age_30.iter().all(|p| p.email != "carol@example.com"));
let frontend: Vec<_> = map.get_by_team(&"frontend".to_string()).collect();
assert!(frontend.is_empty());
let design: Vec<_> = map.get_by_department(&"design".to_string()).collect();
assert!(design.is_empty());
}
#[test]
fn test_remove_via_get_mut_by_department_team_one_of_many() {
let mut map = make_map();
let removed = map
.get_mut_by_department_team(&"engineering".to_string(), &"backend".to_string())
.first()
.unwrap()
.remove();
assert_eq!(map.len(), 2);
let remaining: Vec<_> = map
.get_by_department_team(&"engineering".to_string(), &"backend".to_string()).collect();
assert_eq!(remaining.len(), 1);
assert_ne!(remaining[0].email, removed.email);
}
#[test]
fn test_remove_all_via_get_mut_by_department_team() {
let mut map = make_map();
let emails: Vec<String> = map
.get_mut_by_department_team(&"engineering".to_string(), &"backend".to_string())
.remove_all()
.into_iter()
.map(|x| x.email)
.collect()
;
assert_eq!(emails.len(), 2);
assert!(emails.contains(&"alice@example.com".to_string()));
assert!(emails.contains(&"bob@example.com".to_string()));
assert_eq!(map.len(), 1);
let remaining: Vec<_> = map
.get_by_department_team(&"engineering".to_string(), &"backend".to_string()).collect();
assert!(remaining.is_empty());
assert!(map.get_by_email(&"carol@example.com".to_string()).is_some());
}
#[test]
fn test_remove_via_get_mut_by_age_department_team_single_match() {
let mut map = make_map();
let removed = map
.get_mut_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string())
.first()
.unwrap()
.remove();
assert_eq!(removed.email, "alice@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert!(map.get_by_seniority(&5).is_none());
assert!(map.get_by_email(&"bob@example.com".to_string()).is_some());
let eng_backend: Vec<_> = map
.get_by_department_team(&"engineering".to_string(), &"backend".to_string()).collect();
assert_eq!(eng_backend.len(), 1);
assert_eq!(eng_backend[0].email, "bob@example.com");
}
#[test]
fn test_remove_via_get_mut_by_age_department_team_no_match() {
let mut map = make_map();
let iter =
map.get_mut_by_age_department_team(&99, &"engineering".to_string(), &"backend".to_string()).first();
assert!(iter.is_none());
assert_eq!(map.len(), 3);
}
#[test]
fn test_remove_via_get_mut_by_age_department_team_clears_all_indexes() {
let mut map = make_map();
let removed = map
.get_mut_by_age_department_team(&25, &"engineering".to_string(), &"backend".to_string())
.first()
.unwrap()
.remove();
assert_eq!(removed.email, "bob@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_seniority(&2).is_none());
let age_25: Vec<_> = map.get_by_age(&25).collect();
assert!(age_25.is_empty());
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert!(eng.iter().all(|p| p.email != "bob@example.com"));
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert!(backend.iter().all(|p| p.email != "bob@example.com"));
let remaining: Vec<_> = map
.get_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string())
.into_iter()
.map(|e| e.email.clone())
.collect();
assert_eq!(remaining, vec!["alice@example.com".to_string()]);
}
#[test]
fn test_modify_non_indexed_field() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.age = 99);
assert!(result.is_ok());
assert_eq!(map.len(), 3);
let alice = map.get_by_email(&"alice@example.com".to_string()).unwrap();
assert_eq!(alice.age, 99);
}
#[test]
fn test_modify_unique_index_to_unused_value() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.email = "alice-new@example.com".to_string());
assert!(result.is_ok());
assert_eq!(map.len(), 3);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert!(
map.get_by_email(&"alice-new@example.com".to_string())
.is_some()
);
}
#[test]
fn test_modify_unique_index_clash_removes_entry() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.email = "bob@example.com".to_string());
assert!(result.is_err());
assert_eq!(map.len(), 2); assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert!(map.get_by_email(&"bob@example.com".to_string()).is_some());
assert!(map.get_by_seniority(&5).is_none());
let age_30: Vec<_> = map.get_by_age(&30).collect();
assert!(age_30.iter().all(|p| p.email != "alice@example.com"));
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert!(backend.iter().all(|p| p.email != "alice@example.com"));
}
#[test]
fn test_modify_unique_ordered_index_to_unused_value() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.seniority = 50);
assert!(result.is_ok());
assert_eq!(map.len(), 3);
assert!(map.get_by_seniority(&5).is_none());
assert_eq!(
map.get_by_seniority(&50).unwrap().email,
"alice@example.com"
);
}
#[test]
fn test_modify_unique_ordered_index_clash_removes_entry() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.seniority = 7);
assert!(result.is_err());
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert_eq!(map.get_by_seniority(&7).unwrap().email, "carol@example.com");
assert!(map.get_by_seniority(&5).is_none());
}
#[test]
fn test_modify_non_unique_index_no_clash() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.department = "product".to_string());
assert!(result.is_ok());
assert_eq!(map.len(), 3);
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert!(eng.iter().all(|p| p.email != "alice@example.com"));
let product: Vec<_> = map.get_by_department(&"product".to_string()).collect();
assert_eq!(product.len(), 1);
assert_eq!(product[0].email, "alice@example.com");
}
#[test]
fn test_modify_non_unique_ordered_index_no_clash() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| p.team = "mobile".to_string());
assert!(result.is_ok());
assert_eq!(map.len(), 3);
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert!(backend.iter().all(|p| p.email != "alice@example.com"));
assert_eq!(backend.len(), 1); let mobile: Vec<_> = map.get_by_team(&"mobile".to_string()).collect();
assert_eq!(mobile.len(), 1);
assert_eq!(mobile[0].email, "alice@example.com");
}
#[test]
fn test_modify_via_get_mut_by_department_team() {
let mut map = make_map();
let result = map
.get_mut_by_department_team(&"engineering".to_string(), &"backend".to_string())
.find(|e| e.email == "alice@example.com")
.unwrap()
.modify_or_remove(|p| p.seniority = 99);
assert!(result.is_ok());
assert_eq!(map.len(), 3);
assert_eq!(
map.get_by_seniority(&99).unwrap().email,
"alice@example.com"
);
assert!(map.get_by_seniority(&5).is_none());
}
#[test]
fn test_modify_via_get_mut_by_department_team_clash_removes_entry() {
let mut map = make_map();
let result = map
.get_mut_by_department_team(&"engineering".to_string(), &"backend".to_string())
.find(|e| e.email == "alice@example.com")
.unwrap()
.modify_or_remove(|p| p.seniority = 2);
assert!(result.is_err());
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_none());
assert_eq!(map.get_by_seniority(&2).unwrap().email, "bob@example.com");
}
#[test]
fn test_modify_via_get_mut_by_age_department_team() {
let mut map = make_map();
let result = map
.get_mut_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string())
.first()
.unwrap()
.modify_or_remove(|p| p.team = "platform".to_string());
assert!(result.is_ok());
assert_eq!(map.len(), 3);
let backend: Vec<_> = map.get_by_team(&"backend".to_string()).collect();
assert!(backend.iter().all(|p| p.email != "alice@example.com"));
let platform: Vec<_> = map.get_by_team(&"platform".to_string()).collect();
assert_eq!(platform.len(), 1);
assert_eq!(platform[0].email, "alice@example.com");
let old_combined: Vec<_> = map
.get_by_age_department_team(&30, &"engineering".to_string(), &"backend".to_string()).collect();
assert!(old_combined.iter().all(|p| p.email != "alice@example.com"));
}
#[test]
fn test_modify_clash_error_contains_attempted_value() {
let mut map = make_map();
let result = map
.get_mut_by_email(&"alice@example.com".to_string())
.unwrap()
.modify_or_remove(|p| {
p.email = "bob@example.com".to_string();
p.seniority = 999;
});
let err = result.unwrap_err();
assert_eq!(err.value.email, "bob@example.com");
assert_eq!(err.value.seniority, 999);
}
#[test]
fn test_first_by_seniority() {
let map = make_map();
let first = map.first_by_seniority().unwrap();
assert_eq!(first.email, "bob@example.com");
}
#[test]
fn test_last_by_seniority() {
let map = make_map();
let last = map.last_by_seniority().unwrap();
assert_eq!(last.email, "carol@example.com");
}
#[test]
fn test_first_by_seniority_empty() {
let map = PersonMap::new();
assert!(map.first_by_seniority().is_none());
}
#[test]
fn test_last_by_seniority_empty() {
let map = PersonMap::new();
assert!(map.last_by_seniority().is_none());
}
#[test]
fn test_first_by_team() {
let map = make_map();
let first: Vec<_> = map.first_by_team().collect();
assert_eq!(first.len(), 2);
assert!(first.iter().any(|p| p.email == "alice@example.com"));
assert!(first.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_last_by_team() {
let map = make_map();
let last: Vec<_> = map.last_by_team().collect();
assert_eq!(last.len(), 1);
assert_eq!(last[0].email, "carol@example.com");
}
#[test]
fn test_first_by_team_empty() {
let map = PersonMap::new();
let first: Vec<_> = map.first_by_team().collect();
assert!(first.is_empty());
}
#[test]
fn test_get_by_seniority_range_inclusive() {
let map = make_map();
let results: Vec<_> = map.get_by_seniority_range(2..=5).collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_get_by_seniority_range_exclusive() {
let map = make_map();
let results: Vec<_> = map.get_by_seniority_range(2..5).collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0].email, "bob@example.com");
}
#[test]
fn test_get_by_seniority_range_from() {
let map = make_map();
let results: Vec<_> = map.get_by_seniority_range(5..).collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "carol@example.com"));
}
#[test]
fn test_get_by_seniority_range_to() {
let map = make_map();
let results: Vec<_> = map.get_by_seniority_range(..5).collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0].email, "bob@example.com");
}
#[test]
fn test_get_by_seniority_range_no_match() {
let map = make_map();
let results: Vec<_> = map.get_by_seniority_range(10..=20).collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_team_range_full() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range("backend".to_string()..="frontend".to_string())
.collect();
assert_eq!(results.len(), 3);
}
#[test]
fn test_get_by_team_range_partial() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range("backend".to_string()..="backend".to_string())
.collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_get_by_team_range_no_match() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range("zzz".to_string()..)
.collect();
assert!(results.is_empty());
}
#[test]
fn test_first_by_team_department() {
let map = make_map();
let first = map.first_by_team_department(&"engineering".to_string());
assert!(first.is_some());
assert_eq!(first.unwrap().department, "engineering");
}
#[test]
fn test_last_by_team_department() {
let map = make_map();
let last = map.last_by_team_department(&"design".to_string());
assert_eq!(last.unwrap().email, "carol@example.com");
}
#[test]
fn test_first_by_team_age() {
let map = make_map();
let first = map.first_by_team_age(&30);
assert_eq!(first.unwrap().email, "alice@example.com");
}
#[test]
fn test_last_by_team_age() {
let map = make_map();
let last = map.last_by_team_age(&30);
assert_eq!(last.unwrap().email, "carol@example.com");
}
#[test]
fn test_first_by_team_department_age() {
let map = make_map();
let first = map.first_by_team_age_department(&30, &"engineering".to_string());
assert_eq!(first.unwrap().email, "alice@example.com");
}
#[test]
fn test_first_by_team_department_no_match() {
let map = make_map();
assert!(map.first_by_team_department(&"hr".to_string()).is_none());
}
#[test]
fn test_last_by_team_department_no_match() {
let map = make_map();
assert!(map.last_by_team_department(&"hr".to_string()).is_none());
}
#[test]
fn test_first_by_team_age_no_match() {
let map = make_map();
assert!(map.first_by_team_age(&99).is_none());
}
#[test]
fn test_get_by_team_range_department() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range_department(
"backend".to_string()..="frontend".to_string(),
&"engineering".to_string(),
)
.collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "bob@example.com"));
}
#[test]
fn test_get_by_team_range_department_narrows_result() {
let map = make_map();
let all: Vec<_> = map
.get_by_team_range("backend".to_string()..="frontend".to_string())
.collect();
assert_eq!(all.len(), 3);
let filtered: Vec<_> = map
.get_by_team_range_department(
"backend".to_string()..="frontend".to_string(),
&"engineering".to_string(),
)
.collect();
assert_eq!(filtered.len(), 2);
assert!(filtered.iter().all(|p| p.department == "engineering"));
}
#[test]
fn test_get_by_team_range_age() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range_age(
"backend".to_string()..="frontend".to_string(),
&30,
)
.collect();
assert_eq!(results.len(), 2);
assert!(results.iter().any(|p| p.email == "alice@example.com"));
assert!(results.iter().any(|p| p.email == "carol@example.com"));
}
#[test]
fn test_get_by_team_range_department_age() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range_age_department(
"backend".to_string()..,
&30,
&"engineering".to_string(),
)
.collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0].email, "alice@example.com");
}
#[test]
fn test_get_by_team_range_department_no_match_range() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range_department(
"zzz".to_string()..,
&"engineering".to_string(),
)
.collect();
assert!(results.is_empty());
}
#[test]
fn test_get_by_team_range_department_no_match_filter() {
let map = make_map();
let results: Vec<_> = map
.get_by_team_range_department(
"backend".to_string()..="frontend".to_string(),
&"hr".to_string(),
)
.collect();
assert!(results.is_empty());
}
#[test]
fn test_get_mut_by_team_range_department_modify() {
let mut map = make_map();
map.get_mut_by_team_range_department(
"backend".to_string()..="frontend".to_string(),
&"engineering".to_string(),
)
.for_each(|mut e| {
e.modify_or_remove(|p| p.department = "platform".to_string()).unwrap();
});
let platform: Vec<_> = map.get_by_department(&"platform".to_string()).collect();
assert_eq!(platform.len(), 2);
let eng: Vec<_> = map.get_by_department(&"engineering".to_string()).collect();
assert!(eng.is_empty());
assert_eq!(map.get_by_email(&"carol@example.com".to_string()).unwrap().department, "design");
}
#[test]
fn test_get_mut_by_team_range_department_remove_all() {
let mut map = make_map();
let removed = map
.get_mut_by_team_range_department(
"backend".to_string()..="backend".to_string(),
&"engineering".to_string(),
)
.remove_all();
assert_eq!(removed.len(), 2);
assert!(removed.iter().any(|p| p.email == "alice@example.com"));
assert!(removed.iter().any(|p| p.email == "bob@example.com"));
assert_eq!(map.len(), 1);
assert!(map.get_by_email(&"carol@example.com".to_string()).is_some());
}
#[test]
fn test_get_mut_by_team_range_department_no_match() {
let mut map = make_map();
let removed = map
.get_mut_by_team_range_department(
"zzz".to_string()..,
&"engineering".to_string(),
)
.remove_all();
assert!(removed.is_empty());
assert_eq!(map.len(), 3);
}
#[test]
fn test_get_mut_by_team_range_age_filter_then_remove() {
let mut map = make_map();
let removed = map
.get_mut_by_team_range_age(
"backend".to_string()..="frontend".to_string(),
&30,
)
.filter(|p| p.seniority > 5)
.remove_all();
assert_eq!(removed.len(), 1);
assert_eq!(removed[0].email, "carol@example.com");
assert_eq!(map.len(), 2);
assert!(map.get_by_email(&"alice@example.com".to_string()).is_some());
}