]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/vector-sort-failure-safe.rs
2575e53b6a3bbdaefe8116488b8bd35846c1896b
[rust.git] / src / test / run-pass / vector-sort-failure-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::task;
12 use std::rand::{task_rng, Rng};
13
14 static MAX_LEN: uint = 20;
15 static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
16 static mut clone_count: uint = 0;
17
18 #[deriving(Rand, PartialEq, PartialOrd, Eq, Ord)]
19 struct DropCounter { x: uint, clone_num: uint }
20
21 impl Clone for DropCounter {
22     fn clone(&self) -> DropCounter {
23         let num = unsafe { clone_count };
24         unsafe { clone_count += 1; }
25         DropCounter {
26             x: self.x,
27             clone_num: num
28         }
29     }
30 }
31
32 impl Drop for DropCounter {
33     fn drop(&mut self) {
34         unsafe {
35             // Rand creates some with arbitrary clone_nums
36             if self.clone_num < MAX_LEN {
37                 drop_counts[self.clone_num] += 1;
38             }
39         }
40     }
41 }
42
43 pub fn main() {
44     // len can't go above 64.
45     for len in range(2u, MAX_LEN) {
46         for _ in range(0, 10) {
47             let main = task_rng().gen_iter::<DropCounter>()
48                                  .take(len)
49                                  .collect::<Vec<DropCounter>>();
50
51             // work out the total number of comparisons required to sort
52             // this array...
53             let mut count = 0;
54             main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });
55
56             // ... and then fail on each and every single one.
57             for fail_countdown in range(0, count) {
58                 // refresh the counters.
59                 unsafe {
60                     drop_counts = [0, .. MAX_LEN];
61                     clone_count = 0;
62                 }
63
64                 let v = main.clone();
65
66                 task::try(proc() {
67                         let mut v = v;
68                         let mut fail_countdown = fail_countdown;
69                         v.as_mut_slice().sort_by(|a, b| {
70                                 if fail_countdown == 0 {
71                                     fail!()
72                                 }
73                                 fail_countdown -= 1;
74                                 a.cmp(b)
75                             })
76                     });
77
78                 // check that the number of things dropped is exactly
79                 // what we expect (i.e. the contents of `v`).
80                 unsafe {
81                     for (i, &c) in drop_counts.iter().enumerate() {
82                         let expected = if i < len {1} else {0};
83                         assert!(c == expected,
84                                 "found drop count == {} for i == {}, len == {}",
85                                 c, i, len);
86                     }
87                 }
88             }
89         }
90     }
91 }