1 use std::cmp::Ord;
2 use std::collections::hash_map::DefaultHasher;
3 use std::collections::{HashMap, HashSet};
4 use std::ffi::CString;
5 use std::hash::BuildHasherDefault;
6 use std::path::PathBuf;
7
8 use super::{quickcheck, Gen, QuickCheck, TestResult};
9
10 #[test]
11 #[cfg(not(target_os = "android"))]
prop_oob()12 fn prop_oob() {
13 fn prop() -> bool {
14 let zero: Vec<bool> = vec![];
15 zero[0]
16 }
17 match QuickCheck::new().quicktest(prop as fn() -> bool) {
18 Ok(n) => panic!(
19 "prop_oob should fail with a runtime error \
20 but instead it passed {} tests.",
21 n
22 ),
23 _ => return,
24 }
25 }
26
27 #[test]
prop_reverse_reverse()28 fn prop_reverse_reverse() {
29 fn prop(xs: Vec<usize>) -> bool {
30 let rev: Vec<_> = xs.clone().into_iter().rev().collect();
31 let revrev: Vec<_> = rev.into_iter().rev().collect();
32 xs == revrev
33 }
34 quickcheck(prop as fn(Vec<usize>) -> bool);
35 }
36
37 quickcheck! {
38 fn prop_reverse_reverse_macro(xs: Vec<usize>) -> bool {
39 let rev: Vec<_> = xs.clone().into_iter().rev().collect();
40 let revrev: Vec<_> = rev.into_iter().rev().collect();
41 xs == revrev
42 }
43
44 #[should_panic]
45 fn prop_macro_panic(_x: u32) -> bool {
46 assert!(false);
47 false
48 }
49 }
50
51 #[test]
reverse_single()52 fn reverse_single() {
53 fn prop(xs: Vec<usize>) -> TestResult {
54 if xs.len() != 1 {
55 TestResult::discard()
56 } else {
57 TestResult::from_bool(
58 xs == xs.clone().into_iter().rev().collect::<Vec<_>>(),
59 )
60 }
61 }
62 quickcheck(prop as fn(Vec<usize>) -> TestResult);
63 }
64
65 #[test]
reverse_app()66 fn reverse_app() {
67 fn prop(xs: Vec<usize>, ys: Vec<usize>) -> bool {
68 let mut app = xs.clone();
69 app.extend(ys.iter().cloned());
70 let app_rev: Vec<usize> = app.into_iter().rev().collect();
71
72 let rxs: Vec<usize> = xs.into_iter().rev().collect();
73 let mut rev_app = ys.into_iter().rev().collect::<Vec<usize>>();
74 rev_app.extend(rxs.into_iter());
75
76 app_rev == rev_app
77 }
78 quickcheck(prop as fn(Vec<usize>, Vec<usize>) -> bool);
79 }
80
81 #[test]
max()82 fn max() {
83 fn prop(x: isize, y: isize) -> TestResult {
84 if x > y {
85 TestResult::discard()
86 } else {
87 TestResult::from_bool(::std::cmp::max(x, y) == y)
88 }
89 }
90 quickcheck(prop as fn(isize, isize) -> TestResult);
91 }
92
93 #[test]
sort()94 fn sort() {
95 fn prop(mut xs: Vec<isize>) -> bool {
96 xs.sort_by(|x, y| x.cmp(y));
97 for i in xs.windows(2) {
98 if i[0] > i[1] {
99 return false;
100 }
101 }
102 true
103 }
104 quickcheck(prop as fn(Vec<isize>) -> bool);
105 }
106
sieve(n: usize) -> Vec<usize>107 fn sieve(n: usize) -> Vec<usize> {
108 if n <= 1 {
109 return vec![];
110 }
111
112 let mut marked = vec![false; n + 1];
113 marked[0] = true;
114 marked[1] = true;
115 marked[2] = true;
116 for p in 2..n {
117 for i in (2 * p..n).filter(|&n| n % p == 0) {
118 marked[i] = true;
119 }
120 }
121 marked
122 .iter()
123 .enumerate()
124 .filter_map(|(i, &m)| if m { None } else { Some(i) })
125 .collect()
126 }
127
is_prime(n: usize) -> bool128 fn is_prime(n: usize) -> bool {
129 n != 0 && n != 1 && (2..).take_while(|i| i * i <= n).all(|i| n % i != 0)
130 }
131
132 #[test]
133 #[should_panic]
sieve_not_prime()134 fn sieve_not_prime() {
135 fn prop_all_prime(n: u8) -> bool {
136 sieve(n as usize).into_iter().all(is_prime)
137 }
138 quickcheck(prop_all_prime as fn(u8) -> bool);
139 }
140
141 #[test]
142 #[should_panic]
sieve_not_all_primes()143 fn sieve_not_all_primes() {
144 fn prop_prime_iff_in_the_sieve(n: u8) -> bool {
145 let n = n as usize;
146 sieve(n) == (0..(n + 1)).filter(|&i| is_prime(i)).collect::<Vec<_>>()
147 }
148 quickcheck(prop_prime_iff_in_the_sieve as fn(u8) -> bool);
149 }
150
151 #[test]
testable_result()152 fn testable_result() {
153 fn result() -> Result<bool, String> {
154 Ok(true)
155 }
156 quickcheck(result as fn() -> Result<bool, String>);
157 }
158
159 #[test]
160 #[should_panic]
testable_result_err()161 fn testable_result_err() {
162 quickcheck(Err::<bool, i32> as fn(i32) -> Result<bool, i32>);
163 }
164
165 #[test]
testable_unit()166 fn testable_unit() {
167 fn do_nothing() {}
168 quickcheck(do_nothing as fn());
169 }
170
171 #[test]
172 #[cfg(not(target_os = "android"))]
testable_unit_panic()173 fn testable_unit_panic() {
174 fn panic() {
175 panic!()
176 }
177 assert!(QuickCheck::new().quicktest(panic as fn()).is_err());
178 }
179
180 #[test]
regression_issue_83()181 fn regression_issue_83() {
182 fn prop(_: u8) -> bool {
183 true
184 }
185 QuickCheck::new().gen(Gen::new(1024)).quickcheck(prop as fn(u8) -> bool)
186 }
187
188 #[test]
regression_issue_83_signed()189 fn regression_issue_83_signed() {
190 fn prop(_: i8) -> bool {
191 true
192 }
193 QuickCheck::new().gen(Gen::new(1024)).quickcheck(prop as fn(i8) -> bool)
194 }
195
196 // Test that we can show the message after panic
197 #[test]
198 #[should_panic(expected = "foo")]
panic_msg_1()199 fn panic_msg_1() {
200 fn prop() -> bool {
201 panic!("foo");
202 }
203 quickcheck(prop as fn() -> bool);
204 }
205
206 #[test]
207 #[should_panic(expected = "foo")]
panic_msg_2()208 fn panic_msg_2() {
209 fn prop() -> bool {
210 assert!("foo" == "bar");
211 true
212 }
213 quickcheck(prop as fn() -> bool);
214 }
215
216 #[test]
217 #[should_panic(expected = "foo")]
panic_msg_3()218 fn panic_msg_3() {
219 fn prop() -> bool {
220 assert_eq!("foo", "bar");
221 true
222 }
223 quickcheck(prop as fn() -> bool);
224 }
225
226 #[test]
227 #[should_panic]
regression_issue_107_hang()228 fn regression_issue_107_hang() {
229 fn prop(a: Vec<u8>) -> bool {
230 a.contains(&1)
231 }
232 quickcheck(prop as fn(_) -> bool);
233 }
234
235 #[test]
236 #[should_panic(
237 expected = "(Unable to generate enough tests, 0 not discarded.)"
238 )]
all_tests_discarded_min_tests_passed_set()239 fn all_tests_discarded_min_tests_passed_set() {
240 fn prop_discarded(_: u8) -> TestResult {
241 TestResult::discard()
242 }
243
244 QuickCheck::new()
245 .tests(16)
246 .min_tests_passed(8)
247 .quickcheck(prop_discarded as fn(u8) -> TestResult)
248 }
249
250 #[test]
all_tests_discarded_min_tests_passed_missing()251 fn all_tests_discarded_min_tests_passed_missing() {
252 fn prop_discarded(_: u8) -> TestResult {
253 TestResult::discard()
254 }
255
256 QuickCheck::new().quickcheck(prop_discarded as fn(u8) -> TestResult)
257 }
258
259 quickcheck! {
260 /// The following is a very simplistic test, which only verifies
261 /// that our PathBuf::arbitrary does not panic. Still, that's
262 /// something! :)
263 fn pathbuf(_p: PathBuf) -> bool {
264 true
265 }
266
267 fn basic_hashset(_set: HashSet<u8>) -> bool {
268 true
269 }
270
271 fn basic_hashmap(_map: HashMap<u8, u8>) -> bool {
272 true
273 }
274
275 fn substitute_hashset(
276 _set: HashSet<u8, BuildHasherDefault<DefaultHasher>>
277 ) -> bool {
278 true
279 }
280
281 fn substitute_hashmap(
282 _map: HashMap<u8, u8, BuildHasherDefault<DefaultHasher>>
283 ) -> bool {
284 true
285 }
286
287 fn cstring(_p: CString) -> bool {
288 true
289 }
290 }
291