diff options
author | Douwe Maan <douwe@selenight.nl> | 2017-10-05 12:48:22 +0200 |
---|---|---|
committer | Douwe Maan <douwe@selenight.nl> | 2017-10-05 12:48:22 +0200 |
commit | 0c0c2ecd99cd5c4cb22a0c045f8d45d315203832 (patch) | |
tree | 3900ccdcdff0cd6b8e3ed281ba57a317b801ad08 /spec/models | |
parent | ed3c25e4294bfc75f7167ed63e30561e39ac3a97 (diff) | |
parent | de01353b166018a43ea92b38054b1267c3ba5cea (diff) | |
download | gitlab-ce-0c0c2ecd99cd5c4cb22a0c045f8d45d315203832.tar.gz |
Merge branch 'master' into digitalmoksha/gitlab-ce-feature/verify_secondary_emails
# Conflicts:
# app/controllers/admin/users_controller.rb
# app/controllers/confirmations_controller.rb
# app/controllers/profiles/emails_controller.rb
# app/models/user.rb
# app/services/emails/base_service.rb
# app/services/emails/destroy_service.rb
# app/views/devise/mailer/confirmation_instructions.html.haml
# lib/api/users.rb
# spec/services/emails/destroy_service_spec.rb
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/ci/pipeline_variable_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/ci/runner_spec.rb | 69 | ||||
-rw-r--r-- | spec/models/gpg_key_spec.rb | 8 | ||||
-rw-r--r-- | spec/models/key_spec.rb | 10 | ||||
-rw-r--r-- | spec/models/merge_request_spec.rb | 43 | ||||
-rw-r--r-- | spec/models/project_services/kubernetes_service_spec.rb | 2 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 107 | ||||
-rw-r--r-- | spec/models/project_wiki_spec.rb | 64 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 343 | ||||
-rw-r--r-- | spec/models/user_custom_attribute_spec.rb | 16 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 1 | ||||
-rw-r--r-- | spec/models/wiki_page_spec.rb | 14 |
12 files changed, 466 insertions, 213 deletions
diff --git a/spec/models/ci/pipeline_variable_spec.rb b/spec/models/ci/pipeline_variable_spec.rb index 2ce78e34b0c..889c243c8d8 100644 --- a/spec/models/ci/pipeline_variable_spec.rb +++ b/spec/models/ci/pipeline_variable_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Ci::PipelineVariable, models: true do +describe Ci::PipelineVariable do subject { build(:ci_pipeline_variable) } it { is_expected.to include_module(HasVariable) } diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 2e686e515c5..584dfe9a5c1 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -183,75 +183,42 @@ describe Ci::Runner do end end - context 'when runner is locked' do + context 'when runner is shared' do before do - runner.locked = true + runner.is_shared = true + build.project.runners = [] end - shared_examples 'locked build picker' do - context 'when runner cannot pick untagged jobs' do - before do - runner.run_untagged = false - end + it 'can handle builds' do + expect(runner.can_pick?(build)).to be_truthy + end - it 'cannot handle builds without tags' do - expect(runner.can_pick?(build)).to be_falsey - end + context 'when runner is locked' do + before do + runner.locked = true end - context 'when having runner tags' do - before do - runner.tag_list = %w(bb cc) - end - - it 'cannot handle it for builds without matching tags' do - build.tag_list = ['aa'] - - expect(runner.can_pick?(build)).to be_falsey - end + it 'can handle builds' do + expect(runner.can_pick?(build)).to be_truthy end end + end - context 'when serving the same project' do - it 'can handle it' do + context 'when runner is not shared' do + context 'when runner is assigned to a project' do + it 'can handle builds' do expect(runner.can_pick?(build)).to be_truthy end - - it_behaves_like 'locked build picker' - - context 'when having runner tags' do - before do - runner.tag_list = %w(bb cc) - build.tag_list = ['bb'] - end - - it 'can handle it for matching tags' do - expect(runner.can_pick?(build)).to be_truthy - end - end end - context 'serving a different project' do + context 'when runner is not assigned to a project' do before do - runner.runner_projects.destroy_all + build.project.runners = [] end - it 'cannot handle it' do + it 'cannot handle builds' do expect(runner.can_pick?(build)).to be_falsey end - - it_behaves_like 'locked build picker' - - context 'when having runner tags' do - before do - runner.tag_list = %w(bb cc) - build.tag_list = ['bb'] - end - - it 'cannot handle it for matching tags' do - expect(runner.can_pick?(build)).to be_falsey - end - end end end diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb index 067afc0182b..743f2cfcab5 100644 --- a/spec/models/gpg_key_spec.rb +++ b/spec/models/gpg_key_spec.rb @@ -147,6 +147,14 @@ describe GpgKey do expect(gpg_key.verified?).to be_truthy expect(gpg_key.verified_and_belongs_to_email?('bette.cartwright@example.com')).to be_truthy end + + it 'returns true if one of the email addresses in the key belongs to the user and case-insensitively matches the provided email' do + user = create :user, email: 'bette.cartwright@example.com' + gpg_key = create :gpg_key, key: GpgHelpers::User2.public_key, user: user + + expect(gpg_key.verified?).to be_truthy + expect(gpg_key.verified_and_belongs_to_email?('Bette.Cartwright@example.com')).to be_truthy + end end describe '#revoke' do diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 8eabc4ca72f..81c2057e175 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -155,5 +155,15 @@ describe Key, :mailer do it 'strips white spaces' do expect(described_class.new(key: " #{valid_key} ").key).to eq(valid_key) end + + it 'invalidates the public_key attribute' do + key = build(:key) + + original = key.public_key + key.key = valid_key + + expect(original.key_text).not_to be_nil + expect(key.public_key.key_text).to eq(valid_key) + end end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index d80d5657c42..188a0a98ec3 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -791,6 +791,49 @@ describe MergeRequest do end end + describe '#has_ci?' do + let(:merge_request) { build_stubbed(:merge_request) } + + context 'has ci' do + it 'returns true if MR has head_pipeline_id and commits' do + allow(merge_request).to receive_message_chain(:source_project, :ci_service) { nil } + allow(merge_request).to receive(:head_pipeline_id) { double } + allow(merge_request).to receive(:has_no_commits?) { false } + + expect(merge_request.has_ci?).to be(true) + end + + it 'returns true if MR has any pipeline and commits' do + allow(merge_request).to receive_message_chain(:source_project, :ci_service) { nil } + allow(merge_request).to receive(:head_pipeline_id) { nil } + allow(merge_request).to receive(:has_no_commits?) { false } + allow(merge_request).to receive(:all_pipelines) { [double] } + + expect(merge_request.has_ci?).to be(true) + end + + it 'returns true if MR has CI service and commits' do + allow(merge_request).to receive_message_chain(:source_project, :ci_service) { double } + allow(merge_request).to receive(:head_pipeline_id) { nil } + allow(merge_request).to receive(:has_no_commits?) { false } + allow(merge_request).to receive(:all_pipelines) { [] } + + expect(merge_request.has_ci?).to be(true) + end + end + + context 'has no ci' do + it 'returns false if MR has no CI service nor pipeline, and no commits' do + allow(merge_request).to receive_message_chain(:source_project, :ci_service) { nil } + allow(merge_request).to receive(:head_pipeline_id) { nil } + allow(merge_request).to receive(:all_pipelines) { [] } + allow(merge_request).to receive(:has_no_commits?) { true } + + expect(merge_request.has_ci?).to be(false) + end + end + end + describe '#all_pipelines' do shared_examples 'returning pipelines with proper ordering' do let!(:all_pipelines) do diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index 537cdadd528..2298dcab55f 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -208,7 +208,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do config.dig('users', 0, 'user')['token'] = 'token' config.dig('contexts', 0, 'context')['namespace'] = namespace config.dig('clusters', 0, 'cluster')['certificate-authority-data'] = - Base64.encode64('CA PEM DATA') + Base64.strict_encode64('CA PEM DATA') YAML.dump(config) end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 78226c6c3fa..176bb568cbe 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -408,6 +408,18 @@ describe Project do end end + describe '#merge_method' do + it 'returns "ff" merge_method when ff is enabled' do + project = build(:project, merge_requests_ff_only_enabled: true) + expect(project.merge_method).to be :ff + end + + it 'returns "merge" merge_method when ff is disabled' do + project = build(:project, merge_requests_ff_only_enabled: false) + expect(project.merge_method).to be :merge + end + end + describe '#repository_storage_path' do let(:project) { create(:project, repository_storage: 'custom') } @@ -1303,7 +1315,7 @@ describe Project do context 'using a regular repository' do it 'creates the repository' do expect(shell).to receive(:add_repository) - .with(project.repository_storage_path, project.disk_path) + .with(project.repository_storage, project.disk_path) .and_return(true) expect(project.repository).to receive(:after_create) @@ -1313,7 +1325,7 @@ describe Project do it 'adds an error if the repository could not be created' do expect(shell).to receive(:add_repository) - .with(project.repository_storage_path, project.disk_path) + .with(project.repository_storage, project.disk_path) .and_return(false) expect(project.repository).not_to receive(:after_create) @@ -1370,7 +1382,7 @@ describe Project do .and_return(false) expect(shell).to receive(:add_repository) - .with(project.repository_storage_path, project.disk_path) + .with(project.repository_storage, project.disk_path) .and_return(true) project.ensure_repository @@ -2363,12 +2375,24 @@ describe Project do describe '#legacy_storage?' do it 'returns true when storage_version is nil' do - project = build(:project) + project = build(:project, storage_version: nil) + + expect(project.legacy_storage?).to be_truthy + end + + it 'returns true when the storage_version is 0' do + project = build(:project, storage_version: 0) expect(project.legacy_storage?).to be_truthy end end + describe '#hashed_storage?' do + it 'returns false' do + expect(project.hashed_storage?).to be_falsey + end + end + describe '#rename_repo' do before do # Project#gitlab_shell returns a new instance of Gitlab::Shell on every @@ -2425,6 +2449,38 @@ describe Project do expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path)) end end + + describe '#migrate_to_hashed_storage!' do + it 'returns true' do + expect(project.migrate_to_hashed_storage!).to be_truthy + end + + it 'flags as readonly' do + expect { project.migrate_to_hashed_storage! }.to change { project.repository_read_only }.to(true) + end + + it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the project repo is in use' do + Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: false)).increase + + expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in) + + project.migrate_to_hashed_storage! + end + + it 'schedules ProjectMigrateHashedStorageWorker with delayed start when the wiki repo is in use' do + Gitlab::ReferenceCounter.new(project.gl_repository(is_wiki: true)).increase + + expect(ProjectMigrateHashedStorageWorker).to receive(:perform_in) + + project.migrate_to_hashed_storage! + end + + it 'schedules ProjectMigrateHashedStorageWorker' do + expect(ProjectMigrateHashedStorageWorker).to receive(:perform_async).with(project.id) + + project.migrate_to_hashed_storage! + end + end end context 'hashed storage' do @@ -2438,6 +2494,18 @@ describe Project do allow(project).to receive(:gitlab_shell).and_return(gitlab_shell) end + describe '#legacy_storage?' do + it 'returns false' do + expect(project.legacy_storage?).to be_falsey + end + end + + describe '#hashed_storage?' do + it 'returns true' do + expect(project.hashed_storage?).to be_truthy + end + end + describe '#base_dir' do it 'returns base_dir based on hash of project id' do expect(project.base_dir).to eq('@hashed/6b/86') @@ -2508,6 +2576,26 @@ describe Project do expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path)) end end + + describe '#migrate_to_hashed_storage!' do + it 'returns nil' do + expect(project.migrate_to_hashed_storage!).to be_nil + end + + it 'does not flag as readonly' do + expect { project.migrate_to_hashed_storage! }.not_to change { project.repository_read_only } + end + end + end + + describe '#gl_repository' do + let(:project) { create(:project) } + + it 'delegates to Gitlab::GlRepository.gl_repository' do + expect(Gitlab::GlRepository).to receive(:gl_repository).with(project, true) + + project.gl_repository(is_wiki: true) + end end describe '#has_ci?' do @@ -2717,6 +2805,17 @@ describe Project do end end + describe '#check_repository_path_availability' do + let(:project) { build(:project) } + + it 'skips gitlab-shell exists?' do + project.skip_disk_validation = true + + expect(project.gitlab_shell).not_to receive(:exists?) + expect(project.check_repository_path_availability).to be_truthy + end + end + describe '#latest_successful_pipeline_for_default_branch' do let(:project) { build(:project) } diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index 953df7746eb..78fb2df884a 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -6,13 +6,10 @@ describe ProjectWiki do let(:user) { project.owner } let(:gitlab_shell) { Gitlab::Shell.new } let(:project_wiki) { described_class.new(project, user) } + let(:raw_repository) { Gitlab::Git::Repository.new(project.repository_storage, subject.disk_path + '.git', 'foo') } subject { project_wiki } - before do - project_wiki.wiki - end - describe "#path_with_namespace" do it "returns the project path with namespace with the .wiki extension" do expect(subject.path_with_namespace).to eq(project.full_path + '.wiki') @@ -61,8 +58,8 @@ describe ProjectWiki do end describe "#wiki" do - it "contains a Gollum::Wiki instance" do - expect(subject.wiki).to be_a Gollum::Wiki + it "contains a Gitlab::Git::Wiki instance" do + expect(subject.wiki).to be_a Gitlab::Git::Wiki end it "creates a new wiki repo if one does not yet exist" do @@ -70,20 +67,18 @@ describe ProjectWiki do end it "raises CouldNotCreateWikiError if it can't create the wiki repository" do - allow(project_wiki).to receive(:init_repo).and_return(false) - expect { project_wiki.send(:create_repo!) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) + # Create a fresh project which will not have a wiki + project_wiki = described_class.new(create(:project), user) + gitlab_shell = double(:gitlab_shell) + allow(gitlab_shell).to receive(:add_repository) + allow(project_wiki).to receive(:gitlab_shell).and_return(gitlab_shell) + + expect { project_wiki.send(:wiki) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) end end describe "#empty?" do context "when the wiki repository is empty" do - before do - allow_any_instance_of(Gitlab::Shell).to receive(:add_repository) do - create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git") - end - allow(project).to receive(:full_path).and_return("non-existant") - end - describe '#empty?' do subject { super().empty? } it { is_expected.to be_truthy } @@ -154,13 +149,13 @@ describe ProjectWiki do before do file = Gollum::File.new(subject.wiki) allow_any_instance_of(Gollum::Wiki) - .to receive(:file).with('image.jpg', 'master', true) + .to receive(:file).with('image.jpg', 'master') .and_return(file) allow_any_instance_of(Gollum::File) .to receive(:mime_type) .and_return('image/jpeg') allow_any_instance_of(Gollum::Wiki) - .to receive(:file).with('non-existant', 'master', true) + .to receive(:file).with('non-existant', 'master') .and_return(nil) end @@ -178,9 +173,9 @@ describe ProjectWiki do expect(subject.find_file('non-existant')).to eq(nil) end - it 'returns a Gollum::File instance' do + it 'returns a Gitlab::Git::WikiFile instance' do file = subject.find_file('image.jpg') - expect(file).to be_a Gollum::File + expect(file).to be_a Gitlab::Git::WikiFile end end @@ -222,9 +217,9 @@ describe ProjectWiki do describe "#update_page" do before do create_page("update-page", "some content") - @gollum_page = subject.wiki.paged("update-page") + @gitlab_git_wiki_page = subject.wiki.page(title: "update-page") subject.update_page( - @gollum_page, + @gitlab_git_wiki_page, content: "some other content", format: :markdown, message: "updated page" @@ -246,7 +241,7 @@ describe ProjectWiki do it 'updates project activity' do subject.update_page( - @gollum_page, + @gitlab_git_wiki_page, content: 'Yet more content', format: :markdown, message: 'Updated page again' @@ -262,7 +257,7 @@ describe ProjectWiki do describe "#delete_page" do before do create_page("index", "some content") - @page = subject.wiki.paged("index") + @page = subject.wiki.page(title: "index") end it "deletes the page" do @@ -282,27 +277,28 @@ describe ProjectWiki do describe '#create_repo!' do it 'creates a repository' do - expect(subject).to receive(:init_repo) - .with(subject.full_path) - .and_return(true) - + expect(raw_repository.exists?).to eq(false) expect(subject.repository).to receive(:after_create) - expect(subject.create_repo!).to be_an_instance_of(Gollum::Wiki) + subject.send(:create_repo!, raw_repository) + + expect(raw_repository.exists?).to eq(true) end end describe '#ensure_repository' do it 'creates the repository if it not exist' do - allow(subject).to receive(:repository_exists?).and_return(false) - - expect(subject).to receive(:create_repo!) + expect(raw_repository.exists?).to eq(false) + expect(subject).to receive(:create_repo!).and_call_original subject.ensure_repository + + expect(raw_repository.exists?).to eq(true) end it 'does not create the repository if it exists' do - allow(subject).to receive(:repository_exists?).and_return(true) + subject.wiki + expect(raw_repository.exists?).to eq(true) expect(subject).not_to receive(:create_repo!) @@ -329,7 +325,7 @@ describe ProjectWiki do end def commit_details - { name: user.name, email: user.email, message: "test commit" } + Gitlab::Git::Wiki::CommitDetails.new(user.name, user.email, "test commit") end def create_page(name, content) @@ -337,6 +333,6 @@ describe ProjectWiki do end def destroy_page(page) - subject.wiki.delete_page(page, commit_details) + subject.delete_page(page, commit_details) end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 76bb658b10d..7156c1b7aa8 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Repository, models: true do +describe Repository do include RepoHelpers TestBlob = Struct.new(:path) @@ -636,18 +636,18 @@ describe Repository, models: true do describe '#fetch_ref' do describe 'when storage is broken', broken_storage: true do it 'should raise a storage error' do - path = broken_repository.path_to_repo - - expect_to_raise_storage_error { broken_repository.fetch_ref(path, '1', '2') } + expect_to_raise_storage_error do + broken_repository.fetch_ref(broken_repository, source_ref: '1', target_ref: '2') + end end end end describe '#create_ref' do - it 'redirects the call to fetch_ref' do + it 'redirects the call to write_ref' do ref, ref_path = '1', '2' - expect(repository).to receive(:fetch_ref).with(repository.path_to_repo, ref, ref_path) + expect(repository.raw_repository).to receive(:write_ref).with(ref_path, ref) repository.create_ref(ref, ref_path) end @@ -815,45 +815,70 @@ describe Repository, models: true do end describe '#add_branch' do - context 'when pre hooks were successful' do - it 'runs without errors' do - hook = double(trigger: [true, nil]) - expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook) + let(:branch_name) { 'new_feature' } + let(:target) { 'master' } - expect { repository.add_branch(user, 'new_feature', 'master') }.not_to raise_error - end + subject { repository.add_branch(user, branch_name, target) } - it 'creates the branch' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + context 'with Gitaly enabled' do + it "calls Gitaly's OperationService" do + expect_any_instance_of(Gitlab::GitalyClient::OperationService) + .to receive(:user_create_branch).with(branch_name, user, target) + .and_return(nil) - branch = repository.add_branch(user, 'new_feature', 'master') + subject + end - expect(branch.name).to eq('new_feature') + it 'creates_the_branch' do + expect(subject.name).to eq(branch_name) + expect(repository.find_branch(branch_name)).not_to be_nil end - it 'calls the after_create_branch hook' do - expect(repository).to receive(:after_create_branch) + context 'with a non-existing target' do + let(:target) { 'fake-target' } - repository.add_branch(user, 'new_feature', 'master') + it "returns false and doesn't create the branch" do + expect(subject).to be(false) + expect(repository.find_branch(branch_name)).to be_nil + end end end - context 'when pre hooks failed' do - it 'gets an error' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + context 'with Gitaly disabled', skip_gitaly_mock: true do + context 'when pre hooks were successful' do + it 'runs without errors' do + hook = double(trigger: [true, nil]) + expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook) - expect do - repository.add_branch(user, 'new_feature', 'master') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + expect { subject }.not_to raise_error + end + + it 'creates the branch' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + + expect(subject.name).to eq(branch_name) + end + + it 'calls the after_create_branch hook' do + expect(repository).to receive(:after_create_branch) + + subject + end end - it 'does not create the branch' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + context 'when pre hooks failed' do + it 'gets an error' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) - expect do - repository.add_branch(user, 'new_feature', 'master') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) - expect(repository.find_branch('new_feature')).to be_nil + expect { subject }.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end + + it 'does not create the branch' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + + expect { subject }.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + expect(repository.find_branch(branch_name)).to be_nil + end end end end @@ -876,47 +901,6 @@ describe Repository, models: true do end end - describe '#rm_branch' do - let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature - let(:blank_sha) { '0000000000000000000000000000000000000000' } - - context 'when pre hooks were successful' do - it 'runs without errors' do - expect_any_instance_of(Gitlab::Git::HooksService).to receive(:execute) - .with(git_user, repository.raw_repository, old_rev, blank_sha, 'refs/heads/feature') - - expect { repository.rm_branch(user, 'feature') }.not_to raise_error - end - - it 'deletes the branch' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) - - expect { repository.rm_branch(user, 'feature') }.not_to raise_error - - expect(repository.find_branch('feature')).to be_nil - end - end - - context 'when pre hooks failed' do - it 'gets an error' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) - - expect do - repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) - end - - it 'does not delete the branch' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) - - expect do - repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) - expect(repository.find_branch('feature')).not_to be_nil - end - end - end - describe '#update_branch_with_hooks' do let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature let(:new_rev) { 'a74ae73c1ccde9b974a70e82b901588071dc142a' } # commit whose parent is old_rev @@ -1131,21 +1115,31 @@ describe Repository, models: true do end describe '#has_visible_content?' do - subject { repository.has_visible_content? } + before do + # If raw_repository.has_visible_content? gets called more than once then + # caching is broken. We don't want that. + expect(repository.raw_repository).to receive(:has_visible_content?) + .once + .and_return(result) + end - describe 'when there are no branches' do - before do - allow(repository.raw_repository).to receive(:branch_count).and_return(0) - end + context 'when true' do + let(:result) { true } - it { is_expected.to eq(false) } + it 'returns true and caches it' do + expect(repository.has_visible_content?).to eq(true) + # Second call hits the cache + expect(repository.has_visible_content?).to eq(true) + end end - describe 'when there are branches' do - it 'returns true' do - expect(repository.raw_repository).to receive(:branch_count).and_return(3) + context 'when false' do + let(:result) { false } - expect(subject).to eq(true) + it 'returns false and caches it' do + expect(repository.has_visible_content?).to eq(false) + # Second call hits the cache + expect(repository.has_visible_content?).to eq(false) end end end @@ -1262,6 +1256,7 @@ describe Repository, models: true do allow(repository).to receive(:empty?).and_return(true) expect(cache).to receive(:expire).with(:empty?) + expect(cache).to receive(:expire).with(:has_visible_content?) repository.expire_emptiness_caches end @@ -1270,6 +1265,7 @@ describe Repository, models: true do allow(repository).to receive(:empty?).and_return(false) expect(cache).not_to receive(:expire).with(:empty?) + expect(cache).not_to receive(:expire).with(:has_visible_content?) repository.expire_emptiness_caches end @@ -1308,6 +1304,34 @@ describe Repository, models: true do end end + describe '#ff_merge' do + before do + repository.add_branch(user, 'ff-target', 'feature~5') + end + + it 'merges the code and return the commit id' do + merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'ff-target', source_project: project) + merge_commit_id = repository.ff_merge(user, + merge_request.diff_head_sha, + merge_request.target_branch, + merge_request: merge_request) + merge_commit = repository.commit(merge_commit_id) + + expect(merge_commit).to be_present + expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present + end + + it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do + merge_request = create(:merge_request, source_branch: 'feature', target_branch: 'ff-target', source_project: project) + merge_commit_id = repository.ff_merge(user, + merge_request.diff_head_sha, + merge_request.target_branch, + merge_request: merge_request) + + expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id) + end + end + describe '#revert' do let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') } let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') } @@ -1599,7 +1623,7 @@ describe Repository, models: true do describe '#expire_branches_cache' do it 'expires the cache' do expect(repository).to receive(:expire_method_caches) - .with(%i(branch_names branch_count)) + .with(%i(branch_names branch_count has_visible_content?)) .and_call_original repository.expire_branches_cache @@ -1617,27 +1641,41 @@ describe Repository, models: true do end describe '#add_tag' do - context 'with a valid target' do - let(:user) { build_stubbed(:user) } + let(:user) { build_stubbed(:user) } - it 'creates the tag using rugged' do - expect(repository.rugged.tags).to receive(:create) - .with('8.5', repository.commit('master').id, - hash_including(message: 'foo', - tagger: hash_including(name: user.name, email: user.email))) - .and_call_original + shared_examples 'adding tag' do + context 'with a valid target' do + it 'creates the tag' do + repository.add_tag(user, '8.5', 'master', 'foo') - repository.add_tag(user, '8.5', 'master', 'foo') - end + tag = repository.find_tag('8.5') + expect(tag).to be_present + expect(tag.message).to eq('foo') + expect(tag.dereferenced_target.id).to eq(repository.commit('master').id) + end - it 'returns a Gitlab::Git::Tag object' do - tag = repository.add_tag(user, '8.5', 'master', 'foo') + it 'returns a Gitlab::Git::Tag object' do + tag = repository.add_tag(user, '8.5', 'master', 'foo') + + expect(tag).to be_a(Gitlab::Git::Tag) + end + end - expect(tag).to be_a(Gitlab::Git::Tag) + context 'with an invalid target' do + it 'returns false' do + expect(repository.add_tag(user, '8.5', 'bar', 'foo')).to be false + end end + end + + context 'when Gitaly operation_user_add_tag feature is enabled' do + it_behaves_like 'adding tag' + end + + context 'when Gitaly operation_user_add_tag feature is disabled', skip_gitaly_mock: true do + it_behaves_like 'adding tag' - it 'passes commit SHA to pre-receive and update hooks,\ - and tag SHA to post-receive hook' do + it 'passes commit SHA to pre-receive and update hooks and tag SHA to post-receive hook' do pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', project) update_hook = Gitlab::Git::Hook.new('update', project) post_receive_hook = Gitlab::Git::Hook.new('post-receive', project) @@ -1655,39 +1693,105 @@ describe Repository, models: true do tag_sha = tag.target expect(pre_receive_hook).to have_received(:trigger) - .with(anything, anything, commit_sha, anything) + .with(anything, anything, anything, commit_sha, anything) expect(update_hook).to have_received(:trigger) - .with(anything, anything, commit_sha, anything) + .with(anything, anything, anything, commit_sha, anything) expect(post_receive_hook).to have_received(:trigger) - .with(anything, anything, tag_sha, anything) + .with(anything, anything, anything, tag_sha, anything) end end + end - context 'with an invalid target' do - it 'returns false' do - expect(repository.add_tag(user, '8.5', 'bar', 'foo')).to be false + describe '#rm_branch' do + shared_examples "user deleting a branch" do + it 'removes a branch' do + expect(repository).to receive(:before_remove_branch) + expect(repository).to receive(:after_remove_branch) + + repository.rm_branch(user, 'feature') end end - end - describe '#rm_branch' do - let(:user) { create(:user) } + context 'with gitaly enabled' do + it_behaves_like "user deleting a branch" - it 'removes a branch' do - expect(repository).to receive(:before_remove_branch) - expect(repository).to receive(:after_remove_branch) + context 'when pre hooks failed' do + before do + allow_any_instance_of(Gitlab::GitalyClient::OperationService) + .to receive(:user_delete_branch).and_raise(Gitlab::Git::HooksService::PreReceiveError) + end - repository.rm_branch(user, 'feature') + it 'gets an error and does not delete the branch' do + expect do + repository.rm_branch(user, 'feature') + end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + + expect(repository.find_branch('feature')).not_to be_nil + end + end + end + + context 'with gitaly disabled', skip_gitaly_mock: true do + it_behaves_like "user deleting a branch" + + let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature + let(:blank_sha) { '0000000000000000000000000000000000000000' } + + context 'when pre hooks were successful' do + it 'runs without errors' do + expect_any_instance_of(Gitlab::Git::HooksService).to receive(:execute) + .with(git_user, repository.raw_repository, old_rev, blank_sha, 'refs/heads/feature') + + expect { repository.rm_branch(user, 'feature') }.not_to raise_error + end + + it 'deletes the branch' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + + expect { repository.rm_branch(user, 'feature') }.not_to raise_error + + expect(repository.find_branch('feature')).to be_nil + end + end + + context 'when pre hooks failed' do + it 'gets an error' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + + expect do + repository.rm_branch(user, 'feature') + end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end + + it 'does not delete the branch' do + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) + + expect do + repository.rm_branch(user, 'feature') + end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + expect(repository.find_branch('feature')).not_to be_nil + end + end end end describe '#rm_tag' do - it 'removes a tag' do - expect(repository).to receive(:before_remove_tag) + shared_examples 'removing tag' do + it 'removes a tag' do + expect(repository).to receive(:before_remove_tag) - repository.rm_tag(create(:user), 'v1.1.0') + repository.rm_tag(build_stubbed(:user), 'v1.1.0') - expect(repository.find_tag('v1.1.0')).to be_nil + expect(repository.find_tag('v1.1.0')).to be_nil + end + end + + context 'when Gitaly operation_user_delete_tag feature is enabled' do + it_behaves_like 'removing tag' + end + + context 'when Gitaly operation_user_delete_tag feature is disabled', skip_gitaly_mock: true do + it_behaves_like 'removing tag' end end @@ -1860,6 +1964,15 @@ describe Repository, models: true do repository.expire_all_method_caches end + + it 'all cache_method definitions are in the lists of method caches' do + methods = repository.methods.map do |method| + match = /^_uncached_(.*)/.match(method) + match[1].to_sym if match + end.compact + + expect(methods).to match_array(Repository::CACHED_METHODS + Repository::MEMOIZED_CACHED_METHODS) + end end describe '#file_on_head' do diff --git a/spec/models/user_custom_attribute_spec.rb b/spec/models/user_custom_attribute_spec.rb new file mode 100644 index 00000000000..37fc3cb64f0 --- /dev/null +++ b/spec/models/user_custom_attribute_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe UserCustomAttribute do + describe 'assocations' do + it { is_expected.to belong_to(:user) } + end + + describe 'validations' do + subject { build :user_custom_attribute } + + it { is_expected.to validate_presence_of(:user_id) } + it { is_expected.to validate_presence_of(:key) } + it { is_expected.to validate_presence_of(:value) } + it { is_expected.to validate_uniqueness_of(:key).scoped_to(:user_id) } + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9ed155b0fa0..e0ac8483189 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -39,6 +39,7 @@ describe User do it { is_expected.to have_many(:chat_names).dependent(:destroy) } it { is_expected.to have_many(:uploads).dependent(:destroy) } it { is_expected.to have_many(:reported_abuse_reports).dependent(:destroy).class_name('AbuseReport') } + it { is_expected.to have_many(:custom_attributes).class_name('UserCustomAttribute') } describe "#abuse_report" do let(:current_user) { create(:user) } diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 9ef8d117123..1f14d06997e 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -80,7 +80,7 @@ describe WikiPage do context "when initialized with an existing gollum page" do before do create_page("test page", "test content") - @page = wiki.wiki.paged("test page") + @page = wiki.wiki.page(title: "test page") @wiki_page = described_class.new(wiki, @page, true) end @@ -105,7 +105,7 @@ describe WikiPage do end it "sets the version attribute" do - expect(@wiki_page.version).to be_a Gollum::Git::Commit + expect(@wiki_page.version).to be_a Gitlab::Git::WikiPageVersion end end end @@ -321,14 +321,14 @@ describe WikiPage do end it 'returns true when requesting an old version' do - old_version = @page.versions.last.to_s + old_version = @page.versions.last.id old_page = wiki.find_page('Update', old_version) expect(old_page.historical?).to eq true end it 'returns false when requesting latest version' do - latest_version = @page.versions.first.to_s + latest_version = @page.versions.first.id latest_page = wiki.find_page('Update', latest_version) expect(latest_page.historical?).to eq false @@ -393,7 +393,7 @@ describe WikiPage do end def commit_details - { name: user.name, email: user.email, message: "test commit" } + Gitlab::Git::Wiki::CommitDetails.new(user.name, user.email, "test commit") end def create_page(name, content) @@ -401,8 +401,8 @@ describe WikiPage do end def destroy_page(title) - page = wiki.wiki.paged(title) - wiki.wiki.delete_page(page, commit_details) + page = wiki.wiki.page(title: title) + wiki.delete_page(page, commit_details) end def get_slugs(page_or_dir) |