Add some generator pass/fail tests

This commit is contained in:
Alex Crichton 2017-07-07 16:12:44 -07:00 committed by John Kåre Alsaker
parent 51bb31ad25
commit 5efb0cbe04
8 changed files with 508 additions and 0 deletions

View 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
}
};
}

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

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

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

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

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

View 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(_) => {}
}
}

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