use crossmist::{ channel, duplex, static_ref, BindValue, Duplex, FnOnceObject, Object, Receiver, Sender, StaticRef, }; #[ctor::ctor] fn ctor() { crossmist::init(); } #[derive(Debug, PartialEq, Object)] struct SimplePair { x: i32, y: i32, } #[test] fn simple() { #[crossmist::func] fn inner() -> i64 { 0x123456789abcdef } assert_eq!(inner.run().unwrap(), 0x123456789abcdef); } #[test] fn ret_string() { #[crossmist::func] fn inner() -> String { "hello".to_string() } assert_eq!(inner.spawn().unwrap().join().unwrap(), "hello"); } #[crossmist::func] fn add_with_arguments_impl(x: i32, y: i32) -> i32 { x + y } #[test] fn add_with_arguments_spawn() { assert_eq!( add_with_arguments_impl.spawn(5, 7).unwrap().join().unwrap(), 12 ); } #[test] fn add_with_arguments_call() { assert_eq!(add_with_arguments_impl.call_object_once((5, 7)), 12); #[cfg(feature = "nightly")] assert_eq!(add_with_arguments_impl(5, 7), 12); } #[test] fn add_with_template() { #[crossmist::func] fn inner + Object + 'static>(x: T, y: T) -> T { x + y } assert_eq!(inner.spawn(5, 7).unwrap().join().unwrap(), 12); } #[test] fn swap_complex_argument() { #[crossmist::func] fn inner(pair: SimplePair) -> SimplePair { SimplePair { x: pair.y, y: pair.x, } } assert_eq!( inner .spawn(SimplePair { x: 5, y: 7 }) .unwrap() .join() .unwrap(), SimplePair { x: 7, y: 5 } ); } #[test] fn inc_with_boxed() { #[crossmist::func] fn inner(item: Box) -> Box { Box::new(*item + 1) } assert_eq!(*inner.spawn(Box::new(7)).unwrap().join().unwrap(), 8); } #[test] fn inc_with_vec_and_box() { #[crossmist::func] fn inner(vec: Vec, box_: Box<[i32]>) -> (i32, i32) { (vec.iter().sum(), box_.iter().sum()) } assert_eq!( inner .spawn(vec![1, 2, 3], Box::new([4, 5, 6])) .unwrap() .join() .unwrap(), (6, 15) ); } trait Trait: Object { fn say(&self) -> String; } #[derive(Object)] struct ImplA(String); #[derive(Object)] struct ImplB(i32); impl Trait for ImplA { fn say(&self) -> String { format!("ImplA says: {}", self.0) } } impl Trait for ImplB { fn say(&self) -> String { format!("ImplB says: {}", self.0) } } impl Trait for bool { fn say(&self) -> String { format!("bool says: {}", self) } } #[test] fn with_passed_trait() { #[crossmist::func] fn inner(arg: Box) -> String { arg.say() } assert_eq!( inner .spawn(Box::new(ImplA("hello".to_string()))) .unwrap() .join() .unwrap(), "ImplA says: hello" ); assert_eq!( inner.spawn(Box::new(ImplB(5))).unwrap().join().unwrap(), "ImplB says: 5" ); assert_eq!( inner.spawn(Box::new(true)).unwrap().join().unwrap(), "bool says: true" ); } #[test] fn with_passed_fn() { #[crossmist::func] fn inner(func: Box>) -> i32 { #[cfg(feature = "nightly")] { func(5, 7) } #[cfg(not(feature = "nightly"))] { func.call_object_once((5, 7)) } } assert_eq!( inner .spawn(Box::new(add_with_arguments_impl)) .unwrap() .join() .unwrap(), 12 ); } #[test] fn with_passed_bound_fn() { #[crossmist::func] fn inner(func: Box>) -> i32 { #[cfg(feature = "nightly")] { func(7) } #[cfg(not(feature = "nightly"))] { func.call_object_once((7,)) } } assert_eq!( inner .spawn(Box::new(add_with_arguments_impl.bind_value(5))) .unwrap() .join() .unwrap(), 12 ); } #[test] fn with_passed_double_bound_fn() { #[crossmist::func] fn inner(func: Box>) -> i32 { #[cfg(feature = "nightly")] { func() } #[cfg(not(feature = "nightly"))] { func.call_object_once(()) } } assert_eq!( inner .spawn(Box::new( add_with_arguments_impl.bind_value(5).bind_value(7) )) .unwrap() .join() .unwrap(), 12 ); } #[test] fn with_passed_rx() { #[crossmist::func] fn inner(mut rx: Receiver) -> i32 { let a = rx.recv().unwrap().unwrap(); let b = rx.recv().unwrap().unwrap(); a - b } let (mut tx, rx) = channel::().unwrap(); let child = inner.spawn(rx).unwrap(); tx.send(&5).unwrap(); tx.send(&7).unwrap(); assert_eq!(child.join().unwrap(), -2); } #[test] fn with_passed_tx() { #[crossmist::func] fn inner(mut tx: Sender) { tx.send(&5).unwrap(); tx.send(&7).unwrap(); } let (tx, mut rx) = channel::().unwrap(); let child = inner.spawn(tx).unwrap(); assert_eq!( rx.recv().unwrap().unwrap() - rx.recv().unwrap().unwrap(), -2 ); child.join().unwrap(); } #[test] fn with_passed_duplex() { #[crossmist::func] fn inner(mut chan: Duplex) { while let Some((x, y)) = chan.recv().unwrap() { chan.send(&(x - y)).unwrap(); } } let (mut local, downstream) = duplex::<(i32, i32), i32>().unwrap(); let child = inner.spawn(downstream).unwrap(); for (x, y) in [(5, 7), (100, -1), (53, 2354)] { local.send(&(x, y)).unwrap(); assert_eq!(local.recv().unwrap().unwrap(), x - y); } drop(local); child.join().unwrap(); } #[test] fn with_passed_nested_channel() { #[crossmist::func] fn inner(mut chan: Receiver>) -> i32 { let mut chan1 = chan.recv().unwrap().unwrap(); chan1.recv().unwrap().unwrap() } let (mut tx, rx) = channel::().unwrap(); let (mut tx1, rx1) = channel::>().unwrap(); tx.send(&5).unwrap(); tx1.send(&rx).unwrap(); assert_eq!(inner.run(rx1).unwrap(), 5); } #[test] fn exitting() { #[crossmist::func] fn inner() { std::process::exit(0); } assert_eq!(inner.run().unwrap(), ()); } #[test] fn with_static_ref() { #[crossmist::func] fn inner(a: StaticRef<&'static str>) -> String { a.to_string() } assert_eq!( inner .run(static_ref!(&'static str, &"Hello, world!")) .unwrap(), "Hello, world!" ); }