CakeSchemaTest.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. <?php
  2. /**
  3. * Test for Schema database management
  4. *
  5. *
  6. * PHP 5
  7. *
  8. * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
  9. * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice
  13. *
  14. * @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  16. * @package Cake.Test.Case.Model
  17. * @since CakePHP(tm) v 1.2.0.5550
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. App::uses('CakeSchema', 'Model');
  21. App::uses('CakeTestFixture', 'TestSuite/Fixture');
  22. /**
  23. * Test for Schema database management
  24. *
  25. * @package Cake.Test.Case.Model
  26. */
  27. class MyAppSchema extends CakeSchema {
  28. /**
  29. * name property
  30. *
  31. * @var string 'MyApp'
  32. */
  33. public $name = 'MyApp';
  34. /**
  35. * connection property
  36. *
  37. * @var string 'test'
  38. */
  39. public $connection = 'test';
  40. /**
  41. * comments property
  42. *
  43. * @var array
  44. */
  45. public $comments = array(
  46. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  47. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  48. 'user_id' => array('type' => 'integer', 'null' => false),
  49. 'title' => array('type' => 'string', 'null' => false, 'length' => 100),
  50. 'comment' => array('type' => 'text', 'null' => false, 'default' => null),
  51. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  52. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  53. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  54. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  55. );
  56. /**
  57. * posts property
  58. *
  59. * @var array
  60. */
  61. public $posts = array(
  62. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  63. 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
  64. 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
  65. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  66. 'summary' => array('type' => 'text', 'null' => true),
  67. 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1),
  68. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  69. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  70. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  71. );
  72. /**
  73. * _foo property
  74. *
  75. * @var array
  76. */
  77. protected $_foo = array('bar');
  78. /**
  79. * setup method
  80. *
  81. * @param mixed $version
  82. * @return void
  83. */
  84. public function setup($version) {
  85. }
  86. /**
  87. * teardown method
  88. *
  89. * @param mixed $version
  90. * @return void
  91. */
  92. public function teardown($version) {
  93. }
  94. /**
  95. * getVar method
  96. *
  97. * @param string $var Name of var
  98. * @return mixed
  99. */
  100. public function getVar($var) {
  101. if (!isset($this->$var)) {
  102. return null;
  103. }
  104. return $this->$var;
  105. }
  106. }
  107. /**
  108. * TestAppSchema class
  109. *
  110. * @package Cake.Test.Case.Model
  111. */
  112. class TestAppSchema extends CakeSchema {
  113. /**
  114. * name property
  115. *
  116. * @var string 'MyApp'
  117. */
  118. public $name = 'MyApp';
  119. /**
  120. * comments property
  121. *
  122. * @var array
  123. */
  124. public $comments = array(
  125. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0,'key' => 'primary'),
  126. 'article_id' => array('type' => 'integer', 'null' => false),
  127. 'user_id' => array('type' => 'integer', 'null' => false),
  128. 'comment' => array('type' => 'text', 'null' => true, 'default' => null),
  129. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  130. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  131. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  132. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  133. 'tableParameters' => array(),
  134. );
  135. /**
  136. * posts property
  137. *
  138. * @var array
  139. */
  140. public $posts = array(
  141. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  142. 'author_id' => array('type' => 'integer', 'null' => false),
  143. 'title' => array('type' => 'string', 'null' => false),
  144. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  145. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  146. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  147. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  148. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  149. 'tableParameters' => array(),
  150. );
  151. /**
  152. * posts_tags property
  153. *
  154. * @var array
  155. */
  156. public $posts_tags = array(
  157. 'post_id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'),
  158. 'tag_id' => array('type' => 'string', 'null' => false, 'key' => 'primary'),
  159. 'indexes' => array('posts_tag' => array('column' => array('tag_id', 'post_id'), 'unique' => 1)),
  160. 'tableParameters' => array()
  161. );
  162. /**
  163. * tags property
  164. *
  165. * @var array
  166. */
  167. public $tags = array(
  168. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  169. 'tag' => array('type' => 'string', 'null' => false),
  170. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  171. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  172. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  173. 'tableParameters' => array()
  174. );
  175. /**
  176. * datatypes property
  177. *
  178. * @var array
  179. */
  180. public $datatypes = array(
  181. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  182. 'float_field' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => ''),
  183. 'huge_int' => array('type' => 'biginteger'),
  184. 'bool' => array('type' => 'boolean', 'null' => false, 'default' => false),
  185. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  186. 'tableParameters' => array()
  187. );
  188. /**
  189. * setup method
  190. *
  191. * @param mixed $version
  192. * @return void
  193. */
  194. public function setup($version) {
  195. }
  196. /**
  197. * teardown method
  198. *
  199. * @param mixed $version
  200. * @return void
  201. */
  202. public function teardown($version) {
  203. }
  204. }
  205. /**
  206. * SchemaPost class
  207. *
  208. * @package Cake.Test.Case.Model
  209. */
  210. class SchemaPost extends CakeTestModel {
  211. /**
  212. * name property
  213. *
  214. * @var string 'SchemaPost'
  215. */
  216. public $name = 'SchemaPost';
  217. /**
  218. * useTable property
  219. *
  220. * @var string 'posts'
  221. */
  222. public $useTable = 'posts';
  223. /**
  224. * hasMany property
  225. *
  226. * @var array
  227. */
  228. public $hasMany = array('SchemaComment');
  229. /**
  230. * hasAndBelongsToMany property
  231. *
  232. * @var array
  233. */
  234. public $hasAndBelongsToMany = array('SchemaTag');
  235. }
  236. /**
  237. * SchemaComment class
  238. *
  239. * @package Cake.Test.Case.Model
  240. */
  241. class SchemaComment extends CakeTestModel {
  242. /**
  243. * name property
  244. *
  245. * @var string 'SchemaComment'
  246. */
  247. public $name = 'SchemaComment';
  248. /**
  249. * useTable property
  250. *
  251. * @var string 'comments'
  252. */
  253. public $useTable = 'comments';
  254. /**
  255. * belongsTo property
  256. *
  257. * @var array
  258. */
  259. public $belongsTo = array('SchemaPost');
  260. }
  261. /**
  262. * SchemaTag class
  263. *
  264. * @package Cake.Test.Case.Model
  265. */
  266. class SchemaTag extends CakeTestModel {
  267. /**
  268. * name property
  269. *
  270. * @var string 'SchemaTag'
  271. */
  272. public $name = 'SchemaTag';
  273. /**
  274. * useTable property
  275. *
  276. * @var string 'tags'
  277. */
  278. public $useTable = 'tags';
  279. /**
  280. * hasAndBelongsToMany property
  281. *
  282. * @var array
  283. */
  284. public $hasAndBelongsToMany = array('SchemaPost');
  285. }
  286. /**
  287. * SchemaDatatype class
  288. *
  289. * @package Cake.Test.Case.Model
  290. */
  291. class SchemaDatatype extends CakeTestModel {
  292. /**
  293. * name property
  294. *
  295. * @var string 'SchemaDatatype'
  296. */
  297. public $name = 'SchemaDatatype';
  298. /**
  299. * useTable property
  300. *
  301. * @var string 'datatypes'
  302. */
  303. public $useTable = 'datatypes';
  304. }
  305. /**
  306. * Testdescribe class
  307. *
  308. * This class is defined purely to inherit the cacheSources variable otherwise
  309. * testSchemaCreateTable will fail if listSources has already been called and
  310. * its source cache populated - I.e. if the test is run within a group
  311. *
  312. * @uses CakeTestModel
  313. * @package
  314. * @package Cake.Test.Case.Model
  315. */
  316. class Testdescribe extends CakeTestModel {
  317. /**
  318. * name property
  319. *
  320. * @var string 'Testdescribe'
  321. */
  322. public $name = 'Testdescribe';
  323. }
  324. /**
  325. * SchemaCrossDatabase class
  326. *
  327. * @package Cake.Test.Case.Model
  328. */
  329. class SchemaCrossDatabase extends CakeTestModel {
  330. /**
  331. * name property
  332. *
  333. * @var string 'SchemaCrossDatabase'
  334. */
  335. public $name = 'SchemaCrossDatabase';
  336. /**
  337. * useTable property
  338. *
  339. * @var string 'posts'
  340. */
  341. public $useTable = 'cross_database';
  342. /**
  343. * useDbConfig property
  344. *
  345. * @var string 'test2'
  346. */
  347. public $useDbConfig = 'test2';
  348. }
  349. /**
  350. * SchemaCrossDatabaseFixture class
  351. *
  352. * @package Cake.Test.Case.Model
  353. */
  354. class SchemaCrossDatabaseFixture extends CakeTestFixture {
  355. /**
  356. * name property
  357. *
  358. * @var string 'CrossDatabase'
  359. */
  360. public $name = 'CrossDatabase';
  361. /**
  362. * table property
  363. *
  364. */
  365. public $table = 'cross_database';
  366. /**
  367. * fields property
  368. *
  369. * @var array
  370. */
  371. public $fields = array(
  372. 'id' => array('type' => 'integer', 'key' => 'primary'),
  373. 'name' => 'string'
  374. );
  375. /**
  376. * records property
  377. *
  378. * @var array
  379. */
  380. public $records = array(
  381. array('id' => 1, 'name' => 'First'),
  382. array('id' => 2, 'name' => 'Second'),
  383. );
  384. }
  385. /**
  386. * SchemaPrefixAuthUser class
  387. *
  388. * @package Cake.Test.Case.Model
  389. */
  390. class SchemaPrefixAuthUser extends CakeTestModel {
  391. /**
  392. * name property
  393. *
  394. * @var string
  395. */
  396. public $name = 'SchemaPrefixAuthUser';
  397. /**
  398. * table prefix
  399. *
  400. * @var string
  401. */
  402. public $tablePrefix = 'auth_';
  403. /**
  404. * useTable
  405. *
  406. * @var string
  407. */
  408. public $useTable = 'users';
  409. }
  410. /**
  411. * CakeSchemaTest
  412. *
  413. * @package Cake.Test.Case.Model
  414. */
  415. class CakeSchemaTest extends CakeTestCase {
  416. /**
  417. * fixtures property
  418. *
  419. * @var array
  420. */
  421. public $fixtures = array(
  422. 'core.post', 'core.tag', 'core.posts_tag', 'core.test_plugin_comment',
  423. 'core.datatype', 'core.auth_user', 'core.author',
  424. 'core.test_plugin_article', 'core.user', 'core.comment',
  425. 'core.prefix_test'
  426. );
  427. /**
  428. * setUp method
  429. *
  430. * @return void
  431. */
  432. public function setUp() {
  433. parent::setUp();
  434. ConnectionManager::getDataSource('test')->cacheSources = false;
  435. $this->Schema = new TestAppSchema();
  436. }
  437. /**
  438. * tearDown method
  439. *
  440. * @return void
  441. */
  442. public function tearDown() {
  443. parent::tearDown();
  444. if (file_exists(TMP . 'tests' . DS . 'schema.php')) {
  445. unlink(TMP . 'tests' . DS . 'schema.php');
  446. }
  447. unset($this->Schema);
  448. CakePlugin::unload();
  449. }
  450. /**
  451. * testSchemaName method
  452. *
  453. * @return void
  454. */
  455. public function testSchemaName() {
  456. $Schema = new CakeSchema();
  457. $this->assertEquals(Inflector::camelize(Inflector::slug(APP_DIR)), $Schema->name);
  458. Configure::write('App.dir', 'Some.name.with.dots');
  459. $Schema = new CakeSchema();
  460. $this->assertEquals('SomeNameWithDots', $Schema->name);
  461. Configure::write('App.dir', 'Some-name-with-dashes');
  462. $Schema = new CakeSchema();
  463. $this->assertEquals('SomeNameWithDashes', $Schema->name);
  464. Configure::write('App.dir', 'Some name with spaces');
  465. $Schema = new CakeSchema();
  466. $this->assertEquals('SomeNameWithSpaces', $Schema->name);
  467. Configure::write('App.dir', 'Some,name;with&weird=characters');
  468. $Schema = new CakeSchema();
  469. $this->assertEquals('SomeNameWithWeirdCharacters', $Schema->name);
  470. Configure::write('App.dir', 'app');
  471. }
  472. /**
  473. * testSchemaRead method
  474. *
  475. * @return void
  476. */
  477. public function testSchemaRead() {
  478. $read = $this->Schema->read(array(
  479. 'connection' => 'test',
  480. 'name' => 'TestApp',
  481. 'models' => array('SchemaPost', 'SchemaComment', 'SchemaTag', 'SchemaDatatype')
  482. ));
  483. unset($read['tables']['missing']);
  484. $expected = array('comments', 'datatypes', 'posts', 'posts_tags', 'tags');
  485. foreach ($expected as $table) {
  486. $this->assertTrue(isset($read['tables'][$table]), 'Missing table ' . $table);
  487. }
  488. foreach ($this->Schema->tables as $table => $fields) {
  489. $this->assertEquals(array_keys($fields), array_keys($read['tables'][$table]));
  490. }
  491. if (isset($read['tables']['datatypes']['float_field']['length'])) {
  492. $this->assertEquals(
  493. $read['tables']['datatypes']['float_field']['length'],
  494. $this->Schema->tables['datatypes']['float_field']['length']
  495. );
  496. }
  497. $this->assertEquals(
  498. $read['tables']['datatypes']['float_field']['type'],
  499. $this->Schema->tables['datatypes']['float_field']['type']
  500. );
  501. $this->assertEquals(
  502. $read['tables']['datatypes']['float_field']['null'],
  503. $this->Schema->tables['datatypes']['float_field']['null']
  504. );
  505. $db = ConnectionManager::getDataSource('test');
  506. $config = $db->config;
  507. $config['prefix'] = 'schema_test_prefix_';
  508. ConnectionManager::create('schema_prefix', $config);
  509. $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false));
  510. $this->assertTrue(empty($read['tables']));
  511. $read = $this->Schema->read(array(
  512. 'connection' => 'test',
  513. 'name' => 'TestApp',
  514. 'models' => array('SchemaComment', 'SchemaTag', 'SchemaPost')
  515. ));
  516. $this->assertFalse(isset($read['tables']['missing']['posts_tags']), 'Join table marked as missing');
  517. }
  518. /**
  519. * testSchemaReadWithAppModel method
  520. *
  521. * @access public
  522. * @return void
  523. */
  524. public function testSchemaReadWithAppModel() {
  525. $connections = ConnectionManager::enumConnectionObjects();
  526. ConnectionManager::drop('default');
  527. ConnectionManager::create('default', $connections['test']);
  528. try {
  529. $read = $this->Schema->read(array(
  530. 'connection' => 'default',
  531. 'name' => 'TestApp',
  532. 'models' => array('AppModel')
  533. ));
  534. } catch(MissingTableException $mte) {
  535. ConnectionManager::drop('default');
  536. $this->fail($mte->getMessage());
  537. }
  538. ConnectionManager::drop('default');
  539. }
  540. /**
  541. * testSchemaReadWithOddTablePrefix method
  542. *
  543. * @return void
  544. */
  545. public function testSchemaReadWithOddTablePrefix() {
  546. $config = ConnectionManager::getDataSource('test')->config;
  547. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  548. $SchemaPost = ClassRegistry::init('SchemaPost');
  549. $SchemaPost->tablePrefix = 'po';
  550. $SchemaPost->useTable = 'sts';
  551. $read = $this->Schema->read(array(
  552. 'connection' => 'test',
  553. 'name' => 'TestApp',
  554. 'models' => array('SchemaPost')
  555. ));
  556. $this->assertFalse(isset($read['tables']['missing']['posts']), 'Posts table was not read from tablePrefix');
  557. }
  558. /**
  559. * test read() with tablePrefix properties.
  560. *
  561. * @return void
  562. */
  563. public function testSchemaReadWithTablePrefix() {
  564. $config = ConnectionManager::getDataSource('test')->config;
  565. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  566. $model = new SchemaPrefixAuthUser();
  567. $Schema = new CakeSchema();
  568. $read = $Schema->read(array(
  569. 'connection' => 'test',
  570. 'name' => 'TestApp',
  571. 'models' => array('SchemaPrefixAuthUser')
  572. ));
  573. unset($read['tables']['missing']);
  574. $this->assertTrue(isset($read['tables']['auth_users']), 'auth_users key missing %s');
  575. }
  576. /**
  577. * test reading schema with config prefix.
  578. *
  579. * @return void
  580. */
  581. public function testSchemaReadWithConfigPrefix() {
  582. $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite');
  583. $db = ConnectionManager::getDataSource('test');
  584. $config = $db->config;
  585. $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.');
  586. $config['prefix'] = 'schema_test_prefix_';
  587. ConnectionManager::create('schema_prefix', $config);
  588. $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false));
  589. $this->assertTrue(empty($read['tables']));
  590. $config['prefix'] = 'prefix_';
  591. ConnectionManager::create('schema_prefix2', $config);
  592. $read = $this->Schema->read(array(
  593. 'connection' => 'schema_prefix2',
  594. 'name' => 'TestApp',
  595. 'models' => false));
  596. $this->assertTrue(isset($read['tables']['prefix_tests']));
  597. }
  598. /**
  599. * test reading schema from plugins.
  600. *
  601. * @return void
  602. */
  603. public function testSchemaReadWithPlugins() {
  604. App::objects('model', null, false);
  605. App::build(array(
  606. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  607. ));
  608. CakePlugin::load('TestPlugin');
  609. $Schema = new CakeSchema();
  610. $Schema->plugin = 'TestPlugin';
  611. $read = $Schema->read(array(
  612. 'connection' => 'test',
  613. 'name' => 'TestApp',
  614. 'models' => true
  615. ));
  616. unset($read['tables']['missing']);
  617. $this->assertTrue(isset($read['tables']['auth_users']));
  618. $this->assertTrue(isset($read['tables']['authors']));
  619. $this->assertTrue(isset($read['tables']['test_plugin_comments']));
  620. $this->assertTrue(isset($read['tables']['posts']));
  621. $this->assertTrue(count($read['tables']) >= 4);
  622. App::build();
  623. }
  624. /**
  625. * test reading schema with tables from another database.
  626. *
  627. * @return void
  628. */
  629. public function testSchemaReadWithCrossDatabase() {
  630. $config = ConnectionManager::enumConnectionObjects();
  631. $this->skipIf(
  632. !isset($config['test']) || !isset($config['test2']),
  633. 'Primary and secondary test databases not configured, ' .
  634. 'skipping cross-database join tests. ' .
  635. 'To run these tests, you must define $test and $test2 in your database configuration.'
  636. );
  637. $db = ConnectionManager::getDataSource('test2');
  638. $fixture = new SchemaCrossDatabaseFixture();
  639. $fixture->create($db);
  640. $fixture->insert($db);
  641. $read = $this->Schema->read(array(
  642. 'connection' => 'test',
  643. 'name' => 'TestApp',
  644. 'models' => array('SchemaCrossDatabase', 'SchemaPost')
  645. ));
  646. $this->assertTrue(isset($read['tables']['posts']));
  647. $this->assertFalse(isset($read['tables']['cross_database']), 'Cross database should not appear');
  648. $this->assertFalse(isset($read['tables']['missing']['cross_database']), 'Cross database should not appear');
  649. $read = $this->Schema->read(array(
  650. 'connection' => 'test2',
  651. 'name' => 'TestApp',
  652. 'models' => array('SchemaCrossDatabase', 'SchemaPost')
  653. ));
  654. $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
  655. $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
  656. $this->assertTrue(isset($read['tables']['cross_database']));
  657. $fixture->drop($db);
  658. }
  659. /**
  660. * test that tables are generated correctly
  661. *
  662. * @return void
  663. */
  664. public function testGenerateTable() {
  665. $posts = array(
  666. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  667. 'author_id' => array('type' => 'integer', 'null' => false),
  668. 'title' => array('type' => 'string', 'null' => false),
  669. 'body' => array('type' => 'text', 'null' => true, 'default' => null),
  670. 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
  671. 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
  672. 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
  673. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
  674. );
  675. $result = $this->Schema->generateTable('posts', $posts);
  676. $this->assertRegExp('/public \$posts/', $result);
  677. }
  678. /**
  679. * testSchemaWrite method
  680. *
  681. * @return void
  682. */
  683. public function testSchemaWrite() {
  684. $write = $this->Schema->write(array(
  685. 'name' => 'MyOtherApp',
  686. 'tables' => $this->Schema->tables,
  687. 'path' => TMP . 'tests'
  688. ));
  689. $file = file_get_contents(TMP . 'tests' . DS . 'schema.php');
  690. $this->assertEquals($write, $file);
  691. require_once TMP . 'tests' . DS . 'schema.php';
  692. $OtherSchema = new MyOtherAppSchema();
  693. $this->assertEquals($this->Schema->tables, $OtherSchema->tables);
  694. }
  695. /**
  696. * testSchemaComparison method
  697. *
  698. * @return void
  699. */
  700. public function testSchemaComparison() {
  701. $New = new MyAppSchema();
  702. $compare = $New->compare($this->Schema);
  703. $expected = array(
  704. 'comments' => array(
  705. 'add' => array(
  706. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'after' => 'id'),
  707. 'title' => array('type' => 'string', 'null' => false, 'length' => 100, 'after' => 'user_id'),
  708. ),
  709. 'drop' => array(
  710. 'article_id' => array('type' => 'integer', 'null' => false),
  711. 'tableParameters' => array(),
  712. ),
  713. 'change' => array(
  714. 'comment' => array('type' => 'text', 'null' => false, 'default' => null),
  715. )
  716. ),
  717. 'posts' => array(
  718. 'add' => array(
  719. 'summary' => array('type' => 'text', 'null' => true, 'after' => 'body'),
  720. ),
  721. 'drop' => array(
  722. 'tableParameters' => array(),
  723. ),
  724. 'change' => array(
  725. 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
  726. 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
  727. 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1)
  728. )
  729. ),
  730. );
  731. $this->assertEquals($expected, $compare);
  732. $this->assertNull($New->getVar('comments'));
  733. $this->assertEquals(array('bar'), $New->getVar('_foo'));
  734. $tables = array(
  735. 'missing' => array(
  736. 'categories' => array(
  737. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  738. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null),
  739. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null),
  740. 'name' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 100),
  741. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  742. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  743. )
  744. ),
  745. 'ratings' => array(
  746. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  747. 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null),
  748. 'model' => array('type' => 'varchar', 'null' => false, 'default' => null),
  749. 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null),
  750. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null),
  751. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null),
  752. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  753. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  754. )
  755. );
  756. $compare = $New->compare($this->Schema, $tables);
  757. $expected = array(
  758. 'ratings' => array(
  759. 'add' => array(
  760. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  761. 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null, 'after' => 'id'),
  762. 'model' => array('type' => 'varchar', 'null' => false, 'default' => null, 'after' => 'foreign_key'),
  763. 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null, 'after' => 'model'),
  764. 'created' => array('type' => 'datetime', 'null' => false, 'default' => null, 'after' => 'value'),
  765. 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null, 'after' => 'created'),
  766. 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
  767. 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
  768. )
  769. )
  770. );
  771. $this->assertEquals($expected, $compare);
  772. }
  773. /**
  774. * test comparing '' and null and making sure they are different.
  775. *
  776. * @return void
  777. */
  778. public function testCompareEmptyStringAndNull() {
  779. $One = new CakeSchema(array(
  780. 'posts' => array(
  781. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  782. 'name' => array('type' => 'string', 'null' => false, 'default' => '')
  783. )
  784. ));
  785. $Two = new CakeSchema(array(
  786. 'posts' => array(
  787. 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'),
  788. 'name' => array('type' => 'string', 'null' => false, 'default' => null)
  789. )
  790. ));
  791. $compare = $One->compare($Two);
  792. $expected = array(
  793. 'posts' => array(
  794. 'change' => array(
  795. 'name' => array('type' => 'string', 'null' => false, 'default' => null)
  796. )
  797. )
  798. );
  799. $this->assertEquals($expected, $compare);
  800. }
  801. /**
  802. * Test comparing tableParameters and indexes.
  803. *
  804. * @return void
  805. */
  806. public function testTableParametersAndIndexComparison() {
  807. $old = array(
  808. 'posts' => array(
  809. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  810. 'author_id' => array('type' => 'integer', 'null' => false),
  811. 'title' => array('type' => 'string', 'null' => false),
  812. 'indexes' => array(
  813. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  814. ),
  815. 'tableParameters' => array(
  816. 'charset' => 'latin1',
  817. 'collate' => 'latin1_general_ci'
  818. )
  819. ),
  820. 'comments' => array(
  821. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  822. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  823. 'comment' => array('type' => 'text'),
  824. 'indexes' => array(
  825. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  826. 'post_id' => array('column' => 'post_id'),
  827. ),
  828. 'tableParameters' => array(
  829. 'engine' => 'InnoDB',
  830. 'charset' => 'latin1',
  831. 'collate' => 'latin1_general_ci'
  832. )
  833. )
  834. );
  835. $new = array(
  836. 'posts' => array(
  837. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  838. 'author_id' => array('type' => 'integer', 'null' => false),
  839. 'title' => array('type' => 'string', 'null' => false),
  840. 'indexes' => array(
  841. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  842. 'author_id' => array('column' => 'author_id'),
  843. ),
  844. 'tableParameters' => array(
  845. 'charset' => 'utf8',
  846. 'collate' => 'utf8_general_ci',
  847. 'engine' => 'MyISAM'
  848. )
  849. ),
  850. 'comments' => array(
  851. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  852. 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
  853. 'comment' => array('type' => 'text'),
  854. 'indexes' => array(
  855. 'PRIMARY' => array('column' => 'id', 'unique' => true),
  856. ),
  857. 'tableParameters' => array(
  858. 'charset' => 'utf8',
  859. 'collate' => 'utf8_general_ci'
  860. )
  861. )
  862. );
  863. $compare = $this->Schema->compare($old, $new);
  864. $expected = array(
  865. 'posts' => array(
  866. 'add' => array(
  867. 'indexes' => array('author_id' => array('column' => 'author_id')),
  868. ),
  869. 'change' => array(
  870. 'tableParameters' => array(
  871. 'charset' => 'utf8',
  872. 'collate' => 'utf8_general_ci',
  873. 'engine' => 'MyISAM'
  874. )
  875. )
  876. ),
  877. 'comments' => array(
  878. 'drop' => array(
  879. 'indexes' => array('post_id' => array('column' => 'post_id')),
  880. ),
  881. 'change' => array(
  882. 'tableParameters' => array(
  883. 'charset' => 'utf8',
  884. 'collate' => 'utf8_general_ci',
  885. )
  886. )
  887. )
  888. );
  889. $this->assertEquals($expected, $compare);
  890. }
  891. /**
  892. * Test comparing with field changed from VARCHAR to DATETIME
  893. *
  894. * @return void
  895. */
  896. public function testCompareVarcharToDatetime() {
  897. $old = array(
  898. 'posts' => array(
  899. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  900. 'author_id' => array('type' => 'integer', 'null' => false),
  901. 'title' => array('type' => 'string', 'null' => true, 'length' => 45),
  902. 'indexes' => array(
  903. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  904. ),
  905. 'tableParameters' => array(
  906. 'charset' => 'latin1',
  907. 'collate' => 'latin1_general_ci'
  908. )
  909. ),
  910. );
  911. $new = array(
  912. 'posts' => array(
  913. 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
  914. 'author_id' => array('type' => 'integer', 'null' => false),
  915. 'title' => array('type' => 'datetime', 'null' => false),
  916. 'indexes' => array(
  917. 'PRIMARY' => array('column' => 'id', 'unique' => true)
  918. ),
  919. 'tableParameters' => array(
  920. 'charset' => 'latin1',
  921. 'collate' => 'latin1_general_ci'
  922. )
  923. ),
  924. );
  925. $compare = $this->Schema->compare($old, $new);
  926. $expected = array(
  927. 'posts' => array(
  928. 'change' => array(
  929. 'title' => array(
  930. 'type' => 'datetime',
  931. 'null' => false,
  932. )
  933. )
  934. ),
  935. );
  936. $this->assertEquals($expected, $compare, 'Invalid SQL, datetime does not have length');
  937. }
  938. /**
  939. * testSchemaLoading method
  940. *
  941. * @return void
  942. */
  943. public function testSchemaLoading() {
  944. $Other = $this->Schema->load(array('name' => 'MyOtherApp', 'path' => TMP . 'tests'));
  945. $this->assertEquals('MyOtherApp', $Other->name);
  946. $this->assertEquals($Other->tables, $this->Schema->tables);
  947. }
  948. /**
  949. * test loading schema files inside of plugins.
  950. *
  951. * @return void
  952. */
  953. public function testSchemaLoadingFromPlugin() {
  954. App::build(array(
  955. 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS)
  956. ));
  957. CakePlugin::load('TestPlugin');
  958. $Other = $this->Schema->load(array('name' => 'TestPluginApp', 'plugin' => 'TestPlugin'));
  959. $this->assertEquals('TestPluginApp', $Other->name);
  960. $this->assertEquals(array('test_plugin_acos'), array_keys($Other->tables));
  961. App::build();
  962. }
  963. /**
  964. * testSchemaCreateTable method
  965. *
  966. * @return void
  967. */
  968. public function testSchemaCreateTable() {
  969. $db = ConnectionManager::getDataSource('test');
  970. $db->cacheSources = false;
  971. $Schema = new CakeSchema(array(
  972. 'connection' => 'test',
  973. 'testdescribes' => array(
  974. 'id' => array('type' => 'integer', 'key' => 'primary'),
  975. 'int_null' => array('type' => 'integer', 'null' => true),
  976. 'int_not_null' => array('type' => 'integer', 'null' => false),
  977. ),
  978. ));
  979. $sql = $db->createSchema($Schema);
  980. $col = $Schema->tables['testdescribes']['int_null'];
  981. $col['name'] = 'int_null';
  982. $column = $this->db->buildColumn($col);
  983. $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql);
  984. $col = $Schema->tables['testdescribes']['int_not_null'];
  985. $col['name'] = 'int_not_null';
  986. $column = $this->db->buildColumn($col);
  987. $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql);
  988. }
  989. }