Révision 219d19c4
Ajouté par Assos Assos il y a plus de 3 ans
drupal7/sites/all/modules/ctools/tests/math_expression.test | ||
---|---|---|
27 | 27 |
} |
28 | 28 |
|
29 | 29 |
/** |
30 |
* Returns a random double between 0 and 1. |
|
30 |
* Return the sign of the numeric arg $n as an integer -1, 0, 1. |
|
31 |
* |
|
32 |
* Note: Not defined when $n is Infinity or NaN (or NULL or ...)! |
|
33 |
* |
|
34 |
* @param int|float $n |
|
35 |
* The number to test. |
|
36 |
* |
|
37 |
* @return int |
|
38 |
* -1 if the $n is negative, 0 if $n is zero or 1 if $n is positive. |
|
39 |
* |
|
40 |
* @see gmp_sign() |
|
41 |
*/ |
|
42 |
protected static function sign($n) { |
|
43 |
return ($n > 0) - ($n < 0); |
|
44 |
} |
|
45 |
|
|
46 |
/** |
|
47 |
* Returns a random number between 0 and 1. |
|
48 |
* |
|
49 |
* @return float |
|
50 |
* A random number between 0 and 1 inclusive. |
|
31 | 51 |
*/ |
32 | 52 |
protected function rand01() { |
33 |
return rand(0, PHP_INT_MAX) / PHP_INT_MAX; |
|
53 |
return mt_rand(0, PHP_INT_MAX) / PHP_INT_MAX;
|
|
34 | 54 |
} |
35 | 55 |
|
36 | 56 |
/** |
37 | 57 |
* A custom assertion with checks the values in a certain range. |
58 |
* |
|
59 |
* @param float $first |
|
60 |
* A value to check for equality. |
|
61 |
* @param float $second |
|
62 |
* A value to check for equality. |
|
63 |
* @param string $message |
|
64 |
* The message describing the correct behaviour, eg. "2/4 equals 1/2". The |
|
65 |
* default message is used if this value is empty. |
|
66 |
* @param float $delta |
|
67 |
* The precision with which values must match. This accounts for rounding |
|
68 |
* errors and imprecise representation errors in the floating point format. |
|
69 |
* The value passed in should ideally be proportional to the values being |
|
70 |
* compared. |
|
71 |
* @param string $group |
|
72 |
* Which group this assert belongs to. |
|
73 |
* |
|
74 |
* @return bool |
|
75 |
* TRUE if the assertion was correct (that is, $first == $second within the |
|
76 |
* given limits), FALSE otherwise. |
|
38 | 77 |
*/ |
39 |
protected function assertFloat($first, $second, $delta = 0.0000001, $message = '', $group = 'Other') { |
|
40 |
return $this->assert(abs($first - $second) <= $delta, $message ? $message : t('Value @first is equal to value @second.', array('@first' => var_export($first, TRUE), '@second' => var_export($second, TRUE))), $group); |
|
78 |
protected function assertFloat($first, $second, $message = '', $delta = 0.00000001, $group = 'Other') { |
|
79 |
// Check for NaN and Inf because the abs() and sign() code won't like those. |
|
80 |
$equal = FALSE |
|
81 |
// Equal if both an infinity. |
|
82 |
|| (is_infinite($first) && is_infinite($second)) |
|
83 |
|
|
84 |
// Equal if both NaN. |
|
85 |
|| (is_nan($first) && is_nan($second)) |
|
86 |
|
|
87 |
// Equal if same absolute value (within limits) and same sign. |
|
88 |
|| ((abs($first - $second) <= $delta) && (self::sign($first) === self::sign($second))); |
|
89 |
|
|
90 |
if (empty($message)) { |
|
91 |
$default = t('Value !first is equal to value !second.', |
|
92 |
array( |
|
93 |
'!first' => var_export($first, TRUE), |
|
94 |
'!second' => var_export($second, TRUE), |
|
95 |
)); |
|
96 |
$message = $default; |
|
97 |
} |
|
98 |
|
|
99 |
return $this->assert($equal, $message, $group); |
|
41 | 100 |
} |
42 | 101 |
|
43 | 102 |
/** |
44 | 103 |
* Test some arithmetic handling. |
45 | 104 |
*/ |
46 | 105 |
public function testArithmetic() { |
47 |
$math_expression = new ctools_math_expr(); |
|
48 |
|
|
49 |
// Test constant expressions. |
|
50 |
$this->assertEqual($math_expression->e('2'), 2); |
|
51 |
$random_number = rand(0, 10); |
|
52 |
$this->assertEqual($random_number, $math_expression->e((string) $random_number)); |
|
53 |
|
|
54 |
// Test simple arithmetic. |
|
55 |
$random_number_a = rand(5, 10); |
|
56 |
$random_number_b = rand(5, 10); |
|
57 |
$this->assertEqual($random_number_a + $random_number_b, $math_expression->e("$random_number_a + $random_number_b")); |
|
58 |
$this->assertEqual($random_number_a - $random_number_b, $math_expression->e("$random_number_a - $random_number_b")); |
|
59 |
$this->assertEqual($random_number_a * $random_number_b, $math_expression->e("$random_number_a * $random_number_b")); |
|
60 |
$this->assertEqual($random_number_a / $random_number_b, $math_expression->e("$random_number_a / $random_number_b")); |
|
61 |
|
|
62 |
// Test Associative property. |
|
63 |
$random_number_c = rand(5, 10); |
|
64 |
$this->assertEqual($math_expression->e("$random_number_a + ($random_number_b + $random_number_c)"), $math_expression->e("($random_number_a + $random_number_b) + $random_number_c")); |
|
65 |
$this->assertEqual($math_expression->e("$random_number_a * ($random_number_b * $random_number_c)"), $math_expression->e("($random_number_a * $random_number_b) * $random_number_c")); |
|
66 |
|
|
67 |
// Test Commutative property. |
|
68 |
$this->assertEqual($math_expression->e("$random_number_a + $random_number_b"), $math_expression->e("$random_number_b + $random_number_a")); |
|
69 |
$this->assertEqual($math_expression->e("$random_number_a * $random_number_b"), $math_expression->e("$random_number_b * $random_number_a")); |
|
70 |
|
|
71 |
// Test Distributive property. |
|
72 |
$this->assertEqual($math_expression->e("($random_number_a + $random_number_b) * $random_number_c"), $math_expression->e("($random_number_a * $random_number_c + $random_number_b * $random_number_c)")); |
|
73 |
|
|
74 |
$this->assertEqual(pow($random_number_a, $random_number_b), $math_expression->e("$random_number_a ^ $random_number_b")); |
|
106 |
$math_expr = new ctools_math_expr(); |
|
107 |
|
|
108 |
$this->assertEqual($math_expr->evaluate('2'), 2, 'Check Literal 2'); |
|
109 |
|
|
110 |
$this->assertEqual($math_expr->e('2+1'), $math_expr->evaluate('2+1'), 'Check that e() and evaluate() are equivalent.'); |
|
111 |
|
|
112 |
foreach (range(1, 4) as $n) { |
|
113 |
// Test constant expressions. |
|
114 |
$random_number = mt_rand(0, 20); |
|
115 |
$this->assertEqual($random_number, $math_expr->evaluate((string) $random_number), "Literal $random_number"); |
|
116 |
|
|
117 |
// Test simple arithmetic. |
|
118 |
$number_a = mt_rand(-55, 777); |
|
119 |
$number_b = mt_rand(-555, 77); |
|
120 |
$this->assertEqual( |
|
121 |
$number_a + $number_b, |
|
122 |
$math_expr->evaluate("$number_a + $number_b"), |
|
123 |
"Addition: $number_a + $number_b"); |
|
124 |
$this->assertEqual( |
|
125 |
$number_a - $number_b, |
|
126 |
$math_expr->evaluate("$number_a - $number_b"), |
|
127 |
"Subtraction: $number_a + $number_b"); |
|
128 |
$this->assertFloat( |
|
129 |
($number_a * $number_b), |
|
130 |
$math_expr->evaluate("$number_a * $number_b"), |
|
131 |
"Multiplication: $number_a * $number_b = " . ($number_a * $number_b)); |
|
132 |
$this->assertFloat( |
|
133 |
($number_a / $number_b), |
|
134 |
$math_expr->evaluate("$number_a / $number_b"), |
|
135 |
"Division: $number_a / $number_b = " . ($number_a / $number_b)); |
|
136 |
|
|
137 |
// Test Associative property. |
|
138 |
$number_c = mt_rand(-99, 77); |
|
139 |
$this->assertEqual( |
|
140 |
$math_expr->evaluate("$number_a + ($number_b + $number_c)"), |
|
141 |
$math_expr->evaluate("($number_a + $number_b) + $number_c"), |
|
142 |
"Associative: $number_a + ($number_b + $number_c)"); |
|
143 |
$this->assertEqual( |
|
144 |
$math_expr->evaluate("$number_a * ($number_b * $number_c)"), |
|
145 |
$math_expr->evaluate("($number_a * $number_b) * $number_c"), |
|
146 |
"Associative: $number_a * ($number_b * $number_c)"); |
|
147 |
|
|
148 |
// Test Commutative property. |
|
149 |
$this->assertEqual( |
|
150 |
$math_expr->evaluate("$number_a + $number_b"), |
|
151 |
$math_expr->evaluate("$number_b + $number_a"), |
|
152 |
"Commutative: $number_a + $number_b"); |
|
153 |
$this->assertEqual( |
|
154 |
$math_expr->evaluate("$number_a * $number_b"), |
|
155 |
$math_expr->evaluate("$number_b * $number_a"), |
|
156 |
"Commutative: $number_a * $number_b"); |
|
157 |
|
|
158 |
// Test Distributive property. |
|
159 |
$this->assertEqual( |
|
160 |
$math_expr->evaluate("($number_a + $number_b) * $number_c"), |
|
161 |
$math_expr->evaluate("($number_a * $number_c + $number_b * $number_c)"), |
|
162 |
"Distributive: ($number_a + $number_b) * $number_c"); |
|
163 |
|
|
164 |
// @todo: Doesn't work with zero or negative powers when number is zero or negative, e.g. 0^0, 0^-2, -2^0, -2^-2. |
|
165 |
$random_number = mt_rand(1, 15); |
|
166 |
$random_power = mt_rand(-15, 15); |
|
167 |
|
|
168 |
$this->assertFloat( |
|
169 |
pow($random_number, $random_power), |
|
170 |
$math_expr->evaluate("$random_number ^ $random_power"), |
|
171 |
"$random_number ^ $random_power"); |
|
172 |
|
|
173 |
$this->assertFloat( |
|
174 |
pow($random_number, $random_power), |
|
175 |
$math_expr->evaluate("pow($random_number, $random_power)"), |
|
176 |
"pow($random_number, $random_power)"); |
|
177 |
} |
|
75 | 178 |
} |
76 | 179 |
|
77 | 180 |
/** |
78 |
* Test the basic built-in functions in the math expression library.
|
|
181 |
* Test various built-in transcendental and extended functions.
|
|
79 | 182 |
*/ |
80 | 183 |
public function testBuildInFunctions() { |
81 |
$math_expression = new ctools_math_expr(); |
|
82 |
|
|
83 |
// @todo Maybe run this code multiple times to test different values. |
|
84 |
$random_double = $this->rand01(); |
|
85 |
$random_int = rand(5, 10); |
|
86 |
$this->assertFloat(sin($random_double), $math_expression->e("sin($random_double)")); |
|
87 |
$this->assertFloat(cos($random_double), $math_expression->e("cos($random_double)")); |
|
88 |
$this->assertFloat(tan($random_double), $math_expression->e("tan($random_double)")); |
|
89 |
$this->assertFloat(exp($random_double), $math_expression->e("exp($random_double)")); |
|
90 |
$this->assertFloat(sqrt($random_double), $math_expression->e("sqrt($random_double)")); |
|
91 |
$this->assertFloat(log($random_double), $math_expression->e("ln($random_double)")); |
|
92 |
$this->assertFloat(round($random_double), $math_expression->e("round($random_double)")); |
|
93 |
$this->assertFloat(abs($random_double + $random_int), $math_expression->e('abs(' . ($random_double + $random_int) . ')')); |
|
94 |
$this->assertEqual(round($random_double + $random_int), $math_expression->e('round(' . ($random_double + $random_int) . ')')); |
|
95 |
$this->assertEqual(ceil($random_double + $random_int), $math_expression->e('ceil(' . ($random_double + $random_int) . ')')); |
|
96 |
$this->assertEqual(floor($random_double + $random_int), $math_expression->e('floor(' . ($random_double + $random_int) . ')')); |
|
97 |
|
|
98 |
// @fixme: you can't run time without an argument. |
|
99 |
$this->assertFloat(time(), $math_expression->e('time(1)')); |
|
184 |
$math_expr = new ctools_math_expr(); |
|
185 |
|
|
186 |
foreach (range(1, 4) as $n) { |
|
187 |
$random_double = $this->rand01(); |
|
188 |
$random_int = mt_rand(-65535, 65535); |
|
189 |
$this->assertFloat(sin($random_double), $math_expr->evaluate("sin($random_double)"), "sin($random_double)"); |
|
190 |
$this->assertFloat(cos($random_double), $math_expr->evaluate("cos($random_double)"), "cos($random_double)"); |
|
191 |
$this->assertFloat(tan($random_double), $math_expr->evaluate("tan($random_double)"), "tan($random_double)"); |
|
192 |
$this->assertFloat(exp($random_double), $math_expr->evaluate("exp($random_double)"), "exp($random_double)"); |
|
193 |
$this->assertFloat(sqrt($random_double), $math_expr->evaluate("sqrt($random_double)"), "sqrt($random_double)"); |
|
194 |
$this->assertFloat(log($random_double), $math_expr->evaluate("ln($random_double)"), "ln($random_double)"); |
|
195 |
$this->assertFloat(round($random_double), $math_expr->evaluate("round($random_double)"), "round($random_double)"); |
|
196 |
|
|
197 |
$random_real = $random_double + $random_int; |
|
198 |
$this->assertFloat(abs($random_real), $math_expr->evaluate('abs(' . $random_real . ')'), "abs($random_real)"); |
|
199 |
$this->assertEqual(round($random_real), $math_expr->evaluate('round(' . $random_real . ')'), "round($random_real)"); |
|
200 |
$this->assertEqual(ceil($random_real), $math_expr->evaluate('ceil(' . $random_real . ')'), "ceil($random_real)"); |
|
201 |
$this->assertEqual(floor($random_real), $math_expr->evaluate('floor(' . $random_real . ')'), "floor($random_real)"); |
|
202 |
} |
|
203 |
|
|
204 |
$this->assertFloat(time(), $math_expr->evaluate('time()'), "time()"); |
|
100 | 205 |
|
101 | 206 |
$random_double_a = $this->rand01(); |
102 | 207 |
$random_double_b = $this->rand01(); |
103 |
// @fixme: max/min don't work at the moment. |
|
104 |
// $this->assertFloat(max($random_double_a, $random_double_b), $math_expression->e("max($random_double_a, $random_double_b)")); |
|
105 |
// $this->assertFloat(min($random_double_a, $random_double_b), $math_expression->e("min($random_double_a, $random_double_b)")); |
|
208 |
$this->assertFloat( |
|
209 |
max($random_double_a, $random_double_b), |
|
210 |
$math_expr->evaluate("max($random_double_a, $random_double_b)"), |
|
211 |
"max($random_double_a, $random_double_b)"); |
|
212 |
$this->assertFloat( |
|
213 |
min($random_double_a, $random_double_b), |
|
214 |
$math_expr->evaluate("min($random_double_a, $random_double_b)"), |
|
215 |
"min($random_double_a, $random_double_b)"); |
|
106 | 216 |
} |
107 | 217 |
|
108 | 218 |
/** |
109 | 219 |
* Test variable handling. |
110 | 220 |
*/ |
111 | 221 |
public function testVariables() { |
112 |
$math_expression = new ctools_math_expr(); |
|
222 |
$math_expr = new ctools_math_expr(); |
|
223 |
|
|
224 |
// We should have a definition of pi: |
|
225 |
$this->assertFloat(pi(), $math_expr->evaluate('pi')); |
|
226 |
|
|
227 |
// And a definition of e: |
|
228 |
$this->assertFloat(exp(1), $math_expr->evaluate('e')); |
|
229 |
|
|
230 |
$number_a = 5; |
|
231 |
$number_b = 10; |
|
232 |
|
|
233 |
// Store the first number and use it on a calculation. |
|
234 |
$math_expr->evaluate("var = $number_a"); |
|
235 |
$this->assertEqual($number_a + $number_b, $math_expr->evaluate("var + $number_b")); |
|
113 | 236 |
|
114 |
$random_number_a = rand(5, 10); |
|
115 |
$random_number_b = rand(5, 10); |
|
237 |
// Change the value and check the new value is used. |
|
238 |
$math_expr->evaluate("var = $number_b"); |
|
239 |
$this->assertEqual( |
|
240 |
$number_b + $number_b, |
|
241 |
$math_expr->evaluate("var + $number_b"), |
|
242 |
"var + $number_b"); |
|
116 | 243 |
|
117 |
// Store the first random number and use it on calculations. |
|
118 |
$math_expression->e("var = $random_number_a"); |
|
119 |
$this->assertEqual($random_number_a + $random_number_b, $math_expression->e("var + $random_number_b")); |
|
120 |
$this->assertEqual($random_number_a * $random_number_b, $math_expression->e("var * $random_number_b")); |
|
121 |
$this->assertEqual($random_number_a - $random_number_b, $math_expression->e("var - $random_number_b")); |
|
122 |
$this->assertEqual($random_number_a / $random_number_b, $math_expression->e("var / $random_number_b")); |
|
244 |
// Store another number and use it on a calculation. |
|
245 |
$math_expr->evaluate("var = $number_a"); |
|
246 |
$math_expr->evaluate("newvar = $number_a"); |
|
247 |
|
|
248 |
$this->assertEqual( |
|
249 |
$number_a + $number_a, |
|
250 |
$math_expr->evaluate('var + newvar'), |
|
251 |
'var + newvar'); |
|
252 |
|
|
253 |
$this->assertFloat( |
|
254 |
$number_a / $number_b, |
|
255 |
$math_expr->evaluate("var / $number_b"), |
|
256 |
"var / $number_b"); |
|
123 | 257 |
} |
124 | 258 |
|
125 | 259 |
/** |
126 | 260 |
* Test custom function handling. |
127 | 261 |
*/ |
128 | 262 |
public function testCustomFunctions() { |
129 |
$math_expression = new ctools_math_expr();
|
|
263 |
$math_expr = new ctools_math_expr(); |
|
130 | 264 |
|
131 |
$random_number_a = rand(5, 10);
|
|
132 |
$random_number_b = rand(5, 10);
|
|
265 |
$number_a = mt_rand(5, 10);
|
|
266 |
$number_b = mt_rand(5, 10);
|
|
133 | 267 |
|
134 | 268 |
// Create a one-argument function. |
135 |
$math_expression->e("f(x) = 2 * x");
|
|
136 |
$this->assertEqual($random_number_a * 2, $math_expression->e("f($random_number_a)"));
|
|
137 |
$this->assertEqual($random_number_b * 2, $math_expression->e("f($random_number_b)"));
|
|
269 |
$math_expr->evaluate("f(x) = 2 * x");
|
|
270 |
$this->assertEqual($number_a * 2, $math_expr->evaluate("f($number_a)"));
|
|
271 |
$this->assertEqual($number_b * 2, $math_expr->evaluate("f($number_b)"));
|
|
138 | 272 |
|
139 | 273 |
// Create a two-argument function. |
140 |
$math_expression->e("g(x, y) = 2 * x + y"); |
|
141 |
$this->assertEqual($random_number_a * 2 + $random_number_b, $math_expression->e("g($random_number_a, $random_number_b)")); |
|
274 |
$math_expr->evaluate("g(x, y) = 2 * x + y"); |
|
275 |
$this->assertEqual( |
|
276 |
$number_a * 2 + $number_b, |
|
277 |
$math_expr->evaluate("g($number_a, $number_b)"), |
|
278 |
"g($number_a, $number_b)"); |
|
142 | 279 |
|
143 | 280 |
// Use a custom function in another function. |
144 |
$this->assertEqual(($random_number_a * 2 + $random_number_b) * 2, $math_expression->e("f(g($random_number_a, $random_number_b))")); |
|
281 |
$this->assertEqual( |
|
282 |
($number_a * 2 + $number_b) * 2, |
|
283 |
$math_expr->evaluate("f(g($number_a, $number_b))"), |
|
284 |
"f(g($number_a, $number_b))"); |
|
285 |
} |
|
286 |
|
|
287 |
/** |
|
288 |
* Test conditional handling. |
|
289 |
*/ |
|
290 |
public function testIf() { |
|
291 |
$math_expr = new ctools_math_expr(); |
|
292 |
|
|
293 |
$number_a = mt_rand(1, 10); |
|
294 |
$number_b = mt_rand(11, 20); |
|
295 |
|
|
296 |
foreach (range(1, 4) as $n) { |
|
297 |
// @todo: Doesn't work with negative numbers. |
|
298 |
if ($n == 2 || $n == 4) { |
|
299 |
//$number_a = -$number_a; |
|
300 |
} |
|
301 |
|
|
302 |
if ($n == 3 || $n == 4) { |
|
303 |
//$number_b = -$number_b; |
|
304 |
} |
|
305 |
|
|
306 |
$this->assertEqual( |
|
307 |
$number_a, |
|
308 |
$math_expr->evaluate("if(1, $number_a, $number_b)"), |
|
309 |
"if(1, $number_a, $number_b)"); |
|
310 |
|
|
311 |
$this->assertEqual( |
|
312 |
$number_a, |
|
313 |
$math_expr->evaluate("if(1, $number_a)", |
|
314 |
"if(1, $number_a)")); |
|
315 |
|
|
316 |
$this->assertEqual( |
|
317 |
$number_b, |
|
318 |
$math_expr->evaluate("if(0, $number_a, $number_b)"), |
|
319 |
"if(0, $number_a, $number_b)"); |
|
320 |
|
|
321 |
// Also add an expression so ensure it's evaluated. |
|
322 |
$this->assertEqual( |
|
323 |
$number_b, |
|
324 |
$math_expr->evaluate("if($number_a > $number_b, $number_a, $number_b)"), |
|
325 |
"if($number_a > $number_b, $number_a, $number_b)"); |
|
326 |
|
|
327 |
$this->assertEqual( |
|
328 |
$number_b, |
|
329 |
$math_expr->evaluate("if($number_a < $number_b, $number_b, $number_a)"), |
|
330 |
"if($number_a < $number_b, $number_b, $number_a)"); |
|
331 |
} |
|
145 | 332 |
} |
146 | 333 |
|
147 | 334 |
} |
Formats disponibles : Unified diff
Weekly update of contrib modules