use precedence_net::{DurationType, Error, Network, NetworkBuilder, Result, StartType}; fn compare(mut vec_1: Vec<&str>, mut vec_2: Vec<&str>) { vec_1.sort(); vec_2.sort(); assert_eq!(vec_1, vec_2) } fn test_calculations( network: &Network, reference: &str, earliest_start: f64, latest_start: f64, earliest_finish: f64, latest_finish: f64, total_float: f64, early_float: f64, ) -> Result<()> { assert_eq!(earliest_start, network.earliest_start(reference)?); assert_eq!(latest_start, network.latest_start(reference)?); assert_eq!(earliest_finish, network.earliest_finish(reference)?); assert_eq!(latest_finish, network.latest_finish(reference)?); assert_eq!(total_float, network.total_float(reference)?); assert_eq!(early_float, network.free_float(reference)?); Ok(()) } #[test] fn test_network() -> Result<()> { let mut network_builder = Network::builder(); network_builder.add_activity("a", 1.0)?; network_builder.add_activity("b", 1.0)?; network_builder.add_activity("c", 1.0)?; network_builder.add_activity("d", 1.0)?; network_builder.connect("a", "b")?; network_builder.connect("b", "c")?; network_builder.connect("b", "d")?; let network = Network::try_from(network_builder)?; assert!(network.connected("a", "b")?); assert!(network.connected("b", "c")?); assert!(network.connected("b", "d")?); assert!(!network.connected("a", "c")?); assert!(!network.connected("a", "d")?); assert!(!network.connected("b", "a")?); assert!(!network.connected("c", "b")?); assert!(!network.connected("d", "b")?); assert_eq!(vec!["a"], network.start_activities()?); compare(vec!["c", "d"], network.finish_activities()?); assert_eq!(vec!["b"], network.next_activities("a")?); compare(vec!["c", "d"], network.next_activities("b")?); assert_eq!(Vec::::new(), network.next_activities("c")?); assert_eq!(Vec::::new(), network.next_activities("d")?); Ok(()) } #[test] fn test_depth() -> Result<()> { let mut network_builder = Network::builder(); network_builder.add_activity("a", 1.0)?; network_builder.add_activity("b", 1.0)?; network_builder.add_activity("c", 1.0)?; network_builder.add_activity("d", 1.0)?; network_builder.connect("a", "b")?; network_builder.connect("b", "c")?; network_builder.connect("b", "d")?; let network = Network::try_from(network_builder)?; assert_eq!(1, network.depth("a")?); assert_eq!(2, network.depth("b")?); assert_eq!(3, network.depth("c")?); assert_eq!(3, network.depth("d")?); Ok(()) } fn create_network_builder() -> Result { let mut network_builder = Network::builder(); for i in 1..8 { network_builder.add_activity(&format!("a{i}"), i.into())?; } Ok(network_builder) } #[test] fn test_earliest_finish() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a3", "a4")?; network_builder.connect("a2", "a4")?; let network = Network::try_from(network_builder)?; assert_eq!(1.0, network.earliest_finish("a1")?); assert_eq!(3.0, network.earliest_finish("a2")?); assert_eq!(8.0, network.earliest_finish("a4")?); Ok(()) } #[test] fn test_latest_finish() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a3", "a4")?; network_builder.connect("a2", "a4")?; let network = Network::try_from(network_builder)?; assert_eq!(1.0, network.latest_finish("a1")?); assert_eq!(2.0, network.latest_start("a2")?); assert_eq!(8.0, network.latest_finish("a4")?); Ok(()) } #[test] fn test_critical_path_1() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a3", "a4")?; network_builder.connect("a2", "a4")?; let network = Network::try_from(network_builder)?; assert!(network.on_critical_path("a1")?); assert!(!network.on_critical_path("a2")?); assert!(network.on_critical_path("a3")?); assert!(network.on_critical_path("a4")?); Ok(()) } #[test] fn test_critical_path_2() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a2", "a3")?; network_builder.connect("a2", "a4")?; let network = Network::try_from(network_builder)?; assert!(network.on_critical_path("a1")?); assert!(network.on_critical_path("a2")?); assert!(!network.on_critical_path("a3")?); assert!(network.on_critical_path("a4")?); Ok(()) } #[test] fn test_total_float() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a3", "a4")?; network_builder.connect("a2", "a4")?; let network = Network::try_from(network_builder)?; assert_eq!(0.0, network.total_float("a1")?); assert_eq!(1.0, network.total_float("a2")?); assert_eq!(0.0, network.total_float("a3")?); assert_eq!(0.0, network.total_float("a4")?); Ok(()) } #[test] fn test_total_and_early_float() -> Result<()> { let mut network_builder = Network::builder(); network_builder.add_activity("a1", 1.0)?; network_builder.add_activity("a2", 3.0)?; network_builder.add_activity("a3", 2.0)?; network_builder.add_activity("a4", 4.0)?; network_builder.add_activity("a5", 2.0)?; network_builder.add_activity("a6", 1.0)?; network_builder.add_activity("a7", 2.0)?; network_builder.add_activity("a8", 4.0)?; network_builder.connect("a1", "a3")?; network_builder.connect("a2", "a4")?; network_builder.connect("a2", "a5")?; network_builder.connect("a3", "a8")?; network_builder.connect("a4", "a6")?; network_builder.connect("a5", "a7")?; network_builder.connect("a6", "a8")?; network_builder.connect("a7", "a8")?; let network = Network::try_from(network_builder)?; assert!(network.on_critical_path("a2")?); assert!(network.on_critical_path("a4")?); assert!(network.on_critical_path("a6")?); assert!(network.on_critical_path("a8")?); assert!(!network.on_critical_path("a1")?); assert!(!network.on_critical_path("a3")?); assert!(!network.on_critical_path("a5")?); assert!(!network.on_critical_path("a7")?); test_calculations(&network, "a1", 0.0, 5.0, 1.0, 6.0, 5.0, 0.0)?; test_calculations(&network, "a2", 0.0, 0.0, 3.0, 3.0, 0.0, 0.0)?; test_calculations(&network, "a3", 1.0, 6.0, 3.0, 8.0, 5.0, 5.0)?; test_calculations(&network, "a4", 3.0, 3.0, 7.0, 7.0, 0.0, 0.0)?; test_calculations(&network, "a5", 3.0, 4.0, 5.0, 6.0, 1.0, 0.0)?; test_calculations(&network, "a6", 7.0, 7.0, 8.0, 8.0, 0.0, 0.0)?; test_calculations(&network, "a7", 5.0, 6.0, 7.0, 8.0, 1.0, 1.0)?; test_calculations(&network, "a8", 8.0, 8.0, 12.0, 12.0, 0.0, 0.0)?; Ok(()) } #[test] fn test_active_on() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a2", "a4")?; network_builder.connect("a3", "a4")?; let network = Network::try_from(network_builder)?; assert!(network.active_at("a1", 0.0)?); assert!(network.active_at("a1", 0.5)?); assert!(!network.active_at("a1", 1.0)?); assert!(network.active_at("a2", 1.0)?); assert!(network.active_at("a3", 1.0)?); assert!(!network.active_at("a2", 3.0)?); assert!(network.active_at("a3", 3.0)?); assert!(!network.active_at("a3", 4.0)?); assert!(network.active_at("a4", 4.0)?); assert!(!network.active_at("a4", 8.0)?); Ok(()) } #[test] fn test_during() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a1", "a3")?; network_builder.connect("a2", "a4")?; network_builder.connect("a3", "a4")?; let network = Network::try_from(network_builder)?; assert!(network.active_during("a1", 0.0..1.0)?); assert!(!network.active_during("a1", 1.0..2.0)?); assert!(network.active_during("a2", 1.0..2.0)?); assert!(network.active_during("a3", 1.0..2.0)?); Ok(()) } #[test] fn test_variance_standard_deviation() -> Result<()> { let mut network_builder = Network::builder(); network_builder.add_extended_activity( "a1", "a1", 1.0, 2.0, 4.0, StartType::Earliest, DurationType::Expected, )?; let network: Network = Network::try_from(network_builder)?; assert_eq!(0.25, network.variance("a1")?); assert_eq!(0.5, network.standard_deviation("a1")?); Ok(()) } #[test] fn test_to_builder() -> Result<()> { let mut network_builder = create_network_builder()?; for i in 1..7 { network_builder.connect(&format!("a{i}"), &format!("a{}", i + 1))?; } let network = Network::try_from(network_builder)?; let network_2 = Network::try_from(NetworkBuilder::from(&network))?; assert_eq!(network.start_activities()?, network_2.start_activities()?); assert_eq!(network.finish_activities()?, network_2.finish_activities()?); assert_eq!(network.activities()?, network_2.activities()?); for i in 1..7 { assert!(network.connected(&format!("a{i}"), &format!("a{}", i + 1))?); assert!(network_2.connected(&format!("a{i}"), &format!("a{}", i + 1))?); } Ok(()) } #[test] fn test_to_network_from_reference_to_network_builder() -> Result<()> { let mut network_builder = create_network_builder()?; for i in 1..7 { network_builder.connect(&format!("a{i}"), &format!("a{}", i + 1))?; } let network = Network::try_from(&mut network_builder)?; let network_2 = Network::try_from(&mut network_builder)?; assert_eq!(network.start_activities()?, network_2.start_activities()?); assert_eq!(network.finish_activities()?, network_2.finish_activities()?); assert_eq!(network.activities()?, network_2.activities()?); for i in 1..7 { assert!(network.connected(&format!("a{i}"), &format!("a{}", i + 1))?); assert!(network_2.connected(&format!("a{i}"), &format!("a{}", i + 1))?); } Ok(()) } #[test] fn test_updating_activity() -> Result<()> { let mut network_builder = create_network_builder()?; let network = Network::try_from(&mut network_builder)?; let updated_network = network.update_activity("a1", |activity_builder| { activity_builder.minimum_duration(2.0); activity_builder.expected_duration(2.0); activity_builder.maximum_duration(2.0); })?; assert_eq!(2.0, updated_network.earliest_finish("a1")?); Ok(()) } #[test] fn test_cycle_detection() -> Result<()> { let mut network_builder = create_network_builder()?; network_builder.connect("a1", "a2")?; network_builder.connect("a2", "a3")?; network_builder.connect("a3", "a1")?; match Network::try_from(network_builder) { Err(Error::CycleDetected) => (), Err(error) => panic!("Unexpected error: {:?}", error), Ok(_) => panic!("No cycle detected"), } Ok(()) }