LimeOutputTap.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. /*
  3. * This file is part of the Lime framework.
  4. *
  5. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  6. * (c) Bernhard Schussek <bernhard.schussek@symfony-project.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. class LimeOutputTap implements LimeOutputInterface
  12. {
  13. protected
  14. $options = array(),
  15. $expected = null,
  16. $passed = 0,
  17. $actual = 0,
  18. $warnings = 0,
  19. $errors = 0,
  20. $file = null,
  21. $printer = null;
  22. public function __construct(LimePrinter $printer, array $options = array())
  23. {
  24. $this->printer = $printer;
  25. $this->options = array_merge(array(
  26. 'verbose' => false,
  27. 'base_dir' => null,
  28. ), $options);
  29. }
  30. public function supportsThreading()
  31. {
  32. return false;
  33. }
  34. private function stripBaseDir($path)
  35. {
  36. return is_null($this->options['base_dir']) ? $path : str_replace($this->options['base_dir'], '', $path);
  37. }
  38. public function focus($file)
  39. {
  40. if ($this->file !== $file)
  41. {
  42. $this->printer->printLine('# '.$this->stripBaseDir($file), LimePrinter::INFO);
  43. $this->file = $file;
  44. }
  45. }
  46. public function close()
  47. {
  48. }
  49. public function plan($amount)
  50. {
  51. $this->expected += $amount;
  52. }
  53. public function pass($message, $file, $line)
  54. {
  55. $this->actual++;
  56. $this->passed++;
  57. if (empty($message))
  58. {
  59. $this->printer->printLine('ok '.$this->actual, LimePrinter::OK);
  60. }
  61. else
  62. {
  63. $this->printer->printText('ok '.$this->actual, LimePrinter::OK);
  64. $this->printer->printLine(' - '.$message);
  65. }
  66. }
  67. public function fail($message, $file, $line, $error = null)
  68. {
  69. $this->actual++;
  70. if (empty($message))
  71. {
  72. $this->printer->printLine('not ok '.$this->actual, LimePrinter::NOT_OK);
  73. }
  74. else
  75. {
  76. $this->printer->printText('not ok '.$this->actual, LimePrinter::NOT_OK);
  77. $this->printer->printLine(' - '.$message);
  78. }
  79. $this->printer->printLine(sprintf('# Failed test (%s at line %s)', $this->stripBaseDir($file), $line), LimePrinter::COMMENT);
  80. if (!is_null($error))
  81. {
  82. foreach (explode("\n", $error) as $line)
  83. {
  84. $this->printer->printLine('# '.$line, LimePrinter::COMMENT);
  85. }
  86. }
  87. }
  88. public function skip($message, $file, $line)
  89. {
  90. $this->actual++;
  91. $this->passed++;
  92. if (empty($message))
  93. {
  94. $this->printer->printText('ok '.$this->actual, LimePrinter::SKIP);
  95. $this->printer->printText(' ');
  96. }
  97. else
  98. {
  99. $this->printer->printText('ok '.$this->actual, LimePrinter::SKIP);
  100. $this->printer->printText(' - '.$message.' ');
  101. }
  102. $this->printer->printLine('# SKIP', LimePrinter::SKIP);
  103. }
  104. public function todo($message, $file, $line)
  105. {
  106. $this->actual++;
  107. $this->passed++;
  108. if (empty($message))
  109. {
  110. $this->printer->printText('not ok '.$this->actual, LimePrinter::TODO);
  111. $this->printer->printText(' ');
  112. }
  113. else
  114. {
  115. $this->printer->printText('not ok '.$this->actual, LimePrinter::TODO);
  116. $this->printer->printText(' - '.$message.' ');
  117. }
  118. $this->printer->printLine('# TODO', LimePrinter::TODO);
  119. }
  120. public function warning($message, $file, $line)
  121. {
  122. $this->warnings++;
  123. $message .= sprintf("\n(in %s on line %s)", $this->stripBaseDir($file), $line);
  124. $this->printer->printLargeBox($message, LimePrinter::WARNING);
  125. }
  126. public function error(LimeError $error)
  127. {
  128. $this->errors++;
  129. $message = sprintf("%s: %s\n(in %s on line %s)", $error->getType(),
  130. $error->getMessage(), $this->stripBaseDir($error->getFile()), $error->getLine());
  131. $this->printer->printLargeBox($message, LimePrinter::ERROR);
  132. $this->printer->printLine('Exception trace:', LimePrinter::COMMENT);
  133. $this->printTrace(null, $error->getFile(), $error->getLine());
  134. foreach ($error->getTrace() as $trace)
  135. {
  136. // hide the part of the trace that is responsible for getting the
  137. // annotations to work
  138. if (strpos($trace['function'], '__lime_annotation_') === 0 && !$this->options['verbose'])
  139. {
  140. break;
  141. }
  142. if (array_key_exists('class', $trace))
  143. {
  144. $method = sprintf('%s%s%s()', $trace['class'], $trace['type'], $trace['function']);
  145. }
  146. else
  147. {
  148. $method = sprintf('%s()', $trace['function']);
  149. }
  150. if (array_key_exists('file', $trace))
  151. {
  152. $this->printTrace($method, $trace['file'], $trace['line']);
  153. }
  154. else
  155. {
  156. $this->printTrace($method);
  157. }
  158. }
  159. $this->printer->printLine('');
  160. }
  161. private function printTrace($method = null, $file = null, $line = null)
  162. {
  163. if (!is_null($method))
  164. {
  165. $method .= ' ';
  166. }
  167. $this->printer->printText(' '.$method.'at ');
  168. if (!is_null($file) && !is_null($line))
  169. {
  170. $this->printer->printText($this->stripBaseDir($file), LimePrinter::TRACE);
  171. $this->printer->printText(':');
  172. $this->printer->printLine($line, LimePrinter::TRACE);
  173. }
  174. else
  175. {
  176. $this->printer->printLine('[internal function]');
  177. }
  178. }
  179. public function info($message)
  180. {
  181. $this->printer->printLine('# '.$message, LimePrinter::INFO);
  182. }
  183. public function comment($message)
  184. {
  185. $this->printer->printLine('# '.$message, LimePrinter::COMMENT);
  186. }
  187. public static function getMessages($actual, $expected, $passed, $errors, $warnings)
  188. {
  189. $messages = array();
  190. if ($passed == $expected && $passed === $actual && $errors == 0)
  191. {
  192. if ($warnings > 0)
  193. {
  194. $messages[] = array('Looks like you\'re nearly there.', LimePrinter::WARNING);
  195. }
  196. else
  197. {
  198. $messages[] = array('Looks like everything went fine.', LimePrinter::HAPPY);
  199. }
  200. }
  201. else if ($passed != $actual)
  202. {
  203. $messages[] = array(sprintf('Looks like you failed %s tests of %s.', $actual - $passed, $actual), LimePrinter::ERROR);
  204. }
  205. else if ($errors > 0)
  206. {
  207. $messages[] = array('Looks like some errors occurred.', LimePrinter::ERROR);
  208. }
  209. if ($actual > $expected && $expected > 0)
  210. {
  211. $messages[] = array(sprintf('Looks like you only planned %s tests but ran %s.', $expected, $actual), LimePrinter::ERROR);
  212. }
  213. else if ($actual < $expected)
  214. {
  215. $messages[] = array(sprintf('Looks like you planned %s tests but only ran %s.', $expected, $actual), LimePrinter::ERROR);
  216. }
  217. return $messages;
  218. }
  219. public function flush()
  220. {
  221. if (is_null($this->expected))
  222. {
  223. $this->plan($this->actual);
  224. }
  225. $this->printer->printLine('1..'.$this->expected);
  226. $messages = self::getMessages($this->actual, $this->expected, $this->passed, $this->errors, $this->warnings);
  227. foreach ($messages as $message)
  228. {
  229. list ($message, $style) = $message;
  230. $this->printer->printBox(' '.$message, $style);
  231. }
  232. }
  233. }