about summary refs log tree commit diff
path: root/src/test/run-pass
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-07-07 16:12:44 -0700
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2017-07-28 15:46:23 +0200
commit5efb0cbe046127d074fd2c85b7cafb5a4d5aea44 (patch)
tree6736bbaf8eac112a672735fcbb0106d1ecea624b /src/test/run-pass
parent51bb31ad2551c0bf82a556792303ec1de5b76dbc (diff)
downloadrust-5efb0cbe046127d074fd2c85b7cafb5a4d5aea44.tar.gz
rust-5efb0cbe046127d074fd2c85b7cafb5a4d5aea44.zip
Add some generator pass/fail tests
Diffstat (limited to 'src/test/run-pass')
-rw-r--r--src/test/run-pass/generator/control-flow.rs56
-rw-r--r--src/test/run-pass/generator/drop-env.rs73
-rw-r--r--src/test/run-pass/generator/panic-drops.rs58
-rw-r--r--src/test/run-pass/generator/panic-safe.rs35
-rw-r--r--src/test/run-pass/generator/resume-after-return.rs33
-rw-r--r--src/test/run-pass/generator/smoke.rs187
6 files changed, 442 insertions, 0 deletions
diff --git a/src/test/run-pass/generator/control-flow.rs b/src/test/run-pass/generator/control-flow.rs
new file mode 100644
index 00000000000..911bb96b582
--- /dev/null
+++ b/src/test/run-pass/generator/control-flow.rs
@@ -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
+    });
+}
diff --git a/src/test/run-pass/generator/drop-env.rs b/src/test/run-pass/generator/drop-env.rs
new file mode 100644
index 00000000000..43d0af7a073
--- /dev/null
+++ b/src/test/run-pass/generator/drop-env.rs
@@ -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);
+}
diff --git a/src/test/run-pass/generator/panic-drops.rs b/src/test/run-pass/generator/panic-drops.rs
new file mode 100644
index 00000000000..6b9d7da197f
--- /dev/null
+++ b/src/test/run-pass/generator/panic-drops.rs
@@ -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);
+}
diff --git a/src/test/run-pass/generator/panic-safe.rs b/src/test/run-pass/generator/panic-safe.rs
new file mode 100644
index 00000000000..7d86d7b6d94
--- /dev/null
+++ b/src/test/run-pass/generator/panic-safe.rs
@@ -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());
+    }
+}
diff --git a/src/test/run-pass/generator/resume-after-return.rs b/src/test/run-pass/generator/resume-after-return.rs
new file mode 100644
index 00000000000..ca85d2545c8
--- /dev/null
+++ b/src/test/run-pass/generator/resume-after-return.rs
@@ -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(_) => {}
+    }
+}
diff --git a/src/test/run-pass/generator/smoke.rs b/src/test/run-pass/generator/smoke.rs
new file mode 100644
index 00000000000..daa32aa3213
--- /dev/null
+++ b/src/test/run-pass/generator/smoke.rs
@@ -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();
+}