diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/bootstrap.php | 2 | ||||
| -rw-r--r-- | tests/fixtures/migrations/2019_12_22_FooBar.php | 10 | ||||
| -rw-r--r-- | tests/fixtures/migrations/2019_12_23_Baz.php | 10 | ||||
| -rw-r--r-- | tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php | 10 | ||||
| -rw-r--r-- | tests/fixtures/migrations_with_failing/2020_01_12_Baz.php | 10 | ||||
| -rw-r--r-- | tests/lib/Minz/MigratorTest.php | 321 |
6 files changed, 363 insertions, 0 deletions
diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 5c42f12f7..dbeee2330 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -3,5 +3,7 @@ error_reporting(E_ALL); ini_set('display_errors', 1); +define('COPY_LOG_TO_SYSLOG', false); + require(__DIR__ . '/../constants.php'); require(LIB_PATH . '/lib_rss.php'); //Includes class autoloader diff --git a/tests/fixtures/migrations/2019_12_22_FooBar.php b/tests/fixtures/migrations/2019_12_22_FooBar.php new file mode 100644 index 000000000..4568ea8c9 --- /dev/null +++ b/tests/fixtures/migrations/2019_12_22_FooBar.php @@ -0,0 +1,10 @@ +<?php + +class FreshRSS_Migration_2019_12_22_FooBar { + /** + * @return boolean true if the migration was successful, false otherwise + */ + public static function migrate() { + return true; + } +} diff --git a/tests/fixtures/migrations/2019_12_23_Baz.php b/tests/fixtures/migrations/2019_12_23_Baz.php new file mode 100644 index 000000000..c13b2a814 --- /dev/null +++ b/tests/fixtures/migrations/2019_12_23_Baz.php @@ -0,0 +1,10 @@ +<?php + +class FreshRSS_Migration_2019_12_23_Baz { + /** + * @return boolean true if the migration was successful, false otherwise + */ + public static function migrate() { + return true; + } +} diff --git a/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php b/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php new file mode 100644 index 000000000..cdc2dd2c8 --- /dev/null +++ b/tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php @@ -0,0 +1,10 @@ +<?php + +class FreshRSS_Migration_2020_01_11_FooBar { + /** + * @return boolean true if the migration was successful, false otherwise + */ + public static function migrate() { + return true; + } +} diff --git a/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php b/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php new file mode 100644 index 000000000..cd8ff10f3 --- /dev/null +++ b/tests/fixtures/migrations_with_failing/2020_01_12_Baz.php @@ -0,0 +1,10 @@ +<?php + +class FreshRSS_Migration_2020_01_12_Baz { + /** + * @return boolean true if the migration was successful, false otherwise + */ + public static function migrate() { + return false; + } +} diff --git a/tests/lib/Minz/MigratorTest.php b/tests/lib/Minz/MigratorTest.php new file mode 100644 index 000000000..8f23895aa --- /dev/null +++ b/tests/lib/Minz/MigratorTest.php @@ -0,0 +1,321 @@ +<?php + +use PHPUnit\Framework\TestCase; + +class Minz_MigratorTest extends TestCase +{ + public function testAddMigration() { + $migrator = new Minz_Migrator(); + + $migrator->addMigration('foo', function () { + return true; + }); + + $migrations = $migrator->migrations(); + $this->assertArrayHasKey('foo', $migrations); + $result = $migrations['foo'](); + $this->assertTrue($result); + } + + public function testAddMigrationFailsIfUncallableMigration() { + $this->expectException(BadFunctionCallException::class); + $this->expectExceptionMessage('foo migration cannot be called.'); + + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', null); + } + + public function testMigrationsIsSorted() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('2_foo', function () { + return true; + }); + $migrator->addMigration('10_foo', function () { + return true; + }); + $migrator->addMigration('1_foo', function () { + return true; + }); + $expected_versions = ['1_foo', '2_foo', '10_foo']; + + $migrations = $migrator->migrations(); + + $this->assertSame($expected_versions, array_keys($migrations)); + } + + public function testSetAppliedVersions() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', function () { + return true; + }); + + $migrator->setAppliedVersions(['foo']); + + $this->assertSame(['foo'], $migrator->appliedVersions()); + } + + public function testSetAppliedVersionsTrimArgument() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', function () { + return true; + }); + + $migrator->setAppliedVersions(["foo\n"]); + + $this->assertSame(['foo'], $migrator->appliedVersions()); + } + + public function testSetAppliedVersionsFailsIfMigrationDoesNotExist() { + $this->expectException(DomainException::class); + $this->expectExceptionMessage('foo migration does not exist.'); + + $migrator = new Minz_Migrator(); + + $migrator->setAppliedVersions(['foo']); + } + + public function testVersions() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', function () { + return true; + }); + $migrator->addMigration('bar', function () { + return true; + }); + + $versions = $migrator->versions(); + + $this->assertSame(['bar', 'foo'], $versions); + } + + public function testMigrate() { + $migrator = new Minz_Migrator(); + $spy = false; + $migrator->addMigration('foo', function () use (&$spy) { + $spy = true; + return true; + }); + $this->assertEmpty($migrator->appliedVersions()); + + $result = $migrator->migrate(); + + $this->assertTrue($spy); + $this->assertSame(['foo'], $migrator->appliedVersions()); + $this->assertSame([ + 'foo' => true, + ], $result); + } + + public function testMigrateCallsMigrationsInSortedOrder() { + $migrator = new Minz_Migrator(); + $spy_foo_1_is_called = false; + $migrator->addMigration('2_foo', function () use (&$spy_foo_1_is_called) { + return $spy_foo_1_is_called; + }); + $migrator->addMigration('1_foo', function () use (&$spy_foo_1_is_called) { + $spy_foo_1_is_called = true; + return true; + }); + + $result = $migrator->migrate(); + + $this->assertSame(['1_foo', '2_foo'], $migrator->appliedVersions()); + $this->assertSame([ + '1_foo' => true, + '2_foo' => true, + ], $result); + } + + public function testMigrateDoesNotCallAppliedMigrations() { + $migrator = new Minz_Migrator(); + $spy = false; + $migrator->addMigration('1_foo', function () use (&$spy) { + $spy = true; + return true; + }); + $migrator->setAppliedVersions(['1_foo']); + + $result = $migrator->migrate(); + + $this->assertFalse($spy); + $this->assertSame([], $result); + } + + public function testMigrateCallNonAppliedBetweenTwoApplied() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('1_foo', function () { + return true; + }); + $migrator->addMigration('2_foo', function () { + return true; + }); + $migrator->addMigration('3_foo', function () { + return true; + }); + $migrator->setAppliedVersions(['1_foo', '3_foo']); + + $result = $migrator->migrate(); + + $this->assertSame(['1_foo', '2_foo', '3_foo'], $migrator->appliedVersions()); + $this->assertSame([ + '2_foo' => true, + ], $result); + } + + public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('1_foo', function () { + return true; + }); + $migrator->addMigration('2_foo', function () { + return false; + }); + + $result = $migrator->migrate(); + + $this->assertSame(['1_foo'], $migrator->appliedVersions()); + $this->assertSame([ + '1_foo' => true, + '2_foo' => false, + ], $result); + } + + public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('1_foo', function () { + return false; + }); + $spy = false; + $migrator->addMigration('2_foo', function () use (&$spy) { + $spy = true; + return true; + }); + + $result = $migrator->migrate(); + + $this->assertEmpty($migrator->appliedVersions()); + $this->assertFalse($spy); + $this->assertSame([ + '1_foo' => false, + ], $result); + } + + public function testMigrateWithFailingMigration() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', function () { + throw new \Exception('Oops, it failed.'); + }); + + $result = $migrator->migrate(); + + $this->assertEmpty($migrator->appliedVersions()); + $this->assertSame([ + 'foo' => 'Oops, it failed.', + ], $result); + } + + public function testUpToDate() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('foo', function () { + return true; + }); + $migrator->setAppliedVersions(['foo']); + + $upToDate = $migrator->upToDate(); + + $this->assertTrue($upToDate); + } + + public function testUpToDateIfRemainingMigration() { + $migrator = new Minz_Migrator(); + $migrator->addMigration('1_foo', function () { + return true; + }); + $migrator->addMigration('2_foo', function () { + return true; + }); + $migrator->setAppliedVersions(['2_foo']); + + $upToDate = $migrator->upToDate(); + + $this->assertFalse($upToDate); + } + + public function testUpToDateIfNoMigrations() { + $migrator = new Minz_Migrator(); + + $upToDate = $migrator->upToDate(); + + $this->assertTrue($upToDate); + } + + public function testConstructorLoadsDirectory() { + $migrations_path = TESTS_PATH . '/fixtures/migrations/'; + $migrator = new Minz_Migrator($migrations_path); + $expected_versions = ['2019_12_22_FooBar', '2019_12_23_Baz']; + + $migrations = $migrator->migrations(); + + $this->assertSame($expected_versions, array_keys($migrations)); + } + + public function testExecute() { + $migrations_path = TESTS_PATH . '/fixtures/migrations/'; + $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); + + $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path); + + $this->assertTrue($result); + $versions = file_get_contents($applied_migrations_path); + $this->assertSame("2019_12_22_FooBar\n2019_12_23_Baz", $versions); + } + + public function testExecuteWithAlreadyAppliedMigration() { + $migrations_path = TESTS_PATH . '/fixtures/migrations/'; + $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); + file_put_contents($applied_migrations_path, '2019_12_22_FooBar'); + + $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path); + + $this->assertTrue($result); + $versions = file_get_contents($applied_migrations_path); + $this->assertSame("2019_12_22_FooBar\n2019_12_23_Baz", $versions); + } + + public function testExecuteWithAppliedMigrationInDifferentOrder() { + $migrations_path = TESTS_PATH . '/fixtures/migrations/'; + $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); + file_put_contents($applied_migrations_path, "2019_12_23_Baz\n2019_12_22_FooBar"); + + $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path); + + $this->assertTrue($result); + $versions = file_get_contents($applied_migrations_path); + // if the order changes, it probably means the first versions comparaison + // test doesn't work anymore + $this->assertSame("2019_12_23_Baz\n2019_12_22_FooBar", $versions); + } + + public function testExecuteFailsIfVersionPathDoesNotExist() { + $migrations_path = TESTS_PATH . '/fixtures/migrations/'; + $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); + $expected_result = "Cannot open the {$applied_migrations_path} file"; + unlink($applied_migrations_path); + + $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path); + + $this->assertSame($expected_result, $result); + } + + public function testExecuteFailsIfAMigrationIsFailing() { + $migrations_path = TESTS_PATH . '/fixtures/migrations_with_failing/'; + $applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt'); + $expected_result = 'A migration failed to be applied, please see previous logs'; + + $result = Minz_Migrator::execute($migrations_path, $applied_migrations_path); + + $this->assertSame($expected_result, $result); + $versions = file_get_contents($applied_migrations_path); + $this->assertSame('2020_01_11_FooBar', $versions); + } +} |
