]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/vector-sort-failure-safe.rs
create a sensible comparison trait hierarchy
[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, Eq, Ord, TotalEq, TotalOrd)]
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_vec::<DropCounter>(len);
48
49             // work out the total number of comparisons required to sort
50             // this array...
51             let mut count = 0;
52             main.clone().sort_by(|a, b| { count += 1; a.cmp(b) });
53
54             // ... and then fail on each and every single one.
55             for fail_countdown in range(0, count) {
56                 // refresh the counters.
57                 unsafe {
58                     drop_counts = [0, .. MAX_LEN];
59                     clone_count = 0;
60                 }
61
62                 let v = main.clone();
63
64                 task::try(proc() {
65                         let mut v = v;
66                         let mut fail_countdown = fail_countdown;
67                         v.sort_by(|a, b| {
68                                 if fail_countdown == 0 {
69                                     fail!()
70                                 }
71                                 fail_countdown -= 1;
72                                 a.cmp(b)
73                             })
74                     });
75
76                 // check that the number of things dropped is exactly
77                 // what we expect (i.e. the contents of `v`).
78                 unsafe {
79                     for (i, &c) in drop_counts.iter().enumerate() {
80                         let expected = if i < len {1} else {0};
81                         assert!(c == expected,
82                                 "found drop count == {} for i == {}, len == {}",
83                                 c, i, len);
84                     }
85                 }
86             }
87         }
88     }
89 }