diff options
author | Pawel Chojnacki <pawel@chojnacki.ws> | 2018-01-29 19:49:23 +0100 |
---|---|---|
committer | Pawel Chojnacki <pawel@chojnacki.ws> | 2018-01-29 19:49:23 +0100 |
commit | f87afeff18337fa6205ee65710033b33a7c5aa66 (patch) | |
tree | 8c583c5c97d882767f9fc126a7e9d6fa76160ec1 /spec/lib | |
parent | 4b1d42bbc583b0884498bd129653587acc69ab0f (diff) | |
parent | 44edd1111f9ba6dd0dacffad23b54c0c85a723c4 (diff) | |
download | gitlab-ce-f87afeff18337fa6205ee65710033b33a7c5aa66.tar.gz |
Merge remote-tracking branch 'upstream/master' into pawel/connect_to_prometheus_through_proxy-30480
Diffstat (limited to 'spec/lib')
34 files changed, 913 insertions, 104 deletions
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb index 7e17457ce70..3ca4652f7cc 100644 --- a/spec/lib/banzai/filter/relative_link_filter_spec.rb +++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb @@ -278,18 +278,19 @@ describe Banzai::Filter::RelativeLinkFilter do expect(doc.at_css('a')['href']).to eq 'http://example.com' end - it 'supports Unicode filenames' do + it 'supports unescaped Unicode filenames' do path = '/uploads/한글.png' - escaped = Addressable::URI.escape(path) + doc = filter(link(path)) - # Stub these methods so the file doesn't actually need to be in the repo - allow_any_instance_of(described_class) - .to receive(:file_exists?).and_return(true) - allow_any_instance_of(described_class) - .to receive(:image?).with(path).and_return(true) + expect(doc.at_css('a')['href']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") + end + it 'supports escaped Unicode filenames' do + path = '/uploads/한글.png' + escaped = Addressable::URI.escape(path) doc = filter(image(escaped)) - expect(doc.at_css('img')['src']).to match "/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png" + + expect(doc.at_css('img')['src']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index a6fbec295b5..cc202ce8bca 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -136,8 +136,8 @@ describe Gitlab::Auth do it 'grants deploy key write permissions' do project = create(:project) - key = create(:deploy_key, can_push: true) - create(:deploy_keys_project, deploy_key: key, project: project) + key = create(:deploy_key) + create(:deploy_keys_project, :write_access, deploy_key: key, project: project) token = Gitlab::LfsToken.new(key).token expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") @@ -146,7 +146,7 @@ describe Gitlab::Auth do it 'does not grant deploy key write permissions' do project = create(:project) - key = create(:deploy_key, can_push: true) + key = create(:deploy_key) token = Gitlab::LfsToken.new(key).token expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb index d21183b668b..c8df6dd2118 100644 --- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb +++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :truncate, :migration, schema: 20171114162227 do +describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :migration, schema: 20171114162227 do let(:merge_request_diffs) { table(:merge_request_diffs) } let(:merge_requests) { table(:merge_requests) } diff --git a/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb b/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb index 7b5a00c6111..021e1d14b18 100644 --- a/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_system_uploads_to_new_folder_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder do +describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder, :delete do let(:migration) { described_class.new } before do @@ -8,7 +8,7 @@ describe Gitlab::BackgroundMigration::MigrateSystemUploadsToNewFolder do end describe '#perform' do - it 'renames the path of system-uploads', :truncate do + it 'renames the path of system-uploads' do upload = create(:upload, model: create(:project), path: 'uploads/system/project/avatar.jpg') migration.perform('uploads/system/', 'uploads/-/system/') diff --git a/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb b/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb index e99257e3481..4cdb679c97f 100644 --- a/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb +++ b/spec/lib/gitlab/background_migration/populate_merge_request_metrics_with_events_data_spec.rb @@ -7,6 +7,10 @@ describe Gitlab::BackgroundMigration::PopulateMergeRequestMetricsWithEventsData, .to receive(:commits_count=).and_return(nil) end + after do + [MergeRequest, MergeRequestDiff].each(&:reset_column_information) + end + describe '#perform' do let(:mr_with_event) { create(:merge_request) } let!(:merged_event) { create(:event, :merged, target: mr_with_event) } diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb index 05e2d94cbd6..7549e9941b6 100644 --- a/spec/lib/gitlab/ci/ansi2html_spec.rb +++ b/spec/lib/gitlab/ci/ansi2html_spec.rb @@ -217,11 +217,58 @@ describe Gitlab::Ci::Ansi2html do "#{section_end[0...-5]}</div>" end - it "prints light red" do - text = "#{section_start}\e[91mHello\e[0m\n#{section_end}" - html = %{#{section_start_html}<span class="term-fg-l-red">Hello</span><br>#{section_end_html}} + shared_examples 'forbidden char in section_name' do + it 'ignores sections' do + text = "#{section_start}Some text#{section_end}" + html = text.gsub("\033[0K", '').gsub('<', '<') - expect(convert_html(text)).to eq(html) + expect(convert_html(text)).to eq(html) + end + end + + shared_examples 'a legit section' do + let(:text) { "#{section_start}Some text#{section_end}" } + + it 'prints light red' do + text = "#{section_start}\e[91mHello\e[0m\n#{section_end}" + html = %{#{section_start_html}<span class="term-fg-l-red">Hello</span><br>#{section_end_html}} + + expect(convert_html(text)).to eq(html) + end + + it 'begins with a section_start html marker' do + expect(convert_html(text)).to start_with(section_start_html) + end + + it 'ends with a section_end html marker' do + expect(convert_html(text)).to end_with(section_end_html) + end + end + + it_behaves_like 'a legit section' + + context 'section name includes $' do + let(:section_name) { 'my_$ection'} + + it_behaves_like 'forbidden char in section_name' + end + + context 'section name includes <' do + let(:section_name) { '<a_tag>'} + + it_behaves_like 'forbidden char in section_name' + end + + context 'section name contains .-_' do + let(:section_name) { 'a.Legit-SeCtIoN_namE' } + + it_behaves_like 'a legit section' + end + + it 'do not allow XSS injections' do + text = "#{section_start}section_end:1:2<script>alert('XSS Hack!');</script>#{section_end}" + + expect(convert_html(text)).not_to include('<script>') end end diff --git a/spec/lib/gitlab/ci/config/entry/key_spec.rb b/spec/lib/gitlab/ci/config/entry/key_spec.rb index 5d4de60bc8a..3cbf19bea8b 100644 --- a/spec/lib/gitlab/ci/config/entry/key_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/key_spec.rb @@ -4,6 +4,26 @@ describe Gitlab::Ci::Config::Entry::Key do let(:entry) { described_class.new(config) } describe 'validations' do + shared_examples 'key with slash' do + it 'is invalid' do + expect(entry).not_to be_valid + end + + it 'reports errors with config value' do + expect(entry.errors).to include 'key config cannot contain the "/" character' + end + end + + shared_examples 'key with only dots' do + it 'is invalid' do + expect(entry).not_to be_valid + end + + it 'reports errors with config value' do + expect(entry.errors).to include 'key config cannot be "." or ".."' + end + end + context 'when entry config value is correct' do let(:config) { 'test' } @@ -30,6 +50,48 @@ describe Gitlab::Ci::Config::Entry::Key do end end end + + context 'when entry value contains slash' do + let(:config) { 'key/with/some/slashes' } + + it_behaves_like 'key with slash' + end + + context 'when entry value contains URI encoded slash (%2F)' do + let(:config) { 'key%2Fwith%2Fsome%2Fslashes' } + + it_behaves_like 'key with slash' + end + + context 'when entry value is a dot' do + let(:config) { '.' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is two dots' do + let(:config) { '..' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is a URI encoded dot (%2E)' do + let(:config) { '%2e' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is two URI encoded dots (%2E)' do + let(:config) { '%2E%2e' } + + it_behaves_like 'key with only dots' + end + + context 'when entry value is one dot and one URI encoded dot' do + let(:config) { '.%2e' } + + it_behaves_like 'key with only dots' + end end describe '.default' do diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 43761c2fe0c..1de3a14b809 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -1038,7 +1038,7 @@ describe Gitlab::Database::MigrationHelpers do end describe '#change_column_type_using_background_migration' do - let!(:issue) { create(:issue) } + let!(:issue) { create(:issue, :closed, closed_at: Time.zone.now) } let(:issue_model) do Class.new(ActiveRecord::Base) do diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb index 596cc435bd9..cc7cb3f23fd 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :truncate do +describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb index 1143182531f..f31475dbd71 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces, :truncate do +describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces, :delete do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } let(:namespace) { create(:group, name: 'the-path') } diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb index e850b5cd6a4..0958144643b 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProjects, :truncate do +describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProjects, :delete do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } let(:project) do diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1_spec.rb index 7695b95dc57..1d31f96159c 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1_spec.rb @@ -13,7 +13,7 @@ shared_examples 'renames child namespaces' do |type| end end -describe Gitlab::Database::RenameReservedPathsMigration::V1, :truncate do +describe Gitlab::Database::RenameReservedPathsMigration::V1, :delete do let(:subject) { FakeRenameReservedPathMigrationV1.new } before do diff --git a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb new file mode 100644 index 00000000000..5d22dcfb508 --- /dev/null +++ b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Gitlab::Git::AttributesAtRefParser, seed_helper: true do + let(:project) { create(:project, :repository) } + let(:repository) { project.repository } + + subject { described_class.new(repository, 'lfs') } + + it 'loads .gitattributes blob' do + repository.raw # Initialize repository in advance since this also checks attributes + + expected_filter = 'filter=lfs diff=lfs merge=lfs' + receive_blob = receive(:new).with(a_string_including(expected_filter)) + expect(Gitlab::Git::AttributesParser).to receive_blob.and_call_original + + subject + end + + it 'handles missing blobs' do + expect { described_class.new(repository, 'non-existant-branch') }.not_to raise_error + end + + describe '#attributes' do + it 'returns the attributes as a Hash' do + expect(subject.attributes('test.lfs')['filter']).to eq('lfs') + end + end +end diff --git a/spec/lib/gitlab/git/attributes_spec.rb b/spec/lib/gitlab/git/attributes_parser_spec.rb index b715fc3410a..323334e99a5 100644 --- a/spec/lib/gitlab/git/attributes_spec.rb +++ b/spec/lib/gitlab/git/attributes_parser_spec.rb @@ -1,11 +1,10 @@ require 'spec_helper' -describe Gitlab::Git::Attributes, seed_helper: true do - let(:path) do - File.join(SEED_STORAGE_PATH, 'with-git-attributes.git') - end +describe Gitlab::Git::AttributesParser, seed_helper: true do + let(:attributes_path) { File.join(SEED_STORAGE_PATH, 'with-git-attributes.git', 'info', 'attributes') } + let(:data) { File.read(attributes_path) } - subject { described_class.new(path) } + subject { described_class.new(data) } describe '#attributes' do context 'using a path with attributes' do @@ -66,6 +65,26 @@ describe Gitlab::Git::Attributes, seed_helper: true do expect(subject.attributes('test.foo')).to eq({}) end end + + context 'when attributes data is a file handle' do + subject do + File.open(attributes_path, 'r') do |file_handle| + described_class.new(file_handle) + end + end + + it 'returns the attributes as a Hash' do + expect(subject.attributes('test.txt')).to eq({ 'text' => true }) + end + end + + context 'when attributes data is nil' do + let(:data) { nil } + + it 'returns an empty Hash' do + expect(subject.attributes('test.foo')).to eq({}) + end + end end describe '#patterns' do @@ -74,14 +93,14 @@ describe Gitlab::Git::Attributes, seed_helper: true do end it 'parses an entry that uses a tab to separate the pattern and attributes' do - expect(subject.patterns[File.join(path, '*.md')]) + expect(subject.patterns[File.join('/', '*.md')]) .to eq({ 'gitlab-language' => 'markdown' }) end it 'stores patterns in reverse order' do first = subject.patterns.to_a[0] - expect(first[0]).to eq(File.join(path, 'bla/bla.txt')) + expect(first[0]).to eq(File.join('/', 'bla/bla.txt')) end # It's a bit hard to test for something _not_ being processed. As such we'll @@ -89,14 +108,6 @@ describe Gitlab::Git::Attributes, seed_helper: true do it 'ignores any comments and empty lines' do expect(subject.patterns.length).to eq(10) end - - it 'does not parse anything when the attributes file does not exist' do - expect(File).to receive(:exist?) - .with(File.join(path, 'info/attributes')) - .and_return(false) - - expect(subject.patterns).to eq({}) - end end describe '#parse_attributes' do @@ -132,17 +143,9 @@ describe Gitlab::Git::Attributes, seed_helper: true do expect { |b| subject.each_line(&b) }.to yield_successive_args(*args) end - it 'does not yield when the attributes file does not exist' do - expect(File).to receive(:exist?) - .with(File.join(path, 'info/attributes')) - .and_return(false) - - expect { |b| subject.each_line(&b) }.not_to yield_control - end - it 'does not yield when the attributes file has an unsupported encoding' do - path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git') - attrs = described_class.new(path) + path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git', 'info', 'attributes') + attrs = described_class.new(File.read(path)) expect { |b| attrs.each_line(&b) }.not_to yield_control end diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb index 07eb5b82d5f..8ac960133c5 100644 --- a/spec/lib/gitlab/git/blob_spec.rb +++ b/spec/lib/gitlab/git/blob_spec.rb @@ -16,6 +16,18 @@ describe Gitlab::Git::Blob, seed_helper: true do end shared_examples 'finding blobs' do + context 'nil path' do + let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, nil) } + + it { expect(blob).to eq(nil) } + end + + context 'blank path' do + let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, '') } + + it { expect(blob).to eq(nil) } + end + context 'file in subdir' do let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "files/ruby/popen.rb") } @@ -248,29 +260,57 @@ describe Gitlab::Git::Blob, seed_helper: true do ) end - it 'returns a list of Gitlab::Git::Blob' do - blobs = described_class.batch_lfs_pointers(repository, [lfs_blob.id]) + shared_examples 'fetching batch of LFS pointers' do + it 'returns a list of Gitlab::Git::Blob' do + blobs = described_class.batch_lfs_pointers(repository, [lfs_blob.id]) - expect(blobs.count).to eq(1) - expect(blobs).to all( be_a(Gitlab::Git::Blob) ) - end + expect(blobs.count).to eq(1) + expect(blobs).to all( be_a(Gitlab::Git::Blob) ) + end - it 'silently ignores tree objects' do - blobs = described_class.batch_lfs_pointers(repository, [tree_object.oid]) + it 'accepts blob IDs as a lazy enumerator' do + blobs = described_class.batch_lfs_pointers(repository, [lfs_blob.id].lazy) - expect(blobs).to eq([]) - end + expect(blobs.count).to eq(1) + expect(blobs).to all( be_a(Gitlab::Git::Blob) ) + end + + it 'handles empty list of IDs gracefully' do + blobs_1 = described_class.batch_lfs_pointers(repository, [].lazy) + blobs_2 = described_class.batch_lfs_pointers(repository, []) - it 'silently ignores non lfs objects' do - blobs = described_class.batch_lfs_pointers(repository, [non_lfs_blob.id]) + expect(blobs_1).to eq([]) + expect(blobs_2).to eq([]) + end + + it 'silently ignores tree objects' do + blobs = described_class.batch_lfs_pointers(repository, [tree_object.oid]) + + expect(blobs).to eq([]) + end + + it 'silently ignores non lfs objects' do + blobs = described_class.batch_lfs_pointers(repository, [non_lfs_blob.id]) - expect(blobs).to eq([]) + expect(blobs).to eq([]) + end + + it 'avoids loading large blobs into memory' do + # This line could call `lookup` on `repository`, so do here before mocking. + non_lfs_blob_id = non_lfs_blob.id + + expect(repository).not_to receive(:lookup) + + described_class.batch_lfs_pointers(repository, [non_lfs_blob_id]) + end end - it 'avoids loading large blobs into memory' do - expect(repository).not_to receive(:lookup) + context 'when Gitaly batch_lfs_pointers is enabled' do + it_behaves_like 'fetching batch of LFS pointers' + end - described_class.batch_lfs_pointers(repository, [non_lfs_blob.id]) + context 'when Gitaly batch_lfs_pointers is disabled', :disable_gitaly do + it_behaves_like 'fetching batch of LFS pointers' end end diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb index 6a07a3ca8b8..85e6efd7ca2 100644 --- a/spec/lib/gitlab/git/commit_spec.rb +++ b/spec/lib/gitlab/git/commit_spec.rb @@ -388,6 +388,84 @@ describe Gitlab::Git::Commit, seed_helper: true do end end end + + describe '.extract_signature' do + subject { described_class.extract_signature(repository, commit_id) } + + shared_examples '.extract_signature' do + context 'when the commit is signed' do + let(:commit_id) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } + + it 'returns signature and signed text' do + signature, signed_text = subject + + expected_signature = <<~SIGNATURE + -----BEGIN PGP SIGNATURE----- + Version: GnuPG/MacGPG2 v2.0.22 (Darwin) + Comment: GPGTools - https://gpgtools.org + + iQEcBAABCgAGBQJTDvaZAAoJEGJ8X1ifRn8XfvYIAMuB0yrbTGo1BnOSoDfyrjb0 + Kw2EyUzvXYL72B63HMdJ+/0tlSDC6zONF3fc+bBD8z+WjQMTbwFNMRbSSy2rKEh+ + mdRybOP3xBIMGgEph0/kmWln39nmFQBsPRbZBWoU10VfI/ieJdEOgOphszgryRar + TyS73dLBGE9y9NIININVaNISet9D9QeXFqc761CGjh4YIghvPpi+YihMWapGka6v + hgKhX+hc5rj+7IEE0CXmlbYR8OYvAbAArc5vJD7UTxAY4Z7/l9d6Ydt9GQ25khfy + ANFgltYzlR6evLFmDjssiP/mx/ZMN91AL0ueJ9nNGv411Mu2CUW+tDCaQf35mdc= + =j51i + -----END PGP SIGNATURE----- + SIGNATURE + + expect(signature).to eq(expected_signature.chomp) + expect(signature).to be_a_binary_string + + expected_signed_text = <<~SIGNED_TEXT + tree 22bfa2fbd217df24731f43ff43a4a0f8db759dae + parent ae73cb07c9eeaf35924a10f713b364d32b2dd34f + author Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200 + committer Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200 + + Feature added + + Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> + SIGNED_TEXT + + expect(signed_text).to eq(expected_signed_text) + expect(signed_text).to be_a_binary_string + end + end + + context 'when the commit has no signature' do + let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' } + + it 'returns nil' do + expect(subject).to be_nil + end + end + + context 'when the commit cannot be found' do + let(:commit_id) { Gitlab::Git::BLANK_SHA } + + it 'returns nil' do + expect(subject).to be_nil + end + end + + context 'when the commit ID is invalid' do + let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e' } + + it 'raises ArgumentError' do + expect { subject }.to raise_error(ArgumentError) + end + end + end + + context 'with gitaly' do + it_behaves_like '.extract_signature' + end + + context 'without gitaly', :skip_gitaly_mock do + it_behaves_like '.extract_signature' + end + end end describe '#init_from_rugged' do diff --git a/spec/lib/gitlab/git/gitlab_projects_spec.rb b/spec/lib/gitlab/git/gitlab_projects_spec.rb index 78e4fbca28e..f4b964e1ee9 100644 --- a/spec/lib/gitlab/git/gitlab_projects_spec.rb +++ b/spec/lib/gitlab/git/gitlab_projects_spec.rb @@ -219,6 +219,9 @@ describe Gitlab::Git::GitlabProjects do before do FileUtils.mkdir_p(dest_repos_path) + + # Undo spec_helper stub that deletes hooks + allow_any_instance_of(described_class).to receive(:fork_repository).and_call_original end after do diff --git a/spec/lib/gitlab/git/info_attributes_spec.rb b/spec/lib/gitlab/git/info_attributes_spec.rb new file mode 100644 index 00000000000..ea84909c3e0 --- /dev/null +++ b/spec/lib/gitlab/git/info_attributes_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +describe Gitlab::Git::InfoAttributes, seed_helper: true do + let(:path) do + File.join(SEED_STORAGE_PATH, 'with-git-attributes.git') + end + + subject { described_class.new(path) } + + describe '#attributes' do + context 'using a path with attributes' do + it 'returns the attributes as a Hash' do + expect(subject.attributes('test.txt')).to eq({ 'text' => true }) + end + + it 'returns an empty Hash for a defined path without attributes' do + expect(subject.attributes('bla/bla.txt')).to eq({}) + end + end + end + + describe '#parser' do + it 'parses a file with entries' do + expect(subject.patterns).to be_an_instance_of(Hash) + expect(subject.patterns["/*.txt"]).to eq({ 'text' => true }) + end + + it 'does not parse anything when the attributes file does not exist' do + expect(File).to receive(:exist?) + .with(File.join(path, 'info/attributes')) + .and_return(false) + + expect(subject.patterns).to eq({}) + end + + it 'does not parse attributes files with unsupported encoding' do + path = File.join(SEED_STORAGE_PATH, 'with-invalid-git-attributes.git') + subject = described_class.new(path) + + expect(subject.patterns).to eq({}) + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 3cf165716bd..935d1df6dad 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -981,6 +981,16 @@ describe Gitlab::Git::Repository, seed_helper: true do end end end + + context 'limit validation' do + where(:limit) do + [0, nil, '', 'foo'] + end + + with_them do + it { expect { repository.log(limit: limit) }.to raise_error(ArgumentError) } + end + end end describe "#rugged_commits_between" do @@ -1964,6 +1974,75 @@ describe Gitlab::Git::Repository, seed_helper: true do it { expect(subject.repository_relative_path).to eq(repository.relative_path) } end + describe '#bundle_to_disk' do + shared_examples 'bundling to disk' do + let(:save_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") } + + after do + FileUtils.rm_rf(save_path) + end + + it 'saves a bundle to disk' do + repository.bundle_to_disk(save_path) + + success = system( + *%W(#{Gitlab.config.git.bin_path} -C #{repository.path} bundle verify #{save_path}), + [:out, :err] => '/dev/null' + ) + expect(success).to be true + end + end + + context 'when Gitaly bundle_to_disk feature is enabled' do + it_behaves_like 'bundling to disk' + end + + context 'when Gitaly bundle_to_disk feature is disabled', :disable_gitaly do + it_behaves_like 'bundling to disk' + end + end + + describe '#create_from_bundle' do + shared_examples 'creating repo from bundle' do + let(:bundle_path) { File.join(Dir.tmpdir, "repo-#{SecureRandom.hex}.bundle") } + let(:project) { create(:project) } + let(:imported_repo) { project.repository.raw } + + before do + expect(repository.bundle_to_disk(bundle_path)).to be true + end + + after do + FileUtils.rm_rf(bundle_path) + end + + it 'creates a repo from a bundle file' do + expect(imported_repo).not_to exist + + result = imported_repo.create_from_bundle(bundle_path) + + expect(result).to be true + expect(imported_repo).to exist + expect { imported_repo.fsck }.not_to raise_exception + end + + it 'creates a symlink to the global hooks dir' do + imported_repo.create_from_bundle(bundle_path) + hooks_path = File.join(imported_repo.path, 'hooks') + + expect(File.readlink(hooks_path)).to eq(Gitlab.config.gitlab_shell.hooks_path) + end + end + + context 'when Gitaly create_repo_from_bundle feature is enabled' do + it_behaves_like 'creating repo from bundle' + end + + context 'when Gitaly create_repo_from_bundle feature is disabled', :disable_gitaly do + it_behaves_like 'creating repo from bundle' + end + end + context 'gitlab_projects commands' do let(:gitlab_projects) { repository.gitlab_projects } let(:timeout) { Gitlab.config.gitlab_shell.git_timeout } diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 4290fbb0087..2009a8ac48c 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -51,12 +51,12 @@ describe Gitlab::GitAccess do context 'when the project exists' do context 'when actor exists' do context 'when actor is a DeployKey' do - let(:deploy_key) { create(:deploy_key, user: user, can_push: true) } + let(:deploy_key) { create(:deploy_key, user: user) } let(:actor) { deploy_key } context 'when the DeployKey has access to the project' do before do - deploy_key.projects << project + deploy_key.deploy_keys_projects.create(project: project, can_push: true) end it 'allows push and pull access' do @@ -696,15 +696,13 @@ describe Gitlab::GitAccess do end describe 'deploy key permissions' do - let(:key) { create(:deploy_key, user: user, can_push: can_push) } + let(:key) { create(:deploy_key, user: user) } let(:actor) { key } context 'when deploy_key can push' do - let(:can_push) { true } - context 'when project is authorized' do before do - key.projects << project + key.deploy_keys_projects.create(project: project, can_push: true) end it { expect { push_access_check }.not_to raise_error } @@ -732,11 +730,9 @@ describe Gitlab::GitAccess do end context 'when deploy_key cannot push' do - let(:can_push) { false } - context 'when project is authorized' do before do - key.projects << project + key.deploy_keys_projects.create(project: project, can_push: false) end it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) } diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb index b2275119a04..3722a91c050 100644 --- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb @@ -131,6 +131,29 @@ describe Gitlab::GitalyClient::CommitService do end end + describe '#commit_count' do + before do + expect_any_instance_of(Gitaly::CommitService::Stub) + .to receive(:count_commits) + .with(gitaly_request_with_path(storage_name, relative_path), + kind_of(Hash)) + .and_return([]) + end + + it 'sends a commit_count message' do + client.commit_count(revision) + end + + context 'with UTF-8 params strings' do + let(:revision) { "branch\u011F" } + let(:path) { "foo/\u011F.txt" } + + it 'handles string encodings correctly' do + client.commit_count(revision, path: path) + end + end + end + describe '#find_commit' do let(:revision) { '4b825dc642cb6eb9a060e54bf8d69288fbee4904' } it 'sends an RPC request' do diff --git a/spec/lib/gitlab/gitaly_client/health_check_service_spec.rb b/spec/lib/gitlab/gitaly_client/health_check_service_spec.rb new file mode 100644 index 00000000000..2c7e5eb5787 --- /dev/null +++ b/spec/lib/gitlab/gitaly_client/health_check_service_spec.rb @@ -0,0 +1,41 @@ +require 'spec_helper' + +describe Gitlab::GitalyClient::HealthCheckService do + let(:project) { create(:project) } + let(:storage_name) { project.repository_storage } + + subject { described_class.new(storage_name) } + + describe '#check' do + it 'successfully sends a health check request' do + expect(Gitlab::GitalyClient).to receive(:call).with( + storage_name, + :health_check, + :check, + instance_of(Grpc::Health::V1::HealthCheckRequest), + timeout: Gitlab::GitalyClient.fast_timeout).and_call_original + + expect(subject.check).to eq({ success: true }) + end + + it 'receives an unsuccessful health check request' do + expect_any_instance_of(Grpc::Health::V1::Health::Stub) + .to receive(:check) + .and_return(double(status: false)) + + expect(subject.check).to eq({ success: false }) + end + + it 'gracefully handles gRPC error' do + expect(Gitlab::GitalyClient).to receive(:call).with( + storage_name, + :health_check, + :check, + instance_of(Grpc::Health::V1::HealthCheckRequest), + timeout: Gitlab::GitalyClient.fast_timeout) + .and_raise(GRPC::Unavailable.new('Connection refused')) + + expect(subject.check).to eq({ success: false, message: '14:Connection refused' }) + end + end +end diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb index 9d540446532..872377c93d8 100644 --- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb @@ -44,4 +44,18 @@ describe Gitlab::GitalyClient::RemoteService do expect(client.fetch_internal_remote(remote_repository)).to be(true) end end + + describe '#update_remote_mirror' do + let(:ref_name) { 'remote_mirror_1' } + let(:only_branches_matching) { ['my-branch', 'master'] } + + it 'sends an update_remote_mirror message' do + expect_any_instance_of(Gitaly::RemoteService::Stub) + .to receive(:update_remote_mirror) + .with(kind_of(Enumerator), kind_of(Hash)) + .and_return(double(:update_remote_mirror_response)) + + client.update_remote_mirror(ref_name, only_branches_matching) + end + end end diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb index 309b7338ef0..81bcd8c28ed 100644 --- a/spec/lib/gitlab/gitaly_client_spec.rb +++ b/spec/lib/gitlab/gitaly_client_spec.rb @@ -3,6 +3,31 @@ require 'spec_helper' # We stub Gitaly in `spec/support/gitaly.rb` for other tests. We don't want # those stubs while testing the GitalyClient itself. describe Gitlab::GitalyClient, skip_gitaly_mock: true do + describe '.stub_class' do + it 'returns the gRPC health check stub' do + expect(described_class.stub_class(:health_check)).to eq(::Grpc::Health::V1::Health::Stub) + end + + it 'returns a Gitaly stub' do + expect(described_class.stub_class(:ref_service)).to eq(::Gitaly::RefService::Stub) + end + end + + describe '.stub_address' do + it 'returns the same result after being called multiple times' do + address = 'localhost:9876' + prefixed_address = "tcp://#{address}" + + allow(Gitlab.config.repositories).to receive(:storages).and_return({ + 'default' => { 'gitaly_address' => prefixed_address } + }) + + 2.times do + expect(described_class.stub_address('default')).to eq('localhost:9876') + end + end + end + describe '.stub' do # Notice that this is referring to gRPC "stubs", not rspec stubs before do diff --git a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb index d72572cd510..44695acbe7d 100644 --- a/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_requests_importer_spec.rb @@ -244,7 +244,7 @@ describe Gitlab::GithubImport::Importer::PullRequestsImporter do it 'returns true when a commit exists' do expect(project.repository) - .to receive(:lookup) + .to receive(:commit) .with('123') .and_return(double(:commit)) @@ -253,9 +253,9 @@ describe Gitlab::GithubImport::Importer::PullRequestsImporter do it 'returns false when a commit does not exist' do expect(project.repository) - .to receive(:lookup) + .to receive(:commit) .with('123') - .and_raise(Rugged::OdbError) + .and_return(nil) expect(importer.commit_exists?('123')).to eq(false) end diff --git a/spec/lib/gitlab/gpg/commit_spec.rb b/spec/lib/gitlab/gpg/commit_spec.rb index a6c99bc07d4..e3bf2801406 100644 --- a/spec/lib/gitlab/gpg/commit_spec.rb +++ b/spec/lib/gitlab/gpg/commit_spec.rb @@ -38,8 +38,8 @@ describe Gitlab::Gpg::Commit do end before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User1.signed_commit_signature, @@ -77,8 +77,8 @@ describe Gitlab::Gpg::Commit do end before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User3.signed_commit_signature, @@ -116,8 +116,8 @@ describe Gitlab::Gpg::Commit do end before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User1.signed_commit_signature, @@ -151,8 +151,8 @@ describe Gitlab::Gpg::Commit do end before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User1.signed_commit_signature, @@ -187,8 +187,8 @@ describe Gitlab::Gpg::Commit do end before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User1.signed_commit_signature, @@ -217,8 +217,8 @@ describe Gitlab::Gpg::Commit do let!(:commit) { create :commit, project: project, sha: commit_sha } before do - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return( [ GpgHelpers::User1.signed_commit_signature, diff --git a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb index d6000af0ecd..c034eccf2a6 100644 --- a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb +++ b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb @@ -26,8 +26,8 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do before do allow_any_instance_of(Project).to receive(:commit).and_return(commit) - allow(Rugged::Commit).to receive(:extract_signature) - .with(Rugged::Repository, commit_sha) + allow(Gitlab::Git::Commit).to receive(:extract_signature) + .with(Gitlab::Git::Repository, commit_sha) .and_return(signature) end diff --git a/spec/lib/gitlab/health_checks/gitaly_check_spec.rb b/spec/lib/gitlab/health_checks/gitaly_check_spec.rb new file mode 100644 index 00000000000..724beefff69 --- /dev/null +++ b/spec/lib/gitlab/health_checks/gitaly_check_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe Gitlab::HealthChecks::GitalyCheck do + let(:result_class) { Gitlab::HealthChecks::Result } + let(:repository_storages) { ['default'] } + + before do + allow(described_class).to receive(:repository_storages) { repository_storages } + end + + describe '#readiness' do + subject { described_class.readiness } + + before do + expect(Gitlab::GitalyClient::HealthCheckService).to receive(:new).and_return(gitaly_check) + end + + context 'Gitaly server is up' do + let(:gitaly_check) { double(check: { success: true }) } + + it { is_expected.to eq([result_class.new(true, nil, shard: 'default')]) } + end + + context 'Gitaly server is down' do + let(:gitaly_check) { double(check: { success: false, message: 'Connection refused' }) } + + it { is_expected.to eq([result_class.new(false, 'Connection refused', shard: 'default')]) } + end + end + + describe '#metrics' do + subject { described_class.metrics } + + before do + expect(Gitlab::GitalyClient::HealthCheckService).to receive(:new).and_return(gitaly_check) + end + + context 'Gitaly server is up' do + let(:gitaly_check) { double(check: { success: true }) } + + it 'provides metrics' do + expect(subject).to all(have_attributes(labels: { shard: 'default' })) + expect(subject).to include(an_object_having_attributes(name: 'gitaly_health_check_success', value: 1)) + expect(subject).to include(an_object_having_attributes(name: 'gitaly_health_check_latency_seconds', value: be >= 0)) + end + end + + context 'Gitaly server is down' do + let(:gitaly_check) { double(check: { success: false, message: 'Connection refused' }) } + + it 'provides metrics' do + expect(subject).to include(an_object_having_attributes(name: 'gitaly_health_check_success', value: 0)) + expect(subject).to include(an_object_having_attributes(name: 'gitaly_health_check_latency_seconds', value: be >= 0)) + end + end + end +end diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb index 162b776e107..5cdc5138fda 100644 --- a/spec/lib/gitlab/import_export/file_importer_spec.rb +++ b/spec/lib/gitlab/import_export/file_importer_spec.rb @@ -12,30 +12,61 @@ describe Gitlab::ImportExport::FileImporter do stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0) allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) allow_any_instance_of(Gitlab::ImportExport::CommandLineUtil).to receive(:untar_zxf).and_return(true) - + allow(SecureRandom).to receive(:hex).and_return('abcd') setup_files - - described_class.import(archive_file: '', shared: shared) end after do FileUtils.rm_rf(export_path) end - it 'removes symlinks in root folder' do - expect(File.exist?(symlink_file)).to be false - end + context 'normal run' do + before do + described_class.import(archive_file: '', shared: shared) + end - it 'removes hidden symlinks in root folder' do - expect(File.exist?(hidden_symlink_file)).to be false - end + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end - it 'removes symlinks in subfolders' do - expect(File.exist?(subfolder_symlink_file)).to be false + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end + + it 'creates the file in the right subfolder' do + expect(shared.export_path).to include('test/abcd') + end end - it 'does not remove a valid file' do - expect(File.exist?(valid_file)).to be true + context 'error' do + before do + allow_any_instance_of(described_class).to receive(:wait_for_archived_file).and_raise(StandardError) + described_class.import(archive_file: '', shared: shared) + end + + it 'removes symlinks in root folder' do + expect(File.exist?(symlink_file)).to be false + end + + it 'removes hidden symlinks in root folder' do + expect(File.exist?(hidden_symlink_file)).to be false + end + + it 'removes symlinks in subfolders' do + expect(File.exist?(subfolder_symlink_file)).to be false + end + + it 'does not remove a valid file' do + expect(File.exist?(valid_file)).to be true + end end def setup_files diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 4cf33778d15..b6c1f0c81cb 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -7096,7 +7096,7 @@ "project_id": 5, "created_at": "2016-06-14T15:01:51.232Z", "updated_at": "2016-06-14T15:01:51.232Z", - "active": false, + "active": true, "properties": { }, diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 08e5bbbd400..5804c45871e 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -164,6 +164,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver do expect(saved_project_json['services'].first['type']).to eq('CustomIssueTrackerService') end + it 'saves the properties for a service' do + expect(saved_project_json['services'].first['properties']).to eq('one' => 'value') + end + it 'has project feature' do project_feature = saved_project_json['project_feature'] expect(project_feature).not_to be_empty @@ -279,7 +283,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver do commit_id: ci_build.pipeline.sha) create(:event, :created, target: milestone, project: project, author: user) - create(:service, project: project, type: 'CustomIssueTrackerService', category: 'issue_tracker') + create(:service, project: project, type: 'CustomIssueTrackerService', category: 'issue_tracker', properties: { one: 'value' }) create(:project_custom_attribute, project: project) create(:project_custom_attribute, project: project) diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb new file mode 100644 index 00000000000..4a43dbb2371 --- /dev/null +++ b/spec/lib/gitlab/profiler_spec.rb @@ -0,0 +1,156 @@ +require 'spec_helper' + +describe Gitlab::Profiler do + RSpec::Matchers.define_negated_matcher :not_change, :change + + let(:null_logger) { Logger.new('/dev/null') } + let(:private_token) { 'private' } + + describe '.profile' do + let(:app) { double(:app) } + + before do + allow(ActionDispatch::Integration::Session).to receive(:new).and_return(app) + allow(app).to receive(:get) + end + + it 'returns a profile result' do + expect(described_class.profile('/')).to be_an_instance_of(RubyProf::Profile) + end + + it 'uses the custom logger given' do + expect(described_class).to receive(:create_custom_logger) + .with(null_logger, private_token: anything) + .and_call_original + + described_class.profile('/', logger: null_logger) + end + + it 'sends a POST request when data is passed' do + post_data = '{"a":1}' + + expect(app).to receive(:post).with(anything, post_data, anything) + + described_class.profile('/', post_data: post_data) + end + + it 'uses the private_token for auth if given' do + expect(app).to receive(:get).with('/', nil, 'Private-Token' => private_token) + expect(app).to receive(:get).with('/api/v4/users') + + described_class.profile('/', private_token: private_token) + end + + it 'uses the user for auth if given' do + user = double(:user) + user_token = 'user' + + allow(user).to receive_message_chain(:personal_access_tokens, :active, :pluck, :first).and_return(user_token) + + expect(app).to receive(:get).with('/', nil, 'Private-Token' => user_token) + expect(app).to receive(:get).with('/api/v4/users') + + described_class.profile('/', user: user) + end + + it 'uses the private_token for auth if both it and user are set' do + user = double(:user) + user_token = 'user' + + allow(user).to receive_message_chain(:personal_access_tokens, :active, :pluck, :first).and_return(user_token) + + expect(app).to receive(:get).with('/', nil, 'Private-Token' => private_token) + expect(app).to receive(:get).with('/api/v4/users') + + described_class.profile('/', user: user, private_token: private_token) + end + end + + describe '.create_custom_logger' do + it 'does nothing when nil is passed' do + expect(described_class.create_custom_logger(nil)).to be_nil + end + + context 'the new logger' do + let(:custom_logger) do + described_class.create_custom_logger(null_logger, private_token: private_token) + end + + it 'does not affect the existing logger' do + expect(null_logger).not_to receive(:debug) + expect(custom_logger).to receive(:debug).and_call_original + + custom_logger.debug('Foo') + end + + it 'strips out the private token' do + expect(custom_logger).to receive(:add) do |severity, _progname, message| + expect(severity).to eq(Logger::DEBUG) + expect(message).to include('public').and include(described_class::FILTERED_STRING) + expect(message).not_to include(private_token) + end + + custom_logger.debug("public #{private_token}") + end + + it 'tracks model load times by model' do + custom_logger.debug('This is not a model load') + custom_logger.debug('User Load (1.2ms)') + custom_logger.debug('User Load (1.3ms)') + custom_logger.debug('Project Load (10.4ms)') + + expect(custom_logger.load_times_by_model).to eq('User' => 2.5, + 'Project' => 10.4) + end + + it 'logs the backtrace, ignoring lines as appropriate' do + # Skip Rails's backtrace cleaning. + allow(Rails.backtrace_cleaner).to receive(:clean, &:itself) + + expect(custom_logger).to receive(:add) + .with(Logger::DEBUG, + anything, + a_string_matching(File.basename(__FILE__))) + .twice + + expect(custom_logger).not_to receive(:add).with(Logger::DEBUG, + anything, + a_string_matching('lib/gitlab/profiler.rb')) + + # Force a part of the backtrace to be in the (ignored) profiler source + # file. + described_class.with_custom_logger(nil) { custom_logger.debug('Foo') } + end + end + end + + describe '.with_custom_logger' do + context 'when the logger is set' do + it 'uses the replacement logger for the duration of the block' do + expect(null_logger).to receive(:debug).and_call_original + + expect { described_class.with_custom_logger(null_logger) { ActiveRecord::Base.logger.debug('foo') } } + .to not_change { ActiveRecord::Base.logger } + .and not_change { ActionController::Base.logger } + .and not_change { ActiveSupport::LogSubscriber.colorize_logging } + end + + it 'returns the result of the block' do + expect(described_class.with_custom_logger(null_logger) { 2 }).to eq(2) + end + end + + context 'when the logger is nil' do + it 'returns the result of the block' do + expect(described_class.with_custom_logger(nil) { 2 }).to eq(2) + end + + it 'does not modify the standard Rails loggers' do + expect { described_class.with_custom_logger(nil) { } } + .to not_change { ActiveRecord::Base.logger } + .and not_change { ActionController::Base.logger } + .and not_change { ActiveSupport::LogSubscriber.colorize_logging } + end + end + end +end diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb index b5a9ac570e6..17b48b3d062 100644 --- a/spec/lib/gitlab/search_results_spec.rb +++ b/spec/lib/gitlab/search_results_spec.rb @@ -19,6 +19,12 @@ describe Gitlab::SearchResults do project.add_developer(user) end + describe '#objects' do + it 'returns without_page collection by default' do + expect(results.objects('projects')).to be_kind_of(Kaminari::PaginatableWithoutCount) + end + end + describe '#projects_count' do it 'returns the total amount of projects' do expect(results.projects_count).to eq(1) @@ -43,6 +49,58 @@ describe Gitlab::SearchResults do end end + context "when count_limit is lower than total amount" do + before do + allow(results).to receive(:count_limit).and_return(1) + end + + describe '#limited_projects_count' do + it 'returns the limited amount of projects' do + create(:project, name: 'foo2') + + expect(results.limited_projects_count).to eq(1) + end + end + + describe '#limited_merge_requests_count' do + it 'returns the limited amount of merge requests' do + create(:merge_request, :simple, source_project: project, title: 'foo2') + + expect(results.limited_merge_requests_count).to eq(1) + end + end + + describe '#limited_milestones_count' do + it 'returns the limited amount of milestones' do + create(:milestone, project: project, title: 'foo2') + + expect(results.limited_milestones_count).to eq(1) + end + end + + describe '#limited_issues_count' do + it 'runs single SQL query to get the limited amount of issues' do + create(:milestone, project: project, title: 'foo2') + + expect(results).to receive(:issues).with(public_only: true).and_call_original + expect(results).not_to receive(:issues).with(no_args).and_call_original + + expect(results.limited_issues_count).to eq(1) + end + end + end + + context "when count_limit is higher than total amount" do + describe '#limited_issues_count' do + it 'runs multiple queries to get the limited amount of issues' do + expect(results).to receive(:issues).with(public_only: true).and_call_original + expect(results).to receive(:issues).with(no_args).and_call_original + + expect(results.limited_issues_count).to eq(1) + end + end + end + it 'includes merge requests from source and target projects' do forked_project = fork_project(project, user) merge_request_2 = create(:merge_request, target_project: project, source_project: forked_project, title: 'foo') diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb index e872a5290c5..bda239b7871 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/spec/lib/gitlab/utils_spec.rb @@ -17,6 +17,22 @@ describe Gitlab::Utils do end end + describe '.remove_line_breaks' do + using RSpec::Parameterized::TableSyntax + + where(:original, :expected) do + "foo\nbar\nbaz" | "foobarbaz" + "foo\r\nbar\r\nbaz" | "foobarbaz" + "foobar" | "foobar" + end + + with_them do + it "replace line breaks with an empty string" do + expect(described_class.remove_line_breaks(original)).to eq(expected) + end + end + end + describe '.to_boolean' do it 'accepts booleans' do expect(to_boolean(true)).to be(true) |