diff options
Diffstat (limited to 'spec/lib/gitlab/database/migrations/runner_spec.rb')
-rw-r--r-- | spec/lib/gitlab/database/migrations/runner_spec.rb | 195 |
1 files changed, 109 insertions, 86 deletions
diff --git a/spec/lib/gitlab/database/migrations/runner_spec.rb b/spec/lib/gitlab/database/migrations/runner_spec.rb index a37247ba0c6..f364ebfa522 100644 --- a/spec/lib/gitlab/database/migrations/runner_spec.rb +++ b/spec/lib/gitlab/database/migrations/runner_spec.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true require 'spec_helper' -RSpec.describe Gitlab::Database::Migrations::Runner do +RSpec.describe Gitlab::Database::Migrations::Runner, :reestablished_active_record_base do include Database::MultipleDatabases - let(:result_dir) { Pathname.new(Dir.mktmpdir) } + let(:base_result_dir) { Pathname.new(Dir.mktmpdir) } let(:migration_runs) { [] } # This list gets populated as the runner tries to run migrations @@ -26,11 +26,14 @@ RSpec.describe Gitlab::Database::Migrations::Runner do end before do - stub_const('Gitlab::Database::Migrations::Runner::BASE_RESULT_DIR', result_dir) + skip_if_multiple_databases_not_setup unless database == :main + + stub_const('Gitlab::Database::Migrations::Runner::BASE_RESULT_DIR', base_result_dir) allow(ActiveRecord::Migrator).to receive(:new) do |dir, _all_migrations, _schema_migration_class, version_to_migrate| migrator = double(ActiveRecord::Migrator) expect(migrator).to receive(:run) do - migration_runs << double('migrator', dir: dir, version_to_migrate: version_to_migrate) + config_for_migration_run = ActiveRecord::Base.connection_db_config + migration_runs << double('migrator', dir: dir, version_to_migrate: version_to_migrate, database: config_for_migration_run.name) end migrator end @@ -39,133 +42,153 @@ RSpec.describe Gitlab::Database::Migrations::Runner do migrations = applied_migrations_other_branches + applied_migrations_this_branch + pending_migrations ctx = double(ActiveRecord::MigrationContext, get_all_versions: all_versions, migrations: migrations, schema_migration: ActiveRecord::SchemaMigration) - allow(described_class).to receive(:migration_context).and_return(ctx) + allow(ActiveRecord::Base.connection).to receive(:migration_context).and_return(ctx) names_this_branch = (applied_migrations_this_branch + pending_migrations).map { |m| "db/migrate/#{m.version}_#{m.name}.rb" } allow(described_class).to receive(:migration_file_names_this_branch).and_return(names_this_branch) end after do - FileUtils.rm_rf(result_dir) + FileUtils.rm_rf(base_result_dir) end - it 'creates the results dir when one does not exist' do - FileUtils.rm_rf(result_dir) - - expect do - described_class.new(direction: :up, migrations: [], result_dir: result_dir).run - end.to change { Dir.exist?(result_dir) }.from(false).to(true) + where(:case_name, :database, :result_dir, :legacy_mode, :expected_schema_version) do + [ + ['main database', :main, lazy { base_result_dir.join('main') }, false, described_class::SCHEMA_VERSION], + ['main database (legacy mode)', :main, lazy { base_result_dir }, true, 3], + ['ci database', :ci, lazy { base_result_dir.join('ci') }, false, described_class::SCHEMA_VERSION] + ] end - describe '.up' do - context 'result directory' do - it 'uses the /up subdirectory' do - expect(described_class.up.result_dir).to eq(result_dir.join('up')) - end + with_them do + it 'creates the results dir when one does not exist' do + FileUtils.rm_rf(result_dir) + + expect do + described_class.new(direction: :up, migrations: [], database: database).run + end.to change { Dir.exist?(result_dir) }.from(false).to(true) end - context 'migrations to run' do - subject(:up) { described_class.up } + describe '.up' do + context 'result directory' do + it 'uses the /up subdirectory' do + expect(described_class.up(database: database, legacy_mode: legacy_mode).result_dir).to eq(result_dir.join('up')) + end + end + + context 'migrations to run' do + subject(:up) { described_class.up(database: database, legacy_mode: legacy_mode) } - it 'is the list of pending migrations' do - expect(up.migrations).to eq(pending_migrations) + it 'is the list of pending migrations' do + expect(up.migrations).to eq(pending_migrations) + end end - end - context 'running migrations' do - subject(:up) { described_class.up } + context 'running migrations' do + subject(:up) { described_class.up(database: database, legacy_mode: legacy_mode) } - it 'runs the unapplied migrations in version order', :aggregate_failures do - up.run + it 'runs the unapplied migrations in version order', :aggregate_failures do + up.run - expect(migration_runs.map(&:dir)).to match_array([:up, :up]) - expect(migration_runs.map(&:version_to_migrate)).to eq(pending_migrations.map(&:version)) - end + expect(migration_runs.map(&:dir)).to match_array([:up, :up]) + expect(migration_runs.map(&:version_to_migrate)).to eq(pending_migrations.map(&:version)) + end - it 'writes a metadata file with the current schema version' do - up.run + it 'writes a metadata file with the current schema version and database name' do + up.run - metadata_file = result_dir.join('up', described_class::METADATA_FILENAME) - expect(metadata_file.exist?).to be_truthy - metadata = Gitlab::Json.parse(File.read(metadata_file)) - expect(metadata).to match('version' => described_class::SCHEMA_VERSION) + metadata_file = result_dir.join('up', described_class::METADATA_FILENAME) + expect(metadata_file.exist?).to be_truthy + metadata = Gitlab::Json.parse(File.read(metadata_file)) + expect(metadata).to match('version' => expected_schema_version, 'database' => database.to_s) + end + + it 'runs the unapplied migrations on the correct database' do + up.run + + expect(migration_runs.map(&:database).uniq).to contain_exactly(database.to_s) + end end end - end - describe '.down' do - subject(:down) { described_class.down } + describe '.down' do + subject(:down) { described_class.down(database: database, legacy_mode: legacy_mode) } - context 'result directory' do - it 'is the /down subdirectory' do - expect(down.result_dir).to eq(result_dir.join('down')) + context 'result directory' do + it 'is the /down subdirectory' do + expect(down.result_dir).to eq(result_dir.join('down')) + end end - end - context 'migrations to run' do - it 'is the list of migrations that are up and on this branch' do - expect(down.migrations).to eq(applied_migrations_this_branch) + context 'migrations to run' do + it 'is the list of migrations that are up and on this branch' do + expect(down.migrations).to eq(applied_migrations_this_branch) + end end - end - context 'running migrations' do - it 'runs the applied migrations for the current branch in reverse order', :aggregate_failures do - down.run + context 'running migrations' do + it 'runs the applied migrations for the current branch in reverse order', :aggregate_failures do + down.run - expect(migration_runs.map(&:dir)).to match_array([:down, :down]) - expect(migration_runs.map(&:version_to_migrate)).to eq(applied_migrations_this_branch.reverse.map(&:version)) + expect(migration_runs.map(&:dir)).to match_array([:down, :down]) + expect(migration_runs.map(&:version_to_migrate)).to eq(applied_migrations_this_branch.reverse.map(&:version)) + end end - end - - it 'writes a metadata file with the current schema version' do - down.run - metadata_file = result_dir.join('down', described_class::METADATA_FILENAME) - expect(metadata_file.exist?).to be_truthy - metadata = Gitlab::Json.parse(File.read(metadata_file)) - expect(metadata).to match('version' => described_class::SCHEMA_VERSION) - end - end + it 'writes a metadata file with the current schema version' do + down.run - describe '.background_migrations' do - it 'is a TestBackgroundRunner' do - expect(described_class.background_migrations).to be_a(Gitlab::Database::Migrations::TestBackgroundRunner) + metadata_file = result_dir.join('down', described_class::METADATA_FILENAME) + expect(metadata_file.exist?).to be_truthy + metadata = Gitlab::Json.parse(File.read(metadata_file)) + expect(metadata).to match('version' => expected_schema_version, 'database' => database.to_s) + end end - it 'is configured with a result dir of /background_migrations' do - runner = described_class.background_migrations + describe '.background_migrations' do + it 'is a TestBackgroundRunner' do + expect(described_class.background_migrations).to be_a(Gitlab::Database::Migrations::TestBackgroundRunner) + end - expect(runner.result_dir).to eq(described_class::BASE_RESULT_DIR.join( 'background_migrations')) - end - end + it 'is configured with a result dir of /background_migrations' do + runner = described_class.background_migrations - describe '.batched_background_migrations' do - it 'is a TestBatchedBackgroundRunner' do - expect(described_class.batched_background_migrations(for_database: 'main')).to be_a(Gitlab::Database::Migrations::TestBatchedBackgroundRunner) + expect(runner.result_dir).to eq(described_class::BASE_RESULT_DIR.join( 'background_migrations')) + end end - context 'choosing the database to test against' do - it 'chooses the main database' do - runner = described_class.batched_background_migrations(for_database: 'main') + describe '.batched_background_migrations' do + it 'is a TestBatchedBackgroundRunner' do + expect(described_class.batched_background_migrations(for_database: database)).to be_a(Gitlab::Database::Migrations::TestBatchedBackgroundRunner) + end - chosen_connection_name = Gitlab::Database.db_config_name(runner.connection) + context 'choosing the database to test against' do + it 'chooses the provided database' do + runner = described_class.batched_background_migrations(for_database: database) - expect(chosen_connection_name).to eq('main') - end + chosen_connection_name = Gitlab::Database.db_config_name(runner.connection) - it 'chooses the ci database' do - skip_if_multiple_databases_not_setup + expect(chosen_connection_name).to eq(database.to_s) + end - runner = described_class.batched_background_migrations(for_database: 'ci') + it 'throws an error with an invalid name' do + expect { described_class.batched_background_migrations(for_database: 'not_a_database') } + .to raise_error(/not a valid database name/) + end - chosen_connection_name = Gitlab::Database.db_config_name(runner.connection) + it 'includes the database name in the result dir' do + runner = described_class.batched_background_migrations(for_database: database) - expect(chosen_connection_name).to eq('ci') + expect(runner.result_dir).to eq(base_result_dir.join(database.to_s, 'background_migrations')) + end end - it 'throws an error with an invalid name' do - expect { described_class.batched_background_migrations(for_database: 'not_a_database') } - .to raise_error(/not a valid database name/) + context 'legacy mode' do + it 'does not include the database name in the path' do + runner = described_class.batched_background_migrations(for_database: database, legacy_mode: true) + + expect(runner.result_dir).to eq(base_result_dir.join('background_migrations')) + end end end end |