3
* Test for Schema database management
8
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
9
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
11
* Licensed under The Open Group Test Suite License
12
* Redistributions of files must retain the above copyright notice.
14
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
15
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
17
* @subpackage cake.tests.cases.libs
18
* @since CakePHP(tm) v 1.2.0.5550
19
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
21
App::import('Model', 'CakeSchema', false);
24
* Test for Schema database management
27
* @subpackage cake.tests.cases.libs
29
class MyAppSchema extends CakeSchema {
42
* @var string 'test_suite'
45
var $connection = 'test_suite';
53
var $comments = array(
54
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
55
'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
56
'user_id' => array('type' => 'integer', 'null' => false),
57
'title' => array('type' => 'string', 'null' => false, 'length' => 100),
58
'comment' => array('type' => 'text', 'null' => false, 'default' => null),
59
'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
60
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
61
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
62
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
72
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
73
'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
74
'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
75
'body' => array('type' => 'text', 'null' => true, 'default' => null),
76
'summary' => array('type' => 'text', 'null' => true),
77
'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1),
78
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
79
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
80
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
86
* @param mixed $version
90
function setup($version) {
96
* @param mixed $version
100
function teardown($version) {
105
* TestAppSchema class
108
* @subpackage cake.tests.cases.libs.model
110
class TestAppSchema extends CakeSchema {
115
* @var string 'MyApp'
126
var $comments = array(
127
'id' => array('type' => 'integer', 'null' => false, 'default' => 0,'key' => 'primary'),
128
'article_id' => array('type' => 'integer', 'null' => false),
129
'user_id' => array('type' => 'integer', 'null' => false),
130
'comment' => array('type' => 'text', 'null' => true, 'default' => null),
131
'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
132
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
133
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
134
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
135
'tableParameters' => array(),
145
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
146
'author_id' => array('type' => 'integer', 'null' => false),
147
'title' => array('type' => 'string', 'null' => false),
148
'body' => array('type' => 'text', 'null' => true, 'default' => null),
149
'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
150
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
151
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
152
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
153
'tableParameters' => array(),
157
* posts_tags property
162
var $posts_tags = array(
163
'post_id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'),
164
'tag_id' => array('type' => 'string', 'null' => false, 'key' => 'primary'),
165
'indexes' => array('posts_tag' => array('column' => array('tag_id', 'post_id'), 'unique' => 1)),
166
'tableParameters' => array()
176
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
177
'tag' => array('type' => 'string', 'null' => false),
178
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
179
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
180
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
181
'tableParameters' => array()
190
var $datatypes = array(
191
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
192
'float_field' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => ''),
193
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
194
'tableParameters' => array()
200
* @param mixed $version
204
function setup($version) {
210
* @param mixed $version
214
function teardown($version) {
222
* @subpackage cake.tests.cases.libs.model
224
class SchemaPost extends CakeTestModel {
229
* @var string 'SchemaPost'
232
var $name = 'SchemaPost';
237
* @var string 'posts'
240
var $useTable = 'posts';
248
var $hasMany = array('SchemaComment');
251
* hasAndBelongsToMany property
256
var $hasAndBelongsToMany = array('SchemaTag');
260
* SchemaComment class
263
* @subpackage cake.tests.cases.libs.model
265
class SchemaComment extends CakeTestModel {
270
* @var string 'SchemaComment'
273
var $name = 'SchemaComment';
278
* @var string 'comments'
281
var $useTable = 'comments';
289
var $belongsTo = array('SchemaPost');
296
* @subpackage cake.tests.cases.libs.model
298
class SchemaTag extends CakeTestModel {
303
* @var string 'SchemaTag'
306
var $name = 'SchemaTag';
314
var $useTable = 'tags';
317
* hasAndBelongsToMany property
322
var $hasAndBelongsToMany = array('SchemaPost');
326
* SchemaDatatype class
329
* @subpackage cake.tests.cases.libs.model
331
class SchemaDatatype extends CakeTestModel {
336
* @var string 'SchemaDatatype'
339
var $name = 'SchemaDatatype';
344
* @var string 'datatypes'
347
var $useTable = 'datatypes';
353
* This class is defined purely to inherit the cacheSources variable otherwise
354
* testSchemaCreatTable will fail if listSources has already been called and
355
* its source cache populated - I.e. if the test is run within a group
357
* @uses CakeTestModel
359
* @subpackage cake.tests.cases.libs.model
361
class Testdescribe extends CakeTestModel {
366
* @var string 'Testdescribe'
369
var $name = 'Testdescribe';
373
* SchemaCrossDatabase class
376
* @subpackage cake.tests.cases.libs.model
378
class SchemaCrossDatabase extends CakeTestModel {
383
* @var string 'SchemaCrossDatabase'
386
var $name = 'SchemaCrossDatabase';
391
* @var string 'posts'
394
var $useTable = 'cross_database';
397
* useDbConfig property
399
* @var string 'test2'
402
var $useDbConfig = 'test2';
406
* SchemaCrossDatabaseFixture class
409
* @subpackage cake.tests.cases.libs.model
411
class SchemaCrossDatabaseFixture extends CakeTestFixture {
416
* @var string 'CrossDatabase'
419
var $name = 'CrossDatabase';
426
var $table = 'cross_database';
435
'id' => array('type' => 'integer', 'key' => 'primary'),
445
var $records = array(
446
array('id' => 1, 'name' => 'First'),
447
array('id' => 2, 'name' => 'Second'),
452
* SchemaPrefixAuthUser class
455
* @subpackage cake.tests.cases.libs.model
457
class SchemaPrefixAuthUser extends CakeTestModel {
463
var $name = 'SchemaPrefixAuthUser';
469
var $tablePrefix = 'auth_';
475
var $useTable = 'users';
482
* @subpackage cake.tests.cases.libs
484
class CakeSchemaTest extends CakeTestCase {
492
var $fixtures = array(
493
'core.post', 'core.tag', 'core.posts_tag', 'core.test_plugin_comment',
494
'core.datatype', 'core.auth_user', 'core.author',
495
'core.test_plugin_article', 'core.user', 'core.comment'
504
function startTest() {
505
$this->Schema = new TestAppSchema();
514
function tearDown() {
515
@unlink(TMP . 'tests' . DS .'schema.php');
516
unset($this->Schema);
517
ClassRegistry::flush();
521
* testSchemaName method
526
function testSchemaName() {
527
$Schema = new CakeSchema();
528
$this->assertEqual(strtolower($Schema->name), strtolower(APP_DIR));
530
Configure::write('App.dir', 'Some.name.with.dots');
531
$Schema = new CakeSchema();
532
$this->assertEqual($Schema->name, 'SomeNameWithDots');
534
Configure::write('App.dir', 'app');
538
* testSchemaRead method
543
function testSchemaRead() {
544
$read = $this->Schema->read(array(
545
'connection' => 'test_suite',
547
'models' => array('SchemaPost', 'SchemaComment', 'SchemaTag', 'SchemaDatatype')
549
unset($read['tables']['missing']);
551
$expected = array('comments', 'datatypes', 'posts', 'posts_tags', 'tags');
552
$this->assertEqual(array_keys($read['tables']), $expected);
553
foreach ($read['tables'] as $table => $fields) {
554
$this->assertEqual(array_keys($fields), array_keys($this->Schema->tables[$table]));
558
$read['tables']['datatypes']['float_field'],
559
$this->Schema->tables['datatypes']['float_field']
562
$SchemaPost =& ClassRegistry::init('SchemaPost');
563
$SchemaPost->table = 'sts';
564
$SchemaPost->tablePrefix = 'po';
565
$read = $this->Schema->read(array(
566
'connection' => 'test_suite',
568
'models' => array('SchemaPost')
570
$this->assertFalse(isset($read['tables']['missing']['posts']), 'Posts table was not read from tablePrefix %s');
572
$read = $this->Schema->read(array(
573
'connection' => 'test_suite',
575
'models' => array('SchemaComment', 'SchemaTag', 'SchemaPost')
577
$this->assertFalse(isset($read['tables']['missing']['posts_tags']), 'Join table marked as missing %s');
581
* test read() with tablePrefix properties.
585
function testSchemaReadWithTablePrefix() {
586
$model =& new SchemaPrefixAuthUser();
588
$Schema =& new CakeSchema();
589
$read = $Schema->read(array(
590
'connection' => 'test_suite',
592
'models' => array('SchemaPrefixAuthUser')
594
unset($read['tables']['missing']);
595
$this->assertTrue(isset($read['tables']['auth_users']), 'auth_users key missing %s');
600
* test reading schema with config prefix.
604
function testSchemaReadWithConfigPrefix() {
605
$db =& ConnectionManager::getDataSource('test_suite');
606
$config = $db->config;
607
$config['prefix'] = 'schema_test_prefix_';
608
ConnectionManager::create('schema_prefix', $config);
609
$read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false));
610
$this->assertTrue(empty($read['tables']));
614
* test reading schema from plugins.
618
function testSchemaReadWithPlugins() {
619
App::objects('model', null, false);
621
'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS)
624
$Schema =& new CakeSchema();
625
$Schema->plugin = 'TestPlugin';
626
$read = $Schema->read(array(
627
'connection' => 'test_suite',
631
unset($read['tables']['missing']);
632
$this->assertTrue(isset($read['tables']['auth_users']));
633
$this->assertTrue(isset($read['tables']['authors']));
634
$this->assertTrue(isset($read['tables']['test_plugin_comments']));
635
$this->assertTrue(isset($read['tables']['posts']));
636
$this->assertEqual(count($read['tables']), 4);
642
* test reading schema with tables from another database.
646
function testSchemaReadWithCrossDatabase() {
647
$config = new DATABASE_CONFIG();
648
$skip = $this->skipIf(
649
!isset($config->test) || !isset($config->test2),
650
'%s Primary and secondary test databases not configured, skipping cross-database '
652
.' To run these tests, you must define $test and $test2 in your database configuration.'
658
$db2 =& ConnectionManager::getDataSource('test2');
659
$fixture = new SchemaCrossDatabaseFixture();
660
$fixture->create($db2);
661
$fixture->insert($db2);
663
$read = $this->Schema->read(array(
664
'connection' => 'test_suite',
666
'models' => array('SchemaCrossDatabase', 'SchemaPost')
668
$this->assertTrue(isset($read['tables']['posts']));
669
$this->assertFalse(isset($read['tables']['cross_database']), 'Cross database should not appear');
670
$this->assertFalse(isset($read['tables']['missing']['cross_database']), 'Cross database should not appear');
672
$read = $this->Schema->read(array(
673
'connection' => 'test2',
675
'models' => array('SchemaCrossDatabase', 'SchemaPost')
677
$this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
678
$this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear');
679
$this->assertTrue(isset($read['tables']['cross_database']));
681
$fixture->drop($db2);
685
* test that tables are generated correctly
689
function testGenerateTable() {
691
'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'),
692
'author_id' => array('type' => 'integer', 'null' => false),
693
'title' => array('type' => 'string', 'null' => false),
694
'body' => array('type' => 'text', 'null' => true, 'default' => null),
695
'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1),
696
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
697
'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
698
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)),
700
$result = $this->Schema->generateTable('posts', $fields);
701
$this->assertPattern('/var \$posts/', $result);
703
eval(substr($result, 4));
704
$this->assertEqual($posts, $fields);
707
* testSchemaWrite method
712
function testSchemaWrite() {
713
$write = $this->Schema->write(array('name' => 'MyOtherApp', 'tables' => $this->Schema->tables, 'path' => TMP . 'tests'));
714
$file = file_get_contents(TMP . 'tests' . DS .'schema.php');
715
$this->assertEqual($write, $file);
717
require_once( TMP . 'tests' . DS .'schema.php');
718
$OtherSchema = new MyOtherAppSchema();
719
$this->assertEqual($this->Schema->tables, $OtherSchema->tables);
723
* testSchemaComparison method
728
function testSchemaComparison() {
729
$New = new MyAppSchema();
730
$compare = $New->compare($this->Schema);
734
'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0),
735
'title' => array('type' => 'string', 'null' => false, 'length' => 100),
738
'article_id' => array('type' => 'integer', 'null' => false),
739
'tableParameters' => array(),
742
'comment' => array('type' => 'text', 'null' => false, 'default' => null),
747
'summary' => array('type' => 'text', 'null' => 1),
750
'tableParameters' => array(),
753
'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''),
754
'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'),
755
'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => '1')
759
$this->assertEqual($expected, $compare);
763
'categories' => array(
764
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
765
'created' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
766
'modified' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
767
'name' => array('type' => 'string', 'null' => false, 'default' => NULL, 'length' => 100),
768
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
769
'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
773
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
774
'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => NULL),
775
'model' => array('type' => 'varchar', 'null' => false, 'default' => NULL),
776
'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => NULL),
777
'created' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
778
'modified' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
779
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
780
'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
783
$compare = $New->compare($this->Schema, $tables);
787
'id' => array('type' => 'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'),
788
'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => NULL),
789
'model' => array('type' => 'varchar', 'null' => false, 'default' => NULL),
790
'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => NULL),
791
'created' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
792
'modified' => array('type' => 'datetime', 'null' => false, 'default' => NULL),
793
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
794
'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM')
798
$this->assertEqual($expected, $compare);
802
* Test comparing tableParameters and indexes.
806
function testTableParametersAndIndexComparison() {
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),
813
'PRIMARY' => array('column' => 'id', 'unique' => true)
815
'tableParameters' => array(
816
'charset' => 'latin1',
817
'collate' => 'latin1_general_ci'
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'),
825
'PRIMARY' => array('column' => 'id', 'unique' => true),
826
'post_id' => array('column' => 'post_id'),
828
'tableParameters' => array(
829
'engine' => 'InnoDB',
830
'charset' => 'latin1',
831
'collate' => 'latin1_general_ci'
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),
841
'PRIMARY' => array('column' => 'id', 'unique' => true),
842
'author_id' => array('column' => 'author_id'),
844
'tableParameters' => array(
846
'collate' => 'utf8_general_ci',
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'),
855
'PRIMARY' => array('column' => 'id', 'unique' => true),
857
'tableParameters' => array(
859
'collate' => 'utf8_general_ci'
863
$compare = $this->Schema->compare($old, $new);
867
'indexes' => array('author_id' => array('column' => 'author_id')),
870
'tableParameters' => array(
872
'collate' => 'utf8_general_ci',
879
'indexes' => array('post_id' => array('column' => 'post_id')),
882
'tableParameters' => array(
884
'collate' => 'utf8_general_ci',
889
$this->assertEqual($compare, $expected);
893
* testSchemaLoading method
898
function testSchemaLoading() {
899
$Other =& $this->Schema->load(array('name' => 'MyOtherApp', 'path' => TMP . 'tests'));
900
$this->assertEqual($Other->name, 'MyOtherApp');
901
$this->assertEqual($Other->tables, $this->Schema->tables);
905
* test loading schema files inside of plugins.
909
function testSchemaLoadingFromPlugin() {
911
'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS)
913
$Other =& $this->Schema->load(array('name' => 'TestPluginApp', 'plugin' => 'TestPlugin'));
914
$this->assertEqual($Other->name, 'TestPluginApp');
915
$this->assertEqual(array_keys($Other->tables), array('acos'));
921
* testSchemaCreateTable method
926
function testSchemaCreateTable() {
927
$db =& ConnectionManager::getDataSource('test_suite');
928
$db->cacheSources = false;
930
$Schema =& new CakeSchema(array(
931
'connection' => 'test_suite',
932
'testdescribes' => array(
933
'id' => array('type' => 'integer', 'key' => 'primary'),
934
'int_null' => array('type' => 'integer', 'null' => true),
935
'int_not_null' => array('type' => 'integer', 'null' => false),
938
$sql = $db->createSchema($Schema);
940
$col = $Schema->tables['testdescribes']['int_null'];
941
$col['name'] = 'int_null';
942
$column = $this->db->buildColumn($col);
943
$this->assertPattern('/' . preg_quote($column, '/') . '/', $sql);
945
$col = $Schema->tables['testdescribes']['int_not_null'];
946
$col['name'] = 'int_not_null';
947
$column = $this->db->buildColumn($col);
948
$this->assertPattern('/' . preg_quote($column, '/') . '/', $sql);