Add some generator pass/fail tests
This commit is contained in:
parent
51bb31ad25
commit
5efb0cbe04
8 changed files with 508 additions and 0 deletions
32
src/test/compile-fail/generator/borrowing.rs
Normal file
32
src/test/compile-fail/generator/borrowing.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{State, Generator};
|
||||
use std::cell::Cell;
|
||||
|
||||
fn main() {
|
||||
let _b = {
|
||||
let a = 3;
|
||||
(|| yield &a).resume(())
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
};
|
||||
|
||||
let _b = {
|
||||
let a = 3;
|
||||
|| {
|
||||
let _: () = gen arg; // TODO: shouldn't be needed for inference
|
||||
yield &a
|
||||
//~^ ERROR: `a` does not live long enough
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
34
src/test/compile-fail/generator/not-send-sync.rs
Normal file
34
src/test/compile-fail/generator/not-send-sync.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{State, Generator};
|
||||
use std::cell::Cell;
|
||||
|
||||
fn main() {
|
||||
fn assert_sync<T: Sync>(_: T) {}
|
||||
fn assert_send<T: Send>(_: T) {}
|
||||
|
||||
assert_sync(|| {
|
||||
//~^ ERROR: Sync` is not satisfied
|
||||
let a = Cell::new(2);
|
||||
yield;
|
||||
let _: () = gen arg;
|
||||
});
|
||||
|
||||
let a = Cell::new(2);
|
||||
assert_send(|| {
|
||||
//~^ ERROR: Sync` is not satisfied
|
||||
drop(&a);
|
||||
yield;
|
||||
let _: () = gen arg;
|
||||
});
|
||||
}
|
||||
56
src/test/run-pass/generator/control-flow.rs
Normal file
56
src/test/run-pass/generator/control-flow.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{State, Generator};
|
||||
|
||||
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
|
||||
where T: Generator<(), Yield = ()>
|
||||
{
|
||||
loop {
|
||||
match t.resume(()) {
|
||||
State::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
|
||||
State::Complete(ret) => {
|
||||
assert_eq!(amt, 0);
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
finish(1, || yield);
|
||||
finish(8, || {
|
||||
for _ in 0..8 {
|
||||
yield;
|
||||
}
|
||||
});
|
||||
finish(1, || {
|
||||
if true {
|
||||
yield;
|
||||
} else {
|
||||
}
|
||||
});
|
||||
finish(1, || {
|
||||
if false {
|
||||
} else {
|
||||
yield;
|
||||
}
|
||||
});
|
||||
finish(2, || {
|
||||
if { yield; false } {
|
||||
yield;
|
||||
panic!()
|
||||
}
|
||||
yield
|
||||
});
|
||||
}
|
||||
73
src/test/run-pass/generator/drop-env.rs
Normal file
73
src/test/run-pass/generator/drop-env.rs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
|
||||
static A: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
struct B;
|
||||
|
||||
impl Drop for B {
|
||||
fn drop(&mut self) {
|
||||
A.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
t1();
|
||||
t2();
|
||||
t3();
|
||||
}
|
||||
|
||||
fn t1() {
|
||||
let b = B;
|
||||
let mut foo = || {
|
||||
yield;
|
||||
drop(b);
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(foo.resume(()));
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
drop(foo);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
||||
fn t2() {
|
||||
let b = B;
|
||||
let mut foo = || {
|
||||
yield b;
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
drop(foo.resume(()));
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
drop(foo);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
}
|
||||
|
||||
fn t3() {
|
||||
let b = B;
|
||||
let mut foo = || {
|
||||
let _: () = gen arg; // TODO: this line should not be necessary
|
||||
yield;
|
||||
drop(b);
|
||||
};
|
||||
|
||||
let n = A.load(Ordering::SeqCst);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
drop(foo);
|
||||
// TODO: we should assert n+1 here, not n
|
||||
// assert_eq!(A.load(Ordering::SeqCst), n + 1);
|
||||
assert_eq!(A.load(Ordering::SeqCst), n);
|
||||
}
|
||||
58
src/test/run-pass/generator/panic-drops.rs
Normal file
58
src/test/run-pass/generator/panic-drops.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::panic;
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
|
||||
static A: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
struct B;
|
||||
|
||||
impl Drop for B {
|
||||
fn drop(&mut self) {
|
||||
A.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = B;
|
||||
let mut foo = || {
|
||||
if true {
|
||||
panic!();
|
||||
}
|
||||
drop(b);
|
||||
yield;
|
||||
};
|
||||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 0);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
foo.resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
|
||||
let mut foo = || {
|
||||
if true {
|
||||
panic!();
|
||||
}
|
||||
drop(B);
|
||||
yield;
|
||||
};
|
||||
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
foo.resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
assert_eq!(A.load(Ordering::SeqCst), 1);
|
||||
}
|
||||
35
src/test/run-pass/generator/panic-safe.rs
Normal file
35
src/test/run-pass/generator/panic-safe.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::Generator;
|
||||
use std::panic;
|
||||
|
||||
fn main() {
|
||||
let mut foo = || {
|
||||
if true {
|
||||
panic!();
|
||||
}
|
||||
yield;
|
||||
};
|
||||
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
foo.resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
|
||||
for _ in 0..10 {
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
foo.resume(())
|
||||
}));
|
||||
assert!(res.is_err());
|
||||
}
|
||||
}
|
||||
33
src/test/run-pass/generator/resume-after-return.rs
Normal file
33
src/test/run-pass/generator/resume-after-return.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{State, Generator};
|
||||
use std::panic;
|
||||
|
||||
fn main() {
|
||||
let mut foo = || {
|
||||
if true {
|
||||
return
|
||||
}
|
||||
yield;
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
|
||||
match panic::catch_unwind(move || foo.resume(())) {
|
||||
Ok(_) => panic!("generator successfully resumed"),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
187
src/test/run-pass/generator/smoke.rs
Normal file
187
src/test/run-pass/generator/smoke.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --test
|
||||
|
||||
#![feature(generators, generator_trait)]
|
||||
|
||||
use std::ops::{State, Generator};
|
||||
use std::thread;
|
||||
|
||||
#[test]
|
||||
fn simple() {
|
||||
let mut foo = || {
|
||||
if false {
|
||||
yield;
|
||||
}
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_capture() {
|
||||
let a = String::from("foo");
|
||||
let mut foo = || {
|
||||
if false {
|
||||
yield;
|
||||
}
|
||||
a
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_yield() {
|
||||
let mut foo = || {
|
||||
yield;
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_capture() {
|
||||
let b = String::from("foo");
|
||||
let mut foo = || {
|
||||
yield b;
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Yielded(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_yield_value() {
|
||||
let mut foo = || {
|
||||
yield String::from("bar");
|
||||
return String::from("foo")
|
||||
};
|
||||
|
||||
match foo.resume(()) {
|
||||
State::Yielded(ref s) if *s == "bar" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::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 foo.resume(()) {
|
||||
State::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::Complete(ref s) if *s == "foo" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_and_sync() {
|
||||
assert_send_sync(|| {
|
||||
let _: () = gen arg;
|
||||
yield
|
||||
});
|
||||
assert_send_sync(|| {
|
||||
let _: () = gen arg;
|
||||
yield String::from("foo");
|
||||
});
|
||||
assert_send_sync(|| {
|
||||
let _: () = gen arg;
|
||||
yield;
|
||||
return String::from("foo");
|
||||
});
|
||||
let a = 3;
|
||||
assert_send_sync(|| {
|
||||
let _: () = gen arg;
|
||||
yield a;
|
||||
return
|
||||
});
|
||||
let a = 3;
|
||||
assert_send_sync(move || {
|
||||
let _: () = gen arg;
|
||||
yield a;
|
||||
return
|
||||
});
|
||||
let a = String::from("a");
|
||||
assert_send_sync(|| {
|
||||
let _: () = gen arg;
|
||||
yield ;
|
||||
drop(a);
|
||||
return
|
||||
});
|
||||
let a = String::from("a");
|
||||
assert_send_sync(move || {
|
||||
let _: () = gen arg;
|
||||
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 foo.resume(()) {
|
||||
State::Yielded(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}).join().unwrap();
|
||||
|
||||
let a = String::from("a");
|
||||
let mut foo = || { yield a };
|
||||
thread::spawn(move || {
|
||||
match foo.resume(()) {
|
||||
State::Yielded(ref s) if *s == "a" => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
match foo.resume(()) {
|
||||
State::Complete(()) => {}
|
||||
s => panic!("bad state: {:?}", s),
|
||||
}
|
||||
}).join().unwrap();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue