Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 10:08:36 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-21 10:08:36 +0300
commit48aff82709769b098321c738f3444b9bdaa694c6 (patch)
treee00c7c43e2d9b603a5a6af576b1685e400410dee /spec/migrations
parent879f5329ee916a948223f8f43d77fba4da6cd028 (diff)
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'spec/migrations')
-rw-r--r--spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb46
-rw-r--r--spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb58
-rw-r--r--spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb22
-rw-r--r--spec/migrations/backfill_status_page_published_incidents_spec.rb2
-rw-r--r--spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb101
-rw-r--r--spec/migrations/ensure_filled_file_store_on_package_files_spec.rb40
-rw-r--r--spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb70
-rw-r--r--spec/migrations/schedule_blocked_by_links_replacement_spec.rb37
-rw-r--r--spec/migrations/schedule_migrate_u2f_webauthn_spec.rb58
-rw-r--r--spec/migrations/set_job_waiter_ttl_spec.rb30
10 files changed, 463 insertions, 1 deletions
diff --git a/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb b/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
new file mode 100644
index 00000000000..1a618712b32
--- /dev/null
+++ b/spec/migrations/20200929052138_create_initial_versions_for_pre_versioning_terraform_states_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200929052138_create_initial_versions_for_pre_versioning_terraform_states.rb')
+
+RSpec.describe CreateInitialVersionsForPreVersioningTerraformStates do
+ let(:namespace) { table(:namespaces).create!(name: 'terraform', path: 'terraform') }
+ let(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) }
+ let(:terraform_state_versions) { table(:terraform_state_versions) }
+
+ def create_state!(project, versioning_enabled:)
+ table(:terraform_states).create!(
+ project_id: project.id,
+ uuid: 'uuid',
+ file_store: 2,
+ file: 'state.tfstate',
+ versioning_enabled: versioning_enabled
+ )
+ end
+
+ describe '#up' do
+ context 'for a state that is already versioned' do
+ let!(:terraform_state) { create_state!(project, versioning_enabled: true) }
+
+ it 'does not insert a version record' do
+ expect { migrate! }.not_to change { terraform_state_versions.count }
+ end
+ end
+
+ context 'for a state that is not yet versioned' do
+ let!(:terraform_state) { create_state!(project, versioning_enabled: false) }
+
+ it 'creates a version using the current state data' do
+ expect { migrate! }.to change { terraform_state_versions.count }.by(1)
+
+ migrated_version = terraform_state_versions.last
+ expect(migrated_version.terraform_state_id).to eq(terraform_state.id)
+ expect(migrated_version.version).to be_zero
+ expect(migrated_version.file_store).to eq(terraform_state.file_store)
+ expect(migrated_version.file).to eq(terraform_state.file)
+ expect(migrated_version.created_at).to be_present
+ expect(migrated_version.updated_at).to be_present
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb b/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
new file mode 100644
index 00000000000..134bea6b666
--- /dev/null
+++ b/spec/migrations/20201014205300_drop_backfill_jira_tracker_deployment_type_jobs_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20201014205300_drop_backfill_jira_tracker_deployment_type_jobs.rb')
+
+RSpec.describe DropBackfillJiraTrackerDeploymentTypeJobs, :sidekiq, :redis, schema: 2020_10_14_205300 do
+ subject(:migration) { described_class.new }
+
+ describe '#up' do
+ let(:retry_set) { Sidekiq::RetrySet.new }
+ let(:scheduled_set) { Sidekiq::ScheduledSet.new }
+
+ context 'there are only affected jobs on the queue' do
+ let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } }
+ let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
+
+ it 'removes enqueued BackfillJiraTrackerDeploymentType background jobs' do
+ Sidekiq::Testing.disable! do # https://github.com/mperham/sidekiq/wiki/testing#api Sidekiq's API does not have a testing mode
+ retry_set.schedule(1.hour.from_now, payload)
+ scheduled_set.schedule(1.hour.from_now, payload)
+ Sidekiq::Client.push(queue_payload)
+
+ expect { migration.up }.to change { Sidekiq::Queue.new(described_class::QUEUE).size }.from(1).to(0)
+ expect(retry_set.size).to eq(0)
+ expect(scheduled_set.size).to eq(0)
+ end
+ end
+ end
+
+ context 'there are not any affected jobs on the queue' do
+ let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1] } }
+ let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) }
+
+ it 'skips other enqueued jobs' do
+ Sidekiq::Testing.disable! do
+ retry_set.schedule(1.hour.from_now, payload)
+ scheduled_set.schedule(1.hour.from_now, payload)
+ Sidekiq::Client.push(queue_payload)
+
+ expect { migration.up }.not_to change { Sidekiq::Queue.new(described_class::QUEUE).size }
+ expect(retry_set.size).to eq(1)
+ expect(scheduled_set.size).to eq(1)
+ end
+ end
+ end
+
+ context 'other queues' do
+ it 'does not modify them' do
+ Sidekiq::Testing.disable! do
+ Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1])
+ Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1])
+
+ expect { migration.up }.not_to change { Sidekiq::Queue.new('other').size }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb b/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
new file mode 100644
index 00000000000..018d48bea66
--- /dev/null
+++ b/spec/migrations/add_partial_index_to_ci_builds_table_on_user_id_name_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200908064229_add_partial_index_to_ci_builds_table_on_user_id_name.rb')
+
+RSpec.describe AddPartialIndexToCiBuildsTableOnUserIdName do
+ let(:migration) { described_class.new }
+
+ describe '#up' do
+ it 'creates temporary partial index on type' do
+ expect { migration.up }.to change { migration.index_exists?(:ci_builds, [:user_id, :name], name: described_class::INDEX_NAME) }.from(false).to(true)
+ end
+ end
+
+ describe '#down' do
+ it 'removes temporary partial index on type' do
+ migration.up
+
+ expect { migration.down }.to change { migration.index_exists?(:ci_builds, [:user_id, :name], name: described_class::INDEX_NAME) }.from(true).to(false)
+ end
+ end
+end
diff --git a/spec/migrations/backfill_status_page_published_incidents_spec.rb b/spec/migrations/backfill_status_page_published_incidents_spec.rb
index 2b1ab891038..674484cdf0a 100644
--- a/spec/migrations/backfill_status_page_published_incidents_spec.rb
+++ b/spec/migrations/backfill_status_page_published_incidents_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe BackfillStatusPagePublishedIncidents, :migration do
end
it 'creates a StatusPage::PublishedIncident record for each published issue' do
- Timecop.freeze(current_time) do
+ travel_to(current_time) do
expect(incidents.all).to be_empty
migrate!
diff --git a/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb b/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
new file mode 100644
index 00000000000..f9285c857de
--- /dev/null
+++ b/spec/migrations/cleanup_group_import_states_with_null_user_id_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+# In order to test the CleanupGroupImportStatesWithNullUserId migration, we need
+# to first create GroupImportState with NULL user_id
+# and then run the migration to check that user_id was populated or record removed
+#
+# The problem is that the CleanupGroupImportStatesWithNullUserId migration comes
+# after the NOT NULL constraint has been added with a previous migration (AddNotNullConstraintToUserOnGroupImportStates)
+# That means that while testing the current class we can not insert GroupImportState records with an
+# invalid user_id as constraint is blocking it from doing so
+#
+# To solve this problem, use SchemaVersionFinder to set schema one version prior to AddNotNullConstraintToUserOnGroupImportStates
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200907092715_add_not_null_constraint_to_user_on_group_import_states.rb')
+require Rails.root.join('db', 'post_migrate', '20200909161624_cleanup_group_import_states_with_null_user_id.rb')
+
+RSpec.describe CleanupGroupImportStatesWithNullUserId, :migration,
+ schema: MigrationHelpers::SchemaVersionFinder.migration_prior(AddNotNullConstraintToUserOnGroupImportStates) do
+ let(:namespaces_table) { table(:namespaces) }
+ let(:users_table) { table(:users) }
+ let(:group_import_states_table) { table(:group_import_states) }
+ let(:members_table) { table(:members) }
+
+ describe 'Group import states clean up' do
+ context 'when user_id is present' do
+ it 'does not update group_import_state record' do
+ user_1 = users_table.create!(name: 'user1', email: 'user1@example.com', projects_limit: 1)
+ group_1 = namespaces_table.create!(name: 'group_1', path: 'group_1', type: 'Group')
+ create_member(user_id: user_1.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_1.id, access_level: described_class::Group::OWNER)
+ group_import_state_1 = group_import_states_table.create!(group_id: group_1.id, user_id: user_1.id, status: 0)
+
+ expect(group_import_state_1.user_id).to eq(user_1.id)
+
+ disable_migrations_output { migrate! }
+
+ expect(group_import_state_1.reload.user_id).to eq(user_1.id)
+ end
+ end
+
+ context 'when user_id is missing' do
+ it 'updates user_id with group default owner id' do
+ user_2 = users_table.create!(name: 'user2', email: 'user2@example.com', projects_limit: 1)
+ group_2 = namespaces_table.create!(name: 'group_2', path: 'group_2', type: 'Group')
+ create_member(user_id: user_2.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_2.id, access_level: described_class::Group::OWNER)
+ group_import_state_2 = group_import_states_table.create!(group_id: group_2.id, user_id: nil, status: 0)
+
+ disable_migrations_output { migrate! }
+
+ expect(group_import_state_2.reload.user_id).to eq(user_2.id)
+ end
+ end
+
+ context 'when group does not contain any owners' do
+ it 'removes group_import_state record' do
+ group_3 = namespaces_table.create!(name: 'group_3', path: 'group_3', type: 'Group')
+ group_import_state_3 = group_import_states_table.create!(group_id: group_3.id, user_id: nil, status: 0)
+
+ disable_migrations_output { migrate! }
+
+ expect { group_import_state_3.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'when group has parent' do
+ it 'updates user_id with parent group default owner id' do
+ user = users_table.create!(name: 'user4', email: 'user4@example.com', projects_limit: 1)
+ group_1 = namespaces_table.create!(name: 'group_1', path: 'group_1', type: 'Group')
+ create_member(user_id: user.id, type: 'GroupMember', source_type: 'Namespace', source_id: group_1.id, access_level: described_class::Group::OWNER)
+ group_2 = namespaces_table.create!(name: 'group_2', path: 'group_2', type: 'Group', parent_id: group_1.id)
+ group_import_state = group_import_states_table.create!(group_id: group_2.id, user_id: nil, status: 0)
+
+ disable_migrations_output { migrate! }
+
+ expect(group_import_state.reload.user_id).to eq(user.id)
+ end
+ end
+
+ context 'when group has owner_id' do
+ it 'updates user_id with owner_id' do
+ user = users_table.create!(name: 'user', email: 'user@example.com', projects_limit: 1)
+ group = namespaces_table.create!(name: 'group', path: 'group', type: 'Group', owner_id: user.id)
+ group_import_state = group_import_states_table.create!(group_id: group.id, user_id: nil, status: 0)
+
+ disable_migrations_output { migrate! }
+
+ expect(group_import_state.reload.user_id).to eq(user.id)
+ end
+ end
+ end
+
+ def create_member(options)
+ members_table.create!(
+ {
+ notification_level: 0,
+ ldap: false,
+ override: false
+ }.merge(options)
+ )
+ end
+end
diff --git a/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb b/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
new file mode 100644
index 00000000000..8a0f51ab27e
--- /dev/null
+++ b/spec/migrations/ensure_filled_file_store_on_package_files_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200915185707_ensure_filled_file_store_on_package_files.rb')
+
+RSpec.describe EnsureFilledFileStoreOnPackageFiles, schema: 20200910175553 do
+ let!(:packages_package_files) { table(:packages_package_files) }
+ let!(:packages_packages) { table(:packages_packages) }
+ let!(:namespaces) { table(:namespaces) }
+ let!(:projects) { table(:projects) }
+ let!(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:project) { projects.create!(namespace_id: namespace.id) }
+ let!(:package) { packages_packages.create!(project_id: project.id, name: 'bar', package_type: 1) }
+
+ before do
+ constraint_name = 'check_4c5e6bb0b3'
+
+ # In order to insert a row with a NULL to fill.
+ ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files DROP CONSTRAINT #{constraint_name}"
+
+ @file_store_1 = packages_package_files.create!(file_store: 1, file_name: 'foo_1', file: 'foo_1', package_id: package.id)
+ @file_store_2 = packages_package_files.create!(file_store: 2, file_name: 'foo_2', file: 'foo_2', package_id: package.id)
+ @file_store_nil = packages_package_files.create!(file_store: nil, file_name: 'foo_nil', file: 'foo_nil', package_id: package.id)
+
+ # revert DB structure
+ ActiveRecord::Base.connection.execute "ALTER TABLE packages_package_files ADD CONSTRAINT #{constraint_name} CHECK ((file_store IS NOT NULL)) NOT VALID"
+ end
+
+ it 'correctly migrates nil file_store to 1' do
+ migrate!
+
+ @file_store_1.reload
+ @file_store_2.reload
+ @file_store_nil.reload
+
+ expect(@file_store_1.file_store).to eq(1) # unchanged
+ expect(@file_store_2.file_store).to eq(2) # unchanged
+ expect(@file_store_nil.file_store).to eq(1) # nil => 1
+ end
+end
diff --git a/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
new file mode 100644
index 00000000000..cd2ec81abb7
--- /dev/null
+++ b/spec/migrations/migrate_compliance_framework_enum_to_database_framework_record_spec.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201005094331_migrate_compliance_framework_enum_to_database_framework_record.rb')
+
+RSpec.describe MigrateComplianceFrameworkEnumToDatabaseFrameworkRecord, schema: 20201005092753 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:project_compliance_framework_settings) { table(:project_compliance_framework_settings) }
+ let(:compliance_management_frameworks) { table(:compliance_management_frameworks) }
+
+ let(:gdpr_framework) { 1 }
+ let(:sox_framework) { 5 }
+
+ let!(:root_group) { namespaces.create!(type: 'Group', name: 'a', path: 'a') }
+ let!(:sub_group) { namespaces.create!(type: 'Group', name: 'b', path: 'b', parent_id: root_group.id) }
+ let!(:sub_sub_group) { namespaces.create!(type: 'Group', name: 'c', path: 'c', parent_id: sub_group.id) }
+
+ let!(:namespace) { namespaces.create!(name: 'd', path: 'd') }
+
+ let!(:project_on_root_level) { projects.create!(namespace_id: root_group.id) }
+ let!(:project_on_sub_sub_level_1) { projects.create!(namespace_id: sub_sub_group.id) }
+ let!(:project_on_sub_sub_level_2) { projects.create!(namespace_id: sub_sub_group.id) }
+ let!(:project_on_namespace) { projects.create!(namespace_id: namespace.id) }
+
+ let!(:project_on_root_level_compliance_setting) { project_compliance_framework_settings.create!(project_id: project_on_root_level.id, framework: gdpr_framework) }
+ let!(:project_on_sub_sub_level_compliance_setting_1) { project_compliance_framework_settings.create!(project_id: project_on_sub_sub_level_1.id, framework: sox_framework) }
+ let!(:project_on_sub_sub_level_compliance_setting_2) { project_compliance_framework_settings.create!(project_id: project_on_sub_sub_level_2.id, framework: gdpr_framework) }
+ let!(:project_on_namespace_level_compliance_setting) { project_compliance_framework_settings.create!(project_id: project_on_namespace.id, framework: gdpr_framework) }
+
+ subject { described_class.new.up }
+
+ context 'when Gitlab.ee? is true' do
+ before do
+ expect(Gitlab).to receive(:ee?).and_return(true)
+ end
+
+ it 'updates the project settings' do
+ subject
+
+ gdpr_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'GDPR')
+ expect(project_on_root_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id)
+ expect(project_on_sub_sub_level_compliance_setting_2.reload.framework_id).to eq(gdpr_framework.id)
+
+ sox_framework = compliance_management_frameworks.find_by(namespace_id: root_group.id, name: 'SOX')
+ expect(project_on_sub_sub_level_compliance_setting_1.reload.framework_id).to eq(sox_framework.id)
+
+ gdpr_framework = compliance_management_frameworks.find_by(namespace_id: namespace.id, name: 'GDPR')
+ expect(project_on_namespace_level_compliance_setting.reload.framework_id).to eq(gdpr_framework.id)
+ end
+
+ it 'adds two framework records' do
+ subject
+
+ expect(compliance_management_frameworks.count).to eq(3)
+ end
+ end
+
+ context 'when Gitlab.ee? is false' do
+ before do
+ expect(Gitlab).to receive(:ee?).and_return(false)
+ end
+
+ it 'does nothing' do
+ subject
+
+ expect(compliance_management_frameworks.count).to eq(0)
+ end
+ end
+end
diff --git a/spec/migrations/schedule_blocked_by_links_replacement_spec.rb b/spec/migrations/schedule_blocked_by_links_replacement_spec.rb
new file mode 100644
index 00000000000..36610507921
--- /dev/null
+++ b/spec/migrations/schedule_blocked_by_links_replacement_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20201015073808_schedule_blocked_by_links_replacement')
+
+RSpec.describe ScheduleBlockedByLinksReplacement do
+ let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
+ let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
+ let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
+ let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
+ let!(:issue_links) do
+ [
+ table(:issue_links).create!(source_id: issue1.id, target_id: issue2.id, link_type: 1),
+ table(:issue_links).create!(source_id: issue2.id, target_id: issue1.id, link_type: 2),
+ table(:issue_links).create!(source_id: issue1.id, target_id: issue3.id, link_type: 2)
+ ]
+ end
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ it 'schedules jobs for blocked_by links' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 2.minutes, issue_links[1].id, issue_links[1].id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(
+ 4.minutes, issue_links[2].id, issue_links[2].id)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+end
diff --git a/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb b/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
new file mode 100644
index 00000000000..5dc4d676063
--- /dev/null
+++ b/spec/migrations/schedule_migrate_u2f_webauthn_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200929114107_schedule_migrate_u2f_webauthn.rb')
+
+RSpec.describe ScheduleMigrateU2fWebauthn do
+ let(:migration_name) { described_class::MIGRATION }
+ let(:u2f_registrations) { table(:u2f_registrations) }
+ let(:webauthn_registrations) { table(:webauthn_registrations) }
+
+ let(:users) { table(:users) }
+
+ let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+ end
+
+ context 'when there are u2f registrations' do
+ let!(:u2f_reg_1) { create_u2f_registration(1, 'reg1') }
+ let!(:u2f_reg_2) { create_u2f_registration(2, 'reg2') }
+
+ it 'schedules a background migration' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(migration_name).to be_scheduled_delayed_migration(2.minutes, 1, 1)
+ expect(migration_name).to be_scheduled_delayed_migration(4.minutes, 2, 2)
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+ end
+
+ context 'when there are no u2f registrations' do
+ it 'does not schedule background migrations' do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(0)
+ end
+ end
+ end
+ end
+
+ def create_u2f_registration(id, name)
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
+ u2f_registrations.create!({ id: id,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw),
+ counter: 5,
+ name: name,
+ user_id: user.id })
+ end
+end
diff --git a/spec/migrations/set_job_waiter_ttl_spec.rb b/spec/migrations/set_job_waiter_ttl_spec.rb
new file mode 100644
index 00000000000..b9cf7c55798
--- /dev/null
+++ b/spec/migrations/set_job_waiter_ttl_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20200930144340_set_job_waiter_ttl.rb')
+
+RSpec.describe SetJobWaiterTtl, :redis do
+ it 'sets TTLs where necessary' do
+ waiter_with_ttl = Gitlab::JobWaiter.new.key
+ waiter_without_ttl = Gitlab::JobWaiter.new.key
+ key_with_ttl = "foo:bar"
+ key_without_ttl = "foo:qux"
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(waiter_with_ttl, "zzz", ex: 2000)
+ redis.set(waiter_without_ttl, "zzz")
+ redis.set(key_with_ttl, "zzz", ex: 2000)
+ redis.set(key_without_ttl, "zzz")
+
+ described_class.new.up
+
+ # This is the point of the migration. We know the migration uses a TTL of 21_600
+ expect(redis.ttl(waiter_without_ttl)).to be > 20_000
+
+ # Other TTL's should be untouched by the migration
+ expect(redis.ttl(waiter_with_ttl)).to be_between(1000, 2000)
+ expect(redis.ttl(key_with_ttl)).to be_between(1000, 2000)
+ expect(redis.ttl(key_without_ttl)).to eq(-1)
+ end
+ end
+end