diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-28 21:08:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-28 21:08:35 +0300 |
commit | 6315ed9630fb1c6ade3114beb762cd1568d79219 (patch) | |
tree | 2a5d31936d09c14420c8f4c8bd752e268f0eb19f /spec/lib/gitlab/database | |
parent | fedf978f9aa1909ed7bb3fad767ad120a1c6bd7b (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib/gitlab/database')
-rw-r--r-- | spec/lib/gitlab/database/migration_helpers_spec.rb | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index f71d3a67eb9..3797e794985 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -1531,4 +1531,366 @@ describe Gitlab::Database::MigrationHelpers do expect(buffer.read).to include("\"class\":\"#{model.class}\"") end end + + describe '#backfill_iids' do + include MigrationsHelpers + + class self::Issue < ActiveRecord::Base + include AtomicInternalId + + self.table_name = 'issues' + self.inheritance_column = :_type_disabled + + belongs_to :project + + has_internal_id :iid, + scope: :project, + init: ->(s) { s&.project&.issues&.maximum(:iid) }, + backfill: true, + presence: false + end + + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:issues) { table(:issues) } + + def setup + namespace = namespaces.create!(name: 'foo', path: 'foo') + project = projects.create!(namespace_id: namespace.id) + + project + end + + it 'generates iids properly for models created after the migration' do + project = setup + + model.backfill_iids('issues') + + issue = self.class::Issue.create!(project_id: project.id) + + expect(issue.iid).to eq(1) + end + + it 'generates iids properly for models created after the migration when iids are backfilled' do + project = setup + issue_a = issues.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_b = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.iid).to eq(2) + end + + it 'generates iids properly for models created after the migration across multiple projects' do + project_a = setup + project_b = setup + issues.create!(project_id: project_a.id) + issues.create!(project_id: project_b.id) + issues.create!(project_id: project_b.id) + + model.backfill_iids('issues') + + issue_a = self.class::Issue.create!(project_id: project_a.id) + issue_b = self.class::Issue.create!(project_id: project_b.id) + + expect(issue_a.iid).to eq(2) + expect(issue_b.iid).to eq(3) + end + + context 'when the new code creates a row post deploy but before the migration runs' do + it 'does not change the row iid' do + project = setup + issue = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue.reload.iid).to eq(1) + end + + it 'backfills iids for rows already in the database' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + end + + it 'backfills iids across multiple projects' do + project_a = setup + project_b = setup + issue_a = issues.create!(project_id: project_a.id) + issue_b = issues.create!(project_id: project_b.id) + issue_c = self.class::Issue.create!(project_id: project_a.id) + issue_d = self.class::Issue.create!(project_id: project_b.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(1) + expect(issue_c.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(2) + end + + it 'generates iids properly for models created after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_d = self.class::Issue.create!(project_id: project.id) + issue_e = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + expect(issue_d.iid).to eq(4) + expect(issue_e.iid).to eq(5) + end + + it 'backfills iids and properly generates iids for new models across multiple projects' do + project_a = setup + project_b = setup + issue_a = issues.create!(project_id: project_a.id) + issue_b = issues.create!(project_id: project_b.id) + issue_c = self.class::Issue.create!(project_id: project_a.id) + issue_d = self.class::Issue.create!(project_id: project_b.id) + + model.backfill_iids('issues') + + issue_e = self.class::Issue.create!(project_id: project_a.id) + issue_f = self.class::Issue.create!(project_id: project_b.id) + issue_g = self.class::Issue.create!(project_id: project_a.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(1) + expect(issue_c.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(2) + expect(issue_e.iid).to eq(3) + expect(issue_f.iid).to eq(3) + expect(issue_g.iid).to eq(4) + end + end + + context 'when the new code creates a model and then old code creates a model post deploy but before the migration runs' do + it 'backfills iids' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = self.class::Issue.create!(project_id: project.id) + issue_c = issues.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + end + + it 'generates an iid for a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_d = issues.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_e = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + expect(issue_d.reload.iid).to eq(4) + expect(issue_e.iid).to eq(5) + end + end + + context 'when the new code and old code alternate creating models post deploy but before the migration runs' do + it 'backfills iids' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = self.class::Issue.create!(project_id: project.id) + issue_c = issues.create!(project_id: project.id) + issue_d = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + expect(issue_d.reload.iid).to eq(4) + end + + it 'generates an iid for a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_d = issues.create!(project_id: project.id) + issue_e = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_f = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_c.reload.iid).to eq(3) + expect(issue_d.reload.iid).to eq(4) + expect(issue_e.reload.iid).to eq(5) + expect(issue_f.iid).to eq(6) + end + end + + context 'when the new code creates and deletes a model post deploy but before the migration runs' do + it 'backfills iids for rows already in the database' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + end + + it 'successfully creates a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + + model.backfill_iids('issues') + + issue_d = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_d.iid).to eq(3) + end + end + + context 'when the new code creates and deletes a model and old code creates a model post deploy but before the migration runs' do + it 'backfills iids' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + issue_d = issues.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(3) + end + + it 'successfully creates a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + issue_d = issues.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_e = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(3) + expect(issue_e.iid).to eq(4) + end + end + + context 'when the new code creates and deletes a model and then creates another model post deploy but before the migration runs' do + it 'successfully generates an iid for a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + issue_d = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(3) + end + + it 'successfully generates an iid for a new model after the migration' do + project = setup + issue_a = issues.create!(project_id: project.id) + issue_b = issues.create!(project_id: project.id) + issue_c = self.class::Issue.create!(project_id: project.id) + issue_c.delete + issue_d = self.class::Issue.create!(project_id: project.id) + + model.backfill_iids('issues') + + issue_e = self.class::Issue.create!(project_id: project.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + expect(issue_d.reload.iid).to eq(3) + expect(issue_e.iid).to eq(4) + end + end + + context 'when the first model is created for a project after the migration' do + it 'generates an iid' do + project_a = setup + project_b = setup + issue_a = issues.create!(project_id: project_a.id) + + model.backfill_iids('issues') + + issue_b = self.class::Issue.create!(project_id: project_b.id) + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(1) + end + end + + context 'when a row already has an iid set in the database' do + it 'backfills iids' do + project = setup + issue_a = issues.create!(project_id: project.id, iid: 1) + issue_b = issues.create!(project_id: project.id, iid: 2) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(2) + end + + it 'backfills for multiple projects' do + project_a = setup + project_b = setup + issue_a = issues.create!(project_id: project_a.id, iid: 1) + issue_b = issues.create!(project_id: project_b.id, iid: 1) + issue_c = issues.create!(project_id: project_a.id, iid: 2) + + model.backfill_iids('issues') + + expect(issue_a.reload.iid).to eq(1) + expect(issue_b.reload.iid).to eq(1) + expect(issue_c.reload.iid).to eq(2) + end + end + end end |