From 2a72e18f7fba87323b8c5062b757c700474ca42e Mon Sep 17 00:00:00 2001 From: Chuck Hagenbuch Date: Mon, 16 Feb 2009 15:07:04 -0500 Subject: [PATCH] add Mad migration tests --- framework/Db/test/Horde/Db/Migration/BaseTest.php | 525 +++++++++++++++++++++ .../Db/test/Horde/Db/Migration/MigratorTest.php | 213 +++++++++ .../migrations/1_users_have_last_names1.php | 14 + .../fixtures/migrations/2_we_need_reminders1.php | 17 + .../fixtures/migrations/3_innocent_jointable1.php | 17 + .../1_give_me_big_numbers.php | 20 + .../1_users_have_last_names2.php | 14 + .../2_we_need_reminders2.php | 17 + .../fixtures/migrations_with_duplicate/3_foo.php | 12 + .../3_innocent_jointable2.php | 17 + .../1000_users_have_middle_names.php | 14 + .../1_users_have_last_names3.php | 14 + .../3_we_need_reminders.php | 17 + .../4_innocent_jointable3.php | 17 + 14 files changed, 928 insertions(+) create mode 100644 framework/Db/test/Horde/Db/Migration/BaseTest.php create mode 100644 framework/Db/test/Horde/Db/Migration/MigratorTest.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations/1_users_have_last_names1.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations/2_we_need_reminders1.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations/3_innocent_jointable1.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_decimal/1_give_me_big_numbers.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/1_users_have_last_names2.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/2_we_need_reminders2.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/3_foo.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/3_innocent_jointable2.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1000_users_have_middle_names.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1_users_have_last_names3.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/3_we_need_reminders.php create mode 100644 framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/4_innocent_jointable3.php diff --git a/framework/Db/test/Horde/Db/Migration/BaseTest.php b/framework/Db/test/Horde/Db/Migration/BaseTest.php new file mode 100644 index 000000000..0a7db7089 --- /dev/null +++ b/framework/Db/test/Horde/Db/Migration/BaseTest.php @@ -0,0 +1,525 @@ + + * @author Derek DeVries + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php + * @category Horde + * @package Horde_Db + * @subpackage UnitTests + */ + +require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/fixtures/migrations/1_users_have_last_names1.php'; +require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/fixtures/migrations/2_we_need_reminders1.php'; +require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/fixtures/migrations_with_decimal/1_give_me_big_numbers.php'; + +/** + * @author Mike Naberezny + * @author Derek DeVries + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php + * @group horde_db + * @category Horde + * @package Horde_Db + * @subpackage UnitTests + */ +class Horde_Db_Migration_BaseTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + Horde_Db_Migration_Base::$verbose = false; + } + + public function tearDown() + { + $this->_conn->initializeSchemaInformation(); + $this->_conn->update("UPDATE schema_info SET version = 0"); + + // drop tables + foreach (array('reminders', 'users_reminders', 'testings', 'octopuses', + 'octopi', 'binary_testings', 'big_numbers') as $table) { + try { + $this->_conn->dropTable($table); + } catch (Exception $e) {} + } + + // drop cols + foreach (array('first_name', 'middle_name', 'last_name', 'key', 'male', + 'bio', 'age', 'height', 'wealth', 'birthday', 'group', + 'favorite_day', 'moment_of_truth', 'administrator', + 'exgirlfriend', 'contributor', 'nick_name', + 'intelligence_quotient') as $col) { + try { + $this->_conn->removeColumn('users', $col); + } catch (Exception $e) {} + } + $this->_conn->addColumn('users', 'first_name', 'string', array('limit' => 40)); + $this->_conn->changeColumn('users', 'approved', 'boolean', array('default' => true)); + } + + public function testAddIndex() + { + // Limit size of last_name and key columns to support Firebird index limitations + $this->_conn->addColumn('users', 'last_name', 'string', array('limit' => 100)); + $this->_conn->addColumn('users', 'key', 'string', array('limit' => 100)); + $this->_conn->addColumn('users', 'administrator', 'boolean'); + + $this->_conn->addIndex('users', 'last_name'); + $this->_conn->removeIndex('users', 'last_name'); + + $this->_conn->addIndex('users', array('last_name', 'first_name')); + $this->_conn->removeIndex('users', array('column' => array('last_name', 'first_name'))); + + $this->_conn->addIndex('users', array('last_name', 'first_name')); + $this->_conn->removeIndex('users', array('name' => 'index_users_on_last_name_and_first_name')); + + $this->_conn->addIndex('users', array('last_name', 'first_name')); + $this->_conn->removeIndex('users', 'last_name_and_first_name'); + + // # quoting + + $this->_conn->addIndex('users', array('key'), array('name' => 'key_idx', 'unique' => true)); + $this->_conn->removeIndex('users', array('name' => 'key_idx', 'unique' => true)); + + $this->_conn->addIndex('users', array('last_name', 'first_name', 'administrator'), + array('name' => "named_admin")); + + $this->_conn->removeIndex('users', array('name' => 'named_admin')); + } + + public function testCreateTableAddsId() + { + $table = $this->_conn->createTable('testings'); + $table->column('foo', 'string'); + $table->end(); + + $columns = array(); + foreach ($this->_conn->columns('testings') as $col) { + $columns[] = $col->getName(); + } + sort($columns); + $this->assertEquals(array('foo', 'id'), $columns); + } + + public function testCreateTableWithNotNullColumn() + { + $table = $this->_conn->createTable('testings'); + $table->column('foo', 'string', array('null' => false)); + $table->end(); + + try { + $this->_conn->execute("INSERT INTO testings (foo) VALUES (NULL)"); + } catch (Exception $e) { return; } + $this->fail('Expected exception wasn\'t raised'); + } + + /** + * @todo Revisit this test if the boolean casting behavior changes. + * @see Horde_Db_Adapter_Abstract_ColumnTest + */ + public function testCreateTableWithDefaults() + { + $table = $this->_conn->createTable('testings'); + $table->column('one', 'string', array('default' => 'hello')); + $table->column('two', 'boolean', array('default' => true)); + $table->column('three', 'boolean', array('default' => false)); + $table->column('four', 'integer', array('default' => 1)); + $table->end(); + + $columns = array(); + foreach ($this->_conn->columns('testings') as $col) { + $columns[$col->getName()] = $col; + } + + $this->assertEquals('hello', $columns['one']->getDefault()); + + $this->assertTrue($columns['two']->getDefault()); + $this->assertFalse($columns['three']->getDefault()); + + $this->assertEquals('1', $columns['four']->getDefault()); + } + + public function testCreateTableWithLimits() + { + $table = $this->_conn->createTable('testings'); + $table->column('foo', 'string', array('limit' => 80)); + $table->end(); + + $columns = array(); + foreach ($this->_conn->columns('testings') as $col) { + $columns[$col->getName()] = $col; + } + $this->assertEquals(80, $columns['foo']->getLimit()); + } + + public function testAddColumnNotNullWithoutDefault() + { + $table = $this->_conn->createTable('testings'); + $table->column('foo', 'string'); + $table->end(); + $this->_conn->addColumn('testings', 'bar', 'string', array('null' => false)); + + try { + $this->_conn->execute("INSERT INTO testings (foo, bar) VALUES ('hello', NULL)"); + } catch (Exception $e) { return; } + $this->fail('Expected exception wasn\'t raised'); + + } + + public function testAddColumnNotNullWithDefault() + { + $table = $this->_conn->createTable('testings'); + $table->column('foo', 'string'); + $table->end(); + + $this->_conn->execute("INSERT INTO testings (id, foo) VALUES ('1', 'hello')"); + + $this->_conn->addColumn('testings', 'bar', 'string', array('null' => false, 'default' => 'default')); + + try { + $this->_conn->execute("INSERT INTO testings (id, foo, bar) VALUES (2, 'hello', NULL)"); + } catch (Exception $e) { return; } + $this->fail('Expected exception wasn\'t raised'); + } + + /** + * We specifically do a manual INSERT here, and then test only the SELECT + * functionality. This allows us to more easily catch INSERT being broken, + * but SELECT actually working fine. + */ + public function testNativeDecimalInsertManualVsAutomatic() + { + $correctValue = 12345678901234567890.0123456789; + + User::deleteAll(); + $this->_conn->addColumn("users", "wealth", 'decimal', array('precision' => 30, 'scale' => 10)); + + // do a manual insertion + $this->_conn->execute("INSERT INTO users (wealth) VALUES ('12345678901234567890.0123456789')"); + + // SELECT @todo - type cast attribute values + $user = User::find('first'); + // assert_kind_of BigDecimal, row.wealth + + // If this assert fails, that means the SELECT is broken! + $this->assertEquals($correctValue, $user->wealth); + + // Reset to old state + User::deleteAll(); + + // Now use the Rails insertion + User::create(array('wealth' => '12345678901234567890.0123456789')); + + // SELECT @todo - type cast attribute values + $user = User::find('first'); + // assert_kind_of BigDecimal, row.wealth + + // If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! + $this->assertEquals($correctValue, $user->wealth); + } + + public function testNativeTypes() + { + User::deleteAll(); + + $this->_conn->addColumn("users", "last_name", 'string'); + $this->_conn->addColumn("users", "bio", 'text'); + $this->_conn->addColumn("users", "age", 'integer'); + $this->_conn->addColumn("users", "height", 'float'); + $this->_conn->addColumn("users", "wealth", 'decimal', array('precision' => '30', 'scale' => '10')); + $this->_conn->addColumn("users", "birthday", 'datetime'); + $this->_conn->addColumn("users", "favorite_day", 'date'); + $this->_conn->addColumn("users", "moment_of_truth", 'datetime'); + $this->_conn->addColumn("users", "male", 'boolean'); + + User::create(array('first_name' => 'bob', 'last_name' => 'bobsen', + 'bio' => "I was born ....", 'age' => 18, 'height' => 1.78, + 'wealth' => "12345678901234567890.0123456789", + 'birthday' => '2005-01-01 12:23:40', + 'favorite_day' => '1980-03-05', + 'moment_of_truth' => "1582-10-10 21:40:18", + 'male' => true, 'company_id' => 1)); + + $bob = User::find('first'); + $this->assertEquals('bob', $bob->first_name); + $this->assertEquals('bobsen', $bob->last_name); + $this->assertEquals('I was born ....', $bob->bio); + $this->assertEquals(18, $bob->age); + + // Test for 30 significent digits (beyond the 16 of float), 10 of them + // after the decimal place. + $this->assertEquals('12345678901234567890.0123456789', $bob->wealth); + $this->assertEquals('1', $bob->male); + + // @todo - type casting + } + + public function testUnabstractedDatabaseDependentTypes() + { + User::deleteAll(); + + $this->_conn->addColumn('users', 'intelligence_quotient', 'tinyint'); + User::create(array('intelligence_quotient' => 300)); + + $jonnyg = User::find('first'); + $this->assertEquals('127', $jonnyg->intelligence_quotient); + $jonnyg->destroy(); + } + + public function testAddRemoveSingleField() + { + $user = new User; + + $this->assertFalse(in_array('last_name', $user->columnNames())); + + $this->_conn->addColumn('users', 'last_name', 'string'); + $user->resetColumnInformation(); + $this->assertTrue(in_array('last_name', $user->columnNames())); + + $this->_conn->removeColumn('users', 'last_name'); + $user->resetColumnInformation(); + $this->assertFalse(in_array('last_name', $user->columnNames())); + } + + public function testAddRename() + { + User::deleteAll(); + + $this->_conn->addColumn('users', 'girlfriend', 'string'); + User::create(array('girlfriend' => 'bobette')); + + $this->_conn->renameColumn('users', 'girlfriend', 'exgirlfriend'); + + $bob = User::find('first'); + $this->assertEquals('bobette', $bob->exgirlfriend); + } + + public function testRenameColumn() + { + $this->_conn->renameColumn('users', 'first_name', 'nick_name'); + + $user = new User; + $this->assertTrue(in_array('nick_name', $user->columnNames())); + } + + public function testRenameColumnWithSqlReservedWord() + { + $this->_conn->renameColumn('users', 'first_name', 'group'); + + $user = new User; + $this->assertTrue(in_array('group', $user->columnNames())); + } + + public function testRenameTable() + { + $table = $this->_conn->createTable('octopuses'); + $table->column('url', 'string'); + $table->end(); + + $this->_conn->renameTable('octopuses', 'octopi'); + + $sql = "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"; + $this->_conn->execute($sql); + + $this->assertEquals('http://www.foreverflying.com/octopus-black7.jpg', + $this->_conn->selectValue("SELECT url FROM octopi WHERE id=1")); + } + + public function testRenameTableWithAnIndex() + { + $table = $this->_conn->createTable('octopuses'); + $table->column('url', 'string'); + $table->end(); + $this->_conn->addIndex('octopuses', 'url'); + $this->_conn->renameTable('octopuses', 'octopi'); + + $sql = "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"; + $this->_conn->execute($sql); + + $this->assertEquals('http://www.foreverflying.com/octopus-black7.jpg', + $this->_conn->selectValue("SELECT url FROM octopi WHERE id=1")); + + $indexes = $this->_conn->indexes('octopi'); + $this->assertEquals('url', $indexes[0]->columns[0]); + } + + public function testChangeColumn() + { + $user = new User; + + $this->_conn->addColumn('users', 'age', 'integer'); + $oldColumns = $this->_conn->columns($user->tableName(), "User Columns"); + + $found = false; + foreach ($oldColumns as $c) { + if ($c->getName() == 'age' && $c->getType() == 'integer') { $found = true; } + } + $this->assertTrue($found); + + $this->_conn->changeColumn('users', 'age', 'string'); + + $newColumns = $this->_conn->columns($user->tableName(), "User Columns"); + + $found = false; + foreach ($newColumns as $c) { + if ($c->getName() == 'age' && $c->getType() == 'integer') { $found = true; } + } + $this->assertFalse($found); + $found = false; + foreach ($newColumns as $c) { + if ($c->getName() == 'age' && $c->getType() == 'string') { $found = true; } + } + $this->assertTrue($found); + + $found = false; + foreach ($oldColumns as $c) { + if ($c->getName() == 'approved' && $c->getType() == 'boolean' && + $c->getDefault() == true) { $found = true; } + } + $this->assertTrue($found); + + // changeColumn() throws exception on error + $this->_conn->changeColumn('users', 'approved', 'boolean', array('default' => false)); + + $newColumns = $this->_conn->columns($user->tableName(), "User Columns"); + + $found = false; + foreach ($newColumns as $c) { + if ($c->getName() == 'approved' && $c->getType() == 'boolean' && + $c->getDefault() == true) { $found = true; } + } + $this->assertFalse($found); + + $found = false; + foreach ($newColumns as $c) { + if ($c->getName() == 'approved' && $c->getType() == 'boolean' && + $c->getDefault() == false) { $found = true; } + } + $this->assertTrue($found); + + // changeColumn() throws exception on error + $this->_conn->changeColumn('users', 'approved', 'boolean', array('default' => true)); + } + + public function testChangeColumnWithNilDefault() + { + $this->_conn->addColumn('users', 'contributor', 'boolean', array('default' => true)); + $user = new User; + $this->assertTrue($user->contributor); + + // changeColumn() throws exception on error + $this->_conn->changeColumn('users', 'contributor', 'boolean', array('default' => null)); + + $user = new User; + $this->assertNull($user->contributor); + } + + public function testChangeColumnWithNewDefault() + { + $this->_conn->addColumn('users', 'administrator', 'boolean', array('default' => true)); + $user = new User; + $this->assertTrue($user->administrator); + + // changeColumn() throws exception on error + $this->_conn->changeColumn('users', 'administrator', 'boolean', array('default' => false)); + + $user = new User; + $this->assertFalse($user->administrator); + } + + public function testChangeColumnDefault() + { + $this->_conn->changeColumnDefault('users', 'first_name', 'Tester'); + + $user = new User; + $this->assertEquals('Tester', $user->first_name); + } + + public function testChangeColumnDefaultToNull() + { + $this->_conn->changeColumnDefault('users', 'first_name', null); + + $user = new User; + $this->assertNull($user->first_name); + } + + public function testAddTable() + { + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + $m = new WeNeedReminders1; + $m->up(); + + $result = Reminder::create(array('content' => 'hello world', + 'remind_at' => '2005-01-01 11:10:01')); + $this->assertType('Reminder', $result); + + $this->assertEquals('hello world', Reminder::find('first')->content); + + $m->down(); + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + } + + public function testAddTableWithDecimals() + { + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM big_numbers"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + $m = new GiveMeBigNumbers; + $m->up(); + + $result = BigNumber::create(array( + 'bank_balance' => '1586.43', + 'big_bank_balance' => "1000234000567.95", + 'world_population' => '6000000000', + 'my_house_population' => '3', + 'value_of_e' => "2.7182818284590452353602875" + )); + $this->assertType('BigNumber', $result); + + $b = BigNumber::find('first'); + $this->assertNotNull($b->bank_balance); + $this->assertNotNull($b->big_bank_balance); + $this->assertNotNull($b->world_population); + $this->assertNotNull($b->my_house_population); + $this->assertNotNull($b->value_of_e); + + $m->down(); + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM big_numbers"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + } + + public function testCreateTableWithBinaryColumn() + { + try { + $table = $this->_conn->createTable('binary_testings'); + $table->column('data', 'binary', array('null' => false)); + $table->end(); + } catch (Exception $e) { $this->fail('Unexepected exception raised'); } + + $columns = $this->_conn->columns('binary_testings'); + + foreach ($columns as $c) { + if ($c->getName() == 'data') { $dataColumn = $c; } + } + $this->assertEquals('', $dataColumn->getDefault()); + } + +} diff --git a/framework/Db/test/Horde/Db/Migration/MigratorTest.php b/framework/Db/test/Horde/Db/Migration/MigratorTest.php new file mode 100644 index 000000000..6e50d5a90 --- /dev/null +++ b/framework/Db/test/Horde/Db/Migration/MigratorTest.php @@ -0,0 +1,213 @@ + + * @author Derek DeVries + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php + * @category Horde + * @package Horde_Db + * @subpackage UnitTests + */ + +/** + * @author Mike Naberezny + * @author Derek DeVries + * @author Chuck Hagenbuch + * @license http://opensource.org/licenses/bsd-license.php + * @group horde_db + * @category Horde + * @package Horde_Db + * @subpackage UnitTests + */ +class Horde_Db_Migration_MigratorTest extends PHPUnit_Framework_TestCase +{ + public function setUp() + { + Horde_Db_Migration_Base::$verbose = false; + } + + public function tearDown() + { + $this->_conn->initializeSchemaInformation(); + $this->_conn->update("UPDATE schema_info SET version = 0"); + + // drop tables + foreach (array('reminders', 'users_reminders', 'testings', 'octopuses', + 'octopi', 'binary_testings', 'big_numbers') as $table) { + try { + $this->_conn->dropTable($table); + } catch (Exception $e) {} + } + + // drop cols + foreach (array('first_name', 'middle_name', 'last_name', 'key', 'male', + 'bio', 'age', 'height', 'wealth', 'birthday', 'group', + 'favorite_day', 'moment_of_truth', 'administrator', + 'exgirlfriend', 'contributor', 'nick_name', + 'intelligence_quotient') as $col) { + try { + $this->_conn->removeColumn('users', $col); + } catch (Exception $e) {} + } + $this->_conn->addColumn('users', 'first_name', 'string', array('limit' => 40)); + $this->_conn->changeColumn('users', 'approved', 'boolean', array('default' => true)); + } + + public function testMigrator() + { + $user = new User; + $columns = $user->columnNames(); + + $this->assertFalse(in_array('last_name', $columns)); + + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + Horde_Db_Migration_Migrator::up($dir); + $this->assertEquals(3, Horde_Db_Migration_Migrator::getCurrentVersion()); + + $user->resetColumnInformation(); + $columns = $user->columnNames(); + $this->assertTrue(in_array('last_name', $columns)); + + $result = Reminder::create(array('content' => 'hello world', + 'remind_at' => '2005-01-01 02:22:23')); + $reminder = Reminder::find('first'); + $this->assertEquals('hello world', $reminder->content); + + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + Horde_Db_Migration_Migrator::down($dir); + $this->assertEquals(0, Horde_Db_Migration_Migrator::getCurrentVersion()); + + $user->resetColumnInformation(); + $columns = $user->columnNames(); + $this->assertFalse(in_array('last_name', $columns)); + + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + } + + public function testOneUp() + { + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + Horde_Db_Migration_Migrator::up($dir, 1); + $this->assertEquals(1, Horde_Db_Migration_Migrator::getCurrentVersion()); + + $user = new User; + $columns = $user->columnNames(); + $this->assertTrue(in_array('last_name', $columns)); + + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + Horde_Db_Migration_Migrator::up($dir, 2); + $this->assertEquals(2, Horde_Db_Migration_Migrator::getCurrentVersion()); + + $result = Reminder::create(array('content' => 'hello world', + 'remind_at' => '2005-01-01 02:22:23')); + $reminder = Reminder::find('first'); + $this->assertEquals('hello world', $reminder->content); + } + + public function testOneDown() + { + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + + Horde_Db_Migration_Migrator::up($dir); + Horde_Db_Migration_Migrator::down($dir, 1); + + $user = new User; + $columns = $user->columnNames(); + $this->assertTrue(in_array('last_name', $columns)); + } + + public function testOneUpOneDown() + { + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + + Horde_Db_Migration_Migrator::up($dir, 1); + Horde_Db_Migration_Migrator::down($dir, 0); + + $user = new User; + $columns = $user->columnNames(); + $this->assertFalse(in_array('last_name', $columns)); + } + + public function testMigratorGoingDownDueToVersionTarget() + { + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations/'; + + Horde_Db_Migration_Migrator::up($dir, 1); + Horde_Db_Migration_Migrator::down($dir, 0); + + $user = new User; + $columns = $user->columnNames(); + $this->assertFalse(in_array('last_name', $columns)); + + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + + Horde_Db_Migration_Migrator::up($dir); + + $user->resetColumnInformation(); + $columns = $user->columnNames(); + $this->assertTrue(in_array('last_name', $columns)); + + $result = Reminder::create(array('content' => 'hello world', + 'remind_at' => '2005-01-01 02:22:23')); + $reminder = Reminder::find('first'); + $this->assertEquals('hello world', $reminder->content); + } + + public function testWithDuplicates() + { + try { + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations_with_duplicate/'; + Horde_Db_Migration_Migrator::up($dir); + } catch (Exception $e) { return; } + $this->fail('Expected exception wasn\'t raised'); + } + + public function testWithMissingVersionNumbers() + { + $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/fixtures/migrations_with_missing_versions/'; + Horde_Db_Migration_Migrator::migrate($dir, 500); + $this->assertEquals(4, Horde_Db_Migration_Migrator::getCurrentVersion()); + + Horde_Db_Migration_Migrator::migrate($dir, 2); + $this->assertEquals(2, Horde_Db_Migration_Migrator::getCurrentVersion()); + + $e = null; + try { + $this->_conn->selectValues("SELECT * FROM reminders"); + } catch (Exception $e) {} + $this->assertType('Horde_Db_Exception', $e); + + $user = new User; + $columns = $user->columnNames(); + $this->assertTrue(in_array('last_name', $columns)); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations/1_users_have_last_names1.php b/framework/Db/test/Horde/Db/fixtures/migrations/1_users_have_last_names1.php new file mode 100644 index 000000000..fd389e570 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations/1_users_have_last_names1.php @@ -0,0 +1,14 @@ +addColumn('users', 'last_name', 'string'); + } + + public function down() + { + $this->removeColumn('users', 'last_name'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations/2_we_need_reminders1.php b/framework/Db/test/Horde/Db/fixtures/migrations/2_we_need_reminders1.php new file mode 100644 index 000000000..9c54859ba --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations/2_we_need_reminders1.php @@ -0,0 +1,17 @@ +createTable('reminders'); + $t->column('content', 'text'); + $t->column('remind_at', 'datetime'); + $t->end(); + } + + public function down() + { + $this->dropTable('reminders'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations/3_innocent_jointable1.php b/framework/Db/test/Horde/Db/fixtures/migrations/3_innocent_jointable1.php new file mode 100644 index 000000000..71106db38 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations/3_innocent_jointable1.php @@ -0,0 +1,17 @@ +createTable('users_reminders', array('id' => false)); + $t->column('reminder_id', 'integer'); + $t->column('user_id', 'integer'); + $t->end(); + } + + public function down() + { + $this->dropTable('users_reminders'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_decimal/1_give_me_big_numbers.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_decimal/1_give_me_big_numbers.php new file mode 100644 index 000000000..dc741700e --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_decimal/1_give_me_big_numbers.php @@ -0,0 +1,20 @@ +createTable('big_numbers'); + $table->column('bank_balance', 'decimal', array('precision' => 10, 'scale' => 2)); + $table->column('big_bank_balance', 'decimal', array('precision' => 15, 'scale' => 2)); + $table->column('world_population', 'decimal', array('precision' => 10)); + $table->column('my_house_population', 'decimal', array('precision' => 2)); + $table->column('value_of_e', 'decimal'); + $table->end(); + } + + public function down() + { + $this->dropTable('big_numbers'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/1_users_have_last_names2.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/1_users_have_last_names2.php new file mode 100644 index 000000000..b35c7948c --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/1_users_have_last_names2.php @@ -0,0 +1,14 @@ +addColumn('users', 'last_name', 'string'); + } + + public function down() + { + $this->removeColumn('users', 'last_name'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/2_we_need_reminders2.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/2_we_need_reminders2.php new file mode 100644 index 000000000..94d2811ba --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/2_we_need_reminders2.php @@ -0,0 +1,17 @@ +createTable('reminders'); + $t->column('content', 'text'); + $t->column('remind_at', 'datetime'); + $t->end(); + } + + public function down() + { + $this->dropTable('reminders'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/3_foo.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/3_foo.php new file mode 100644 index 000000000..99eb23498 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_duplicate/3_foo.php @@ -0,0 +1,12 @@ +createTable('users_reminders', array('id' => false)); + $t->column('reminder_id', 'integer'); + $t->column('user_id', 'integer'); + $t->end(); + } + + public function down() + { + $this->dropTable('users_reminders'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1000_users_have_middle_names.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1000_users_have_middle_names.php new file mode 100644 index 000000000..a74310b59 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1000_users_have_middle_names.php @@ -0,0 +1,14 @@ +addColumn('users', 'middle_name', 'string'); + } + + public function down() + { + $this->removeColumn('users', 'middle_name'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1_users_have_last_names3.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1_users_have_last_names3.php new file mode 100644 index 000000000..ba494e22f --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/1_users_have_last_names3.php @@ -0,0 +1,14 @@ +addColumn('users', 'last_name', 'string'); + } + + public function down() + { + $this->removeColumn('users', 'last_name'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/3_we_need_reminders.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/3_we_need_reminders.php new file mode 100644 index 000000000..5d0cba067 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/3_we_need_reminders.php @@ -0,0 +1,17 @@ +createTable('reminders'); + $t->column('content', 'text'); + $t->column('remind_at', 'datetime'); + $t->end(); + } + + public function down() + { + $this->dropTable('reminders'); + } +} \ No newline at end of file diff --git a/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/4_innocent_jointable3.php b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/4_innocent_jointable3.php new file mode 100644 index 000000000..400a76378 --- /dev/null +++ b/framework/Db/test/Horde/Db/fixtures/migrations_with_missing_versions/4_innocent_jointable3.php @@ -0,0 +1,17 @@ +createTable('users_reminders', array('id' => false)); + $t->column('reminder_id', 'integer'); + $t->column('user_id', 'integer'); + $t->end(); + } + + public function down() + { + $this->dropTable('users_reminders'); + } +} \ No newline at end of file -- 2.11.0