//@ run-pass //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 //@ needs-threads //@ compile-flags: --test #![feature(coroutines, coroutine_trait)] use std::ops::{CoroutineState, Coroutine}; use std::pin::Pin; use std::thread; #[test] fn simple() { let mut foo = || { if false { yield; } }; match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(()) => {} s => panic!("bad state: {:?}", s), } } #[test] fn return_capture() { let a = String::from("foo"); let mut foo = || { if false { yield; } a }; match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } } #[test] fn simple_yield() { let mut foo = || { yield; }; match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(()) => {} s => panic!("bad state: {:?}", s), } } #[test] fn yield_capture() { let b = String::from("foo"); let mut foo = || { yield b; }; match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(()) => {} s => panic!("bad state: {:?}", s), } } #[test] fn simple_yield_value() { let mut foo = || { yield String::from("bar"); return String::from("foo") }; match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(ref s) if *s == "bar" => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } } #[test] fn return_after_yield() { let a = String::from("foo"); let mut foo = || { yield; return a }; match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(ref s) if *s == "foo" => {} s => panic!("bad state: {:?}", s), } } #[test] fn send_and_sync() { assert_send_sync(|| { yield }); assert_send_sync(|| { yield String::from("foo"); }); assert_send_sync(|| { yield; return String::from("foo"); }); let a = 3; assert_send_sync(|| { yield a; return }); let a = 3; assert_send_sync(move || { yield a; return }); let a = String::from("a"); assert_send_sync(|| { yield ; drop(a); return }); let a = String::from("a"); assert_send_sync(move || { yield ; drop(a); return }); fn assert_send_sync(_: T) {} } #[test] fn send_over_threads() { let mut foo = || { yield }; thread::spawn(move || { match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(()) => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(()) => {} s => panic!("bad state: {:?}", s), } }).join().unwrap(); let a = String::from("a"); let mut foo = || { yield a }; thread::spawn(move || { match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(ref s) if *s == "a" => {} s => panic!("bad state: {:?}", s), } match Pin::new(&mut foo).resume(()) { CoroutineState::Complete(()) => {} s => panic!("bad state: {:?}", s), } }).join().unwrap(); }