1 //- 2 // Copyright 2017, 2018 The proptest developers 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::fmt; 11 12 use crate::strategy::{NewTree, Strategy, ValueTree}; 13 use crate::test_runner::TestRunner; 14 15 macro_rules! noshrink { 16 () => { 17 fn simplify(&mut self) -> bool { 18 false 19 } 20 fn complicate(&mut self) -> bool { 21 false 22 } 23 }; 24 } 25 26 //============================================================================== 27 // Just 28 //============================================================================== 29 30 /// A `Strategy` which always produces a single value value and never 31 /// simplifies. 32 #[derive(Clone, Copy, Debug)] 33 #[must_use = "strategies do nothing unless used"] 34 pub struct Just<T: Clone + fmt::Debug>( 35 /// The value produced by this strategy. 36 pub T, 37 ); 38 39 impl<T: Clone + fmt::Debug> Strategy for Just<T> { 40 type Tree = Self; 41 type Value = T; 42 new_tree(&self, _: &mut TestRunner) -> NewTree<Self>43 fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> { 44 Ok(self.clone()) 45 } 46 } 47 48 impl<T: Clone + fmt::Debug> ValueTree for Just<T> { 49 type Value = T; 50 noshrink!(); current(&self) -> T51 fn current(&self) -> T { 52 self.0.clone() 53 } 54 } 55 56 //============================================================================== 57 // LazyJust 58 //============================================================================== 59 60 /// A `Strategy` which always produces a single value value and never 61 /// simplifies. If `T` is `Clone`, you should use `Just` instead. 62 /// 63 /// This is a generalization of `Just` and works by calling 64 /// the provided `Fn () -> T` in `.current()` every time. This is not a 65 /// very interesting strategy, but is required in cases where `T` is 66 /// not `Clone`. It is also used in `proptest_derive` where we can't 67 /// assume that your type is `Clone`. 68 /// 69 /// **It is important that the function used be pure.** 70 #[must_use = "strategies do nothing unless used"] 71 pub struct LazyJust<T, F: Fn() -> T> { 72 /// The function executed in `.current()`. 73 function: F, 74 } 75 76 /// Shorthand for `LazyJust<T, fn () -> T>`. 77 pub type LazyJustFn<V> = LazyJust<V, fn() -> V>; 78 79 impl<T, F: Fn() -> T> LazyJust<T, F> { 80 /// Constructs a `LazyJust` strategy given the function/closure 81 /// that produces the value. 82 /// 83 /// **It is important that the function used be pure.** new(function: F) -> Self84 pub fn new(function: F) -> Self { 85 Self { function } 86 } 87 } 88 89 impl<T: fmt::Debug, F: Clone + Fn() -> T> Strategy for LazyJust<T, F> { 90 type Tree = Self; 91 type Value = T; 92 new_tree(&self, _: &mut TestRunner) -> NewTree<Self>93 fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> { 94 Ok(self.clone()) 95 } 96 } 97 98 impl<T: fmt::Debug, F: Fn() -> T> ValueTree for LazyJust<T, F> { 99 type Value = T; 100 noshrink!(); current(&self) -> Self::Value101 fn current(&self) -> Self::Value { 102 (self.function)() 103 } 104 } 105 106 impl<T, F: Copy + Fn() -> T> Copy for LazyJust<T, F> {} 107 108 impl<T, F: Clone + Fn() -> T> Clone for LazyJust<T, F> { clone(&self) -> Self109 fn clone(&self) -> Self { 110 Self { 111 function: self.function.clone(), 112 } 113 } 114 } 115 116 impl<T, F: Fn() -> T> fmt::Debug for LazyJust<T, F> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result117 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 118 fmt.debug_struct("LazyJust") 119 .field("function", &"<function>") 120 .finish() 121 } 122 } 123 124 //============================================================================== 125 // Any `fn () -> T` is a Strategy 126 //============================================================================== 127 128 // TODO: try 'F: Fn () -> T' instead when we've got specialization. 129 130 impl<T: fmt::Debug> Strategy for fn() -> T { 131 type Tree = Self; 132 type Value = T; 133 new_tree(&self, _: &mut TestRunner) -> NewTree<Self>134 fn new_tree(&self, _: &mut TestRunner) -> NewTree<Self> { 135 Ok(*self) 136 } 137 } 138 139 impl<T: fmt::Debug> ValueTree for fn() -> T { 140 type Value = T; 141 noshrink!(); current(&self) -> Self::Value142 fn current(&self) -> Self::Value { 143 self() 144 } 145 } 146