/tests/_PHPUnitCommon/phpunit_helpers/MockWrapper.php

https://github.com/georgeredinger/openinviter · PHP · 453 lines · 142 code · 75 blank · 236 comment · 12 complexity · 016d03765f7f984f9d12ad3f1be7b1ea MD5 · raw file

  1. <?php
  2. /**
  3. * Holds the classes needed to amend PHPUnit's awkward memory-hogging behaviour,
  4. * namely that it tries to dump all the actual parameters of a mocked method
  5. * using print_r() when an expectation for said method has not been met.
  6. * This behaviour causes OutOfMemory errors when an object with a large recursive
  7. * structure is among said actual parameters, like e.g. an Exception with a huge
  8. * stack trace. Who would have thought, that Exceptions, like any other objects
  9. * could be passed around? And that stack traces of these Exceptions could become HUGE
  10. * because they are usually invoked from a test, with HUGE, HEAVILY RECURSIVE objects
  11. * like other mock objects are all around?
  12. *
  13. * PHP version: 5.2
  14. *
  15. * @category File
  16. * @package Testhelper
  17. *
  18. * @author fqqdk <fqqdk@clusterone.hu>
  19. * @license GPL3.0
  20. * GNU GENERAL PUBLIC LICENSE
  21. * Version 3, 29 June 2007
  22. *
  23. * Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  24. * Everyone is permitted to copy and distribute verbatim copies
  25. * of this license document, but changing it is not allowed.
  26. * @link http://www.assembla.com/spaces/p-pex
  27. */
  28. /**
  29. * This class is used to wrap a PHPUnit_Framework_MockObject_InvocationMocker
  30. * instance to provide a way to inject wrapped instances of
  31. * PHPUnit_Framework_MockObject_Matcher_Invocation to it.
  32. *
  33. * @category Class
  34. * @package Testhelper
  35. *
  36. * @author fqqdk <fqqdk@clusterone.hu>
  37. * @license GPL3.0
  38. * GNU GENERAL PUBLIC LICENSE
  39. * Version 3, 29 June 2007
  40. *
  41. * Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  42. * Everyone is permitted to copy and distribute verbatim copies
  43. * of this license document, but changing it is not allowed.
  44. * @link http://www.assembla.com/spaces/p-pex
  45. */
  46. class InvocationMockerWrapper
  47. implements PHPUnit_Framework_MockObject_Stub_MatcherCollection
  48. {
  49. /**
  50. * @var PHPUnit_Framework_MockObject_InvocationMocker the wrapped object
  51. */
  52. private $_delegate;
  53. /**
  54. * Constructor
  55. *
  56. * @param PHPUnit_Framework_MockObject_InvocationMocker $delegate the object
  57. * to wrap
  58. *
  59. * @return InvocationMockerWrapper
  60. */
  61. public function __construct(PHPUnit_Framework_MockObject_InvocationMocker $delegate)
  62. {
  63. $this->_delegate = $delegate;
  64. }//end __construct()
  65. /**
  66. * Wraps the passed matcher instance in a MatcherWrapper and passes it to the delegate
  67. *
  68. * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher the matcher to wrap
  69. *
  70. * @return void
  71. */
  72. public function addMatcher(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
  73. {
  74. $newMatcher = new MatcherWrapper($matcher);
  75. $this->_delegate->addMatcher($newMatcher);
  76. }//end addMatcher()
  77. }//end class
  78. /**
  79. * This class is used to wrap a PHPUnit_Framework_MockObject_MockObject instance
  80. * to provide a way to inject wrapped instances of InvocationMockerWrapper
  81. * to the PHPUnit_Framework_MockObject_Builder_InvocationMocker instance so that
  82. * after a call to expects() an amended expectation builder can be used by test
  83. * method that uses the wrapped mock object.
  84. *
  85. * @category Class
  86. * @package Testhelper
  87. *
  88. * @author fqqdk <fqqdk@clusterone.hu>
  89. * @license GPL3.0
  90. * GNU GENERAL PUBLIC LICENSE
  91. * Version 3, 29 June 2007
  92. *
  93. * Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  94. * Everyone is permitted to copy and distribute verbatim copies
  95. * of this license document, but changing it is not allowed.
  96. * @link http://www.assembla.com/spaces/p-pex
  97. */
  98. class MockObjectWrapper implements PHPUnit_Framework_MockObject_MockObject
  99. {
  100. /**
  101. * @var PHPUnit_Framework_MockObject_MockObject the wrapped mock object
  102. */
  103. public $mock;
  104. /**
  105. * Constructor
  106. *
  107. * @param PHPUnit_Framework_MockObject_MockObject $mock the mock object to wrap
  108. *
  109. * @return MockObjectWrapper
  110. */
  111. public function __construct(PHPUnit_Framework_MockObject_MockObject $mock)
  112. {
  113. $this->mock = $mock;
  114. }//end __construct()
  115. /**
  116. * Uses the passed matcher to create an amended expectation builder to be
  117. * used by the test method that is the client of the wrapped mock object
  118. *
  119. * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher the matcher
  120. *
  121. * @see PHPUnit_Framework_MockObject_MockObject::expects()
  122. * @see PHPUnit_Framework_MockObject_Matcher_Invocation
  123. *
  124. * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker the amended
  125. * expectation
  126. * builder
  127. */
  128. public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
  129. {
  130. $wrapper = new InvocationMockerWrapper(
  131. $this->mock->__phpunit_getInvocationMocker());
  132. $mocker = new PHPUnit_Framework_MockObject_Builder_InvocationMocker(
  133. $wrapper,
  134. $matcher
  135. );
  136. return $mocker;
  137. }//end expects()
  138. /**
  139. * Simply delegates
  140. *
  141. * @return PHPUnit_Framework_MockObject_InvocationMocker
  142. */
  143. public function __phpunit_getInvocationMocker()
  144. {
  145. return $this->mock->__phpunit_getInvocationMocker();
  146. }//end __phpunit_getInvocationMocker()
  147. /**
  148. * Simply delegates
  149. *
  150. * @return void
  151. * @throws PHPUnit_Framework_ExpectationFailedException
  152. */
  153. public function __phpunit_verify() {
  154. return $this->mock->__phpunit_verify();
  155. }//end __phpunit_verify()
  156. }//end class
  157. /**
  158. * This class is used to wrap a PHPUnit_Framework_MockObject_Matcher_Invocation instance
  159. * to provide a way to inject wrapped instances of PHPUnit_Framework_MockObject_Invocation
  160. * to the wrapped object.
  161. *
  162. * @category Class
  163. * @package Testhelper
  164. *
  165. * @author fqqdk <fqqdk@clusterone.hu>
  166. * @license GPL3.0
  167. * GNU GENERAL PUBLIC LICENSE
  168. * Version 3, 29 June 2007
  169. *
  170. * Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  171. * Everyone is permitted to copy and distribute verbatim copies
  172. * of this license document, but changing it is not allowed.
  173. * @link http://www.assembla.com/spaces/p-pex
  174. */
  175. class MatcherWrapper implements PHPUnit_Framework_MockObject_Matcher_Invocation
  176. {
  177. /**
  178. * @var PHPUnit_Framework_MockObject_Matcher_Invocation the wrapped matcher
  179. */
  180. private $_delegate;
  181. /**
  182. * Constructor
  183. *
  184. * @param PHPUnit_Framework_MockObject_Matcher_Invocation $delegate the matcher to wrap
  185. *
  186. * @return MatcherWrapper
  187. */
  188. public function __construct(PHPUnit_Framework_MockObject_Matcher_Invocation $delegate)
  189. {
  190. $this->_delegate = $delegate;
  191. }//end __construct()
  192. /**
  193. * This method is used to inject wrapped invocations (instances of
  194. * PHPUnit_Framework_MockObject_Invocation wrapped with InvocationWrapper)
  195. * to the delegate
  196. *
  197. * @param PHPUnit_Framework_MockObject_Invocation $invocation the invocation
  198. *
  199. * @override
  200. *
  201. * @return mixed
  202. */
  203. public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
  204. {
  205. $wrapper = new InvocationWrapper($invocation);
  206. return $this->_delegate->invoked($wrapper);
  207. }//end invoked()
  208. /**
  209. * This method is used to inject wrapped invocations (instances of
  210. * PHPUnit_Framework_MockObject_Invocation wrapped with InvocationWrapper)
  211. * to the delegate
  212. *
  213. * @param PHPUnit_Framework_MockObject_Invocation $invocation the invocation
  214. *
  215. * @override
  216. *
  217. * @return bool
  218. */
  219. public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
  220. {
  221. $wrapper = new InvocationWrapper($invocation);
  222. return $this->_delegate->matches($wrapper);
  223. }//end matches()
  224. /**
  225. * Just a simple delegating method
  226. *
  227. * @return string
  228. */
  229. public function toString()
  230. {
  231. return $this->_delegate->toString();
  232. }//end toString()
  233. /**
  234. * Just a simple delegating method
  235. *
  236. * @return void
  237. */
  238. public function verify()
  239. {
  240. return $this->_delegate->verify();
  241. }//end verify()
  242. }//end class
  243. /**
  244. * Wraps an instance of PHPUnit_Framework_MockObject_Invocation to provide a way
  245. * to intercept calls to its toString() method which would indirectly cause
  246. * out of memory errors when any of the actual parameters of the invocation represented
  247. * by the wrapped object is too complex to simply print_r() them.
  248. *
  249. * @category Class
  250. * @package Testhelper
  251. *
  252. * @author fqqdk <fqqdk@clusterone.hu>
  253. * @license GPL3.0
  254. * GNU GENERAL PUBLIC LICENSE
  255. * Version 3, 29 June 2007
  256. *
  257. * Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  258. * Everyone is permitted to copy and distribute verbatim copies
  259. * of this license document, but changing it is not allowed.
  260. * @link http://www.assembla.com/spaces/p-pex
  261. */
  262. class InvocationWrapper extends PHPUnit_Framework_MockObject_Invocation
  263. {
  264. /**
  265. * @var mixed the object
  266. */
  267. public $object;
  268. /**
  269. * @var string the class name
  270. */
  271. public $className;
  272. /**
  273. * @var string the name of the method
  274. */
  275. public $methodName;
  276. /**
  277. * @var array the actual parameters of the invocation
  278. */
  279. public $parameters;
  280. /**
  281. * Constructor
  282. *
  283. * @param PHPUnit_Framework_MockObject_Invocation $delegate the object to wrap
  284. *
  285. * @return InvocationWrapper
  286. */
  287. public function __construct(PHPUnit_Framework_MockObject_Invocation $delegate)
  288. {
  289. $this->object = $delegate->object;
  290. $this->className = $delegate->className;
  291. $this->methodName = $delegate->methodName;
  292. $this->parameters = $delegate->parameters;
  293. }//end __construct()
  294. /**
  295. * Prints a SHORT, human readable summary of the invocation.
  296. *
  297. * @return string
  298. */
  299. public function toString()
  300. {
  301. return sprintf('%s::%s(%s)',
  302. $this->className,
  303. $this->methodName,
  304. join(
  305. ', ',
  306. array_map(
  307. array($this, 'shortenedExport'),
  308. $this->parameters
  309. )
  310. )
  311. );
  312. }//end toString()
  313. /**
  314. * Copypasted and amended version of PHPUnit_Util_Type::shortenedExport()
  315. * In this version, every call to PHPUnit_Util_Type::toString() is called
  316. * with true passed to second parameter ($short) which PHPUnit's version of this
  317. * method does not do.
  318. *
  319. * @param mixed $variable the variable to output
  320. *
  321. * @return string
  322. */
  323. public function shortenedExport($variable)
  324. {
  325. if (is_string($variable)) {
  326. return PHPUnit_Util_Type::shortenedString($variable);
  327. } elseif (is_array($variable)) {
  328. return $this->shortenedExportArray($variable);
  329. } else if (is_object($variable)) {
  330. return get_class($variable) . '(...)';
  331. }
  332. return PHPUnit_Util_Type::toString($variable, true);
  333. }//end shortenedExport()
  334. /**
  335. * Exports an array variable
  336. *
  337. * @param array $variable the variable to export
  338. *
  339. * @return string
  340. */
  341. private function shortenedExportArray(array $variable)
  342. {
  343. if (count($variable) == 0) {
  344. return 'array()';
  345. }
  346. $a1 = array_slice($variable, 0, 1, true);
  347. $k1 = key($a1);
  348. $v1 = $a1[$k1];
  349. if (is_string($v1)) {
  350. $v1 = PHPUnit_Util_Type::shortenedString($v1);
  351. } elseif (is_array($v1)) {
  352. $v1 = 'array(...)';
  353. } else {
  354. $v1 = PHPUnit_Util_Type::toString($v1, true);
  355. }
  356. $a2 = false;
  357. if (count($variable) > 1) {
  358. $a2 = array_slice($variable, -1, 1, true);
  359. $k2 = key($a2);
  360. $v2 = $a2[$k2];
  361. if (is_string($v2)) {
  362. $v2 = PHPUnit_Util_Type::shortenedString($v2);
  363. } elseif (is_array($v2)) {
  364. $v2 = 'array(...)';
  365. } else {
  366. $v2 = PHPUnit_Util_Type::toString($v2, true);
  367. }
  368. }
  369. $text = 'array( ' . PHPUnit_Util_Type::toString($k1, true) . ' => ' . $v1;
  370. if ($a2 !== false) {
  371. $text .= ', ..., ' . PHPUnit_Util_Type::toString($k2, true) . ' => ' . $v2 . ' )';
  372. } else {
  373. $text .= ' )';
  374. }
  375. return $text;
  376. }//end shortenedExportArray()
  377. }//end class
  378. ?>