#[cfg(test)] use std::collections::HashMap; extern crate env_logger; extern crate statechart; use statechart::*; #[test] fn blocked_indefinitely() { let st = state!{ S {} }; let ctx = Context::new(st); let mut it = Interpreter::new(); let result = it.run(&ctx); assert_eq!(result, Err(Fault::BlockedIndefinitely)); } #[test] fn transitions() { let ctx = Context::new(c123()); let st = ctx.root(); assert_eq!(st.node().id(), &vec![]); assert_eq!(st.node().substate("S1").unwrap().node().id(), &vec![0]); assert_eq!(st.node().substate("S2").unwrap().node().id(), &vec![1]); assert_eq!(st.node().substate("S3").unwrap().node().id(), &vec![2]); assert_eq!(st.node().substate("nonesuch"), None); assert_eq!(ctx.state_by_id(&vec![0]).unwrap().node().id(), &vec![0]); assert_eq!(ctx.state_by_id(&vec![1]).unwrap().node().id(), &vec![1]); assert_eq!(ctx.state_by_id(&vec![2]).unwrap().node().id(), &vec![2]); } #[test] fn goto() { let g = goto!(target: S1, topics: ["foo", "bar", "baz"]); assert_eq!(g, TransitionBuilder::default() .target_label(Some("S1".to_string())) .topics(["foo", "bar", "baz"].iter().map(|x| x.to_string()).collect()) .build() .unwrap()); } #[test] fn context() { let ctx = Context::new(c123()); assert_eq!(ctx.state("S1").unwrap().node().label(), "S1"); for ss in vec!["S1", "S2", "S3"] { assert_eq!(ctx.state_by_id(ctx.state(ss).unwrap().node().parent().unwrap()).unwrap().node().label(), "S"); } assert_eq!(ctx.state("S").unwrap().node().parent(), None); let mut it = Interpreter::new(); let result = it.run(&ctx); assert!(result.is_ok(), "{:?}", result.err().unwrap()); assert_eq!(result.unwrap(), Value::Object(HashMap::new())); } #[test] fn parallel() { let ctx = Context::new(phello()); let mut it = Interpreter::new(); let result = it.run(&ctx); assert!(result.is_ok(), "{:?}", result.err().unwrap()); assert_eq!(result.unwrap(), Value::Object(HashMap::new())); } #[test] fn parallel_final() { let ctx = Context::new(phellofinal()); let mut it = Interpreter::new(); let result = it.run(&ctx); assert!(result.is_ok(), "{:?}", result.err().unwrap()); assert_eq!(result.unwrap(), Value::Object(HashMap::new())); } #[test] fn parallel_swap() { let ctx = Context::new(pswap()); let mut it = Interpreter::new(); for _ in 0..100 { let result = it.step(&ctx); assert_eq!(result, Ok(Status::Runnable)); } } fn c123() -> State { let _ = env_logger::init(); states!{ S { substates: [ state!{ S1 { transitions: [goto!(target: S2)], on_entry: [action_log!(message: "hello s1")], }}, state!{ S2 { transitions: [goto!(target: S3)], on_entry: [action_log!(message: "hello s2")], }}, final_state!{ S3 { on_entry: [action_log!(message: "hello s3")], on_exit: [action_log!(message: "and goodbye now")], }}, ]}} } fn phello() -> State { let _ = env_logger::init(); states!{ S { substates: [ parallel!{ P { substates: [ state!{ S1 { transitions: [goto!(target: SF)], on_entry: [action_log!(message: "hello s1")], }}, state!{ S2 { on_entry: [action_log!(message: "hello s2")], }}, state!{ S3 { on_entry: [action_log!(message: "hello s3")], }}, ]}}, final_state!{ SF { on_exit: [action_log!(message: "goodbye now")], }}, ]}} } fn phellofinal() -> State { let _ = env_logger::init(); states!{ S { substates: [ parallel!{ P { substates: [ state!{ S1 { on_entry: [action_log!(message: "hello s1")], }}, state!{ S2 { on_entry: [action_log!(message: "hello s2")], }}, state!{ S3 { on_entry: [action_log!(message: "hello s3")], }}, final_state!{ SF { on_entry: [action_log!(message: "hello sf")], on_exit: [action_log!(message: "goodbye now")], }}, ]}}, ]}} } fn pswap() -> State { let _ = env_logger::init(); states!{ S { substates: [ parallel!{ P { substates: [ state!{ S1 { on_entry: [action_log!(message: "s1 wants to be an s2")], transitions: [goto!(target: S2)], }}, state!{ S2 { on_entry: [action_log!(message: "s2 wants to be an s1")], transitions: [goto!(target: S1)], }}, ]}}, ]}} }