]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/vector-sort-panic-safe.rs
cleanup: s/impl Copy/#[derive(Copy)]/g
[rust.git] / src / test / run-pass / vector-sort-panic-safe.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
12 use std::rand::{thread_rng, Rng, Rand};
13 use std::thread::Thread;
14
15 const REPEATS: uint = 5;
16 const MAX_LEN: uint = 32;
17 static drop_counts: [AtomicUsize;  MAX_LEN] =
18     // FIXME #5244: AtomicUsize is not Copy.
19     [
20         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
21         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
22         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
23         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
24         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
25         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
26         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
27         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
28         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
29         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
30         ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
31      ];
32
33 static creation_count: AtomicUsize = ATOMIC_USIZE_INIT;
34
35 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
36 struct DropCounter { x: uint, creation_id: uint }
37
38 impl Rand for DropCounter {
39     fn rand<R: Rng>(rng: &mut R) -> DropCounter {
40         // (we're not using this concurrently, so Relaxed is fine.)
41         let num = creation_count.fetch_add(1, Ordering::Relaxed);
42         DropCounter {
43             x: rng.gen(),
44             creation_id: num
45         }
46     }
47 }
48
49 impl Drop for DropCounter {
50     fn drop(&mut self) {
51         drop_counts[self.creation_id].fetch_add(1, Ordering::Relaxed);
52     }
53 }
54
55 pub fn main() {
56     assert!(MAX_LEN <= std::uint::BITS);
57     // len can't go above 64.
58     for len in range(2, MAX_LEN) {
59         for _ in range(0, REPEATS) {
60             // reset the count for these new DropCounters, so their
61             // IDs start from 0.
62             creation_count.store(0, Ordering::Relaxed);
63
64             let main = thread_rng().gen_iter::<DropCounter>()
65                                  .take(len)
66                                  .collect::<Vec<DropCounter>>();
67
68             // work out the total number of comparisons required to sort
69             // this array...
70             let mut count = 0;
71             main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });
72
73             // ... and then panic on each and every single one.
74             for panic_countdown in range(0i, count) {
75                 // refresh the counters.
76                 for c in drop_counts.iter() {
77                     c.store(0, Ordering::Relaxed);
78                 }
79
80                 let v = main.clone();
81
82                 let _ = Thread::scoped(move|| {
83                     let mut v = v;
84                     let mut panic_countdown = panic_countdown;
85                     v.as_mut_slice().sort_by(|a, b| {
86                         if panic_countdown == 0 {
87                             panic!()
88                         }
89                         panic_countdown -= 1;
90                         a.cmp(b)
91                     })
92                 }).join();
93
94                 // check that the number of things dropped is exactly
95                 // what we expect (i.e. the contents of `v`).
96                 for (i, c) in drop_counts.iter().enumerate().take(len) {
97                     let count = c.load(Ordering::Relaxed);
98                     assert!(count == 1,
99                             "found drop count == {} for i == {}, len == {}",
100                             count, i, len);
101                 }
102             }
103         }
104     }
105 }