diff --git a/.travis.yml b/.travis.yml index 2302756..c7cd5e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ php: - '5.6' - '7.0' - '7.1' - - nightly install: composer install services: diff --git a/src/DBDiff.php b/src/DBDiff.php index 159f345..7ab31a1 100644 --- a/src/DBDiff.php +++ b/src/DBDiff.php @@ -9,7 +9,8 @@ class DBDiff { - + private $diff; + public function run() { // Increase memory limit @@ -20,14 +21,14 @@ public function run() { // Diff $diffCalculator = new DiffCalculator; - $diff = $diffCalculator->getDiff($params); + $this->diff = $diffCalculator->getDiff($params); // Empty diff - if (empty($diff['schema']) && empty($diff['data'])) { + if (empty($this->diff['schema']) && empty($this->diff['data'])) { Logger::info("Identical resources"); } else { // SQL - $sqlGenerator = new SQLGenerator($diff); + $sqlGenerator = new SQLGenerator($this->diff); $up =''; $down = ''; if ($params->include !== 'down') { $up = $sqlGenerator->getUp(); @@ -53,4 +54,8 @@ public function run() { } } + + public function getDiff() { + return $this->diff; + } } diff --git a/src/SQLGen/DiffSorter.php b/src/SQLGen/DiffSorter.php index 874a11c..a03c4c7 100644 --- a/src/SQLGen/DiffSorter.php +++ b/src/SQLGen/DiffSorter.php @@ -3,7 +3,7 @@ class DiffSorter { - private $up_order = [ + private $up_order = array( "SetDBCharset", "SetDBCollation", @@ -29,9 +29,9 @@ class DiffSorter { "InsertData", "UpdateData" - ]; + ); - private $down_order = [ + private $down_order = array( "SetDBCharset", "SetDBCollation", @@ -57,13 +57,13 @@ class DiffSorter { "DeleteData", "UpdateData" - ]; + ); public function sort($diff, $type) { usort($diff, [$this, 'compare'.ucfirst($type)]); return $diff; } - + private function compareUp($a, $b) { return $this->compare($this->up_order, $a, $b); } @@ -80,9 +80,11 @@ private function compare($order, $a, $b) { $sqlGenClassB = $reflectionB->getShortName(); $indexA = $order[$sqlGenClassA]; $indexB = $order[$sqlGenClassB]; - - if ($indexA === $indexB) return 0; - else if ($indexA > $indexB) return 1; - return -1; + + if ($indexA > $indexB) return 1; + if ($indexA < $indexB) return -1; + if ($a > $b) return 1; + if ($a < $b) return -1; + return 0; } } diff --git a/tests/End2EndTest.php b/tests/End2EndTest.php index 9f7b150..fc112f8 100644 --- a/tests/End2EndTest.php +++ b/tests/End2EndTest.php @@ -1,60 +1,117 @@ exec("DROP DATABASE `$db1`;"); - $dbh->exec("CREATE DATABASE $db1;"); - $dbh->exec("DROP DATABASE `$db2`;"); - $dbh->exec("CREATE DATABASE $db2;"); - - $db1h = new PDO("mysql:host=$host;dbname=$db1;", $user, $pass); - $db1h->exec(file_get_contents('tests/end2end/db1-up.sql')); - $db2h = new PDO("mysql:host=$host;dbname=$db2;", $user, $pass); - $db2h->exec(file_get_contents('tests/end2end/db2-up.sql')); - - $GLOBALS['argv'] = [ - "", - "--server1=$user:$pass@$host:$port", - "--template=templates/simple-db-migrate.tmpl", - "--type=all", - "--include=all", - "--nocomments", - "--output=./tests/end2end/$migration_actual", - "server1.$db1:server1.$db2" - ]; + // db config (detects CI environment) + private $isContinuousIntegrationServer; + private $host; + private $port = 3306; + private $user; + private $pass; + private $db; + private $db_source; + private $db_target; + private $source = "source"; + private $target = "target"; + + // db migration + private $migration_actual = 'migration_actual'; + private $migration_expected = 'migration_expected'; + + function __construct() { + parent::__construct(); + + // Initialise variables + $this->isContinuousIntegrationServer = getenv('CI'); + $this->host = $this->isContinuousIntegrationServer ? "127.0.0.1" : "localhost"; + $this->user = $this->isContinuousIntegrationServer ? "root" : "dbdiff"; + $this->pass = $this->isContinuousIntegrationServer ? "" : "dbdiff"; + $this->db = new PDO("mysql:host=$this->host", $this->user, $this->pass); + + // Set some global arguments for the CLI + $GLOBALS['argv'] = [ + "", + "--server1=$this->user:$this->pass@$this->host:$this->port", + "--template=templates/simple-db-migrate.tmpl", + "--type=all", + "--include=all", + "--nocomments", + "--output=./tests/end2end/$this->migration_actual", + "server1.$this->source:server1.$this->target" + ]; + + // Create databases for test + $this->db->exec("CREATE DATABASE `$this->source`;"); + $this->db->exec("CREATE DATABASE `$this->target`;"); + // Populate databases for test + $this->db_source = new PDO("mysql:host=$this->host;dbname=$this->source;", $this->user, $this->pass); + $this->db_source->exec(file_get_contents("tests/end2end/$this->source.sql")); + $this->db_target = new PDO("mysql:host=$this->host;dbname=$this->target;", $this->user, $this->pass); + $this->db_target->exec(file_get_contents("tests/end2end/$this->target.sql")); + } + + function __destruct() { + // Cleanup + $this->db->exec("DROP DATABASE `$this->source`;"); + $this->db->exec("DROP DATABASE `$this->target`;"); + + // Remove actual migration file + // unlink("./tests/end2end/$migration_actual"); + } + + public function testExpectedMigrationMatchesActualMigration() { ob_start(); $dbdiff = new DBDiff\DBDiff; $dbdiff->run(); ob_end_clean(); - $migration_actual_file = file_get_contents("./tests/end2end/$migration_actual"); - $migration_expected_file = file_get_contents("./tests/end2end/$migration_expected"); - // unlink("./tests/end2end/$migration_actual"); - - // TODO: Apply the migration_actual UP to the target database and expect there to be no differences on the command-line anymore - // TODO: Apply the migration actual DOWN to the target database and expect there to be the same expected differences again - // TODO: Ensure the database is emptied/reset after each test + $migration_actual_file = file_get_contents("./tests/end2end/$this->migration_actual"); + $migration_expected_file = file_get_contents("./tests/end2end/$this->migration_expected"); $this->assertEquals($migration_actual_file, $migration_expected_file); + + $sqlGenerator = new SQLGenerator($dbdiff->getDiff()); + return $sqlGenerator; + } + + /** + * @depends testExpectedMigrationMatchesActualMigration + */ + public function testApplyMigrationUpToTargetDatabaseAndExpectNoDifferences($sqlGenerator) { + /* + $this->db_target->exec($sqlGenerator->getUp()); + + $dbdiff = new DBDiff\DBDiff; + $dbdiff->run(); + + $diff = $dbdiff->getDiff(); + $this->assertEquals(empty($diff['schema']) && empty($diff['data']), true); + + return $sqlGenerator; + */ + } + + /** + * @depends testApplyMigrationUpToTargetDatabaseAndExpectNoDifferences + */ + public function testApplyMigrationDownToTargetDatabaseAndExpectSameMigrationIsProducedAsBefore($sqlGenerator) { + /* + $this->db_target->exec($sqlGenerator->getDown()); + + $dbdiff = new DBDiff\DBDiff; + $dbdiff->run(); + + $migration_actual_file = file_get_contents("./tests/end2end/$this->migration_actual"); + + $this->assertEquals($migration_actual_file, $migration_expected_file); + */ } } ?> diff --git a/tests/end2end/migration_expected b/tests/end2end/migration_expected index 960ac73..89a9126 100644 --- a/tests/end2end/migration_expected +++ b/tests/end2end/migration_expected @@ -4,25 +4,25 @@ CREATE TABLE `cc` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DELETE FROM `asas` WHERE `id` = '2' AND `firstname` = 'x'; -DELETE FROM `asas` WHERE `id` = '7' AND `firstname` = 'e'; DELETE FROM `asas` WHERE `id` = '6' AND `firstname` = 't'; +DELETE FROM `asas` WHERE `id` = '7' AND `firstname` = 'e'; DELETE FROM `zz` WHERE `id` = '1' AND `name` = 'name'; DROP TABLE `zz`; ALTER TABLE `aa` ENGINE = InnoDB; -ALTER TABLE `bb` DEFAULT COLLATE latin1_swedish_ci; ALTER TABLE `aa` DEFAULT COLLATE latin1_swedish_ci; ALTER TABLE `asas` DEFAULT COLLATE latin1_spanish_ci; +ALTER TABLE `bb` DEFAULT COLLATE latin1_swedish_ci; +ALTER TABLE `aa` ADD `as` int(11) NOT NULL; ALTER TABLE `aa` ADD `qw` int(11) NOT NULL; ALTER TABLE `bb` ADD `jj` int(11) NOT NULL; -ALTER TABLE `aa` ADD `as` int(11) NOT NULL; ALTER TABLE `aa` CHANGE `name` `name` varchar(255) NOT NULL; ALTER TABLE `aa` CHANGE `pass` `pass` varchar(255) DEFAULT NULL; ALTER TABLE `asas` CHANGE `firstname` `firstname` varchar(255) COLLATE latin1_spanish_ci NOT NULL; ALTER TABLE `asas` CHANGE `lastname` `lastname` varchar(255) COLLATE latin1_spanish_ci NOT NULL; ALTER TABLE `aa` DROP `zx`; ALTER TABLE `aa` ADD KEY `as` (`as`); -ALTER TABLE `bb` ADD PRIMARY KEY (`id`); ALTER TABLE `aa` ADD UNIQUE KEY `name` (`name`); +ALTER TABLE `bb` ADD PRIMARY KEY (`id`); ALTER TABLE `aa` DROP INDEX `id`; ALTER TABLE `aa` ADD PRIMARY KEY (`id`); ALTER TABLE `aa` DROP INDEX `namekey`; @@ -35,10 +35,10 @@ INSERT INTO `cc` VALUES('11'); UPDATE `asas` SET `lastname` = 'bb' WHERE `id` = '1' AND `firstname` = 'a'; """ SQL_DOWN = u""" -DELETE FROM `cc` WHERE `id` = '11'; -DELETE FROM `asas` WHERE `id` = '4' AND `firstname` = 'v'; -DELETE FROM `asas` WHERE `id` = '3' AND `firstname` = 'x'; DELETE FROM `asas` WHERE `id` = '2' AND `firstname` = 'c'; +DELETE FROM `asas` WHERE `id` = '3' AND `firstname` = 'x'; +DELETE FROM `asas` WHERE `id` = '4' AND `firstname` = 'v'; +DELETE FROM `cc` WHERE `id` = '11'; DROP TABLE `cc`; CREATE TABLE `zz` ( `id` int(11) NOT NULL, @@ -50,16 +50,16 @@ CREATE TABLE `zz` ( KEY `time` (`time`,`bool`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ALTER TABLE `aa` ENGINE = MyISAM; -ALTER TABLE `asas` DEFAULT COLLATE latin1_bin; ALTER TABLE `aa` DEFAULT COLLATE latin1_spanish_ci; +ALTER TABLE `asas` DEFAULT COLLATE latin1_bin; ALTER TABLE `bb` DEFAULT COLLATE latin1_bin; ALTER TABLE `aa` DROP `as`; ALTER TABLE `aa` DROP `qw`; ALTER TABLE `bb` DROP `jj`; -ALTER TABLE `asas` CHANGE `lastname` `lastname` varchar(255) COLLATE latin1_bin NOT NULL; -ALTER TABLE `asas` CHANGE `firstname` `firstname` varchar(255) COLLATE latin1_bin NOT NULL; -ALTER TABLE `aa` CHANGE `pass` `pass` varchar(255) CHARACTER SET latin1 NOT NULL; ALTER TABLE `aa` CHANGE `name` `name` varchar(255) CHARACTER SET latin1 NOT NULL DEFAULT 'aa'; +ALTER TABLE `aa` CHANGE `pass` `pass` varchar(255) CHARACTER SET latin1 NOT NULL; +ALTER TABLE `asas` CHANGE `firstname` `firstname` varchar(255) COLLATE latin1_bin NOT NULL; +ALTER TABLE `asas` CHANGE `lastname` `lastname` varchar(255) COLLATE latin1_bin NOT NULL; ALTER TABLE `aa` ADD `zx` int(11) NOT NULL; ALTER TABLE `aa` DROP INDEX `as`; ALTER TABLE `aa` DROP INDEX `name`; diff --git a/tests/end2end/db1-up.sql b/tests/end2end/source.sql similarity index 100% rename from tests/end2end/db1-up.sql rename to tests/end2end/source.sql diff --git a/tests/end2end/db2-up.sql b/tests/end2end/target.sql similarity index 100% rename from tests/end2end/db2-up.sql rename to tests/end2end/target.sql