1 //- 2 // Copyright 2017 Jason Lingle 3 // 4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 7 // option. This file may not be copied, modified, or distributed 8 // except according to those terms. 9 10 use crate::std_facade::Arc; 11 use core::fmt; 12 use core::marker::PhantomData; 13 14 use crate::strategy::traits::*; 15 use crate::test_runner::*; 16 17 //============================================================================== 18 // Map 19 //============================================================================== 20 21 /// `Strategy` and `ValueTree` map adaptor. 22 /// 23 /// See `Strategy::prop_map()`. 24 #[must_use = "strategies do nothing unless used"] 25 pub struct Map<S, F> { 26 pub(super) source: S, 27 pub(super) fun: Arc<F>, 28 } 29 30 impl<S: fmt::Debug, F> fmt::Debug for Map<S, F> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 32 f.debug_struct("Map") 33 .field("source", &self.source) 34 .field("fun", &"<function>") 35 .finish() 36 } 37 } 38 39 impl<S: Clone, F> Clone for Map<S, F> { clone(&self) -> Self40 fn clone(&self) -> Self { 41 Map { 42 source: self.source.clone(), 43 fun: Arc::clone(&self.fun), 44 } 45 } 46 } 47 48 impl<S: Strategy, O: fmt::Debug, F: Fn(S::Value) -> O> Strategy for Map<S, F> { 49 type Tree = Map<S::Tree, F>; 50 type Value = O; 51 new_tree(&self, runner: &mut TestRunner) -> NewTree<Self>52 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> { 53 self.source.new_tree(runner).map(|v| Map { 54 source: v, 55 fun: Arc::clone(&self.fun), 56 }) 57 } 58 } 59 60 impl<S: ValueTree, O: fmt::Debug, F: Fn(S::Value) -> O> ValueTree 61 for Map<S, F> 62 { 63 type Value = O; 64 current(&self) -> O65 fn current(&self) -> O { 66 (self.fun)(self.source.current()) 67 } 68 simplify(&mut self) -> bool69 fn simplify(&mut self) -> bool { 70 self.source.simplify() 71 } 72 complicate(&mut self) -> bool73 fn complicate(&mut self) -> bool { 74 self.source.complicate() 75 } 76 } 77 78 //============================================================================== 79 // MapInto 80 //============================================================================== 81 82 // NOTE: Since this is external stable API, 83 // we avoid relying on the Map in `statics`. 84 85 /// `Strategy` and `ValueTree` map into adaptor. 86 /// 87 /// See `Strategy::prop_map_into()`. 88 #[must_use = "strategies do nothing unless used"] 89 pub struct MapInto<S, O> { 90 pub(super) source: S, 91 pub(super) output: PhantomData<O>, 92 } 93 94 impl<S, O> MapInto<S, O> { 95 /// Construct a `MapInto` mapper from an `S` strategy into a strategy 96 /// producing `O`s. new(source: S) -> Self97 pub(super) fn new(source: S) -> Self { 98 Self { 99 source, 100 output: PhantomData, 101 } 102 } 103 } 104 105 impl<S: fmt::Debug, O> fmt::Debug for MapInto<S, O> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 107 f.debug_struct("MapInto") 108 .field("source", &self.source) 109 .finish() 110 } 111 } 112 113 impl<S: Clone, O> Clone for MapInto<S, O> { clone(&self) -> Self114 fn clone(&self) -> Self { 115 Self::new(self.source.clone()) 116 } 117 } 118 119 impl<S: Strategy, O: fmt::Debug> Strategy for MapInto<S, O> 120 where 121 S::Value: Into<O>, 122 { 123 type Tree = MapInto<S::Tree, O>; 124 type Value = O; 125 new_tree(&self, runner: &mut TestRunner) -> NewTree<Self>126 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> { 127 self.source.new_tree(runner).map(MapInto::new) 128 } 129 } 130 131 impl<S: ValueTree, O: fmt::Debug> ValueTree for MapInto<S, O> 132 where 133 S::Value: Into<O>, 134 { 135 type Value = O; 136 current(&self) -> O137 fn current(&self) -> O { 138 self.source.current().into() 139 } 140 simplify(&mut self) -> bool141 fn simplify(&mut self) -> bool { 142 self.source.simplify() 143 } 144 complicate(&mut self) -> bool145 fn complicate(&mut self) -> bool { 146 self.source.complicate() 147 } 148 } 149 150 //============================================================================== 151 // Perturb 152 //============================================================================== 153 154 /// `Strategy` perturbation adaptor. 155 /// 156 /// See `Strategy::prop_perturb()`. 157 #[must_use = "strategies do nothing unless used"] 158 pub struct Perturb<S, F> { 159 pub(super) source: S, 160 pub(super) fun: Arc<F>, 161 } 162 163 impl<S: fmt::Debug, F> fmt::Debug for Perturb<S, F> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 165 f.debug_struct("Perturb") 166 .field("source", &self.source) 167 .field("fun", &"<function>") 168 .finish() 169 } 170 } 171 172 impl<S: Clone, F> Clone for Perturb<S, F> { clone(&self) -> Self173 fn clone(&self) -> Self { 174 Perturb { 175 source: self.source.clone(), 176 fun: Arc::clone(&self.fun), 177 } 178 } 179 } 180 181 impl<S: Strategy, O: fmt::Debug, F: Fn(S::Value, TestRng) -> O> Strategy 182 for Perturb<S, F> 183 { 184 type Tree = PerturbValueTree<S::Tree, F>; 185 type Value = O; 186 new_tree(&self, runner: &mut TestRunner) -> NewTree<Self>187 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> { 188 let rng = runner.new_rng(); 189 190 self.source.new_tree(runner).map(|source| PerturbValueTree { 191 source, 192 rng, 193 fun: Arc::clone(&self.fun), 194 }) 195 } 196 } 197 198 /// `ValueTree` perturbation adaptor. 199 /// 200 /// See `Strategy::prop_perturb()`. 201 pub struct PerturbValueTree<S, F> { 202 source: S, 203 fun: Arc<F>, 204 rng: TestRng, 205 } 206 207 impl<S: fmt::Debug, F> fmt::Debug for PerturbValueTree<S, F> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result208 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 209 f.debug_struct("PerturbValueTree") 210 .field("source", &self.source) 211 .field("fun", &"<function>") 212 .field("rng", &self.rng) 213 .finish() 214 } 215 } 216 217 impl<S: Clone, F> Clone for PerturbValueTree<S, F> { clone(&self) -> Self218 fn clone(&self) -> Self { 219 PerturbValueTree { 220 source: self.source.clone(), 221 fun: Arc::clone(&self.fun), 222 rng: self.rng.clone(), 223 } 224 } 225 } 226 227 impl<S: ValueTree, O: fmt::Debug, F: Fn(S::Value, TestRng) -> O> ValueTree 228 for PerturbValueTree<S, F> 229 { 230 type Value = O; 231 current(&self) -> O232 fn current(&self) -> O { 233 (self.fun)(self.source.current(), self.rng.clone()) 234 } 235 simplify(&mut self) -> bool236 fn simplify(&mut self) -> bool { 237 self.source.simplify() 238 } 239 complicate(&mut self) -> bool240 fn complicate(&mut self) -> bool { 241 self.source.complicate() 242 } 243 } 244 245 //============================================================================== 246 // Tests 247 //============================================================================== 248 249 #[cfg(test)] 250 mod test { 251 use std::collections::HashSet; 252 253 use rand::RngCore; 254 255 use super::*; 256 use crate::strategy::just::Just; 257 258 #[test] test_map()259 fn test_map() { 260 TestRunner::default() 261 .run(&(0..10).prop_map(|v| v * 2), |v| { 262 assert!(0 == v % 2); 263 Ok(()) 264 }) 265 .unwrap(); 266 } 267 268 #[test] test_map_into()269 fn test_map_into() { 270 TestRunner::default() 271 .run(&(0..10u8).prop_map_into::<usize>(), |v| { 272 assert!(v < 10); 273 Ok(()) 274 }) 275 .unwrap(); 276 } 277 278 #[test] perturb_uses_same_rng_every_time()279 fn perturb_uses_same_rng_every_time() { 280 let mut runner = TestRunner::default(); 281 let input = Just(1).prop_perturb(|v, mut rng| v + rng.next_u32()); 282 283 for _ in 0..16 { 284 let value = input.new_tree(&mut runner).unwrap(); 285 assert_eq!(value.current(), value.current()); 286 } 287 } 288 289 #[test] perturb_uses_varying_random_seeds()290 fn perturb_uses_varying_random_seeds() { 291 let mut runner = TestRunner::default(); 292 let input = Just(1).prop_perturb(|v, mut rng| v + rng.next_u32()); 293 294 let mut seen = HashSet::new(); 295 for _ in 0..64 { 296 seen.insert(input.new_tree(&mut runner).unwrap().current()); 297 } 298 299 assert_eq!(64, seen.len()); 300 } 301 } 302