mirror of https://github.com/rust-lang/rust.git
178 lines
3.8 KiB
Rust
178 lines
3.8 KiB
Rust
//@ 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: 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();
|
|
}
|