PageRenderTime 70ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/Test/Case/Console/Command/MigrationShellTest.php

https://github.com/JayLoh/migrations
PHP | 976 lines | 699 code | 92 blank | 185 comment | 3 complexity | 654e175426f36c2a2700fbfa52b9a15b MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * Copyright 2009 - 2014, Cake Development Corporation (http://cakedc.com)
  4. *
  5. * Licensed under The MIT License
  6. * Redistributions of files must retain the above copyright notice.
  7. *
  8. * @copyright Copyright 2009 - 2014, Cake Development Corporation (http://cakedc.com)
  9. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  10. */
  11. App::uses('ShellDispatcher', 'Console');
  12. App::uses('MigrationShell', 'Migrations.Console/Command');
  13. /**
  14. * TestMigrationShell
  15. *
  16. */
  17. class TestMigrationShell extends MigrationShell {
  18. /**
  19. * Output property
  20. *
  21. * @var string
  22. */
  23. public $output = '';
  24. /**
  25. * Out method
  26. *
  27. * @param $string
  28. * @return void
  29. */
  30. public function out($message = null, $newlines = 1, $level = 1) {
  31. $this->output .= $message . "\n";
  32. }
  33. /**
  34. * FromComparison method
  35. *
  36. * @param $migration
  37. * @param $comparison
  38. * @param $oldTables
  39. * @param $currentTables
  40. * @return void
  41. */
  42. public function fromComparison($migration, $comparison, $oldTables, $currentTables) {
  43. return $this->_fromComparison($migration, $comparison, $oldTables, $currentTables);
  44. }
  45. /**
  46. * WriteMigration method
  47. *
  48. * @param $name
  49. * @param $class
  50. * @param $migration
  51. * @return void
  52. */
  53. public function writeMigration($name, $class, $migration) {
  54. return $this->_writeMigration($name, $class, $migration);
  55. }
  56. }
  57. /**
  58. * MigrationShellTest
  59. *
  60. */
  61. class MigrationShellTest extends CakeTestCase {
  62. /**
  63. * Fixtures property
  64. *
  65. * @var array
  66. */
  67. public $fixtures = array('plugin.migrations.schema_migrations', 'core.article', 'core.post', 'core.user');
  68. /**
  69. * SetUp method
  70. *
  71. * @return void
  72. */
  73. public function setUp() {
  74. parent::setUp();
  75. $out = $this->getMock('ConsoleOutput', array(), array(), '', false);
  76. $in = $this->getMock('ConsoleInput', array(), array(), '', false);
  77. $this->Shell = $this->getMock(
  78. 'TestMigrationShell',
  79. array('in', 'hr', 'createFile', 'error', 'err', '_stop', '_showInfo', 'dispatchShell'),
  80. array($out, $out, $in));
  81. $this->Shell->Version = $this->getMock(
  82. 'MigrationVersion',
  83. array('getMapping', 'getVersion', 'run'),
  84. array(array('connection' => 'test')));
  85. $this->Shell->type = 'TestMigrationPlugin';
  86. $this->Shell->path = TMP . 'tests' . DS;
  87. $this->Shell->connection = 'test';
  88. $plugins = $this->plugins = App::path('plugins');
  89. $plugins[] = dirname(dirname(dirname(dirname(__FILE__)))) . DS . 'test_app' . DS . 'Plugin' . DS;
  90. App::build(array('Plugin' => $plugins), true);
  91. App::objects('plugins', null, false);
  92. CakePlugin::load('TestMigrationPlugin');
  93. CakePlugin::load('TestMigrationPlugin2');
  94. CakePlugin::load('TestMigrationPlugin3');
  95. CakePlugin::load('TestMigrationPlugin4');
  96. Configure::write('Config.language', 'en');
  97. }
  98. /**
  99. * TearDown method
  100. *
  101. * @return void
  102. */
  103. public function tearDown() {
  104. parent::tearDown();
  105. CakePlugin::unload('TestMigrationPlugin');
  106. CakePlugin::unload('TestMigrationPlugin2');
  107. CakePlugin::unload('TestMigrationPlugin3');
  108. App::build(array('Plugin' => $this->plugins), true);
  109. App::objects('plugins', null, false);
  110. unset($this->Dispatcher, $this->Shell, $this->plugins);
  111. foreach (glob(TMP . 'tests' . DS . '*.php') as $f) {
  112. unlink($f);
  113. }
  114. }
  115. /**
  116. * Tables property
  117. *
  118. * @var array
  119. */
  120. public $tables = array(
  121. 'users' => array(
  122. 'id' => array('type' => 'integer', 'key' => 'primary'),
  123. 'user' => array('type' => 'string', 'null' => false),
  124. 'password' => array('type' => 'string', 'null' => false),
  125. 'created' => 'datetime',
  126. 'updated' => 'datetime'
  127. ),
  128. 'posts' => array(
  129. 'id' => array('type' => 'integer', 'key' => 'primary'),
  130. 'author_id' => array('type' => 'integer', 'null' => false),
  131. 'title' => array('type' => 'string', 'null' => false),
  132. 'body' => 'text',
  133. 'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
  134. 'created' => 'datetime',
  135. 'updated' => 'datetime'
  136. )
  137. );
  138. /**
  139. * TestStartup method
  140. *
  141. * @return void
  142. */
  143. public function testStartup() {
  144. $this->Shell->connection = 'default';
  145. $this->assertEquals($this->Shell->type, 'TestMigrationPlugin');
  146. $this->Shell->params = array(
  147. 'connection' => 'test',
  148. 'plugin' => 'Migrations',
  149. 'no-auto-init' => false,
  150. 'dry' => false,
  151. 'precheck' => 'Migrations.PrecheckException'
  152. );
  153. $this->Shell->startup();
  154. $this->assertEquals($this->Shell->connection, 'test');
  155. $this->assertEquals($this->Shell->type, 'Migrations');
  156. }
  157. /**
  158. * TestRun method
  159. *
  160. * @return void
  161. */
  162. public function testRun() {
  163. $mapping = array();
  164. for ($i = 1; $i <= 10; $i++) {
  165. $mapping[$i] = array(
  166. 'version' => $i, 'name' => '001_schema_dump',
  167. 'class' => 'M4af9d151e1484b74ad9d007058157726',
  168. 'type' => $this->Shell->type, 'migrated' => null
  169. );
  170. }
  171. $this->Shell->expects($this->any())->method('_stop')->will($this->returnValue(false));
  172. // cake migration run - no mapping
  173. $this->Shell->Version->expects($this->at(0))->method('getMapping')->will($this->returnValue(false));
  174. $this->Shell->args = array();
  175. $this->assertFalse($this->Shell->run());
  176. // cake migration run up
  177. $this->Shell->Version->expects($this->any())->method('getMapping')->will($this->returnValue($mapping));
  178. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(0));
  179. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  180. 'type' => 'TestMigrationPlugin',
  181. 'callback' => $this->Shell,
  182. 'direction' => 'up',
  183. 'version' => 1,
  184. 'dry' => false,
  185. 'precheck' => null)));
  186. $this->Shell->args = array('up');
  187. $this->assertTrue($this->Shell->run());
  188. // cake migration run up - on last version == stop
  189. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(10));
  190. $this->Shell->args = array('up');
  191. $this->assertFalse($this->Shell->run());
  192. // cake migration run down - on version 0 == stop
  193. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(0));
  194. $this->Shell->args = array('down');
  195. $this->assertFalse($this->Shell->run());
  196. // cake migration run down
  197. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(1));
  198. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  199. 'type' => 'TestMigrationPlugin',
  200. 'callback' => $this->Shell,
  201. 'direction' => 'down',
  202. 'version' => 1,
  203. 'dry' => false,
  204. 'precheck' => null)));
  205. $this->Shell->args = array('down');
  206. $this->assertTrue($this->Shell->run());
  207. // cake migration run all
  208. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(1));
  209. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  210. 'type' => 'TestMigrationPlugin',
  211. 'callback' => $this->Shell,
  212. 'version' => 10,
  213. 'direction' => 'up',
  214. 'dry' => false,
  215. 'precheck' => null)));
  216. $this->Shell->args = array('all');
  217. $this->assertTrue($this->Shell->run());
  218. // cake migration run reset
  219. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(9));
  220. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  221. 'type' => 'TestMigrationPlugin',
  222. 'callback' => $this->Shell,
  223. 'version' => 0,
  224. 'direction' => 'down',
  225. 'dry' => false,
  226. 'precheck' => null)));
  227. $this->Shell->args = array('reset');
  228. $this->assertTrue($this->Shell->run());
  229. // cake migration run - answers 0, 11, 1
  230. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(0));
  231. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  232. 'type' => 'TestMigrationPlugin',
  233. 'callback' => $this->Shell,
  234. 'version' => 1,
  235. 'direction' => 'up',
  236. 'dry' => false)));
  237. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue(0));
  238. $this->Shell->expects($this->at(4))->method('in')->will($this->returnValue(11));
  239. $this->Shell->expects($this->at(6))->method('in')->will($this->returnValue(1));
  240. $this->Shell->args = array();
  241. $this->assertTrue($this->Shell->run());
  242. // cake migration run - answers 10
  243. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(9));
  244. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  245. 'type' => 'TestMigrationPlugin',
  246. 'callback' => $this->Shell,
  247. 'version' => 10,
  248. 'direction' => 'up',
  249. 'dry' => false)));
  250. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue(10));
  251. $this->Shell->args = array();
  252. $this->assertTrue($this->Shell->run());
  253. // cake migration run 1
  254. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(0));
  255. $this->Shell->Version->expects($this->at(2))->method('run')->with($this->equalTo(array(
  256. 'type' => 'TestMigrationPlugin',
  257. 'callback' => $this->Shell,
  258. 'version' => 1,
  259. 'dry' => false)));
  260. $this->Shell->args = array('1');
  261. $this->assertTrue($this->Shell->run());
  262. // cake migration run 11
  263. $this->Shell->Version->expects($this->at(1))->method('getVersion')->will($this->returnValue(0));
  264. $this->Shell->args = array('11');
  265. $this->assertFalse($this->Shell->run());
  266. }
  267. /**
  268. * TestRunWithFailuresOnce method
  269. *
  270. * @return void
  271. */
  272. public function testRunWithFailuresOnce() {
  273. $this->Shell->expects($this->any())->method('_stop')->will($this->returnValue(false));
  274. $mapping = array(1 => array(
  275. 'version' => 1, 'name' => '001_schema_dump',
  276. 'class' => 'M4af9d151e1484b74ad9d007058157726',
  277. 'type' => $this->Shell->type, 'migrated' => null
  278. ));
  279. $migration = new CakeMigration();
  280. $migration->info = $mapping[1];
  281. $exception = new MigrationException($migration, 'Exception message');
  282. $this->Shell->Version->expects($this->any())->method('getMapping')->will($this->returnValue($mapping));
  283. $this->Shell->Version->expects($this->any())->method('getVersion')->will($this->returnValue(0));
  284. $this->Shell->Version->expects($this->at(2))->method('run')->will($this->throwException($exception));
  285. $this->Shell->expects($this->at(1))->method('in')->will($this->returnValue('y'));
  286. $this->Shell->args = array('up');
  287. $this->assertTrue($this->Shell->run());
  288. $result = $this->Shell->output;
  289. $pattern = <<<TEXT
  290. /Running migrations:
  291. An error occurred when processing the migration:
  292. Migration: 001_schema_dump
  293. Error: Exception message
  294. All migrations have completed./
  295. TEXT;
  296. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), str_replace("\r\n", "\n", $result));
  297. }
  298. /**
  299. * TestRunWithFailuresNotOnce method
  300. *
  301. * @return void
  302. */
  303. public function testRunWithFailuresNotOnce() {
  304. $this->Shell->expects($this->any())->method('_stop')->will($this->returnValue(false));
  305. $mapping = array(
  306. 1 => array(
  307. 'version' => 1, 'name' => '001_schema_dump',
  308. 'class' => 'M4af9d151e1484b74ad9d007058157726',
  309. 'type' => $this->Shell->type, 'migrated' => null
  310. ),
  311. );
  312. $migration = new CakeMigration();
  313. $migration->info = $mapping[1];
  314. $exception = new MigrationException($migration, 'Exception message');
  315. $this->Shell->Version->expects($this->any())->method('getMapping')->will($this->returnValue($mapping));
  316. $this->Shell->Version->expects($this->any())->method('getVersion')->will($this->returnValue(0));
  317. $this->Shell->Version->expects($this->at(2))->method('run')->will($this->throwException($exception));
  318. $this->Shell->Version->expects($this->at(3))->method('run')->will($this->returnValue(true));
  319. $this->Shell->expects($this->at(1))->method('in')->will($this->returnValue('y'));
  320. $this->Shell->args = array('all');
  321. $this->assertTrue($this->Shell->run());
  322. $result = $this->Shell->output;
  323. $pattern = <<<TEXT
  324. /Running migrations:
  325. All migrations have completed./
  326. TEXT;
  327. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), str_replace("\n\n", "\n", $result));
  328. }
  329. /**
  330. * TestFromComparisonTableActions method
  331. *
  332. * @return void
  333. */
  334. public function testFromComparisonTableActions() {
  335. $comparison = array(
  336. 'users' => array('add' => $this->tables['users']),
  337. 'posts' => array('add' => $this->tables['posts'])
  338. );
  339. $oldTables = array();
  340. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $this->tables);
  341. $expected = array(
  342. 'up' => array('create_table' => $this->tables),
  343. 'down' => array('drop_table' => array('users', 'posts'))
  344. );
  345. $this->assertEquals($result, $expected);
  346. $comparison = array('posts' => array('add' => $this->tables['posts']));
  347. $oldTables = array('users' => $this->tables['users']);
  348. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $this->tables);
  349. $expected = array(
  350. 'up' => array(
  351. 'create_table' => array('posts' => $this->tables['posts'])
  352. ),
  353. 'down' => array(
  354. 'drop_table' => array('posts')
  355. )
  356. );
  357. $this->assertEquals($result, $expected);
  358. $comparison = array();
  359. $oldTables = array('posts' => $this->tables['posts'], 'users' => $this->tables['users']);
  360. $currentTables = array('users' => $this->tables['users']);
  361. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $currentTables);
  362. $expected = array(
  363. 'up' => array(
  364. 'drop_table' => array('posts')
  365. ),
  366. 'down' => array(
  367. 'create_table' => array('posts' => $this->tables['posts'])
  368. )
  369. );
  370. $this->assertEquals($result, $expected);
  371. }
  372. /**
  373. * TestFromComparisonFieldActions method
  374. *
  375. * @return void
  376. */
  377. public function testFromComparisonFieldActions() {
  378. // Add field/index
  379. $oldTables = array('posts' => $this->tables['posts']);
  380. $newTables = array('posts' => array());
  381. $comparison = array(
  382. 'posts' => array('add' => array(
  383. 'views' => array('type' => 'integer', 'null' => false)
  384. ))
  385. );
  386. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  387. $expected = array(
  388. 'up' => array(
  389. 'create_field' => array(
  390. 'posts' => array('views' => array('type' => 'integer', 'null' => false))
  391. )
  392. ),
  393. 'down' => array(
  394. 'drop_field' => array(
  395. 'posts' => array('views')
  396. )
  397. )
  398. );
  399. $this->assertEquals($result, $expected);
  400. $comparison = array(
  401. 'posts' => array('add' => array(
  402. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  403. ))
  404. );
  405. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  406. $expected = array(
  407. 'up' => array(
  408. 'create_field' => array(
  409. 'posts' => array(
  410. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  411. )
  412. )
  413. ),
  414. 'down' => array(
  415. 'drop_field' => array(
  416. 'posts' => array('indexes' => array('VIEW_COUNT'))
  417. )
  418. )
  419. );
  420. $this->assertEquals($result, $expected);
  421. $comparison = array(
  422. 'posts' => array('add' => array(
  423. 'views' => array('type' => 'integer', 'null' => false),
  424. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  425. ))
  426. );
  427. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  428. $expected = array(
  429. 'up' => array(
  430. 'create_field' => array(
  431. 'posts' => array(
  432. 'views' => array('type' => 'integer', 'null' => false),
  433. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  434. )
  435. )
  436. ),
  437. 'down' => array(
  438. 'drop_field' => array(
  439. 'posts' => array('views', 'indexes' => array('VIEW_COUNT'))
  440. )
  441. )
  442. );
  443. $this->assertEquals($result, $expected);
  444. // Drop field/index
  445. $oldTables['posts']['views'] = array('type' => 'integer', 'null' => false);
  446. $oldTables['posts']['indexes'] = array('VIEW_COUNT' => array('column' => 'views', 'unique' => false));
  447. $comparison = array(
  448. 'posts' => array('drop' => array(
  449. 'views' => array('type' => 'integer', 'null' => false)
  450. ))
  451. );
  452. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  453. $expected = array(
  454. 'up' => array(
  455. 'drop_field' => array(
  456. 'posts' => array('views')
  457. )
  458. ),
  459. 'down' => array(
  460. 'create_field' => array(
  461. 'posts' => array('views' => array('type' => 'integer', 'null' => false))
  462. )
  463. )
  464. );
  465. $this->assertEquals($result, $expected);
  466. $comparison = array(
  467. 'posts' => array('drop' => array(
  468. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  469. ))
  470. );
  471. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  472. $expected = array(
  473. 'up' => array(
  474. 'drop_field' => array(
  475. 'posts' => array('indexes' => array('VIEW_COUNT'))
  476. )
  477. ),
  478. 'down' => array(
  479. 'create_field' => array(
  480. 'posts' => array('indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false)))
  481. )
  482. )
  483. );
  484. $this->assertEquals($result, $expected);
  485. $comparison = array(
  486. 'posts' => array('drop' => array(
  487. 'views' => array('type' => 'integer', 'null' => false),
  488. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  489. ))
  490. );
  491. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  492. $expected = array(
  493. 'up' => array(
  494. 'drop_field' => array(
  495. 'posts' => array('views', 'indexes' => array('VIEW_COUNT'))
  496. )
  497. ),
  498. 'down' => array(
  499. 'create_field' => array(
  500. 'posts' => array(
  501. 'views' => array('type' => 'integer', 'null' => false),
  502. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  503. )
  504. )
  505. )
  506. );
  507. $this->assertEquals($result, $expected);
  508. // Change field
  509. $comparison = array(
  510. 'posts' => array('change' => array(
  511. 'views' => array('type' => 'integer', 'null' => false, 'length' => 2),
  512. ))
  513. );
  514. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  515. $expected = array(
  516. 'up' => array(
  517. 'alter_field' => array(
  518. 'posts' => array(
  519. 'views' => array('type' => 'integer', 'null' => false, 'length' => 2)
  520. )
  521. )
  522. ),
  523. 'down' => array(
  524. 'alter_field' => array(
  525. 'posts' => array(
  526. 'views' => array('type' => 'integer', 'null' => false)
  527. )
  528. )
  529. )
  530. );
  531. $this->assertEquals($result, $expected);
  532. // Change field with/out length
  533. $oldTables = array('users' => $this->tables['users']);
  534. $newTables = array('users' => array());
  535. $oldTables['users']['last_login'] = array('type' => 'integer', 'null' => false, 'length' => 11);
  536. $comparison = array(
  537. 'users' => array('change' => array(
  538. 'last_login' => array('type' => 'datetime', 'null' => false),
  539. ))
  540. );
  541. $result = $this->Shell->fromComparison(array(), $comparison, $oldTables, $newTables);
  542. $expected = array(
  543. 'up' => array(
  544. 'alter_field' => array(
  545. 'users' => array(
  546. 'last_login' => array('type' => 'datetime', 'null' => false, 'length' => null)
  547. )
  548. )
  549. ),
  550. 'down' => array(
  551. 'alter_field' => array(
  552. 'users' => array(
  553. 'last_login' => array('type' => 'integer', 'null' => false, 'length' => 11)
  554. )
  555. )
  556. )
  557. );
  558. $this->assertEquals($result, $expected);
  559. }
  560. /**
  561. * TestWriteMigration method
  562. *
  563. * @return void
  564. */
  565. public function testWriteMigration() {
  566. // Remove if exists
  567. $this->_unlink('12345_migration_test_file.php');
  568. $users = $this->tables['users'];
  569. $users['indexes'] = array('UNIQUE_USER' => array('column' => 'user', 'unique' => true));
  570. $migration = array(
  571. 'up' => array(
  572. 'create_table' => array('users' => $users),
  573. 'create_field' => array(
  574. 'posts' => array(
  575. 'views' => array('type' => 'integer', 'null' => false),
  576. 'indexes' => array('VIEW_COUNT' => array('column' => 'views', 'unique' => false))
  577. )
  578. )
  579. ),
  580. 'down' => array(
  581. 'drop_table' => array('users'),
  582. 'drop_field' => array(
  583. 'posts' => array('views', 'indexes' => array('VIEW_COUNT'))
  584. )
  585. )
  586. );
  587. $this->assertFalse(file_exists(TMP . 'tests' . DS . '12345_migration_test_file.php'));
  588. $this->assertTrue($this->Shell->writeMigration('migration_test_file', 12345, $migration));
  589. $this->assertTrue(file_exists(TMP . 'tests' . DS . '12345_migration_test_file.php'));
  590. $result = $this->_getMigrationVariable(TMP . 'tests' . DS . '12345_migration_test_file.php');
  591. $expected = <<<TEXT
  592. public \$migration = array(
  593. 'up' => array(
  594. 'create_table' => array(
  595. 'users' => array(
  596. 'id' => array('type' => 'integer', 'key' => 'primary'),
  597. 'user' => array('type' => 'string', 'null' => false),
  598. 'password' => array('type' => 'string', 'null' => false),
  599. 'created' => 'datetime',
  600. 'updated' => 'datetime',
  601. 'indexes' => array(
  602. 'UNIQUE_USER' => array('column' => 'user', 'unique' => true),
  603. ),
  604. ),
  605. ),
  606. 'create_field' => array(
  607. 'posts' => array(
  608. 'views' => array('type' => 'integer', 'null' => false),
  609. 'indexes' => array(
  610. 'VIEW_COUNT' => array('column' => 'views', 'unique' => false),
  611. ),
  612. ),
  613. ),
  614. ),
  615. 'down' => array(
  616. 'drop_table' => array(
  617. 'users'
  618. ),
  619. 'drop_field' => array(
  620. 'posts' => array('views', 'indexes' => array('VIEW_COUNT')),
  621. ),
  622. ),
  623. );
  624. TEXT;
  625. $this->assertEquals($result, str_replace("\r\n", "\n", $expected));
  626. $this->_unlink('12345_migration_test_file.php');
  627. }
  628. /**
  629. * TestGenerate method
  630. *
  631. * @return void
  632. */
  633. public function testGenerate() {
  634. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  635. $this->Shell->expects($this->at(1))->method('in')->will($this->returnValue('n'));
  636. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue('Initial Schema'));
  637. $this->Shell->generate();
  638. $files = glob(TMP . 'tests' . DS . '*initial_schema.php');
  639. foreach ($files as $f) {
  640. unlink($f);
  641. }
  642. $this->assertNotEmpty(preg_grep('/([0-9])+_initial_schema\.php$/i', $files));
  643. }
  644. /**
  645. * TestGenerate2 method
  646. *
  647. * @return void
  648. */
  649. public function testGenerate2() {
  650. $this->Shell->expects($this->atLeastOnce())->method('err');
  651. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  652. $this->Shell->expects($this->at(1))->method('in')->will($this->returnValue('n'));
  653. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue('002 invalid name'));
  654. $this->Shell->expects($this->at(4))->method('in')->will($this->returnValue('invalid-name'));
  655. $this->Shell->expects($this->at(6))->method('in')->will($this->returnValue('create some sample_data'));
  656. $this->Shell->generate();
  657. $files = glob(TMP . 'tests' . DS . '*create_some_sample_data.php');
  658. foreach ($files as $f) {
  659. unlink($f);
  660. }
  661. $this->assertNotEmpty(preg_grep('/([0-9])+_create_some_sample_data\.php$/i', $files));
  662. }
  663. /**
  664. * TestGenerateComparison method
  665. *
  666. * @return void
  667. */
  668. public function testGenerateComparison() {
  669. $this->Shell->type = 'TestMigrationPlugin4';
  670. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('y'));
  671. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue('n'));
  672. $this->Shell->expects($this->at(3))->method('in')->will($this->returnValue('drop slug field'));
  673. $this->Shell->expects($this->at(4))->method('in')->will($this->returnValue('y'));
  674. $this->Shell->expects($this->at(5))->method('dispatchShell')->with('schema generate --connection test --force');
  675. $this->Shell->Version->expects($this->any())->method('getMapping')->will($this->returnCallback(array($this, 'returnMapping')));
  676. $this->assertEmpty(glob(TMP . 'tests' . DS . '*drop_slug_field.php'));
  677. $this->Shell->params['force'] = true;
  678. $this->Shell->generate();
  679. $files = glob(TMP . 'tests' . DS . '*drop_slug_field.php');
  680. $this->assertNotEmpty($files);
  681. $result = $this->_getMigrationVariable(current($files));
  682. foreach ($files as $f) {
  683. unlink($f);
  684. }
  685. $this->assertNotRegExp('/\'schema_migrations\'/', $result);
  686. $pattern = <<<TEXT
  687. / 'drop_field' => array\(
  688. 'articles' => array\('slug',\),
  689. \),/
  690. TEXT;
  691. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), $result);
  692. $pattern = <<<TEXT
  693. / 'create_field' => array\(
  694. 'articles' => array\(
  695. 'slug' => array\('type' => 'string', 'null' => false\),
  696. \),
  697. \),/
  698. TEXT;
  699. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), $result);
  700. }
  701. public function returnMapping() {
  702. return array(
  703. gmdate('U') => array('class' => 'M4af9d15154844819b7a0007058157726')
  704. );
  705. }
  706. /**
  707. * testGenerateFromCliParamsCreateTable method
  708. * test the case of using a command such as:
  709. * app/Console/cake Migrations.migration generate create_products id created modified name description:text in_stock:boolean price:float stock_count:integer
  710. *
  711. * @return void
  712. */
  713. public function testGenerateFromCliParamsCreateTable() {
  714. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  715. $this->assertEmpty(glob(TMP . 'tests' . DS . '*create_products.php'));
  716. $this->Shell->args = array('create_products', 'id', 'created', 'modified', 'name', 'description:text', 'in_stock:boolean', 'price:float', 'stock_count:integer');
  717. $this->Shell->params['force'] = true;
  718. $this->Shell->generate();
  719. $files = glob(TMP . 'tests' . DS . '*create_products.php');
  720. $this->assertNotEmpty($files);
  721. $result = $this->_getMigrationVariable(current($files));
  722. foreach ($files as $f) {
  723. unlink($f);
  724. }
  725. $expected = file_get_contents(CakePlugin::path('Migrations') . '/Test/Fixture/test_migration_create_table_from_cli.txt');
  726. $this->assertEquals($expected, $result);
  727. }
  728. /**
  729. * testGenerateFromCliParamsDropTable method
  730. * test the case of using a command such as:
  731. * app/Console/cake Migrations.migration generate drop_products
  732. *
  733. * @return void
  734. */
  735. public function testGenerateFromCliParamsDropTable() {
  736. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  737. $this->assertEmpty(glob(TMP . 'tests' . DS . '*drop_products.php'));
  738. $this->Shell->args = array('drop_products');
  739. $this->Shell->params['force'] = true;
  740. $this->Shell->generate();
  741. $files = glob(TMP . 'tests' . DS . '*drop_products.php');
  742. $this->assertNotEmpty($files);
  743. $result = $this->_getMigrationVariable(current($files));
  744. foreach ($files as $f) {
  745. unlink($f);
  746. }
  747. $expected = file_get_contents(CakePlugin::path('Migrations') . '/Test/Fixture/test_migration_drop_table_from_cli.txt');
  748. $this->assertEquals($expected, $result);
  749. }
  750. /**
  751. * testGenerateFromCliParamsAddFields method
  752. * test the case of using a command such as:
  753. * app/Console/cake Migrations.migration generate add_all_fields_to_products id created modified name description:text in_stock:boolean price:float stock_count:integer
  754. *
  755. * @return void
  756. */
  757. public function testGenerateFromCliParamsAddFields() {
  758. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  759. $this->assertEmpty(glob(TMP . 'tests' . DS . '*add_all_fields_to_products.php'));
  760. $this->Shell->args = array('add_all_fields_to_products', 'id', 'created', 'modified', 'name', 'description:text', 'in_stock:boolean', 'price:float', 'stock_count:integer');
  761. $this->Shell->params['force'] = true;
  762. $this->Shell->generate();
  763. $files = glob(TMP . 'tests' . DS . '*add_all_fields_to_products.php');
  764. $this->assertNotEmpty($files);
  765. $result = $this->_getMigrationVariable(current($files));
  766. foreach ($files as $f) {
  767. unlink($f);
  768. }
  769. $expected = file_get_contents(CakePlugin::path('Migrations') . '/Test/Fixture/test_migration_add_fields_from_cli.txt');
  770. $this->assertEquals($expected, $result);
  771. }
  772. /**
  773. * testGenerateFromCliParamsRemoveFields method
  774. * test the case of using a command such as:
  775. * app/Console/cake Migrations.migration generate remove_name_and_desc_from_products name description
  776. *
  777. * @return void
  778. */
  779. public function testGenerateFromCliParamsRemoveFields() {
  780. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('n'));
  781. $this->assertEmpty(glob(TMP . 'tests' . DS . '*remove_name_and_desc_from_products.php'));
  782. $this->Shell->args = array('remove_name_and_desc_from_products', 'name', 'description');
  783. $this->Shell->params['force'] = true;
  784. $this->Shell->generate();
  785. $files = glob(TMP . 'tests' . DS . '*remove_name_and_desc_from_products.php');
  786. $this->assertNotEmpty($files);
  787. $result = $this->_getMigrationVariable(current($files));
  788. foreach ($files as $f) {
  789. unlink($f);
  790. }
  791. $expected = file_get_contents(CakePlugin::path('Migrations') . '/Test/Fixture/test_migration_remove_fields_from_cli.txt');
  792. $this->assertEquals($expected, $result);
  793. }
  794. /**
  795. * TestGenerateDump method
  796. *
  797. * @return void
  798. */
  799. public function testGenerateDump() {
  800. $this->Shell->expects($this->at(0))->method('in')->will($this->returnValue('y'));
  801. $this->Shell->expects($this->at(2))->method('in')->will($this->returnValue('n'));
  802. $this->Shell->expects($this->at(3))->method('in')->will($this->returnValue('schema dump'));
  803. $this->Shell->Version->expects($this->any())->method('getMapping')->will($this->returnCallback(array($this, 'returnMapping')));
  804. $this->assertEmpty(glob(TMP . 'tests' . DS . '*schema_dump.php'));
  805. $this->Shell->type = 'TestMigrationPlugin2';
  806. $this->Shell->params['force'] = true;
  807. $this->Shell->params['dry'] = false;
  808. $this->Shell->params['precheck'] = 'Migrations.PrecheckException';
  809. $this->Shell->generate();
  810. $files = glob(TMP . 'tests' . DS . '*schema_dump.php');
  811. $this->assertNotEmpty($files);
  812. $result = $this->_getMigrationVariable(current($files));
  813. foreach ($files as $f) {
  814. unlink($f);
  815. }
  816. $expected = file_get_contents(CakePlugin::path('Migrations') . '/Test/Fixture/test_migration.txt');
  817. $expected = str_replace("\r\n", "\n", $expected);
  818. $this->assertEquals($expected, $result);
  819. }
  820. /**
  821. * TestStatus method
  822. *
  823. * @return void
  824. */
  825. public function testMigrationStatus() {
  826. $this->Shell->Version = new MigrationVersion(array('connection' => 'test'));
  827. $this->Shell->status();
  828. $result = $this->Shell->output;
  829. $pattern = <<<TEXT
  830. /Migrations Plugin
  831. Current version:
  832. #003 003_increase_class_name_length
  833. Latest version:
  834. #003 003_increase_class_name_length/
  835. TEXT;
  836. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), $result);
  837. $this->Shell->Version->setVersion(3, 'migrations', false);
  838. $this->Shell->output = '';
  839. $this->Shell->args = array('outdated');
  840. $this->Shell->status();
  841. $result = $this->Shell->output;
  842. $pattern = <<<TEXT
  843. /Migrations Plugin
  844. Current version:
  845. #002 002_convert_version_to_class_names
  846. Latest version:
  847. #003 003_increase_class_name_length/
  848. TEXT;
  849. $this->assertRegExp(str_replace("\r\n", "\n", $pattern), $result);
  850. }
  851. /**
  852. * Strip all the content surrounding the $migration variable
  853. *
  854. * @param string $file
  855. * @return string
  856. */
  857. protected function _getMigrationVariable($file) {
  858. $result = array();
  859. $array = explode("\n", str_replace("\r\n", "\n", file_get_contents($file)));
  860. foreach ($array as $line) {
  861. if ($line === "\tpublic \$migration = array(") {
  862. $result[] = $line;
  863. } elseif (!empty($result) && $line === "\t);") {
  864. $result[] = $line;
  865. break;
  866. } elseif (!empty($result)) {
  867. $result[] = $line;
  868. }
  869. }
  870. return implode("\n", $result);
  871. }
  872. /**
  873. * Unlink test files from filesystem
  874. *
  875. * @param mixed files
  876. * @return void
  877. */
  878. protected function _unlink() {
  879. $files = func_get_args();
  880. foreach ($files as $file) {
  881. @unlink(TMP . 'tests' . DS . $file);
  882. }
  883. }
  884. }