expectation.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. <?php
  2. /**
  3. * base include file for SimpleTest
  4. * @package SimpleTest
  5. * @subpackage UnitTester
  6. * @version $Id: expectation.php 2009 2011-04-28 08:57:25Z pp11 $
  7. */
  8. /**#@+
  9. * include other SimpleTest class files
  10. */
  11. require_once(dirname(__FILE__) . '/dumper.php');
  12. require_once(dirname(__FILE__) . '/compatibility.php');
  13. /**#@-*/
  14. /**
  15. * Assertion that can display failure information.
  16. * Also includes various helper methods.
  17. * @package SimpleTest
  18. * @subpackage UnitTester
  19. * @abstract
  20. */
  21. class SimpleExpectation {
  22. protected $dumper = false;
  23. private $message;
  24. /**
  25. * Creates a dumper for displaying values and sets
  26. * the test message.
  27. * @param string $message Customised message on failure.
  28. */
  29. function __construct($message = '%s') {
  30. $this->message = $message;
  31. }
  32. /**
  33. * Tests the expectation. True if correct.
  34. * @param mixed $compare Comparison value.
  35. * @return boolean True if correct.
  36. * @access public
  37. * @abstract
  38. */
  39. function test($compare) {
  40. }
  41. /**
  42. * Returns a human readable test message.
  43. * @param mixed $compare Comparison value.
  44. * @return string Description of success
  45. * or failure.
  46. * @access public
  47. * @abstract
  48. */
  49. function testMessage($compare) {
  50. }
  51. /**
  52. * Overlays the generated message onto the stored user
  53. * message. An additional message can be interjected.
  54. * @param mixed $compare Comparison value.
  55. * @param SimpleDumper $dumper For formatting the results.
  56. * @return string Description of success
  57. * or failure.
  58. * @access public
  59. */
  60. function overlayMessage($compare, $dumper) {
  61. $this->dumper = $dumper;
  62. return sprintf($this->message, $this->testMessage($compare));
  63. }
  64. /**
  65. * Accessor for the dumper.
  66. * @return SimpleDumper Current value dumper.
  67. * @access protected
  68. */
  69. protected function getDumper() {
  70. if (! $this->dumper) {
  71. $dumper = new SimpleDumper();
  72. return $dumper;
  73. }
  74. return $this->dumper;
  75. }
  76. /**
  77. * Test to see if a value is an expectation object.
  78. * A useful utility method.
  79. * @param mixed $expectation Hopefully an Expectation
  80. * class.
  81. * @return boolean True if descended from
  82. * this class.
  83. * @access public
  84. */
  85. static function isExpectation($expectation) {
  86. return is_object($expectation) &&
  87. SimpleTestCompatibility::isA($expectation, 'SimpleExpectation');
  88. }
  89. }
  90. /**
  91. * A wildcard expectation always matches.
  92. * @package SimpleTest
  93. * @subpackage MockObjects
  94. */
  95. class AnythingExpectation extends SimpleExpectation {
  96. /**
  97. * Tests the expectation. Always true.
  98. * @param mixed $compare Ignored.
  99. * @return boolean True.
  100. * @access public
  101. */
  102. function test($compare) {
  103. return true;
  104. }
  105. /**
  106. * Returns a human readable test message.
  107. * @param mixed $compare Comparison value.
  108. * @return string Description of success
  109. * or failure.
  110. * @access public
  111. */
  112. function testMessage($compare) {
  113. $dumper = $this->getDumper();
  114. return 'Anything always matches [' . $dumper->describeValue($compare) . ']';
  115. }
  116. }
  117. /**
  118. * An expectation that never matches.
  119. * @package SimpleTest
  120. * @subpackage MockObjects
  121. */
  122. class FailedExpectation extends SimpleExpectation {
  123. /**
  124. * Tests the expectation. Always false.
  125. * @param mixed $compare Ignored.
  126. * @return boolean True.
  127. * @access public
  128. */
  129. function test($compare) {
  130. return false;
  131. }
  132. /**
  133. * Returns a human readable test message.
  134. * @param mixed $compare Comparison value.
  135. * @return string Description of failure.
  136. * @access public
  137. */
  138. function testMessage($compare) {
  139. $dumper = $this->getDumper();
  140. return 'Failed expectation never matches [' . $dumper->describeValue($compare) . ']';
  141. }
  142. }
  143. /**
  144. * An expectation that passes on boolean true.
  145. * @package SimpleTest
  146. * @subpackage MockObjects
  147. */
  148. class TrueExpectation extends SimpleExpectation {
  149. /**
  150. * Tests the expectation.
  151. * @param mixed $compare Should be true.
  152. * @return boolean True on match.
  153. * @access public
  154. */
  155. function test($compare) {
  156. return (boolean)$compare;
  157. }
  158. /**
  159. * Returns a human readable test message.
  160. * @param mixed $compare Comparison value.
  161. * @return string Description of success
  162. * or failure.
  163. * @access public
  164. */
  165. function testMessage($compare) {
  166. $dumper = $this->getDumper();
  167. return 'Expected true, got [' . $dumper->describeValue($compare) . ']';
  168. }
  169. }
  170. /**
  171. * An expectation that passes on boolean false.
  172. * @package SimpleTest
  173. * @subpackage MockObjects
  174. */
  175. class FalseExpectation extends SimpleExpectation {
  176. /**
  177. * Tests the expectation.
  178. * @param mixed $compare Should be false.
  179. * @return boolean True on match.
  180. * @access public
  181. */
  182. function test($compare) {
  183. return ! (boolean)$compare;
  184. }
  185. /**
  186. * Returns a human readable test message.
  187. * @param mixed $compare Comparison value.
  188. * @return string Description of success
  189. * or failure.
  190. * @access public
  191. */
  192. function testMessage($compare) {
  193. $dumper = $this->getDumper();
  194. return 'Expected false, got [' . $dumper->describeValue($compare) . ']';
  195. }
  196. }
  197. /**
  198. * Test for equality.
  199. * @package SimpleTest
  200. * @subpackage UnitTester
  201. */
  202. class EqualExpectation extends SimpleExpectation {
  203. private $value;
  204. /**
  205. * Sets the value to compare against.
  206. * @param mixed $value Test value to match.
  207. * @param string $message Customised message on failure.
  208. * @access public
  209. */
  210. function __construct($value, $message = '%s') {
  211. parent::__construct($message);
  212. $this->value = $value;
  213. }
  214. /**
  215. * Tests the expectation. True if it matches the
  216. * held value.
  217. * @param mixed $compare Comparison value.
  218. * @return boolean True if correct.
  219. * @access public
  220. */
  221. function test($compare) {
  222. return (($this->value == $compare) && ($compare == $this->value));
  223. }
  224. /**
  225. * Returns a human readable test message.
  226. * @param mixed $compare Comparison value.
  227. * @return string Description of success
  228. * or failure.
  229. * @access public
  230. */
  231. function testMessage($compare) {
  232. if ($this->test($compare)) {
  233. return "Equal expectation [" . $this->dumper->describeValue($this->value) . "]";
  234. } else {
  235. return "Equal expectation fails " .
  236. $this->dumper->describeDifference($this->value, $compare);
  237. }
  238. }
  239. /**
  240. * Accessor for comparison value.
  241. * @return mixed Held value to compare with.
  242. * @access protected
  243. */
  244. protected function getValue() {
  245. return $this->value;
  246. }
  247. }
  248. /**
  249. * Test for inequality.
  250. * @package SimpleTest
  251. * @subpackage UnitTester
  252. */
  253. class NotEqualExpectation extends EqualExpectation {
  254. /**
  255. * Sets the value to compare against.
  256. * @param mixed $value Test value to match.
  257. * @param string $message Customised message on failure.
  258. * @access public
  259. */
  260. function __construct($value, $message = '%s') {
  261. parent::__construct($value, $message);
  262. }
  263. /**
  264. * Tests the expectation. True if it differs from the
  265. * held value.
  266. * @param mixed $compare Comparison value.
  267. * @return boolean True if correct.
  268. * @access public
  269. */
  270. function test($compare) {
  271. return ! parent::test($compare);
  272. }
  273. /**
  274. * Returns a human readable test message.
  275. * @param mixed $compare Comparison value.
  276. * @return string Description of success
  277. * or failure.
  278. * @access public
  279. */
  280. function testMessage($compare) {
  281. $dumper = $this->getDumper();
  282. if ($this->test($compare)) {
  283. return "Not equal expectation passes " .
  284. $dumper->describeDifference($this->getValue(), $compare);
  285. } else {
  286. return "Not equal expectation fails [" .
  287. $dumper->describeValue($this->getValue()) .
  288. "] matches";
  289. }
  290. }
  291. }
  292. /**
  293. * Test for being within a range.
  294. * @package SimpleTest
  295. * @subpackage UnitTester
  296. */
  297. class WithinMarginExpectation extends SimpleExpectation {
  298. private $upper;
  299. private $lower;
  300. /**
  301. * Sets the value to compare against and the fuzziness of
  302. * the match. Used for comparing floating point values.
  303. * @param mixed $value Test value to match.
  304. * @param mixed $margin Fuzziness of match.
  305. * @param string $message Customised message on failure.
  306. * @access public
  307. */
  308. function __construct($value, $margin, $message = '%s') {
  309. parent::__construct($message);
  310. $this->upper = $value + $margin;
  311. $this->lower = $value - $margin;
  312. }
  313. /**
  314. * Tests the expectation. True if it matches the
  315. * held value.
  316. * @param mixed $compare Comparison value.
  317. * @return boolean True if correct.
  318. * @access public
  319. */
  320. function test($compare) {
  321. return (($compare <= $this->upper) && ($compare >= $this->lower));
  322. }
  323. /**
  324. * Returns a human readable test message.
  325. * @param mixed $compare Comparison value.
  326. * @return string Description of success
  327. * or failure.
  328. * @access public
  329. */
  330. function testMessage($compare) {
  331. if ($this->test($compare)) {
  332. return $this->withinMessage($compare);
  333. } else {
  334. return $this->outsideMessage($compare);
  335. }
  336. }
  337. /**
  338. * Creates a the message for being within the range.
  339. * @param mixed $compare Value being tested.
  340. * @access private
  341. */
  342. protected function withinMessage($compare) {
  343. return "Within expectation [" . $this->dumper->describeValue($this->lower) . "] and [" .
  344. $this->dumper->describeValue($this->upper) . "]";
  345. }
  346. /**
  347. * Creates a the message for being within the range.
  348. * @param mixed $compare Value being tested.
  349. * @access private
  350. */
  351. protected function outsideMessage($compare) {
  352. if ($compare > $this->upper) {
  353. return "Outside expectation " .
  354. $this->dumper->describeDifference($compare, $this->upper);
  355. } else {
  356. return "Outside expectation " .
  357. $this->dumper->describeDifference($compare, $this->lower);
  358. }
  359. }
  360. }
  361. /**
  362. * Test for being outside of a range.
  363. * @package SimpleTest
  364. * @subpackage UnitTester
  365. */
  366. class OutsideMarginExpectation extends WithinMarginExpectation {
  367. /**
  368. * Sets the value to compare against and the fuzziness of
  369. * the match. Used for comparing floating point values.
  370. * @param mixed $value Test value to not match.
  371. * @param mixed $margin Fuzziness of match.
  372. * @param string $message Customised message on failure.
  373. * @access public
  374. */
  375. function __construct($value, $margin, $message = '%s') {
  376. parent::__construct($value, $margin, $message);
  377. }
  378. /**
  379. * Tests the expectation. True if it matches the
  380. * held value.
  381. * @param mixed $compare Comparison value.
  382. * @return boolean True if correct.
  383. * @access public
  384. */
  385. function test($compare) {
  386. return ! parent::test($compare);
  387. }
  388. /**
  389. * Returns a human readable test message.
  390. * @param mixed $compare Comparison value.
  391. * @return string Description of success
  392. * or failure.
  393. * @access public
  394. */
  395. function testMessage($compare) {
  396. if (! $this->test($compare)) {
  397. return $this->withinMessage($compare);
  398. } else {
  399. return $this->outsideMessage($compare);
  400. }
  401. }
  402. }
  403. /**
  404. * Test for reference.
  405. * @package SimpleTest
  406. * @subpackage UnitTester
  407. */
  408. class ReferenceExpectation {
  409. private $value;
  410. /**
  411. * Sets the reference value to compare against.
  412. * @param mixed $value Test reference to match.
  413. * @param string $message Customised message on failure.
  414. * @access public
  415. */
  416. function __construct(&$value, $message = '%s') {
  417. $this->message = $message;
  418. $this->value = &$value;
  419. }
  420. /**
  421. * Tests the expectation. True if it exactly
  422. * references the held value.
  423. * @param mixed $compare Comparison reference.
  424. * @return boolean True if correct.
  425. * @access public
  426. */
  427. function test(&$compare) {
  428. return SimpleTestCompatibility::isReference($this->value, $compare);
  429. }
  430. /**
  431. * Returns a human readable test message.
  432. * @param mixed $compare Comparison value.
  433. * @return string Description of success
  434. * or failure.
  435. * @access public
  436. */
  437. function testMessage($compare) {
  438. if ($this->test($compare)) {
  439. return "Reference expectation [" . $this->dumper->describeValue($this->value) . "]";
  440. } else {
  441. return "Reference expectation fails " .
  442. $this->dumper->describeDifference($this->value, $compare);
  443. }
  444. }
  445. /**
  446. * Overlays the generated message onto the stored user
  447. * message. An additional message can be interjected.
  448. * @param mixed $compare Comparison value.
  449. * @param SimpleDumper $dumper For formatting the results.
  450. * @return string Description of success
  451. * or failure.
  452. * @access public
  453. */
  454. function overlayMessage($compare, $dumper) {
  455. $this->dumper = $dumper;
  456. return sprintf($this->message, $this->testMessage($compare));
  457. }
  458. /**
  459. * Accessor for the dumper.
  460. * @return SimpleDumper Current value dumper.
  461. * @access protected
  462. */
  463. protected function getDumper() {
  464. if (! $this->dumper) {
  465. $dumper = new SimpleDumper();
  466. return $dumper;
  467. }
  468. return $this->dumper;
  469. }
  470. }
  471. /**
  472. * Test for identity.
  473. * @package SimpleTest
  474. * @subpackage UnitTester
  475. */
  476. class IdenticalExpectation extends EqualExpectation {
  477. /**
  478. * Sets the value to compare against.
  479. * @param mixed $value Test value to match.
  480. * @param string $message Customised message on failure.
  481. * @access public
  482. */
  483. function __construct($value, $message = '%s') {
  484. parent::__construct($value, $message);
  485. }
  486. /**
  487. * Tests the expectation. True if it exactly
  488. * matches the held value.
  489. * @param mixed $compare Comparison value.
  490. * @return boolean True if correct.
  491. * @access public
  492. */
  493. function test($compare) {
  494. return SimpleTestCompatibility::isIdentical($this->getValue(), $compare);
  495. }
  496. /**
  497. * Returns a human readable test message.
  498. * @param mixed $compare Comparison value.
  499. * @return string Description of success
  500. * or failure.
  501. * @access public
  502. */
  503. function testMessage($compare) {
  504. $dumper = $this->getDumper();
  505. if ($this->test($compare)) {
  506. return "Identical expectation [" . $dumper->describeValue($this->getValue()) . "]";
  507. } else {
  508. return "Identical expectation [" . $dumper->describeValue($this->getValue()) .
  509. "] fails with [" .
  510. $dumper->describeValue($compare) . "] " .
  511. $dumper->describeDifference($this->getValue(), $compare, TYPE_MATTERS);
  512. }
  513. }
  514. }
  515. /**
  516. * Test for non-identity.
  517. * @package SimpleTest
  518. * @subpackage UnitTester
  519. */
  520. class NotIdenticalExpectation extends IdenticalExpectation {
  521. /**
  522. * Sets the value to compare against.
  523. * @param mixed $value Test value to match.
  524. * @param string $message Customised message on failure.
  525. * @access public
  526. */
  527. function __construct($value, $message = '%s') {
  528. parent::__construct($value, $message);
  529. }
  530. /**
  531. * Tests the expectation. True if it differs from the
  532. * held value.
  533. * @param mixed $compare Comparison value.
  534. * @return boolean True if correct.
  535. * @access public
  536. */
  537. function test($compare) {
  538. return ! parent::test($compare);
  539. }
  540. /**
  541. * Returns a human readable test message.
  542. * @param mixed $compare Comparison value.
  543. * @return string Description of success
  544. * or failure.
  545. * @access public
  546. */
  547. function testMessage($compare) {
  548. $dumper = $this->getDumper();
  549. if ($this->test($compare)) {
  550. return "Not identical expectation passes " .
  551. $dumper->describeDifference($this->getValue(), $compare, TYPE_MATTERS);
  552. } else {
  553. return "Not identical expectation [" . $dumper->describeValue($this->getValue()) . "] matches";
  554. }
  555. }
  556. }
  557. /**
  558. * Test for a pattern using Perl regex rules.
  559. * @package SimpleTest
  560. * @subpackage UnitTester
  561. */
  562. class PatternExpectation extends SimpleExpectation {
  563. private $pattern;
  564. /**
  565. * Sets the value to compare against.
  566. * @param string $pattern Pattern to search for.
  567. * @param string $message Customised message on failure.
  568. * @access public
  569. */
  570. function __construct($pattern, $message = '%s') {
  571. parent::__construct($message);
  572. $this->pattern = $pattern;
  573. }
  574. /**
  575. * Accessor for the pattern.
  576. * @return string Perl regex as string.
  577. * @access protected
  578. */
  579. protected function getPattern() {
  580. return $this->pattern;
  581. }
  582. /**
  583. * Tests the expectation. True if the Perl regex
  584. * matches the comparison value.
  585. * @param string $compare Comparison value.
  586. * @return boolean True if correct.
  587. * @access public
  588. */
  589. function test($compare) {
  590. return (boolean)preg_match($this->getPattern(), $compare);
  591. }
  592. /**
  593. * Returns a human readable test message.
  594. * @param mixed $compare Comparison value.
  595. * @return string Description of success
  596. * or failure.
  597. * @access public
  598. */
  599. function testMessage($compare) {
  600. if ($this->test($compare)) {
  601. return $this->describePatternMatch($this->getPattern(), $compare);
  602. } else {
  603. $dumper = $this->getDumper();
  604. return "Pattern [" . $this->getPattern() .
  605. "] not detected in [" .
  606. $dumper->describeValue($compare) . "]";
  607. }
  608. }
  609. /**
  610. * Describes a pattern match including the string
  611. * found and it's position.
  612. * @param string $pattern Regex to match against.
  613. * @param string $subject Subject to search.
  614. * @access protected
  615. */
  616. protected function describePatternMatch($pattern, $subject) {
  617. preg_match($pattern, $subject, $matches);
  618. $position = strpos($subject, $matches[0]);
  619. $dumper = $this->getDumper();
  620. return "Pattern [$pattern] detected at character [$position] in [" .
  621. $dumper->describeValue($subject) . "] as [" .
  622. $matches[0] . "] in region [" .
  623. $dumper->clipString($subject, 100, $position) . "]";
  624. }
  625. }
  626. /**
  627. * Fail if a pattern is detected within the
  628. * comparison.
  629. * @package SimpleTest
  630. * @subpackage UnitTester
  631. */
  632. class NoPatternExpectation extends PatternExpectation {
  633. /**
  634. * Sets the reject pattern
  635. * @param string $pattern Pattern to search for.
  636. * @param string $message Customised message on failure.
  637. * @access public
  638. */
  639. function __construct($pattern, $message = '%s') {
  640. parent::__construct($pattern, $message);
  641. }
  642. /**
  643. * Tests the expectation. False if the Perl regex
  644. * matches the comparison value.
  645. * @param string $compare Comparison value.
  646. * @return boolean True if correct.
  647. * @access public
  648. */
  649. function test($compare) {
  650. return ! parent::test($compare);
  651. }
  652. /**
  653. * Returns a human readable test message.
  654. * @param string $compare Comparison value.
  655. * @return string Description of success
  656. * or failure.
  657. * @access public
  658. */
  659. function testMessage($compare) {
  660. if ($this->test($compare)) {
  661. $dumper = $this->getDumper();
  662. return "Pattern [" . $this->getPattern() .
  663. "] not detected in [" .
  664. $dumper->describeValue($compare) . "]";
  665. } else {
  666. return $this->describePatternMatch($this->getPattern(), $compare);
  667. }
  668. }
  669. }
  670. /**
  671. * Tests either type or class name if it's an object.
  672. * @package SimpleTest
  673. * @subpackage UnitTester
  674. */
  675. class IsAExpectation extends SimpleExpectation {
  676. private $type;
  677. /**
  678. * Sets the type to compare with.
  679. * @param string $type Type or class name.
  680. * @param string $message Customised message on failure.
  681. * @access public
  682. */
  683. function __construct($type, $message = '%s') {
  684. parent::__construct($message);
  685. $this->type = $type;
  686. }
  687. /**
  688. * Accessor for type to check against.
  689. * @return string Type or class name.
  690. * @access protected
  691. */
  692. protected function getType() {
  693. return $this->type;
  694. }
  695. /**
  696. * Tests the expectation. True if the type or
  697. * class matches the string value.
  698. * @param string $compare Comparison value.
  699. * @return boolean True if correct.
  700. * @access public
  701. */
  702. function test($compare) {
  703. if (is_object($compare)) {
  704. return SimpleTestCompatibility::isA($compare, $this->type);
  705. } else {
  706. $function = 'is_'.$this->canonicalType($this->type);
  707. if (is_callable($function)) {
  708. return $function($compare);
  709. }
  710. return false;
  711. }
  712. }
  713. /**
  714. * Coerces type name into a is_*() match.
  715. * @param string $type User type.
  716. * @return string Simpler type.
  717. * @access private
  718. */
  719. protected function canonicalType($type) {
  720. $type = strtolower($type);
  721. $map = array('boolean' => 'bool');
  722. if (isset($map[$type])) {
  723. $type = $map[$type];
  724. }
  725. return $type;
  726. }
  727. /**
  728. * Returns a human readable test message.
  729. * @param mixed $compare Comparison value.
  730. * @return string Description of success
  731. * or failure.
  732. * @access public
  733. */
  734. function testMessage($compare) {
  735. $dumper = $this->getDumper();
  736. return "Value [" . $dumper->describeValue($compare) .
  737. "] should be type [" . $this->type . "]";
  738. }
  739. }
  740. /**
  741. * Tests either type or class name if it's an object.
  742. * Will succeed if the type does not match.
  743. * @package SimpleTest
  744. * @subpackage UnitTester
  745. */
  746. class NotAExpectation extends IsAExpectation {
  747. private $type;
  748. /**
  749. * Sets the type to compare with.
  750. * @param string $type Type or class name.
  751. * @param string $message Customised message on failure.
  752. * @access public
  753. */
  754. function __construct($type, $message = '%s') {
  755. parent::__construct($type, $message);
  756. }
  757. /**
  758. * Tests the expectation. False if the type or
  759. * class matches the string value.
  760. * @param string $compare Comparison value.
  761. * @return boolean True if different.
  762. * @access public
  763. */
  764. function test($compare) {
  765. return ! parent::test($compare);
  766. }
  767. /**
  768. * Returns a human readable test message.
  769. * @param mixed $compare Comparison value.
  770. * @return string Description of success
  771. * or failure.
  772. * @access public
  773. */
  774. function testMessage($compare) {
  775. $dumper = $this->getDumper();
  776. return "Value [" . $dumper->describeValue($compare) .
  777. "] should not be type [" . $this->getType() . "]";
  778. }
  779. }
  780. /**
  781. * Tests for existance of a method in an object
  782. * @package SimpleTest
  783. * @subpackage UnitTester
  784. */
  785. class MethodExistsExpectation extends SimpleExpectation {
  786. private $method;
  787. /**
  788. * Sets the value to compare against.
  789. * @param string $method Method to check.
  790. * @param string $message Customised message on failure.
  791. * @return void
  792. */
  793. function __construct($method, $message = '%s') {
  794. parent::__construct($message);
  795. $this->method = &$method;
  796. }
  797. /**
  798. * Tests the expectation. True if the method exists in the test object.
  799. * @param string $compare Comparison method name.
  800. * @return boolean True if correct.
  801. */
  802. function test($compare) {
  803. return (boolean)(is_object($compare) && method_exists($compare, $this->method));
  804. }
  805. /**
  806. * Returns a human readable test message.
  807. * @param mixed $compare Comparison value.
  808. * @return string Description of success
  809. * or failure.
  810. */
  811. function testMessage($compare) {
  812. $dumper = $this->getDumper();
  813. if (! is_object($compare)) {
  814. return 'No method on non-object [' . $dumper->describeValue($compare) . ']';
  815. }
  816. $method = $this->method;
  817. return "Object [" . $dumper->describeValue($compare) .
  818. "] should contain method [$method]";
  819. }
  820. }
  821. /**
  822. * Compares an object member's value even if private.
  823. * @package SimpleTest
  824. * @subpackage UnitTester
  825. */
  826. class MemberExpectation extends IdenticalExpectation {
  827. private $name;
  828. /**
  829. * Sets the value to compare against.
  830. * @param string $method Method to check.
  831. * @param string $message Customised message on failure.
  832. * @return void
  833. */
  834. function __construct($name, $expected) {
  835. $this->name = $name;
  836. parent::__construct($expected);
  837. }
  838. /**
  839. * Tests the expectation. True if the property value is identical.
  840. * @param object $actual Comparison object.
  841. * @return boolean True if identical.
  842. */
  843. function test($actual) {
  844. if (! is_object($actual)) {
  845. return false;
  846. }
  847. return parent::test($this->getProperty($this->name, $actual));
  848. }
  849. /**
  850. * Returns a human readable test message.
  851. * @param mixed $compare Comparison value.
  852. * @return string Description of success
  853. * or failure.
  854. */
  855. function testMessage($actual) {
  856. return parent::testMessage($this->getProperty($this->name, $actual));
  857. }
  858. /**
  859. * Extracts the member value even if private using reflection.
  860. * @param string $name Property name.
  861. * @param object $object Object to read.
  862. * @return mixed Value of property.
  863. */
  864. private function getProperty($name, $object) {
  865. $reflection = new ReflectionObject($object);
  866. $property = $reflection->getProperty($name);
  867. if (method_exists($property, 'setAccessible')) {
  868. $property->setAccessible(true);
  869. }
  870. try {
  871. return $property->getValue($object);
  872. } catch (ReflectionException $e) {
  873. return $this->getPrivatePropertyNoMatterWhat($name, $object);
  874. }
  875. }
  876. /**
  877. * Extracts a private member's value when reflection won't play ball.
  878. * @param string $name Property name.
  879. * @param object $object Object to read.
  880. * @return mixed Value of property.
  881. */
  882. private function getPrivatePropertyNoMatterWhat($name, $object) {
  883. foreach ((array)$object as $mangled_name => $value) {
  884. if ($this->unmangle($mangled_name) == $name) {
  885. return $value;
  886. }
  887. }
  888. }
  889. /**
  890. * Removes crud from property name after it's been converted
  891. * to an array.
  892. * @param string $mangled Name from array cast.
  893. * @return string Cleaned up name.
  894. */
  895. function unmangle($mangled) {
  896. $parts = preg_split('/[^a-zA-Z0-9_\x7f-\xff]+/', $mangled);
  897. return array_pop($parts);
  898. }
  899. }
  900. ?>