use std::fmt;
use crate::name::{ProjectName, TaskName};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TaskId {
pub project: ProjectName,
pub task: TaskName,
}
impl fmt::Display for TaskId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.project, self.task)
}
}
#[cfg(test)]
mod tests {
use std::cmp::Ordering;
use std::collections::BTreeSet;
use std::str::FromStr;
use crate::name::{ProjectName, TaskName};
use crate::task_id::TaskId;
fn id(project: &str, task: &str) -> TaskId {
TaskId {
project: ProjectName::from_str(project).unwrap(),
task: TaskName::from_str(task).unwrap(),
}
}
#[test]
fn display_renders_project_colon_task() {
assert_eq!(id("lib_core", "compile").to_string(), "lib_core:compile");
assert_eq!(
id("web-frontend", "bundle").to_string(),
"web-frontend:bundle"
);
}
#[test]
fn equality_is_structural() {
assert_eq!(id("a", "x"), id("a", "x"));
assert_ne!(id("a", "x"), id("a", "y"));
assert_ne!(id("a", "x"), id("b", "x"));
}
#[test]
fn ord_is_lexicographic_project_then_task() {
assert_eq!(id("p", "a").cmp(&id("p", "b")), Ordering::Less);
assert_eq!(id("a", "z").cmp(&id("b", "a")), Ordering::Less);
}
#[test]
fn btreeset_iterates_in_canonical_order() {
let mut set = BTreeSet::new();
set.insert(id("z", "build"));
set.insert(id("a", "test"));
set.insert(id("a", "build"));
set.insert(id("m", "build"));
let collected: Vec<_> = set.iter().map(ToString::to_string).collect();
assert_eq!(collected, vec!["a:build", "a:test", "m:build", "z:build"],);
}
#[test]
fn clone_preserves_value() {
let original = id("lib_core", "compile");
let cloned = original.clone();
assert_eq!(original, cloned);
}
}