PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/cake/tests/lib/cake_test_case.php

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