PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/tests/lib/cake_test_case.php

https://github.com/msadouni/cakephp2x
PHP | 831 lines | 474 code | 84 blank | 273 comment | 104 complexity | 7d6b92ae1c948b4cbe2dc4fcc317c04a MD5 | raw file
  1. <?php
  2. /**
  3. * CakeTestCase file
  4. *
  5. * Long description for file
  6. *
  7. * PHP Version 5.x
  8. *
  9. * CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
  10. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. *
  12. * Licensed under The Open Group Test Suite License
  13. * Redistributions of files must retain the above copyright notice.
  14. *
  15. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  16. * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
  17. * @package cake
  18. * @subpackage cake.cake.tests.libs
  19. * @since CakePHP(tm) v 1.2.0.4667
  20. * @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
  21. */
  22. if (!class_exists('dispatcher')) {
  23. require CAKE . 'dispatcher.php';
  24. }
  25. require_once CAKE_TESTS_LIB . 'cake_test_model.php';
  26. require_once CAKE_TESTS_LIB . 'cake_test_fixture.php';
  27. App::import('Vendor', 'simpletest' . DS . 'unit_tester');
  28. /**
  29. * CakeTestDispatcher
  30. *
  31. * @package cake
  32. * @subpackage cake.cake.tests.lib
  33. */
  34. class CakeTestDispatcher extends Dispatcher {
  35. /**
  36. * controller property
  37. *
  38. * @var Controller
  39. * @access public
  40. */
  41. var $controller;
  42. var $testCase;
  43. /**
  44. * testCase method
  45. *
  46. * @param CakeTestCase $testCase
  47. * @return void
  48. * @access public
  49. */
  50. function testCase(&$testCase) {
  51. $this->testCase = $testCase;
  52. }
  53. /**
  54. * invoke method
  55. *
  56. * @param Controller $controller
  57. * @param array $params
  58. * @param boolean $missingAction
  59. * @return Controller
  60. * @access protected
  61. */
  62. function _invoke(&$controller, $params, $missingAction = false) {
  63. $this->controller = $controller;
  64. if (isset($this->testCase) && method_exists($this->testCase, 'startController')) {
  65. $this->testCase->startController($this->controller, $params);
  66. }
  67. $result = parent::_invoke($this->controller, $params, $missingAction);
  68. if (isset($this->testCase) && method_exists($this->testCase, 'endController')) {
  69. $this->testCase->endController($this->controller, $params);
  70. }
  71. return $result;
  72. }
  73. }
  74. /**
  75. * CakeTestCase class
  76. *
  77. * @package cake
  78. * @subpackage cake.cake.tests.lib
  79. */
  80. class CakeTestCase extends UnitTestCase {
  81. /**
  82. * Methods used internally.
  83. *
  84. * @var array
  85. * @access public
  86. */
  87. var $methods = array('start', 'end', 'startcase', 'endcase', 'starttest', 'endtest');
  88. /**
  89. * By default, all fixtures attached to this class will be truncated and reloaded after each test.
  90. * Set this to false to handle manually
  91. *
  92. * @var array
  93. * @access public
  94. */
  95. var $autoFixtures = true;
  96. /**
  97. * Set this to false to avoid tables to be dropped if they already exist
  98. *
  99. * @var boolean
  100. * @access public
  101. */
  102. var $dropTables = true;
  103. /**
  104. * Maps fixture class names to fixture identifiers as included in CakeTestCase::$fixtures
  105. *
  106. * @var array
  107. * @access protected
  108. */
  109. var $_fixtureClassMap = array();
  110. /**
  111. * truncated property
  112. *
  113. * @var boolean
  114. * @access private
  115. */
  116. var $__truncated = true;
  117. /**
  118. * savedGetData property
  119. *
  120. * @var array
  121. * @access private
  122. */
  123. var $__savedGetData = array();
  124. /**
  125. * Called when a test case (group of methods) is about to start (to be overriden when needed.)
  126. *
  127. * @param string $method Test method about to get executed.
  128. * @return void
  129. * @access public
  130. */
  131. function startCase() {
  132. }
  133. /**
  134. * Called when a test case (group of methods) has been executed (to be overriden when needed.)
  135. *
  136. * @param string $method Test method about that was executed.
  137. * @return void
  138. * @access public
  139. */
  140. function endCase() {
  141. }
  142. /**
  143. * Called when a test case method is about to start (to be overriden when needed.)
  144. *
  145. * @param string $method Test method about to get executed.
  146. * @return void
  147. * @access public
  148. */
  149. function startTest($method) {
  150. }
  151. /**
  152. * Called when a test case method has been executed (to be overriden when needed.)
  153. *
  154. * @param string $method Test method about that was executed.
  155. * @return void
  156. * @access public
  157. */
  158. function endTest($method) {
  159. }
  160. /**
  161. * Overrides SimpleTestCase::assert to enable calling of skipIf() from within tests
  162. *
  163. * @param Expectation $expectation
  164. * @param mixed $compare
  165. * @param string $message
  166. * @return boolean|null
  167. * @access public
  168. */
  169. function assert(&$expectation, $compare, $message = '%s') {
  170. if ($this->_should_skip) {
  171. return;
  172. }
  173. return parent::assert($expectation, $compare, $message);
  174. }
  175. /**
  176. * Overrides SimpleTestCase::skipIf to provide a boolean return value
  177. *
  178. * @param boolean $shouldSkip
  179. * @param string $message
  180. * @return boolean
  181. * @access public
  182. */
  183. function skipIf($shouldSkip, $message = '%s') {
  184. parent::skipIf($shouldSkip, $message);
  185. return $shouldSkip;
  186. }
  187. /**
  188. * Callback issued when a controller's action is about to be invoked through testAction().
  189. *
  190. * @param Controller $controller Controller that's about to be invoked.
  191. * @param array $params Additional parameters as sent by testAction().
  192. * @return void
  193. * @access public
  194. */
  195. function startController(&$controller, $params = array()) {
  196. if (isset($params['fixturize']) && ((is_array($params['fixturize']) && !empty($params['fixturize'])) || $params['fixturize'] === true)) {
  197. if (!isset($this->db)) {
  198. $this->_initDb();
  199. }
  200. if ($controller->uses === false) {
  201. $list = array($controller->modelClass);
  202. } else {
  203. $list = is_array($controller->uses) ? $controller->uses : array($controller->uses);
  204. }
  205. $models = array();
  206. ClassRegistry::config(array('ds' => $params['connection']));
  207. foreach ($list as $name) {
  208. if ((is_array($params['fixturize']) && in_array($name, $params['fixturize'])) || $params['fixturize'] === true) {
  209. if (class_exists($name) || App::import('Model', $name)) {
  210. $object = ClassRegistry::init($name);
  211. //switch back to specified datasource.
  212. $object->setDataSource($params['connection']);
  213. $db = ConnectionManager::getDataSource($object->useDbConfig);
  214. $db->cacheSources = false;
  215. $models[$object->alias] = array(
  216. 'table' => $object->table,
  217. 'model' => $object->alias,
  218. 'key' => strtolower($name),
  219. );
  220. }
  221. }
  222. }
  223. ClassRegistry::config(array('ds' => 'test_suite'));
  224. if (!empty($models) && isset($this->db)) {
  225. $this->_actionFixtures = array();
  226. foreach ($models as $model) {
  227. $fixture = new CakeTestFixture($this->db);
  228. $fixture->name = $model['model'] . 'Test';
  229. $fixture->table = $model['table'];
  230. $fixture->import = array('model' => $model['model'], 'records' => true);
  231. $fixture->init();
  232. $fixture->create($this->db);
  233. $fixture->insert($this->db);
  234. $this->_actionFixtures[] = $fixture;
  235. }
  236. foreach ($models as $model) {
  237. $object = ClassRegistry::getObject($model['key']);
  238. if ($object !== false) {
  239. $object->setDataSource('test_suite');
  240. $object->cacheSources = false;
  241. }
  242. }
  243. }
  244. }
  245. }
  246. /**
  247. * Callback issued when a controller's action has been invoked through testAction().
  248. *
  249. * @param Controller $controller Controller that has been invoked.
  250. * @param array $params Additional parameters as sent by testAction().
  251. * @return void
  252. * @access public
  253. */
  254. function endController(&$controller, $params = array()) {
  255. if (isset($this->db) && isset($this->_actionFixtures) && !empty($this->_actionFixtures) && $this->dropTables) {
  256. foreach ($this->_actionFixtures as $fixture) {
  257. $fixture->drop($this->db);
  258. }
  259. }
  260. }
  261. /**
  262. * Executes a Cake URL, and can get (depending on the $params['return'] value):
  263. *
  264. * Params:
  265. * - 'return' has several possible values:
  266. * 1. 'result': Whatever the action returns (and also specifies $this->params['requested'] for controller)
  267. * 2. 'view': The rendered view, without the layout
  268. * 3. 'contents': The rendered view, within the layout.
  269. * 4. 'vars': the view vars
  270. *
  271. * - 'fixturize' - Set to true if you want to copy model data from 'connection' to the test_suite connection
  272. * - 'data' - The data you want to insert into $this->data in the controller.
  273. * - 'connection' - Which connection to use in conjunction with fixturize (defaults to 'default')
  274. * - 'method' - What type of HTTP method to simulate (defaults to post)
  275. *
  276. * @param string $url Cake URL to execute (e.g: /articles/view/455)
  277. * @param mixed $params Parameters (see above), or simply a string of what to return
  278. * @return mixed Whatever is returned depending of requested result
  279. * @access public
  280. */
  281. function testAction($url, $params = array()) {
  282. $default = array(
  283. 'return' => 'result',
  284. 'fixturize' => false,
  285. 'data' => array(),
  286. 'method' => 'post',
  287. 'connection' => 'default'
  288. );
  289. if (is_string($params)) {
  290. $params = array('return' => $params);
  291. }
  292. $params = array_merge($default, $params);
  293. $toSave = array(
  294. 'case' => null,
  295. 'group' => null,
  296. 'app' => null,
  297. 'output' => null,
  298. 'show' => null,
  299. 'plugin' => null
  300. );
  301. $this->__savedGetData = (empty($this->__savedGetData))
  302. ? array_intersect_key($_GET, $toSave)
  303. : $this->__savedGetData;
  304. $data = (!empty($params['data'])) ? $params['data'] : array();
  305. if (strtolower($params['method']) == 'get') {
  306. $_GET = array_merge($this->__savedGetData, $data);
  307. $_POST = array();
  308. } else {
  309. $_POST = array('data' => $data);
  310. $_GET = $this->__savedGetData;
  311. }
  312. $return = $params['return'];
  313. $params = array_diff_key($params, array('data' => null, 'method' => null, 'return' => null));
  314. $dispatcher = new CakeTestDispatcher();
  315. $dispatcher->testCase($this);
  316. if ($return != 'result') {
  317. if ($return != 'contents') {
  318. $params['layout'] = false;
  319. }
  320. ob_start();
  321. @$dispatcher->dispatch($url, $params);
  322. $result = ob_get_clean();
  323. if ($return == 'vars') {
  324. $view = ClassRegistry::getObject('view');
  325. $viewVars = $view->getVars();
  326. $result = array();
  327. foreach ($viewVars as $var) {
  328. $result[$var] = $view->getVar($var);
  329. }
  330. if (!empty($view->pageTitle)) {
  331. $result = array_merge($result, array('title' => $view->pageTitle));
  332. }
  333. }
  334. } else {
  335. $params['return'] = 1;
  336. $params['bare'] = 1;
  337. $params['requested'] = 1;
  338. $result = @$dispatcher->dispatch($url, $params);
  339. }
  340. if (isset($this->_actionFixtures)) {
  341. unset($this->_actionFixtures);
  342. }
  343. ClassRegistry::flush();
  344. return $result;
  345. }
  346. /**
  347. * Announces the start of a test.
  348. *
  349. * @param string $method Test method just started.
  350. * @return void
  351. * @access public
  352. */
  353. function before($method) {
  354. parent::before($method);
  355. if (isset($this->fixtures) && (!is_array($this->fixtures) || empty($this->fixtures))) {
  356. unset($this->fixtures);
  357. }
  358. // Set up DB connection
  359. if (isset($this->fixtures) && strtolower($method) == 'start') {
  360. $this->_initDb();
  361. $this->_loadFixtures();
  362. }
  363. // Create records
  364. if (isset($this->_fixtures) && isset($this->db) && !in_array(strtolower($method), array('start', 'end')) && $this->__truncated && $this->autoFixtures == true) {
  365. foreach ($this->_fixtures as $fixture) {
  366. $inserts = $fixture->insert($this->db);
  367. }
  368. }
  369. if (!in_array(strtolower($method), $this->methods)) {
  370. $this->startTest($method);
  371. }
  372. }
  373. /**
  374. * Runs as first test to create tables.
  375. *
  376. * @return void
  377. * @access public
  378. */
  379. function start() {
  380. if (isset($this->_fixtures) && isset($this->db)) {
  381. Configure::write('Cache.disable', true);
  382. $cacheSources = $this->db->cacheSources;
  383. $this->db->cacheSources = false;
  384. $sources = $this->db->listSources();
  385. $this->db->cacheSources = $cacheSources;
  386. if (!$this->dropTables) {
  387. return;
  388. }
  389. foreach ($this->_fixtures as $fixture) {
  390. $table = $this->db->config['prefix'] . $fixture->table;
  391. if (in_array($table, $sources)) {
  392. $fixture->drop($this->db);
  393. $fixture->create($this->db);
  394. } elseif (!in_array($table, $sources)) {
  395. $fixture->create($this->db);
  396. }
  397. }
  398. }
  399. }
  400. /**
  401. * Runs as last test to drop tables.
  402. *
  403. * @return void
  404. * @access public
  405. */
  406. function end() {
  407. if (isset($this->_fixtures) && isset($this->db)) {
  408. if ($this->dropTables) {
  409. foreach (array_reverse($this->_fixtures) as $fixture) {
  410. $fixture->drop($this->db);
  411. }
  412. }
  413. $this->db->sources(true);
  414. Configure::write('Cache.disable', false);
  415. }
  416. if (class_exists('ClassRegistry')) {
  417. ClassRegistry::flush();
  418. }
  419. }
  420. /**
  421. * Announces the end of a test.
  422. *
  423. * @param string $method Test method just finished.
  424. * @return void
  425. * @access public
  426. */
  427. function after($method) {
  428. $isTestMethod = !in_array(strtolower($method), array('start', 'end'));
  429. if (isset($this->_fixtures) && isset($this->db) && $isTestMethod) {
  430. foreach ($this->_fixtures as $fixture) {
  431. $fixture->truncate($this->db);
  432. }
  433. $this->__truncated = true;
  434. } else {
  435. $this->__truncated = false;
  436. }
  437. if (!in_array(strtolower($method), $this->methods)) {
  438. $this->endTest($method);
  439. }
  440. $this->_should_skip = false;
  441. parent::after($method);
  442. }
  443. /**
  444. * Gets a list of test names. Normally that will be all internal methods that start with the
  445. * name "test". This method should be overridden if you want a different rule.
  446. *
  447. * @return array List of test names.
  448. * @access public
  449. */
  450. function getTests() {
  451. return array_merge(
  452. array('start', 'startCase'),
  453. array_diff(parent::getTests(), array('testAction', 'testaction')),
  454. array('endCase', 'end')
  455. );
  456. }
  457. /**
  458. * Chooses which fixtures to load for a given test
  459. *
  460. * @param string $fixture Each parameter is a model name that corresponds to a
  461. * fixture, i.e. 'Post', 'Author', etc.
  462. * @return void
  463. * @access public
  464. * @see CakeTestCase::$autoFixtures
  465. */
  466. function loadFixtures() {
  467. $args = func_get_args();
  468. foreach ($args as $class) {
  469. if (isset($this->_fixtureClassMap[$class])) {
  470. $fixture = $this->_fixtures[$this->_fixtureClassMap[$class]];
  471. $fixture->truncate($this->db);
  472. $fixture->insert($this->db);
  473. } else {
  474. trigger_error("Referenced fixture class {$class} not found", E_USER_WARNING);
  475. }
  476. }
  477. }
  478. /**
  479. * Takes an array $expected and generates a regex from it to match the provided $string.
  480. * Samples for $expected:
  481. *
  482. * Checks for an input tag with a name attribute (contains any non-empty value) and an id
  483. * attribute that contains 'my-input':
  484. * array('input' => array('name', 'id' => 'my-input'))
  485. *
  486. * Checks for two p elements with some text in them:
  487. * array(
  488. * array('p' => true),
  489. * 'textA',
  490. * '/p',
  491. * array('p' => true),
  492. * 'textB',
  493. * '/p'
  494. * )
  495. *
  496. * You can also specify a pattern expression as part of the attribute values, or the tag
  497. * being defined, if you prepend the value with preg: and enclose it with slashes, like so:
  498. * array(
  499. * array('input' => array('name', 'id' => 'preg:/FieldName\d+/')),
  500. * 'preg:/My\s+field/'
  501. * )
  502. *
  503. * Important: This function is very forgiving about whitespace and also accepts any
  504. * permutation of attribute order. It will also allow whitespaces between specified tags.
  505. *
  506. * @param string $string An HTML/XHTML/XML string
  507. * @param array $expected An array, see above
  508. * @param string $message SimpleTest failure output string
  509. * @return boolean
  510. * @access public
  511. */
  512. function assertTags($string, $expected, $fullDebug = false) {
  513. $regex = array();
  514. $normalized = array();
  515. foreach ((array) $expected as $key => $val) {
  516. if (!is_numeric($key)) {
  517. $normalized[] = array($key => $val);
  518. } else {
  519. $normalized[] = $val;
  520. }
  521. }
  522. $i = 0;
  523. foreach ($normalized as $tags) {
  524. if (!is_array($tags)) {
  525. $tags = (string)$tags;
  526. }
  527. $i++;
  528. if (is_string($tags) && $tags{0} == '<') {
  529. $tags = array(substr($tags, 1) => array());
  530. } elseif (is_string($tags)) {
  531. $tagsTrimmed = preg_replace('/\s+/m', '', $tags);
  532. if (preg_match('/^\*?\//', $tags, $match) && $tagsTrimmed !== '//') {
  533. $prefix = array(null, null);
  534. if ($match[0] == '*/') {
  535. $prefix = array('Anything, ', '.*?');
  536. }
  537. $regex[] = array(
  538. sprintf('%sClose %s tag', $prefix[0], substr($tags, strlen($match[0]))),
  539. sprintf('%s<[\s]*\/[\s]*%s[\s]*>[\n\r]*', $prefix[1], substr($tags, strlen($match[0]))),
  540. $i,
  541. );
  542. continue;
  543. }
  544. if (!empty($tags) && preg_match('/^preg\:\/(.+)\/$/i', $tags, $matches)) {
  545. $tags = $matches[1];
  546. $type = 'Regex matches';
  547. } else {
  548. $tags = preg_quote($tags, '/');
  549. $type = 'Text equals';
  550. }
  551. $regex[] = array(
  552. sprintf('%s "%s"', $type, $tags),
  553. $tags,
  554. $i,
  555. );
  556. continue;
  557. }
  558. foreach ($tags as $tag => $attributes) {
  559. $regex[] = array(
  560. sprintf('Open %s tag', $tag),
  561. sprintf('[\s]*<%s', preg_quote($tag, '/')),
  562. $i,
  563. );
  564. if ($attributes === true) {
  565. $attributes = array();
  566. }
  567. $attrs = array();
  568. $explanations = array();
  569. foreach ($attributes as $attr => $val) {
  570. if (is_numeric($attr) && preg_match('/^preg\:\/(.+)\/$/i', $val, $matches)) {
  571. $attrs[] = $matches[1];
  572. $explanations[] = sprintf('Regex "%s" matches', $matches[1]);
  573. continue;
  574. } else {
  575. $quotes = '"';
  576. if (is_numeric($attr)) {
  577. $attr = $val;
  578. $val = '.+?';
  579. $explanations[] = sprintf('Attribute "%s" present', $attr);
  580. } elseif (!empty($val) && preg_match('/^preg\:\/(.+)\/$/i', $val, $matches)) {
  581. $quotes = '"?';
  582. $val = $matches[1];
  583. $explanations[] = sprintf('Attribute "%s" matches "%s"', $attr, $val);
  584. } else {
  585. $explanations[] = sprintf('Attribute "%s" == "%s"', $attr, $val);
  586. $val = preg_quote($val, '/');
  587. }
  588. $attrs[] = '[\s]+'.preg_quote($attr, '/').'='.$quotes.$val.$quotes;
  589. }
  590. }
  591. if ($attrs) {
  592. $permutations = $this->__array_permute($attrs);
  593. $permutationTokens = array();
  594. foreach ($permutations as $permutation) {
  595. $permutationTokens[] = implode('', $permutation);
  596. }
  597. $regex[] = array(
  598. sprintf('%s', implode(', ', $explanations)),
  599. $permutationTokens,
  600. $i,
  601. );
  602. }
  603. $regex[] = array(
  604. sprintf('End %s tag', $tag),
  605. '[\s]*\/?[\s]*>[\n\r]*',
  606. $i,
  607. );
  608. }
  609. }
  610. foreach ($regex as $i => $assertation) {
  611. list($description, $expressions, $itemNum) = $assertation;
  612. $matches = false;
  613. foreach ((array)$expressions as $expression) {
  614. if (preg_match(sprintf('/^%s/s', $expression), $string, $match)) {
  615. $matches = true;
  616. $string = substr($string, strlen($match[0]));
  617. break;
  618. }
  619. }
  620. if (!$matches) {
  621. $this->assert(new TrueExpectation(), false, sprintf('Item #%d / regex #%d failed: %s', $itemNum, $i, $description));
  622. if ($fullDebug) {
  623. debug($string, true);
  624. debug($regex, true);
  625. }
  626. return false;
  627. }
  628. }
  629. return $this->assert(new TrueExpectation(), true, '%s');
  630. }
  631. /**
  632. * Initialize DB connection.
  633. *
  634. * @return void
  635. * @access protected
  636. */
  637. function _initDb() {
  638. $testDbAvailable = in_array('test', array_keys(ConnectionManager::enumConnectionObjects()));
  639. $_prefix = null;
  640. if ($testDbAvailable) {
  641. // Try for test DB
  642. restore_error_handler();
  643. @$db = ConnectionManager::getDataSource('test');
  644. set_error_handler('simpleTestErrorHandler');
  645. $testDbAvailable = $db->isConnected();
  646. }
  647. // Try for default DB
  648. if (!$testDbAvailable) {
  649. $db = ConnectionManager::getDataSource('default');
  650. $_prefix = $db->config['prefix'];
  651. $db->config['prefix'] = 'test_suite_';
  652. }
  653. ConnectionManager::create('test_suite', $db->config);
  654. $db->config['prefix'] = $_prefix;
  655. // Get db connection
  656. $this->db = ConnectionManager::getDataSource('test_suite');
  657. $this->db->cacheSources = false;
  658. ClassRegistry::config(array('ds' => 'test_suite'));
  659. }
  660. /**
  661. * Load fixtures specified in var $fixtures.
  662. *
  663. * @return void
  664. * @access protected
  665. */
  666. function _loadFixtures() {
  667. if (!isset($this->fixtures) || empty($this->fixtures)) {
  668. return;
  669. }
  670. if (!is_array($this->fixtures)) {
  671. $this->fixtures = array_map('trim', explode(',', $this->fixtures));
  672. }
  673. $this->_fixtures = array();
  674. foreach ($this->fixtures as $index => $fixture) {
  675. $fixtureFile = null;
  676. if (strpos($fixture, 'core.') === 0) {
  677. $fixture = substr($fixture, strlen('core.'));
  678. foreach (App::core('cake') as $key => $path) {
  679. $fixturePaths[] = $path . 'tests' . DS . 'fixtures';
  680. }
  681. } elseif (strpos($fixture, 'app.') === 0) {
  682. $fixture = substr($fixture, strlen('app.'));
  683. $fixturePaths = array(
  684. TESTS . 'fixtures',
  685. VENDORS . 'tests' . DS . 'fixtures'
  686. );
  687. } elseif (strpos($fixture, 'plugin.') === 0) {
  688. $parts = explode('.', $fixture, 3);
  689. $pluginName = $parts[1];
  690. $fixture = $parts[2];
  691. $fixturePaths = array(
  692. App::pluginPath($pluginName) . 'tests' . DS . 'fixtures',
  693. TESTS . 'fixtures',
  694. VENDORS . 'tests' . DS . 'fixtures'
  695. );
  696. } else {
  697. $fixturePaths = array(
  698. TESTS . 'fixtures',
  699. VENDORS . 'tests' . DS . 'fixtures',
  700. TEST_CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'tests' . DS . 'fixtures'
  701. );
  702. }
  703. foreach ($fixturePaths as $path) {
  704. if (is_readable($path . DS . $fixture . '_fixture.php')) {
  705. $fixtureFile = $path . DS . $fixture . '_fixture.php';
  706. break;
  707. }
  708. }
  709. if (isset($fixtureFile)) {
  710. require_once($fixtureFile);
  711. $fixtureClass = Inflector::camelize($fixture) . 'Fixture';
  712. $this->_fixtures[$this->fixtures[$index]] = new $fixtureClass($this->db);
  713. $this->_fixtureClassMap[Inflector::camelize($fixture)] = $this->fixtures[$index];
  714. }
  715. }
  716. if (empty($this->_fixtures)) {
  717. unset($this->_fixtures);
  718. }
  719. }
  720. /**
  721. * Generates all permutation of an array $items and returns them in a new array.
  722. *
  723. * @param array $items An array of items
  724. * @return array
  725. * @access private
  726. */
  727. function __array_permute($items, $perms = array()) {
  728. static $permuted;
  729. if (empty($perms)) {
  730. $permuted = array();
  731. }
  732. if (empty($items)) {
  733. $permuted[] = $perms;
  734. } else {
  735. $numItems = count($items) - 1;
  736. for ($i = $numItems; $i >= 0; --$i) {
  737. $newItems = $items;
  738. $newPerms = $perms;
  739. list($tmp) = array_splice($newItems, $i, 1);
  740. array_unshift($newPerms, $tmp);
  741. $this->__array_permute($newItems, $newPerms);
  742. }
  743. return $permuted;
  744. }
  745. }
  746. }
  747. ?>