aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/bootstrap.php2
-rw-r--r--tests/fixtures/migrations/2019_12_22_FooBar.php10
-rw-r--r--tests/fixtures/migrations/2019_12_23_Baz.php10
-rw-r--r--tests/fixtures/migrations_with_failing/2020_01_11_FooBar.php10
-rw-r--r--tests/fixtures/migrations_with_failing/2020_01_12_Baz.php10
-rw-r--r--tests/lib/Minz/MigratorTest.php321
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);
+ }
+}