summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-10-05 12:48:22 +0200
committerDouwe Maan <douwe@selenight.nl>2017-10-05 12:48:22 +0200
commit0c0c2ecd99cd5c4cb22a0c045f8d45d315203832 (patch)
tree3900ccdcdff0cd6b8e3ed281ba57a317b801ad08 /spec/models
parented3c25e4294bfc75f7167ed63e30561e39ac3a97 (diff)
parentde01353b166018a43ea92b38054b1267c3ba5cea (diff)
downloadgitlab-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.rb2
-rw-r--r--spec/models/ci/runner_spec.rb69
-rw-r--r--spec/models/gpg_key_spec.rb8
-rw-r--r--spec/models/key_spec.rb10
-rw-r--r--spec/models/merge_request_spec.rb43
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb2
-rw-r--r--spec/models/project_spec.rb107
-rw-r--r--spec/models/project_wiki_spec.rb64
-rw-r--r--spec/models/repository_spec.rb343
-rw-r--r--spec/models/user_custom_attribute_spec.rb16
-rw-r--r--spec/models/user_spec.rb1
-rw-r--r--spec/models/wiki_page_spec.rb14
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)