def test_first_migration_was_executed(self):
        migrations = [
            Migration("1.0.0", None, None, None, None),
            Migration("1.2.0", None, None, None, None),
            Migration("1.3.0", None, None, None, None),
        ]
        executed_migrations = [
            Migration("1.0.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS])
        ]

        merged_migrations = MigrationMergeService().merge(
            migrations, executed_migrations)

        self.assertEqual(3, len(merged_migrations))
        self.assertEqual(MigrationStatus.SUCCESS,
                         merged_migrations[0].get_status_as_string())
        self.assertEqual(executed_migrations[0], merged_migrations[0])
        self.assertEqual(MigrationStatus.PENDING,
                         merged_migrations[1].get_status_as_string())
        self.assertEqual(MigrationStatus.PENDING,
                         merged_migrations[2].get_status_as_string())
    def test_incorrect_checksum(self):
        migrations = [
            Migration("1.0.0", None, "1234", None, None),
            Migration("1.2.0", None, None, None, None),
        ]
        executed_migrations = [
            Migration("1.0.0",
                      None,
                      "4321",
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
            Migration("1.2.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
        ]

        merged_migrations = MigrationMergeService().merge(
            migrations, executed_migrations)

        self.assertEqual(2, len(merged_migrations))
        self.assertEqual(
            [MigrationStatus.SUCCESS, MigrationStatus.CHECKSUM_MISMATCH],
            merged_migrations[0].status)
    def test_single_migration(self):
        def call_single_migration(expected_version: str,
                                  expected_entries_in_table: int,
                                  pending_migrations_found: int):
            with self.assertLogs() as _cm:
                commandline_parse_phase.start(
                    args=["--migration-path", "/path", "migrate", "--single"])

            self.assertIn(
                "INFO:symigrate.command.migrate_command:Found %d pending migrations"
                % pending_migrations_found, _cm.output)
            self.assertIn(
                "INFO:symigrate.command.migrate_command:Only executing the next pending migration",
                _cm.output)

            migration_table_rows = self.database_connection.execute(
                "SELECT version, status FROM migration").fetchall()
            self.assertEqual(expected_entries_in_table,
                             len(migration_table_rows))
            self.assertEqual(expected_version, migration_table_rows[-1][0])
            self.assertEqual("SUCCESS", migration_table_rows[-1][1])

        self.migration_script_repository_mock.find_all.return_value = [
            Migration(version="1.0.0",
                      description="first migration",
                      checksum="1234",
                      script="",
                      filename="V1.0.0__description.sh"),
            Migration(version="1.1.0",
                      description="second migration",
                      checksum="2345",
                      script="",
                      filename="V1.1.0_descr.sh"),
        ]
        commandline_parse_phase = CommandlineParsePhase()
        self.migration_script_runner_mock.run_migration_script.return_value = MigrationExecutionResult(
            success=True)

        # first single migration call
        call_single_migration(expected_version="1.0.0",
                              expected_entries_in_table=1,
                              pending_migrations_found=2)
        # second single migration call
        call_single_migration(expected_version="1.1.0",
                              expected_entries_in_table=2,
                              pending_migrations_found=1)

        with self.assertLogs() as cm:
            commandline_parse_phase.start(
                args=["--migration-path", "/path", "migrate", "--single"])

        self.assertIn(
            "INFO:symigrate.command.migrate_command:No pending migrations found",
            cm.output)
    def test_push(self):
        migration = Migration("1.2.3",
                              "some description",
                              status=[MigrationStatus.SUCCESS],
                              checksum="1234",
                              script="echo 'huhu'",
                              execution_result=MigrationExecutionResult(),
                              filename="V1.2.3__some_description.sh")

        self.executed_migration_repository.init()
        self.executed_migration_repository.push(migration)

        rows = self.database_connection.execute(
            "SELECT version, description, status, "
            "checksum, scope, script FROM migration").fetchall()

        self.assertEqual(1, len(rows))
        row = rows[0]

        self.assertEqual("1.2.3", row[0])
        self.assertEqual("some description", row[1])
        self.assertEqual("SUCCESS", row[2])
        self.assertEqual("1234", row[3])
        self.assertEqual("DEFAULT", row[4])
        self.assertEqual("echo 'huhu'", row[5])
예제 #5
0
 def _get_table_row_from_migration(migration: Migration) -> list:
     return [
         migration.version, migration.description,
         migration.execution_result.execution_timestamp
         if migration.execution_result is not None else "",
         migration.get_status_as_string()
     ]
    def test_one_pending_migration_failed(self):
        self.migration_script_repository_mock.find_all.return_value = [
            Migration(version="1.0.0",
                      description="test migration",
                      checksum="1234",
                      script="",
                      filename="V1.0.0__description.sh")
        ]

        commandline_parse_phase = CommandlineParsePhase()
        self.migration_script_runner_mock.run_migration_script.return_value = MigrationExecutionResult(
            success=False)

        with self.assertLogs() as cm:
            with self.assertRaises(SystemExit):
                commandline_parse_phase.start(
                    args=["--migration-path", "/path", "migrate"])

        expected_path = os.path.join("/path", "V1.0.0__description.sh")
        self.migration_script_runner_mock.run_migration_script.assert_called_once_with(
            expected_path)

        self.assertIn(
            "INFO:symigrate.command.migrate_command:Found 1 pending migrations",
            cm.output)
        self.assertIn(
            "ERROR:symigrate.main.symigrate:StopOnMigrationError: Stopping migration due to failed "
            "migration script execution", cm.output)

        migration_table_row = self.database_connection.execute(
            "SELECT version, status FROM migration").fetchone()
        self.assertIsNotNone(migration_table_row)
        self.assertEqual("1.0.0", migration_table_row[0])
        self.assertEqual("FAILED", migration_table_row[1])
    def test_all_pending(self):
        migrations = [
            Migration("1.0.0", None, None, None, None),
            Migration("1.2.0", None, None, None, None),
            Migration("1.3.0", None, None, None, None),
        ]
        executed_migrations = []

        merged_migrations = MigrationMergeService().merge(
            migrations, executed_migrations)

        self.assertEqual(3, len(merged_migrations))
        self.assertEqual(MigrationStatus.PENDING,
                         merged_migrations[0].get_status_as_string())
        self.assertEqual(MigrationStatus.PENDING,
                         merged_migrations[1].get_status_as_string())
        self.assertEqual(MigrationStatus.PENDING,
                         merged_migrations[2].get_status_as_string())
    def test_diff_output(self):
        self.migration_script_repository_mock.find_by_version.return_value = \
            Migration(version="1.0.0", description="test migration", checksum="2345", script="", filename="")

        commandline_parse_phase = CommandlineParsePhase()

        with capture_output() as output:
            commandline_parse_phase.start(args=["diff", "--version", "1.0.0"])

        self.assertEqual("- The script", output[0].getvalue())
    def push(self, migration: Migration):
        LOGGER.debug("Saving executed migration %s", migration)
        self.database_connection.execute(
            QUERY_INSERT_MIGRATION,
            (migration.version, migration.description,
             migration.execution_result.execution_timestamp.strftime(
                 SYMIGRATE_TIMESTAMP_FORMAT), migration.get_status_as_string(),
             migration.checksum, migration.scope, migration.script,
             migration.filename))

        self.database_connection.commit()
    def test_diff_no_difference(self):
        self.migration_script_repository_mock.find_by_version.return_value = \
            Migration(version="1.0.0", description="test migration", checksum="1234", script="", filename="")

        commandline_parse_phase = CommandlineParsePhase()

        with self.assertLogs() as log:
            commandline_parse_phase.start(args=["diff", "--version", "1.0.0"])

        self.assertIn(
            "INFO:symigrate.command.diff_command:No difference found",
            log.output)
 def setUp(self):
     self.database_connection = sqlite3.connect(":memory:")
     self.database_connection.execute(DDL_CREATE_MIGRATION_TABLE)
     self.out_stream = StringIO()
     self.migration_script_repository_mock = Mock()
     self.migration_script_repository_mock.find_all = Mock()
     self.migration_script_repository_mock.find_all.return_value = [
         Migration(version="1.0.0",
                   description="test migration",
                   checksum="1234",
                   script="",
                   filename=""),
         Migration(version="1.1.0",
                   description="another migration",
                   checksum="1234",
                   script="",
                   filename=""),
     ]
     InterfaceCreationPhase.database_connection_hook = self.database_connection
     MainPhase.out_stream_hook = self.out_stream
     MainPhase.migration_script_checker_hook = Mock()
     MainPhase.migration_script_repository_hook = self.migration_script_repository_mock
 def _create_migration(self,
                       match_result: MigrationFileMatcher.MatchResult):
     full_file_path = os.path.join(self.path, match_result.filename)
     migration_script_content = self._get_script_content(full_file_path)
     migration = Migration(
         version=match_result.version,
         description=match_result.description,
         checksum=self._calculate_checksum(migration_script_content),
         script=migration_script_content,
         scope=self.scope,
         filename=match_result.filename,
         full_file_path=full_file_path)
     return migration
 def _create_migration_from_row(row):
     migration_execution_result = MigrationExecutionResult(
         execution_timestamp=datetime.strptime(
             row[2], SYMIGRATE_TIMESTAMP_FORMAT), )
     migration = Migration(version=row[0],
                           description=row[1],
                           status=row[3].split(","),
                           checksum=row[4],
                           scope=row[5],
                           script=row[6],
                           execution_result=migration_execution_result,
                           filename=row[7])
     return migration
    def test_missing_migration_script(self):
        migrations = [
            Migration("1.0.0", None, None, None, None),
            Migration("1.2.0", None, None, None, None),
        ]
        executed_migrations = [
            Migration("1.0.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
            Migration("1.2.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
            Migration("1.3.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.FAILED])
        ]

        merged_migrations = MigrationMergeService().merge(
            migrations, executed_migrations)

        self.assertEqual(3, len(merged_migrations))
        self.assertEqual(executed_migrations[0], merged_migrations[0])
        self.assertEqual(executed_migrations[1], merged_migrations[1])
        self.assertEqual(executed_migrations[2], merged_migrations[2])
        self.assertEqual(
            [MigrationStatus.FAILED, MigrationStatus.MISSING_MIGRATION_SCRIPT],
            merged_migrations[2].status)
    def test_no_pending_migrations(self):
        self.database_connection.execute(
            "INSERT INTO migration (scope, version, description, status, timestamp, checksum)"
            "VALUES"
            "('DEFAULT', '1.0.0', 'test migration', 'SUCCESS', '2018-04-29T11:40:00', '1234')"
        )
        self.migration_script_repository_mock.find_all.return_value = [
            Migration(version="1.0.0",
                      description="test migration",
                      checksum="1234",
                      script="",
                      filename="")
        ]

        commandline_parse_phase = CommandlineParsePhase()

        with self.assertLogs() as cm:
            commandline_parse_phase.start(args=["migrate"])

        self.assertIn(
            "INFO:symigrate.command.migrate_command:No pending migrations found",
            cm.output)
    def test_all_migrations_were_executed(self):
        migrations = [
            Migration("1.0.0", None, None, None, None),
            Migration("1.2.0", None, None, None, None),
            Migration("1.3.0", None, None, None, None),
        ]
        executed_migrations = [
            Migration("1.0.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
            Migration("1.2.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.SUCCESS]),
            Migration("1.3.0",
                      None,
                      None,
                      None,
                      None,
                      status=[MigrationStatus.FAILED])
        ]

        merged_migrations = MigrationMergeService().merge(
            migrations, executed_migrations)

        self.assertEqual(3, len(merged_migrations))
        self.assertEqual(executed_migrations[0], merged_migrations[0])
        self.assertEqual(executed_migrations[1], merged_migrations[1])
        self.assertEqual(executed_migrations[2], merged_migrations[2])
        self.assertEqual(MigrationStatus.FAILED,
                         merged_migrations[2].get_status_as_string())