1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\Math\Test\Unit\Visitor; 38 39use Hoa\Compiler; 40use Hoa\File; 41use Hoa\Math as LUT; 42use Hoa\Math\Visitor\Arithmetic as CUT; 43use Hoa\Regex; 44use Hoa\Test; 45 46/** 47 * Class \Hoa\Math\Test\Unit\Visitor\Arithmetic. 48 * 49 * Test suite of the hoa://Library/Math/Arithmetic.pp grammar and the 50 * Hoa\Math\Visitor\Arithmetic class. 51 * 52 * @copyright Copyright © 2007-2017 Hoa community 53 * @license New BSD License 54 */ 55class Arithmetic extends Test\Unit\Suite 56{ 57 public function case_visitor_exhaustively() 58 { 59 $this 60 ->given( 61 $sampler = new Compiler\Llk\Sampler\BoundedExhaustive( 62 Compiler\Llk\Llk::load( 63 new File\Read('hoa://Library/Math/Test/Unit/Arithmetic.pp') 64 ), 65 new Regex\Visitor\Isotropic( 66 new LUT\Sampler\Random() 67 ), 68 9 69 ), 70 $compiler = Compiler\Llk\Llk::load( 71 new File\Read('hoa://Library/Math/Arithmetic.pp') 72 ), 73 $visitor = new CUT() 74 ) 75 ->executeOnFailure(function () use (&$expression) { 76 echo 'Failed expression: ', $expression, '.', "\n"; 77 }) 78 ->when(function () use (&$sampler, &$compiler, &$visitor) { 79 foreach ($sampler as $i=> $expression) { 80 try { 81 $x = (float) $visitor->visit( 82 $compiler->parse($expression) 83 ); 84 } catch (\Exception $e) { 85 continue; 86 } 87 88 eval('$y = (float) ' . $expression . ';'); 89 90 if (is_nan($x) || is_nan($y)) { 91 $this->boolean(true); 92 93 continue; 94 } 95 96 $this 97 ->float($x) 98 ->isNearlyEqualTo($y); 99 } 100 }); 101 } 102 103 public function case_visitor_unknown_variable() 104 { 105 $this 106 ->given( 107 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 108 $visitor = new CUT(), 109 $variableName = 'unknown_variable' 110 ) 111 ->then 112 ->object($compiler->parse($variableName . ' * 2')) 113 ->isInstanceOf('Hoa\Compiler\Llk\TreeNode') 114 ->exception(function () use ($variableName, $compiler, $visitor) { 115 $visitor->visit($compiler->parse($variableName . ' * 2')); 116 }) 117 ->isInstanceOf('Hoa\Math\Exception\UnknownVariable'); 118 } 119 120 public function case_visitor_variable() 121 { 122 $this 123 ->given( 124 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 125 $visitor = new CUT(), 126 $variableName = 'a_variable', 127 $variableValue = 42 128 ) 129 ->when($visitor->addVariable($variableName, function () use ($variableValue) { 130 return $variableValue; 131 })) 132 ->then 133 ->float($visitor->visit($compiler->parse($variableName . ' * 2'))) 134 ->isEqualTo($variableValue * 2); 135 } 136 137 public function case_visitor_unknown_constant() 138 { 139 $this 140 ->given( 141 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 142 $visitor = new CUT(), 143 $constantName = 'UNKNOWN_CONSTANT' 144 ) 145 ->then 146 ->object($compiler->parse($constantName . ' * 2')) 147 ->isInstanceOf('Hoa\Compiler\Llk\TreeNode') 148 ->exception(function () use ($constantName, $compiler, $visitor) { 149 $visitor->visit($compiler->parse($constantName . ' * 2')); 150 }) 151 ->isInstanceOf('Hoa\Math\Exception\UnknownConstant'); 152 } 153 154 public function case_visitor_constant() 155 { 156 $this 157 ->given( 158 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 159 $visitor = new CUT(), 160 $constantName = 'A_CONSTANT', 161 $constantValue = 42 162 ) 163 ->when($visitor->addConstant($constantName, $constantValue)) 164 ->then 165 ->float($visitor->visit($compiler->parse($constantName . ' * 2'))) 166 ->isEqualTo($constantValue * 2); 167 } 168 169 public function case_visitor_unknown_function() 170 { 171 $this 172 ->given( 173 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 174 $visitor = new CUT(), 175 $functionName = 'unknown_function' 176 ) 177 ->then 178 ->object($compiler->parse($functionName . '() * 2')) 179 ->isInstanceOf('Hoa\Compiler\Llk\TreeNode') 180 ->exception(function () use ($functionName, $compiler, $visitor) { 181 $visitor->visit($compiler->parse($functionName . '() * 2')); 182 }) 183 ->isInstanceOf('Hoa\Math\Exception\UnknownFunction'); 184 } 185 186 public function case_visitor_function() 187 { 188 $this 189 ->given( 190 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 191 $visitor = new CUT(), 192 $functionName = 'a_function', 193 $functionResult = 42 194 ) 195 ->when($visitor->addFunction($functionName, function () use ($functionResult) { 196 return $functionResult; 197 })) 198 ->then 199 ->float($visitor->visit($compiler->parse($functionName . '() * 2'))) 200 ->isEqualTo($functionResult * 2); 201 } 202 203 public function case_change_default_context() 204 { 205 $this 206 ->given( 207 $compiler = Compiler\Llk\Llk::load(new File\Read('hoa://Library/Math/Arithmetic.pp')), 208 $visitor = new CUT(), 209 $context = new \Mock\Hoa\Math\Context(), 210 $variableName = 'a_variable', 211 $variableValue = 42 212 ) 213 ->when($context->addVariable($variableName, function () use ($variableValue) { return $variableValue; })) 214 ->then 215 ->object($visitor->setContext($context)) 216 ->isNotIdenticalTo($context) 217 ->object($visitor->getContext()) 218 ->isIdenticalTo($context) 219 ->float($visitor->visit($compiler->parse('abs(' . $variableName . ' - PI)'))) 220 ->isEqualTo(abs($variableValue - M_PI)) 221 ->mock($context) 222 ->call('getFunction')->withArguments('abs')->once 223 ->call('getVariable')->withArguments($variableName)->once 224 ->call('getConstant')->withArguments('PI')->once; 225 } 226} 227