rust/tests/ui/coroutine/smoke.rs
Alex Crichton 75fa9f6dec compiletest: Add a //@ needs-threads directive
This commit is extracted from #122036 and adds a new directive to the
`compiletest` test runner, `//@ needs-threads`. This is intended to
capture the need that a target must implement threading to execute a
specific test, typically one that uses `std::thread`. This is primarily
done for WebAssembly targets which currently do not have threads by
default. This enables transitioning a lot of `//@ ignore-wasm*`-style
ignores into a more self-documenting `//@ needs-threads` directive.
Additionally the `wasm32-wasi-preview1-threads` target, for example,
does actually have threads, but isn't tested in CI at this time. This
change enables running these tests for that target, but not other wasm
targets.
2024-03-06 12:35:07 -08:00

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();
}