PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/PHPUnit/Util/Report/Node.php

https://github.com/item/sugarcrm_dev
PHP | 489 lines | 273 code | 50 blank | 166 comment | 48 complexity | 5535a8a08727a95b86684973cfaaf807 MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @category Testing
  38. * @package PHPUnit
  39. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  40. * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
  41. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42. * @link http://www.phpunit.de/
  43. * @since File available since Release 3.2.0
  44. */
  45. require_once 'PHPUnit/Framework.php';
  46. require_once 'PHPUnit/Util/Filter.php';
  47. require_once 'PHPUnit/Util/Filesystem.php';
  48. require_once 'PHPUnit/Util/Test.php';
  49. PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
  50. /**
  51. * Base class for nodes in the code coverage information tree.
  52. *
  53. * @category Testing
  54. * @package PHPUnit
  55. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  56. * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
  57. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  58. * @version Release: 3.3.17
  59. * @link http://www.phpunit.de/
  60. * @since Class available since Release 3.2.0
  61. */
  62. abstract class PHPUnit_Util_Report_Node
  63. {
  64. /**
  65. * @var array
  66. */
  67. protected $cache = array();
  68. /**
  69. * @var string
  70. */
  71. protected $name;
  72. /**
  73. * @var PHPUnit_Util_Report_Node
  74. */
  75. protected $parent;
  76. /**
  77. * Constructor.
  78. *
  79. * @param string $name
  80. * @param PHPUnit_Util_Report_Node $parent
  81. */
  82. public function __construct($name, PHPUnit_Util_Report_Node $parent = NULL)
  83. {
  84. $this->name = $name;
  85. $this->parent = $parent;
  86. }
  87. /**
  88. * Returns the percentage of classes of which at least one method
  89. * has been called at least once..
  90. *
  91. * @return integer
  92. */
  93. public function getCalledClassesPercent()
  94. {
  95. return $this->calculatePercent(
  96. $this->getNumCalledClasses(),
  97. $this->getNumClasses()
  98. );
  99. }
  100. /**
  101. * Returns the percentage of methods that has been called at least once.
  102. *
  103. * @return integer
  104. */
  105. public function getCalledMethodsPercent()
  106. {
  107. return $this->calculatePercent(
  108. $this->getNumCalledMethods(),
  109. $this->getNumMethods()
  110. );
  111. }
  112. /**
  113. * Returns the percentage of executed lines.
  114. *
  115. * @return integer
  116. */
  117. public function getLineExecutedPercent()
  118. {
  119. return $this->calculatePercent(
  120. $this->getNumExecutedLines(),
  121. $this->getNumExecutableLines()
  122. );
  123. }
  124. /**
  125. * Returns this node's ID.
  126. *
  127. * @return string
  128. */
  129. public function getId()
  130. {
  131. if (!isset($this->cache['id'])) {
  132. if ($this->parent === NULL) {
  133. $this->cache['id'] = 'index';
  134. } else {
  135. $parentId = $this->parent->getId();
  136. if ($parentId == 'index') {
  137. $this->cache['id'] = $this->getName();
  138. } else {
  139. $this->cache['id'] = $parentId . '_' . $this->getName();
  140. }
  141. }
  142. }
  143. return $this->cache['id'];
  144. }
  145. /**
  146. * Returns this node's name.
  147. *
  148. * @param boolean $includeParent
  149. * @return string
  150. */
  151. public function getName($includeParent = FALSE, $includeCommonPath = FALSE)
  152. {
  153. if ($includeParent && $this->parent !== NULL) {
  154. if (!isset($this->cache['nameIncludingParent'])) {
  155. $parent = $this->parent->getName(TRUE);
  156. $this->cache['nameIncludingParent'] = !empty($parent) ? $parent . '/' . $this->name : $this->name;
  157. }
  158. return $this->cache['nameIncludingParent'];
  159. } else {
  160. if ($this->parent !== NULL) {
  161. return $this->name;
  162. } else {
  163. return $includeCommonPath ? $this->name : '';
  164. }
  165. }
  166. }
  167. /**
  168. * Returns the link to this node.
  169. *
  170. * @param boolean $full
  171. * @return string
  172. */
  173. public function getLink($full)
  174. {
  175. if (substr($this->name, -1) == DIRECTORY_SEPARATOR) {
  176. $name = substr($this->name, 0, -1);
  177. } else {
  178. $name = $this->name;
  179. }
  180. $cleanId = PHPUnit_Util_Filesystem::getSafeFilename($this->getId());
  181. if ($full) {
  182. if ($this->parent !== NULL) {
  183. $parent = $this->parent->getLink(TRUE) . DIRECTORY_SEPARATOR;
  184. } else {
  185. $parent = '';
  186. }
  187. return sprintf(
  188. '%s<a href="%s.html">%s</a>',
  189. $parent,
  190. $cleanId,
  191. $name
  192. );
  193. } else {
  194. return sprintf(
  195. '<a href="%s.html">%s</a>',
  196. $cleanId,
  197. $name
  198. );
  199. }
  200. }
  201. /**
  202. * Returns this node's path.
  203. *
  204. * @return string
  205. */
  206. public function getPath()
  207. {
  208. if (!isset($this->cache['path'])) {
  209. if ($this->parent === NULL) {
  210. $this->cache['path'] = $this->getName(FALSE, TRUE);
  211. } else {
  212. if (substr($this->parent->getPath(), -1) == DIRECTORY_SEPARATOR) {
  213. $this->cache['path'] = $this->parent->getPath() .
  214. $this->getName(FALSE, TRUE);
  215. } else {
  216. $this->cache['path'] = $this->parent->getPath() .
  217. DIRECTORY_SEPARATOR .
  218. $this->getName(FALSE, TRUE);
  219. if ($this->parent->getPath() === '' &&
  220. realpath($this->cache['path']) === FALSE &&
  221. realpath($this->getName(FALSE, TRUE)) !== FALSE) {
  222. $this->cache['path'] = $this->getName(FALSE, TRUE);
  223. }
  224. }
  225. }
  226. }
  227. return $this->cache['path'];
  228. }
  229. /**
  230. * Calculates a percentage value.
  231. *
  232. * @param integer $a
  233. * @param integer $b
  234. * @return float ($a / $b) * 100
  235. */
  236. protected function calculatePercent($a, $b)
  237. {
  238. if ($b > 0) {
  239. $percent = ($a / $b) * 100;
  240. } else {
  241. $percent = 100;
  242. }
  243. return sprintf(
  244. '%01.2F',
  245. $percent
  246. );
  247. }
  248. protected function doRenderItemObject(PHPUnit_Util_Report_Node $item, $lowUpperBound, $highLowerBound, $link = NULL, $itemClass = 'coverItem')
  249. {
  250. return $this->doRenderItem(
  251. array(
  252. 'name' => $link != NULL ? $link : $item->getLink(FALSE),
  253. 'itemClass' => $itemClass,
  254. 'numClasses' => $item->getNumClasses(),
  255. 'numCalledClasses' => $item->getNumCalledClasses(),
  256. 'calledClassesPercent' => $item->getCalledClassesPercent(),
  257. 'numMethods' => $item->getNumMethods(),
  258. 'numCalledMethods' => $item->getNumCalledMethods(),
  259. 'calledMethodsPercent' => $item->getCalledMethodsPercent(),
  260. 'numExecutableLines' => $item->getNumExecutableLines(),
  261. 'numExecutedLines' => $item->getNumExecutedLines(),
  262. 'executedLinesPercent' => $item->getLineExecutedPercent()
  263. ),
  264. $lowUpperBound,
  265. $highLowerBound
  266. );
  267. }
  268. protected function doRenderItem(array $data, $lowUpperBound, $highLowerBound, $template = NULL)
  269. {
  270. if ($template === NULL) {
  271. if ($this instanceof PHPUnit_Util_Report_Node_Directory) {
  272. $template = 'directory_item.html';
  273. } else {
  274. $template = 'file_item.html';
  275. }
  276. }
  277. $itemTemplate = new PHPUnit_Util_Template(
  278. PHPUnit_Util_Report::$templatePath . $template
  279. );
  280. if ($data['numClasses'] > 0) {
  281. list($classesColor, $classesLevel) = $this->getColorLevel(
  282. $data['calledClassesPercent'], $lowUpperBound, $highLowerBound
  283. );
  284. $classesNumber = $data['numCalledClasses'] . ' / ' . $data['numClasses'];
  285. } else {
  286. $classesColor = 'snow';
  287. $classesLevel = 'None';
  288. $classesNumber = '&nbsp;';
  289. }
  290. if ($data['numMethods'] > 0) {
  291. list($methodsColor, $methodsLevel) = $this->getColorLevel(
  292. $data['calledMethodsPercent'], $lowUpperBound, $highLowerBound
  293. );
  294. $methodsNumber = $data['numCalledMethods'] . ' / ' . $data['numMethods'];
  295. } else {
  296. $methodsColor = 'snow';
  297. $methodsLevel = 'None';
  298. $methodsNumber = '&nbsp;';
  299. }
  300. list($linesColor, $linesLevel) = $this->getColorLevel(
  301. $data['executedLinesPercent'], $lowUpperBound, $highLowerBound
  302. );
  303. if ($data['name'] == '<b><a href="#0">*</a></b>') {
  304. $functions = TRUE;
  305. } else {
  306. $functions = FALSE;
  307. }
  308. $itemTemplate->setVar(
  309. array(
  310. 'name' => $functions ? 'Functions' : $data['name'],
  311. 'itemClass' => isset($data['itemClass']) ? $data['itemClass'] : 'coverItem',
  312. 'classes_color' => $classesColor,
  313. 'classes_level' => $functions ? 'None' : $classesLevel,
  314. 'classes_called_width' => floor($data['calledClassesPercent']),
  315. 'classes_called_percent' => !$functions && $data['numClasses'] > 0 ? $data['calledClassesPercent'] . '%' : '&nbsp;',
  316. 'classes_not_called_width' => 100 - floor($data['calledClassesPercent']),
  317. 'classes_number' => $functions ? '&nbsp;' : $classesNumber,
  318. 'methods_color' => $methodsColor,
  319. 'methods_level' => $methodsLevel,
  320. 'methods_called_width' => floor($data['calledMethodsPercent']),
  321. 'methods_called_percent' => $data['numMethods'] > 0 ? $data['calledMethodsPercent'] . '%' : '&nbsp;',
  322. 'methods_not_called_width' => 100 - floor($data['calledMethodsPercent']),
  323. 'methods_number' => $methodsNumber,
  324. 'lines_color' => $linesColor,
  325. 'lines_level' => $linesLevel,
  326. 'lines_executed_width' => floor($data['executedLinesPercent']),
  327. 'lines_executed_percent' => $data['executedLinesPercent'] . '%',
  328. 'lines_not_executed_width' => 100 - floor($data['executedLinesPercent']),
  329. 'num_executable_lines' => $data['numExecutableLines'],
  330. 'num_executed_lines' => $data['numExecutedLines']
  331. )
  332. );
  333. return $itemTemplate->render();
  334. }
  335. protected function getColorLevel($percent, $lowUpperBound, $highLowerBound)
  336. {
  337. $floorPercent = floor($percent);
  338. if ($floorPercent < $lowUpperBound) {
  339. $color = 'scarlet_red';
  340. $level = 'Lo';
  341. }
  342. else if ($floorPercent >= $lowUpperBound &&
  343. $floorPercent < $highLowerBound) {
  344. $color = 'butter';
  345. $level = 'Med';
  346. }
  347. else {
  348. $color = 'chameleon';
  349. $level = 'Hi';
  350. }
  351. return array($color, $level);
  352. }
  353. protected function renderTotalItem($lowUpperBound, $highLowerBound, $directory = TRUE)
  354. {
  355. if ($directory && empty($this->directories) && count($this->files) == 1) {
  356. return '';
  357. }
  358. return $this->doRenderItemObject($this, $lowUpperBound, $highLowerBound, 'Total') .
  359. " <tr>\n" .
  360. ' <td class="tableHead" colspan="10">&nbsp;</td>' . "\n" .
  361. " </tr>\n";
  362. }
  363. /**
  364. * @param PHPUnit_Util_Template $template
  365. * @param string $title
  366. * @param string $charset
  367. */
  368. protected function setTemplateVars(PHPUnit_Util_Template $template, $title, $charset)
  369. {
  370. $template->setVar(
  371. array(
  372. 'title' => $title,
  373. 'charset' => $charset,
  374. 'link' => $this->getLink(TRUE),
  375. 'num_executable_lines' => $this->getNumExecutableLines(),
  376. 'num_executed_lines' => $this->getNumExecutedLines(),
  377. 'lines_executed_percent' => $this->getLineExecutedPercent(),
  378. 'date' => $template->getDate(),
  379. 'phpunit_version' => PHPUnit_Runner_Version::id(),
  380. 'xdebug_version' => phpversion('xdebug')
  381. )
  382. );
  383. }
  384. /**
  385. * Returns the classes of this node.
  386. *
  387. * @return array
  388. */
  389. abstract public function getClasses();
  390. /**
  391. * Returns the number of executable lines.
  392. *
  393. * @return integer
  394. */
  395. abstract public function getNumExecutableLines();
  396. /**
  397. * Returns the number of executed lines.
  398. *
  399. * @return integer
  400. */
  401. abstract public function getNumExecutedLines();
  402. /**
  403. * Returns the number of classes.
  404. *
  405. * @return integer
  406. */
  407. abstract public function getNumClasses();
  408. /**
  409. * Returns the number of classes of which at least one method
  410. * has been called at least once.
  411. *
  412. * @return integer
  413. */
  414. abstract public function getNumCalledClasses();
  415. /**
  416. * Returns the number of methods.
  417. *
  418. * @return integer
  419. */
  420. abstract public function getNumMethods();
  421. /**
  422. * Returns the number of methods that has been called at least once.
  423. *
  424. * @return integer
  425. */
  426. abstract public function getNumCalledMethods();
  427. /**
  428. * Renders this node.
  429. *
  430. * @param string $target
  431. * @param string $title
  432. * @param string $charset
  433. * @param integer $lowUpperBound
  434. * @param integer $highLowerBound
  435. */
  436. abstract public function render($target, $title, $charset = 'ISO-8859-1', $lowUpperBound = 35, $highLowerBound = 70);
  437. }
  438. ?>