]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/vector-sort-panic-safe.rs
Merge pull request #20510 from tshepang/patch-6
[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::{AtomicUint, ATOMIC_UINT_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: [AtomicUint;  MAX_LEN] =
18     // FIXME #5244: AtomicUint is not Copy.
19     [
20         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
21         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
22         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
23         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
24
25         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
26         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
27         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
28         ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
29      ];
30
31 static creation_count: AtomicUint = ATOMIC_UINT_INIT;
32
33 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
34 struct DropCounter { x: uint, creation_id: uint }
35
36 impl Rand for DropCounter {
37     fn rand<R: Rng>(rng: &mut R) -> DropCounter {
38         // (we're not using this concurrently, so Relaxed is fine.)
39         let num = creation_count.fetch_add(1, Ordering::Relaxed);
40         DropCounter {
41             x: rng.gen(),
42             creation_id: num
43         }
44     }
45 }
46
47 impl Drop for DropCounter {
48     fn drop(&mut self) {
49         drop_counts[self.creation_id].fetch_add(1, Ordering::Relaxed);
50     }
51 }
52
53 pub fn main() {
54     assert!(MAX_LEN <= std::uint::BITS);
55     // len can't go above 64.
56     for len in range(2, MAX_LEN) {
57         for _ in range(0, REPEATS) {
58             // reset the count for these new DropCounters, so their
59             // IDs start from 0.
60             creation_count.store(0, Ordering::Relaxed);
61
62             let main = thread_rng().gen_iter::<DropCounter>()
63                                  .take(len)
64                                  .collect::<Vec<DropCounter>>();
65
66             // work out the total number of comparisons required to sort
67             // this array...
68             let mut count = 0;
69             main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });
70
71             // ... and then panic on each and every single one.
72             for panic_countdown in range(0i, count) {
73                 // refresh the counters.
74                 for c in drop_counts.iter() {
75                     c.store(0, Ordering::Relaxed);
76                 }
77
78                 let v = main.clone();
79
80                 let _ = Thread::spawn(move|| {
81                     let mut v = v;
82                     let mut panic_countdown = panic_countdown;
83                     v.as_mut_slice().sort_by(|a, b| {
84                         if panic_countdown == 0 {
85                             panic!()
86                         }
87                         panic_countdown -= 1;
88                         a.cmp(b)
89                     })
90                 }).join();
91
92                 // check that the number of things dropped is exactly
93                 // what we expect (i.e. the contents of `v`).
94                 for (i, c) in drop_counts.iter().enumerate().take(len) {
95                     let count = c.load(Ordering::Relaxed);
96                     assert!(count == 1,
97                             "found drop count == {} for i == {}, len == {}",
98                             count, i, len);
99                 }
100             }
101         }
102     }
103 }