Source for file Fixture.php

Documentation is available at Fixture.php

  1. <?php
  2. /**
  3. * FIT Fixture
  4. *
  5. * $Id$
  6. *
  7. * @author Luis A. Floreani <luis.floreani@gmail.com>
  8. * @author gERD Schaufelberger <gerd@php-tools.net>
  9. * @package FIT
  10. * @subpackage Fixture
  11. * @license LGPL http://www.gnu.org/copyleft/lesser.html
  12. * @copyright Copyright (c) 2002-2005 Cunningham & Cunningham, Inc.
  13. */
  14. /**
  15. * path to FIT implementation
  16. */
  17. if( !defined( 'PHPFIT_INCLUDE_DIR' ) ) {
  18. define( 'PHPFIT_INCLUDE_DIR', dirname( __FILE__ ) );
  19. }
  20.  
  21. /**
  22. * path to user's fixtures
  23. */
  24. if( !defined( 'PHPFIT_FIXTURE_DIR' ) ) {
  25. define( 'PHPFIT_FIXTURE_DIR', realpath( PHPFIT_INCLUDE_DIR . '/..' ) );
  26. }
  27.  
  28. /**
  29. * load counts class
  30. */
  31. include_once PHPFIT_INCLUDE_DIR . '/Counts.php';
  32.  
  33. /**
  34. * load scientfic double class
  35. */
  36. include_once PHPFIT_INCLUDE_DIR . '/ScientificDouble.php';
  37.  
  38. /**
  39. * load timer class
  40. */
  41. include_once PHPFIT_INCLUDE_DIR . '/RunTime.php';
  42.  
  43. /**
  44. * FIT Fixture
  45. *
  46. * @version 0.1.0
  47. * @package FIT
  48. * @subpackage Fixture
  49. */
  50. class Fixture {
  51.  
  52. /**
  53. * make the include folder available for user's fixtures
  54. * @var array
  55. */
  56. const INCLUDE_DIR = PHPFIT_INCLUDE_DIR;
  57.  
  58. protected $green = "#cfffcf";
  59. protected $red = "#ffcfcf";
  60. protected $yellow = "#ffffcf";
  61. protected $gray = "#efefef";
  62.  
  63. /**
  64. * collecting information of this fixture
  65. * @var array
  66. */
  67. public $summary = array();
  68. /**
  69. * count what?
  70. * @var object
  71. */
  72. public $counts;
  73. /**
  74. * construtor
  75. *
  76. * instanciate counter
  77. */
  78. function __construct() {
  79. $this->counts = new Counts();
  80. }
  81.  
  82. /**
  83. * Traverse all tables
  84. *
  85. * Tables are packed in Parse-objects
  86. *
  87. * @param Parse $tables
  88. */
  89. public function doTables( $tables ) {
  90.  
  91. $this->summary['run date'] = date( 'F d Y H:i:s.' );
  92. $this->summary['run elapsed time'] = new RunTime();
  93.  
  94. // no tables left
  95. if( $tables == null ) {
  96. return;
  97. }
  98. // fixture name
  99. $fixtureName = $this->fixtureName( $tables );
  100. if( $fixtureName == null ) {
  101. return;
  102. }
  103. try {
  104. $fixture = $this->getLinkedFixtureWithArgs($tables);
  105. $fixture->interpretTables($tables);
  106. }
  107. catch( Exception $e ) {
  108. $this->exception($fixtureName, $e);
  109. $this->interpretFollowingTables($tables);
  110. }
  111. }
  112.  
  113. /**
  114. * CamelCaseString
  115. *
  116. * @todo This looks quite fragile - consider using preg_replace
  117. * @param string $string
  118. * @return string
  119. */
  120. public static function camel( $string ) {
  121. while( ( $pos = stripos($string, " " ) ) !== false ) {
  122. $characterUpper = strtoupper( $string[$pos+1] );
  123. $string[$pos+1] = $characterUpper;
  124. $string[$pos] = "&";
  125. }
  126. $string = str_replace('&', '', $string);
  127. return $string;
  128. }
  129.  
  130. /**
  131. * Work on tables
  132. *
  133. * @param Parse $tables
  134. */
  135. protected function interpretTables($tables) {
  136. try {
  137. $this->doTable($tables);
  138. }
  139. catch( Exception $e ) {
  140. $this->exception($this->fixtureName($tables), $e);
  141. }
  142. $this->interpretFollowingTables($tables);
  143. }
  144.  
  145. /**
  146. * @param Parse tables
  147. */
  148. private function interpretFollowingTables($tables) {
  149. $tables = $tables->more;
  150. while ($tables != null) {
  151. $fixtureName = $this->fixtureName($tables);
  152. if ($fixtureName != null ) {
  153. try {
  154. $fixture = $this->getLinkedFixtureWithArgs($tables);
  155. $fixture->doTable($tables);
  156. } catch (Exception $e) {
  157. $this->exception($fixtureName, $e);
  158. }
  159. }
  160. $tables = $tables->more;
  161. }
  162. }
  163.  
  164. /**
  165. * @param Parse table
  166. */
  167. public function doTable( $table ) {
  168. $this->doRows( $table->parts->more );
  169. }
  170.  
  171. /**
  172. * @param Parse rows
  173. */
  174. public function doRows( $rows ) {
  175. $i = 1;
  176. while( $rows != null ) {
  177. $more = $rows->more;
  178. $this->doRow( $rows );
  179. $rows = $more;
  180. }
  181. }
  182.  
  183. /**
  184. * @param Parse row
  185. */
  186. public function doRow( $row ) {
  187. $this->doCells( $row->parts );
  188. }
  189. /**
  190. * process cells
  191. *
  192. * Generic processing of all upcoming cells. Actually, this method
  193. * just iterates through them and delegates to doCell()
  194. *
  195. * This method may be overwritten by a subclass (ActionFixture)
  196. *
  197. * @param object $cells A parse object
  198. * @return void
  199. * @see doCell()
  200. */
  201. public function doCells( $cells ) {
  202. $i = 0;
  203. while( $cells ) {
  204. try {
  205. $this->doCell( $cells, $i++ );
  206. }
  207. catch( Exception $e ) {
  208. $this->exception( $cells, $e );
  209. }
  210. $cells = $cells->more;
  211. }
  212. }
  213. /**
  214. * process a single cell
  215. *
  216. * Generic processing of a table cell. Well, this function
  217. * just ignores cells.
  218. *
  219. * This method may be overwritten by a subclass (ColumnFixture)
  220. *
  221. * @param object $cell A parse object
  222. * @return void
  223. */
  224. public function doCell( $cell ) {
  225. $this->ignore( $cell );
  226. }
  227.  
  228. /**
  229. * @param Parse tables
  230. * @return Parse
  231. */
  232.  
  233. public function fixtureName($tables) {
  234. return $tables->at(0, 0, 0);
  235. }
  236.  
  237. /**
  238. * @param Parse tables
  239. * @return Fixture
  240. */
  241. protected function getLinkedFixtureWithArgs($tables) {
  242. $header = $tables->at(0, 0, 0);
  243. $fixture = $this->loadFixture($header->text());
  244. $fixture->counts = $this->counts;
  245. $fixture->summary = $this->summary;
  246. return $fixture;
  247. }
  248.  
  249. /**
  250. * load a fixture by java-stylish name (dot-sparated)
  251. *
  252. * A fixture name might be something like: eg.net.Simulator. This will
  253. * load eg/net/Simulator.php and intanciates the clss Simulator. The path name
  254. * is realtive to the basic fixture di
  255. *
  256. * @param string fixtureName
  257. * @return object Fixture
  258. */
  259. public function loadFixture( $fixtureName ) {
  260. $srcFile = str_replace( '.', '/', $fixtureName );
  261. $class = basename( $srcFile );
  262. // load class
  263. if( !include_once PHPFIT_FIXTURE_DIR . '/' . $srcFile . '.php' ) {
  264. throw new Exception( 'Could not load Fixture ' . $fixtureName . 'from ' . $srcFile );
  265. }
  266. // instanciate
  267. $instance = new $class();
  268. return $instance;
  269. }
  270.  
  271.  
  272. /**
  273. * @param Parse cell
  274. * @param TypeAdapter a
  275. */
  276. public function check($cell, $a) {
  277. $text = $cell->text();
  278. if ($text == "") {
  279. try {
  280. $this->info($cell, $a->toString($a->get()));
  281. } catch (Exception $e) {
  282. $this->info($cell, "error");
  283. }
  284. } else if ($a == null) {
  285. $this->ignore($cell);
  286. } else if (strcmp($text, "error") == 0) {
  287. try {
  288. $result = $a->invoke();
  289. $this->wrong($cell, $a->toString());
  290. } catch (Exception $e) {
  291. $this->right($cell);
  292. }
  293. } else {
  294. try {
  295. $result = $a->get(); // the value of the attribute or the return value of the method
  296. if ($a->equals($a->parse($text), $result)) {
  297. $this->right($cell);
  298. } else {
  299. $result = $this->fixBoolToString($result);
  300. $this->wrong($cell, $a->toString($result));
  301. }
  302. } catch (Exception $e) {
  303. $this->exception($cell, $e);
  304. }
  305. }
  306. }
  307. public function fixBoolToString($result) {
  308. if (!is_bool($result))
  309. return $result;
  310. if ($result)
  311. return "true";
  312. else
  313. return "false";
  314. }
  315. /**
  316. * transform an exception to a cell error
  317. *
  318. * @param object $cell Parse object
  319. * @param object $e Exception
  320. * @see error()
  321. */
  322. public function exception( $cell, $e ) {
  323. $this->error( $cell, $e->getMessage() );
  324. }
  325.  
  326. /**
  327. * place an error text into a cell
  328. *
  329. * @param object $cell Parse object
  330. * @param string $message
  331. */
  332. public function error( $cell, $message ) {
  333. $cell->body = $cell->text() . ': '. $this->escape( $message );
  334. $cell->addToTag( ' bgcolor=" '. $this->yellow . '\"' );
  335. $this->counts->exceptions++;
  336. }
  337.  
  338. /**
  339. * @param string s
  340. * @param string type
  341. * @return mixed (object or string)
  342. */
  343. public function parse($s, $type) {
  344. if ($type == "ScientificDouble") {
  345. //echo "PARSE TYPE : " . $type . "<br>";
  346. return ScientificDouble::valueOf($s);
  347. }
  348. return $s;
  349. //echo "<br>type:" . $type;
  350. //return new Exception("can't yet parse " . get_class($s));;
  351. }
  352. // Annotation ///////////////////////////////
  353. /**
  354. * @param Parse cell
  355. */
  356. public function right($cell) {
  357. $cell->addToTag(" bgcolor=\"" . $this->green . "\"");
  358. $this->counts->right++;
  359. }
  360.  
  361. /**
  362. * @param Parse cell
  363. * @param string actual
  364. */
  365. public function wrong($cell, $actual=false) {
  366. $cell->addToTag(" bgcolor=\"" . $this->red . "\"");
  367. $cell->body = $this->escape($cell->text());
  368. $this->counts->wrong++;
  369. if ($actual !== false)
  370. $cell->addToBody($this->label("expected") . "<hr>" . $this->escape($actual) . $this->label("actual"));
  371. }
  372. /**
  373. * @param Parse cell
  374. * @param string message
  375. */
  376. public function info($cell, $message) {
  377. $str = $this->infoS($message);
  378. $cell->addToBody($str);
  379. }
  380. /**
  381. * @param string message
  382. * @return string
  383. */
  384. public function infoS($message) {
  385. return " <font color=\"#808080\">" . $this->escape($message) . "</font>";
  386. }
  387. /**
  388. * @param Parse cell
  389. */
  390.  
  391. public function ignore ($cell) {
  392. $cell->addToTag(" bgcolor=\"" . $this->gray . "\"");
  393. $this->counts->ignores++;
  394. }
  395. /**
  396. * @param string string
  397. * @return string
  398. */
  399. public function label($string) {
  400. return " <font size=-1 color=\"#c08080\"><i>" . $string . "</i></font>";
  401. }
  402. /**
  403. * @param string string
  404. * @return string
  405. */
  406. public function escape($string) {
  407. $string = str_replace('&', '&amp;', $string);
  408. $string = str_replace('<', '&lt;', $string);
  409. $string = str_replace(' ', ' &nbsp;', $string);
  410. $string = str_replace('\r\n', '<br />', $string);
  411. $string = str_replace('\r', '<br />', $string);
  412. $string = str_replace('\n', '<br />', $string);
  413. return $string;
  414. }
  415. /**
  416. * receive member variable's type specification
  417. *
  418. * Use the helper property typeDict to figure out what type
  419. * a variable is.
  420. *
  421. * Type is one of:
  422. * - integer
  423. * - string
  424. * - array
  425. * - object
  426. * - object:CLASSNAME
  427. * - callable
  428. *
  429. * @todo As PHP does automatica type conversation, I reckon this can be spared
  430. * @return string $type
  431. */
  432. public function getType( $name ) {
  433. if( !property_exists( $this, $name ) ) {
  434. throw new Exception( 'Property does not exist! ' . __CLASS__ . '->' . $name );
  435. return null;
  436. }
  437. if( !isset( $this->typeDict[$name] ) ) {
  438. throw new Exception( 'Property has no definition in $typeDict! ' . __CLASS__ . '->' . $name );
  439. return null;
  440. }
  441. return $this->typeDict[$name];
  442. }
  443. }
  444. ?>

Documentation generated on Sun, 02 Apr 2006 16:01:04 +0200 by phpDocumentor 1.3.0RC5