diff options
author | Mike Greiling <mike@pixelcog.com> | 2017-10-24 07:52:21 +0000 |
---|---|---|
committer | Mike Greiling <mike@pixelcog.com> | 2017-10-24 07:52:21 +0000 |
commit | f7bdfe5098c9a5a3a426344ba1d7dd668212cf7e (patch) | |
tree | 5a1cb2a90b0a2b5114f6f23712b68724b3e8a7e0 /spec/lib/gitlab | |
parent | 9cd528aa7ac5066570cb50b909951a6c6b723935 (diff) | |
parent | e16add2267648d3d3ef1d98f9b53f67a29428791 (diff) | |
download | gitlab-ce-f7bdfe5098c9a5a3a426344ba1d7dd668212cf7e.tar.gz |
Merge branch 'master' into 'es-module-autosave'es-module-autosave
# Conflicts:
# app/assets/javascripts/issuable_form.js
# app/assets/javascripts/notes.js
Diffstat (limited to 'spec/lib/gitlab')
28 files changed, 660 insertions, 142 deletions
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 d2e7243ee05..4d3fdbd9554 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 @@ -31,8 +31,8 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t end it 'creates correct entries in the merge_request_diff_commits table' do - expect(updated_merge_request_diff.merge_request_diff_commits.count).to eq(commits.count) - expect(updated_merge_request_diff.commits.map(&:to_hash)).to eq(commits) + expect(updated_merge_request_diff.merge_request_diff_commits.count).to eq(expected_commits.count) + expect(updated_merge_request_diff.commits.map(&:to_hash)).to eq(expected_commits) end it 'creates correct entries in the merge_request_diff_files table' do @@ -199,6 +199,16 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diff has valid commits and diffs' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } + let(:diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) } + let(:expected_diffs) { diffs } + + include_examples 'updated MR diff' + end + + context 'when the merge request diff has diffs but no commits' do + let(:commits) { nil } + let(:expected_commits) { [] } let(:diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) } let(:expected_diffs) { diffs } @@ -207,6 +217,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs do not have too_large set' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } let(:expected_diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) } let(:diffs) do @@ -218,6 +229,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs do not have a_mode and b_mode set' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } let(:expected_diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) } let(:diffs) do @@ -229,6 +241,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs have binary content' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } let(:expected_diffs) { diffs } # The start of a PDF created by Illustrator @@ -257,6 +270,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diff has commits, but no diffs' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } let(:diffs) { [] } let(:expected_diffs) { diffs } @@ -265,6 +279,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs have invalid content' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } + let(:expected_commits) { commits } let(:diffs) { ['--broken-diff'] } let(:expected_diffs) { [] } @@ -274,6 +289,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs are Rugged::Patch instances' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } let(:first_commit) { merge_request.project.repository.commit(merge_request_diff.head_commit_sha) } + let(:expected_commits) { commits } let(:diffs) { first_commit.rugged_diff_from_parent.patches } let(:expected_diffs) { [] } @@ -283,6 +299,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t context 'when the merge request diffs are Rugged::Diff::Delta instances' do let(:commits) { merge_request_diff.commits.map(&:to_hash) } let(:first_commit) { merge_request.project.repository.commit(merge_request_diff.head_commit_sha) } + let(:expected_commits) { commits } let(:diffs) { first_commit.rugged_diff_from_parent.deltas } let(:expected_diffs) { [] } diff --git a/spec/lib/gitlab/backup/manager_spec.rb b/spec/lib/gitlab/backup/manager_spec.rb index 422f2af7266..b68301a066a 100644 --- a/spec/lib/gitlab/backup/manager_spec.rb +++ b/spec/lib/gitlab/backup/manager_spec.rb @@ -172,10 +172,6 @@ describe Backup::Manager do end describe '#unpack' do - before do - allow(Dir).to receive(:chdir) - end - context 'when there are no backup files in the directory' do before do allow(Dir).to receive(:glob).and_return([]) diff --git a/spec/lib/gitlab/conflict/file_collection_spec.rb b/spec/lib/gitlab/conflict/file_collection_spec.rb index a4d7628b03a..5944ce8049a 100644 --- a/spec/lib/gitlab/conflict/file_collection_spec.rb +++ b/spec/lib/gitlab/conflict/file_collection_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Gitlab::Conflict::FileCollection do let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start') } - let(:file_collection) { described_class.read_only(merge_request) } + let(:file_collection) { described_class.new(merge_request) } describe '#files' do it 'returns an array of Conflict::Files' do diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb index 5356e9742b4..bf981d2f6f6 100644 --- a/spec/lib/gitlab/conflict/file_spec.rb +++ b/spec/lib/gitlab/conflict/file_spec.rb @@ -8,9 +8,10 @@ describe Gitlab::Conflict::File do let(:our_commit) { rugged.branches['conflict-resolvable'].target } let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) } let(:index) { rugged.merge_commits(our_commit, their_commit) } - let(:conflict) { index.conflicts.last } - let(:merge_file_result) { index.merge_file('files/ruby/regex.rb') } - let(:conflict_file) { described_class.new(merge_file_result, conflict, merge_request: merge_request) } + let(:rugged_conflict) { index.conflicts.last } + let(:raw_conflict_content) { index.merge_file('files/ruby/regex.rb')[:data] } + let(:raw_conflict_file) { Gitlab::Git::Conflict::File.new(repository, our_commit.oid, rugged_conflict, raw_conflict_content) } + let(:conflict_file) { described_class.new(raw_conflict_file, merge_request: merge_request) } describe '#resolve_lines' do let(:section_keys) { conflict_file.sections.map { |section| section[:id] }.compact } @@ -48,18 +49,18 @@ describe Gitlab::Conflict::File do end end - it 'raises MissingResolution when passed a hash without resolutions for all sections' do + it 'raises ResolutionError when passed a hash without resolutions for all sections' do empty_hash = section_keys.map { |key| [key, nil] }.to_h invalid_hash = section_keys.map { |key| [key, 'invalid'] }.to_h expect { conflict_file.resolve_lines({}) } - .to raise_error(Gitlab::Conflict::File::MissingResolution) + .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError) expect { conflict_file.resolve_lines(empty_hash) } - .to raise_error(Gitlab::Conflict::File::MissingResolution) + .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError) expect { conflict_file.resolve_lines(invalid_hash) } - .to raise_error(Gitlab::Conflict::File::MissingResolution) + .to raise_error(Gitlab::Git::Conflict::Resolver::ResolutionError) end end @@ -144,7 +145,7 @@ describe Gitlab::Conflict::File do end context 'with an example file' do - let(:file) do + let(:raw_conflict_content) do <<FILE # Ensure there is no match line header here def username_regexp @@ -220,7 +221,6 @@ end FILE end - let(:conflict_file) { described_class.new({ data: file }, conflict, merge_request: merge_request) } let(:sections) { conflict_file.sections } it 'sets the correct match line headers' do diff --git a/spec/lib/gitlab/current_settings_spec.rb b/spec/lib/gitlab/current_settings_spec.rb index d57ffcae8e1..492659a82b0 100644 --- a/spec/lib/gitlab/current_settings_spec.rb +++ b/spec/lib/gitlab/current_settings_spec.rb @@ -21,7 +21,7 @@ describe Gitlab::CurrentSettings do it 'falls back to DB if Redis returns an empty value' do expect(ApplicationSetting).to receive(:cached).and_return(nil) - expect(ApplicationSetting).to receive(:last).and_call_original + expect(ApplicationSetting).to receive(:last).and_call_original.twice expect(current_application_settings).to be_a(ApplicationSetting) end diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb index 8af49ed50ff..80c8c189665 100644 --- a/spec/lib/gitlab/diff/parser_spec.rb +++ b/spec/lib/gitlab/diff/parser_spec.rb @@ -143,4 +143,21 @@ eos it { expect(parser.parse([])).to eq([]) } it { expect(parser.parse(nil)).to eq([]) } end + + describe 'tolerates special diff markers in a content' do + it "counts lines correctly" do + diff = <<~END + --- a/test + +++ b/test + @@ -1,2 +1,2 @@ + +ipsum + +++ b + -ipsum + END + + lines = parser.parse(diff.lines).to_a + + expect(lines.size).to eq(3) + end + end end diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb index 9bf54fdecc4..245f24e96d4 100644 --- a/spec/lib/gitlab/diff/position_spec.rb +++ b/spec/lib/gitlab/diff/position_spec.rb @@ -40,7 +40,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 0) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 0) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -108,7 +108,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 15) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 15) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -149,7 +149,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -189,7 +189,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 13, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, 13, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -233,7 +233,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 5) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 5) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -274,7 +274,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -314,7 +314,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 4, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, 4, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -357,7 +357,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 0, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, 0, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -399,7 +399,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, subject.new_line, 0) + line_code = Gitlab::Git.diff_line_code(subject.file_path, subject.new_line, 0) expect(subject.line_code(project.repository)).to eq(line_code) end @@ -447,7 +447,7 @@ describe Gitlab::Diff::Position do describe "#line_code" do it "returns the correct line code" do - line_code = Gitlab::Diff::LineCode.generate(subject.file_path, 0, subject.old_line) + line_code = Gitlab::Git.diff_line_code(subject.file_path, 0, subject.old_line) expect(subject.line_code(project.repository)).to eq(line_code) end diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb index 8b14b227e65..9151c66afb3 100644 --- a/spec/lib/gitlab/encoding_helper_spec.rb +++ b/spec/lib/gitlab/encoding_helper_spec.rb @@ -6,6 +6,9 @@ describe Gitlab::EncodingHelper do describe '#encode!' do [ + ["nil", nil, nil], + ["empty string", "".encode("ASCII-8BIT"), "".encode("UTF-8")], + ["invalid utf-8 encoded string", "my bad string\xE5".force_encoding("UTF-8"), "my bad string"], [ 'leaves ascii only string as is', 'ascii only string', @@ -81,6 +84,9 @@ describe Gitlab::EncodingHelper do describe '#encode_utf8' do [ + ["nil", nil, nil], + ["empty string", "".encode("ASCII-8BIT"), "".encode("UTF-8")], + ["invalid utf-8 encoded string", "my bad string\xE5".force_encoding("UTF-8"), "my bad stringå"], [ "encodes valid utf8 encoded string to utf8", "λ, λ, λ".encode("UTF-8"), @@ -95,12 +101,18 @@ describe Gitlab::EncodingHelper do "encodes valid ISO-8859-1 encoded string to utf8", "Rüby ist eine Programmiersprache. Wir verlängern den text damit ICU die Sprache erkennen kann.".encode("ISO-8859-1", "UTF-8"), "Rüby ist eine Programmiersprache. Wir verlängern den text damit ICU die Sprache erkennen kann.".encode("UTF-8") + ], + [ + # Test case from https://gitlab.com/gitlab-org/gitlab-ce/issues/39227 + "Equifax branch name", + "refs/heads/Equifax".encode("UTF-8"), + "refs/heads/Equifax".encode("UTF-8") ] ].each do |description, test_string, xpect| it description do - r = ext_class.encode_utf8(test_string.force_encoding('UTF-8')) + r = ext_class.encode_utf8(test_string) expect(r).to eq(xpect) - expect(r.encoding.name).to eq('UTF-8') + expect(r.encoding.name).to eq('UTF-8') if xpect end end diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb index 695fd6f8573..8e524f9b05a 100644 --- a/spec/lib/gitlab/file_detector_spec.rb +++ b/spec/lib/gitlab/file_detector_spec.rb @@ -18,6 +18,10 @@ describe Gitlab::FileDetector do expect(described_class.type_of('README.md')).to eq(:readme) end + it 'returns nil for a README file in a directory' do + expect(described_class.type_of('foo/README.md')).to be_nil + end + it 'returns the type of a changelog file' do %w(CHANGELOG HISTORY CHANGES NEWS).each do |file| expect(described_class.type_of(file)).to eq(:changelog) @@ -52,6 +56,14 @@ describe Gitlab::FileDetector do end end + it 'returns the type of an issue template' do + expect(described_class.type_of('.gitlab/issue_templates/foo.md')).to eq(:issue_template) + end + + it 'returns the type of a merge request template' do + expect(described_class.type_of('.gitlab/merge_request_templates/foo.md')).to eq(:merge_request_template) + end + it 'returns nil for an unknown file' do expect(described_class.type_of('foo.txt')).to be_nil end diff --git a/spec/lib/gitlab/conflict/parser_spec.rb b/spec/lib/gitlab/git/conflict/parser_spec.rb index fce606a2bb5..7b035a381f1 100644 --- a/spec/lib/gitlab/conflict/parser_spec.rb +++ b/spec/lib/gitlab/git/conflict/parser_spec.rb @@ -1,11 +1,9 @@ require 'spec_helper' -describe Gitlab::Conflict::Parser do - let(:parser) { described_class.new } - - describe '#parse' do +describe Gitlab::Git::Conflict::Parser do + describe '.parse' do def parse_text(text) - parser.parse(text, our_path: 'README.md', their_path: 'README.md') + described_class.parse(text, our_path: 'README.md', their_path: 'README.md') end context 'when the file has valid conflicts' do @@ -87,33 +85,37 @@ CONFLICT end let(:lines) do - parser.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb') + described_class.parse(text, our_path: 'files/ruby/regex.rb', their_path: 'files/ruby/regex.rb') + end + let(:old_line_numbers) do + lines.select { |line| line[:type] != 'new' }.map { |line| line[:line_old] } end + let(:new_line_numbers) do + lines.select { |line| line[:type] != 'old' }.map { |line| line[:line_new] } + end + let(:line_indexes) { lines.map { |line| line[:line_obj_index] } } it 'sets our lines as new lines' do - expect(lines[8..13]).to all(have_attributes(type: 'new')) - expect(lines[26..27]).to all(have_attributes(type: 'new')) - expect(lines[56..57]).to all(have_attributes(type: 'new')) + expect(lines[8..13]).to all(include(type: 'new')) + expect(lines[26..27]).to all(include(type: 'new')) + expect(lines[56..57]).to all(include(type: 'new')) end it 'sets their lines as old lines' do - expect(lines[14..19]).to all(have_attributes(type: 'old')) - expect(lines[28..29]).to all(have_attributes(type: 'old')) - expect(lines[58..59]).to all(have_attributes(type: 'old')) + expect(lines[14..19]).to all(include(type: 'old')) + expect(lines[28..29]).to all(include(type: 'old')) + expect(lines[58..59]).to all(include(type: 'old')) end it 'sets non-conflicted lines as both' do - expect(lines[0..7]).to all(have_attributes(type: nil)) - expect(lines[20..25]).to all(have_attributes(type: nil)) - expect(lines[30..55]).to all(have_attributes(type: nil)) - expect(lines[60..62]).to all(have_attributes(type: nil)) + expect(lines[0..7]).to all(include(type: nil)) + expect(lines[20..25]).to all(include(type: nil)) + expect(lines[30..55]).to all(include(type: nil)) + expect(lines[60..62]).to all(include(type: nil)) end - it 'sets consecutive line numbers for index, old_pos, and new_pos' do - old_line_numbers = lines.select { |line| line.type != 'new' }.map(&:old_pos) - new_line_numbers = lines.select { |line| line.type != 'old' }.map(&:new_pos) - - expect(lines.map(&:index)).to eq(0.upto(62).to_a) + it 'sets consecutive line numbers for line_obj_index, line_old, and line_new' do + expect(line_indexes).to eq(0.upto(62).to_a) expect(old_line_numbers).to eq(1.upto(53).to_a) expect(new_line_numbers).to eq(1.upto(53).to_a) end @@ -123,12 +125,12 @@ CONFLICT context 'when there is a non-start delimiter first' do it 'raises UnexpectedDelimiter when there is a middle delimiter first' do expect { parse_text('=======') } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'raises UnexpectedDelimiter when there is an end delimiter first' do expect { parse_text('>>>>>>> README.md') } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'does not raise when there is an end delimiter for a different path first' do @@ -143,12 +145,12 @@ CONFLICT it 'raises UnexpectedDelimiter when it is followed by an end delimiter' do expect { parse_text(start_text + '>>>>>>> README.md' + end_text) } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'raises UnexpectedDelimiter when it is followed by another start delimiter' do expect { parse_text(start_text + start_text + end_text) } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'does not raise when it is followed by a start delimiter for a different path' do @@ -163,12 +165,12 @@ CONFLICT it 'raises UnexpectedDelimiter when it is followed by another middle delimiter' do expect { parse_text(start_text + '=======' + end_text) } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'raises UnexpectedDelimiter when it is followed by a start delimiter' do expect { parse_text(start_text + start_text + end_text) } - .to raise_error(Gitlab::Conflict::Parser::UnexpectedDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::UnexpectedDelimiter) end it 'does not raise when it is followed by a start delimiter for another path' do @@ -181,25 +183,25 @@ CONFLICT start_text = "<<<<<<< README.md\n=======\n" expect { parse_text(start_text) } - .to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter) expect { parse_text(start_text + '>>>>>>> some-other-path.md') } - .to raise_error(Gitlab::Conflict::Parser::MissingEndDelimiter) + .to raise_error(Gitlab::Git::Conflict::Parser::MissingEndDelimiter) end end context 'other file types' do it 'raises UnmergeableFile when lines is blank, indicating a binary file' do expect { parse_text('') } - .to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) + .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile) expect { parse_text(nil) } - .to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) + .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile) end it 'raises UnmergeableFile when the file is over 200 KB' do expect { parse_text('a' * 204801) } - .to raise_error(Gitlab::Conflict::Parser::UnmergeableFile) + .to raise_error(Gitlab::Git::Conflict::Parser::UnmergeableFile) end # All text from Rugged has an encoding of ASCII_8BIT, so force that in @@ -214,7 +216,7 @@ CONFLICT context 'when the file contains non-UTF-8 characters' do it 'raises UnsupportedEncoding' do expect { parse_text("a\xC4\xFC".force_encoding(Encoding::ASCII_8BIT)) } - .to raise_error(Gitlab::Conflict::Parser::UnsupportedEncoding) + .to raise_error(Gitlab::Git::Conflict::Parser::UnsupportedEncoding) end end end diff --git a/spec/lib/gitlab/git/env_spec.rb b/spec/lib/gitlab/git/env_spec.rb index d9df99bfe05..03836d49518 100644 --- a/spec/lib/gitlab/git/env_spec.rb +++ b/spec/lib/gitlab/git/env_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::Git::Env do - describe "#set" do + describe ".set" do context 'with RequestStore.store disabled' do before do allow(RequestStore).to receive(:active?).and_return(false) @@ -34,25 +34,57 @@ describe Gitlab::Git::Env do end end - describe "#all" do + describe ".all" do context 'with RequestStore.store enabled' do before do allow(RequestStore).to receive(:active?).and_return(true) described_class.set( GIT_OBJECT_DIRECTORY: 'foo', - GIT_ALTERNATE_OBJECT_DIRECTORIES: 'bar') + GIT_ALTERNATE_OBJECT_DIRECTORIES: ['bar']) end it 'returns an env hash' do expect(described_class.all).to eq({ 'GIT_OBJECT_DIRECTORY' => 'foo', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar' + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => ['bar'] }) end end end - describe "#[]" do + describe ".to_env_hash" do + context 'with RequestStore.store enabled' do + using RSpec::Parameterized::TableSyntax + + let(:key) { 'GIT_OBJECT_DIRECTORY' } + subject { described_class.to_env_hash } + + where(:input, :output) do + nil | nil + 'foo' | 'foo' + [] | '' + ['foo'] | 'foo' + %w[foo bar] | 'foo:bar' + end + + with_them do + before do + allow(RequestStore).to receive(:active?).and_return(true) + described_class.set(key.to_sym => input) + end + + it 'puts the right value in the hash' do + if output + expect(subject.fetch(key)).to eq(output) + else + expect(subject.has_key?(key)).to eq(false) + end + end + end + end + end + + describe ".[]" do context 'with RequestStore.store enabled' do before do allow(RequestStore).to receive(:active?).and_return(true) diff --git a/spec/lib/gitlab/git/popen_spec.rb b/spec/lib/gitlab/git/popen_spec.rb new file mode 100644 index 00000000000..2b65bc1cf15 --- /dev/null +++ b/spec/lib/gitlab/git/popen_spec.rb @@ -0,0 +1,132 @@ +require 'spec_helper' + +describe 'Gitlab::Git::Popen' do + let(:path) { Rails.root.join('tmp').to_s } + + let(:klass) do + Class.new(Object) do + include Gitlab::Git::Popen + end + end + + context 'popen' do + context 'zero status' do + let(:result) { klass.new.popen(%w(ls), path) } + let(:output) { result.first } + let(:status) { result.last } + + it { expect(status).to be_zero } + it { expect(output).to include('tests') } + end + + context 'non-zero status' do + let(:result) { klass.new.popen(%w(cat NOTHING), path) } + let(:output) { result.first } + let(:status) { result.last } + + it { expect(status).to eq(1) } + it { expect(output).to include('No such file or directory') } + end + + context 'unsafe string command' do + it 'raises an error when it gets called with a string argument' do + expect { klass.new.popen('ls', path) }.to raise_error(RuntimeError) + end + end + + context 'with custom options' do + let(:vars) { { 'foobar' => 123, 'PWD' => path } } + let(:options) { { chdir: path } } + + it 'calls popen3 with the provided environment variables' do + expect(Open3).to receive(:popen3).with(vars, 'ls', options) + + klass.new.popen(%w(ls), path, { 'foobar' => 123 }) + end + end + + context 'use stdin' do + let(:result) { klass.new.popen(%w[cat], path) { |stdin| stdin.write 'hello' } } + let(:output) { result.first } + let(:status) { result.last } + + it { expect(status).to be_zero } + it { expect(output).to eq('hello') } + end + end + + context 'popen_with_timeout' do + let(:timeout) { 1.second } + + context 'no timeout' do + context 'zero status' do + let(:result) { klass.new.popen_with_timeout(%w(ls), timeout, path) } + let(:output) { result.first } + let(:status) { result.last } + + it { expect(status).to be_zero } + it { expect(output).to include('tests') } + end + + context 'non-zero status' do + let(:result) { klass.new.popen_with_timeout(%w(cat NOTHING), timeout, path) } + let(:output) { result.first } + let(:status) { result.last } + + it { expect(status).to eq(1) } + it { expect(output).to include('No such file or directory') } + end + + context 'unsafe string command' do + it 'raises an error when it gets called with a string argument' do + expect { klass.new.popen_with_timeout('ls', timeout, path) }.to raise_error(RuntimeError) + end + end + end + + context 'timeout' do + context 'timeout' do + it "raises a Timeout::Error" do + expect { klass.new.popen_with_timeout(%w(sleep 1000), timeout, path) }.to raise_error(Timeout::Error) + end + + it "handles processes that do not shutdown correctly" do + expect { klass.new.popen_with_timeout(['bash', '-c', "trap -- '' SIGTERM; sleep 1000"], timeout, path) }.to raise_error(Timeout::Error) + end + end + + context 'timeout period' do + let(:time_taken) do + begin + start = Time.now + klass.new.popen_with_timeout(%w(sleep 1000), timeout, path) + rescue + Time.now - start + end + end + + it { expect(time_taken).to be >= timeout } + end + + context 'clean up' do + let(:instance) { klass.new } + + it 'kills the child process' do + expect(instance).to receive(:kill_process_group_for_pid).and_wrap_original do |m, *args| + # is the PID, and it should not be running at this point + m.call(*args) + + pid = args.first + begin + Process.getpgid(pid) + raise "The child process should have been killed" + rescue Errno::ESRCH + end + end + + expect { instance.popen_with_timeout(['bash', '-c', "trap -- '' SIGTERM; sleep 1000"], timeout, path) }.to raise_error(Timeout::Error) + end + end + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index d959562c951..b2d2f770e3d 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -87,7 +87,7 @@ describe Gitlab::Git::Repository, seed_helper: true do 'GIT_OBJECT_DIRECTORY_RELATIVE' => './objects/foo', 'GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE' => ['./objects/bar', './objects/baz'], 'GIT_OBJECT_DIRECTORY' => 'ignored', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'ignored:ignored', + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => %w[ignored ignored], 'GIT_OTHER' => 'another_env' }) end @@ -104,7 +104,7 @@ describe Gitlab::Git::Repository, seed_helper: true do before do allow(Gitlab::Git::Env).to receive(:all).and_return({ 'GIT_OBJECT_DIRECTORY' => 'foo', - 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => 'bar:baz', + 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => %w[bar baz], 'GIT_OTHER' => 'another_env' }) end @@ -1510,6 +1510,60 @@ describe Gitlab::Git::Repository, seed_helper: true do end end + describe '#fetch' do + let(:git_path) { Gitlab.config.git.bin_path } + let(:remote_name) { 'my_remote' } + + subject { repository.fetch(remote_name) } + + it 'fetches the remote and returns true if the command was successful' do + expect(repository).to receive(:popen) + .with(%W(#{git_path} fetch #{remote_name}), repository.path) + .and_return(['', 0]) + + expect(subject).to be(true) + end + end + + describe '#merge' do + let(:repository) do + Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') + end + let(:source_sha) { '913c66a37b4a45b9769037c55c2d238bd0942d2e' } + let(:user) { build(:user) } + let(:target_branch) { 'test-merge-target-branch' } + + before do + repository.create_branch(target_branch, '6d394385cf567f80a8fd85055db1ab4c5295806f') + end + + after do + FileUtils.rm_rf(TEST_MUTABLE_REPO_PATH) + ensure_seeds + end + + shared_examples '#merge' do + it 'can perform a merge' do + merge_commit_id = nil + result = repository.merge(user, source_sha, target_branch, 'Test merge') do |commit_id| + merge_commit_id = commit_id + end + + expect(result.newrev).to eq(merge_commit_id) + expect(result.repo_created).to eq(false) + expect(result.branch_created).to eq(false) + end + end + + context 'with gitaly' do + it_behaves_like '#merge' + end + + context 'without gitaly', :skip_gitaly_mock do + it_behaves_like '#merge' + end + end + def create_remote_branch(repository, remote_name, branch_name, source_branch_name) source_branch = repository.branches.find { |branch| branch.name == source_branch_name } rugged = repository.rugged diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb index 98cf7966dad..c8d532df059 100644 --- a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb +++ b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb @@ -10,18 +10,10 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: # Override test-settings for the circuitbreaker with something more realistic # for these specs. stub_storage_settings('default' => { - 'path' => TestEnv.repos_path, - 'failure_count_threshold' => 10, - 'failure_wait_time' => 30, - 'failure_reset_time' => 1800, - 'storage_timeout' => 5 + 'path' => TestEnv.repos_path }, 'broken' => { - 'path' => 'tmp/tests/non-existent-repositories', - 'failure_count_threshold' => 10, - 'failure_wait_time' => 30, - 'failure_reset_time' => 1800, - 'storage_timeout' => 5 + 'path' => 'tmp/tests/non-existent-repositories' }, 'nopath' => { 'path' => nil } ) @@ -49,6 +41,10 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: expect(key_exists).to be_falsey end + + it 'does not break when there are no keys in redis' do + expect { described_class.reset_all! }.not_to raise_error + end end describe '.for_storage' do @@ -75,10 +71,39 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: expect(circuit_breaker.hostname).to eq(hostname) expect(circuit_breaker.storage).to eq('default') expect(circuit_breaker.storage_path).to eq(TestEnv.repos_path) - expect(circuit_breaker.failure_count_threshold).to eq(10) - expect(circuit_breaker.failure_wait_time).to eq(30) - expect(circuit_breaker.failure_reset_time).to eq(1800) - expect(circuit_breaker.storage_timeout).to eq(5) + end + end + + context 'circuitbreaker settings' do + before do + stub_application_setting(circuitbreaker_failure_count_threshold: 0, + circuitbreaker_failure_wait_time: 1, + circuitbreaker_failure_reset_time: 2, + circuitbreaker_storage_timeout: 3) + end + + describe '#failure_count_threshold' do + it 'reads the value from settings' do + expect(circuit_breaker.failure_count_threshold).to eq(0) + end + end + + describe '#failure_wait_time' do + it 'reads the value from settings' do + expect(circuit_breaker.failure_wait_time).to eq(1) + end + end + + describe '#failure_reset_time' do + it 'reads the value from settings' do + expect(circuit_breaker.failure_reset_time).to eq(2) + end + end + + describe '#storage_timeout' do + it 'reads the value from settings' do + expect(circuit_breaker.storage_timeout).to eq(3) + end end end @@ -151,10 +176,7 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: context 'the `failure_wait_time` is set to 0' do before do - stub_storage_settings('default' => { - 'failure_wait_time' => 0, - 'path' => TestEnv.repos_path - }) + stub_application_setting(circuitbreaker_failure_wait_time: 0) end it 'is working even when there is a recent failure' do diff --git a/spec/lib/gitlab/git/storage/health_spec.rb b/spec/lib/gitlab/git/storage/health_spec.rb index 2d3af387971..4a14a5201d1 100644 --- a/spec/lib/gitlab/git/storage/health_spec.rb +++ b/spec/lib/gitlab/git/storage/health_spec.rb @@ -20,36 +20,6 @@ describe Gitlab::Git::Storage::Health, clean_gitlab_redis_shared_state: true, br end end - describe '.load_for_keys' do - let(:subject) do - results = Gitlab::Git::Storage.redis.with do |redis| - fake_future = double - allow(fake_future).to receive(:value).and_return([host1_key]) - described_class.load_for_keys({ 'broken' => fake_future }, redis) - end - - # Make sure the `Redis#future is loaded - results.inject({}) do |result, (name, info)| - info.each { |i| i[:failure_count] = i[:failure_count].value.to_i } - - result[name] = info - - result - end - end - - it 'loads when there is no info in redis' do - expect(subject).to eq('broken' => [{ name: host1_key, failure_count: 0 }]) - end - - it 'reads the correct values for a storage from redis' do - set_in_redis(host1_key, 5) - set_in_redis(host2_key, 7) - - expect(subject).to eq('broken' => [{ name: host1_key, failure_count: 5 }]) - end - end - describe '.for_all_storages' do it 'loads health status for all configured storages' do healths = described_class.for_all_storages diff --git a/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb index 0e645008c88..7ee6d2f3709 100644 --- a/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb +++ b/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb @@ -54,6 +54,10 @@ describe Gitlab::Git::Storage::NullCircuitBreaker do end describe '#failure_count_threshold' do + before do + stub_application_setting(circuitbreaker_failure_count_threshold: 1) + end + it { expect(breaker.failure_count_threshold).to eq(1) } end diff --git a/spec/lib/gitlab/github_import/wiki_formatter_spec.rb b/spec/lib/gitlab/github_import/wiki_formatter_spec.rb index fcd90fab547..2662cc20b32 100644 --- a/spec/lib/gitlab/github_import/wiki_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/wiki_formatter_spec.rb @@ -11,7 +11,7 @@ describe Gitlab::GithubImport::WikiFormatter do describe '#disk_path' do it 'appends .wiki to project path' do - expect(wiki.disk_path).to eq project.disk_path + '.wiki' + expect(wiki.disk_path).to eq project.wiki.disk_path end end diff --git a/spec/lib/gitlab/group_hierarchy_spec.rb b/spec/lib/gitlab/group_hierarchy_spec.rb index 8dc83a6db7f..30686634af4 100644 --- a/spec/lib/gitlab/group_hierarchy_spec.rb +++ b/spec/lib/gitlab/group_hierarchy_spec.rb @@ -18,6 +18,12 @@ describe Gitlab::GroupHierarchy, :postgresql do expect(relation).to include(parent, child1) end + it 'can find ancestors upto a certain level' do + relation = described_class.new(Group.where(id: child2)).base_and_ancestors(upto: child1) + + expect(relation).to contain_exactly(child2) + end + it 'uses ancestors_base #initialize argument' do relation = described_class.new(Group.where(id: child2.id), Group.none).base_and_ancestors @@ -55,6 +61,28 @@ describe Gitlab::GroupHierarchy, :postgresql do end end + describe '#descendants' do + it 'includes only the descendants' do + relation = described_class.new(Group.where(id: parent)).descendants + + expect(relation).to contain_exactly(child1, child2) + end + end + + describe '#ancestors' do + it 'includes only the ancestors' do + relation = described_class.new(Group.where(id: child2)).ancestors + + expect(relation).to contain_exactly(child1, parent) + end + + it 'can find ancestors upto a certain level' do + relation = described_class.new(Group.where(id: child2)).ancestors(upto: child1) + + expect(relation).to be_empty + end + end + describe '#all_groups' do let(:relation) do described_class.new(Group.where(id: child1.id)).all_groups diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 80d92b2e6a3..121c0ed04ed 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -496,6 +496,7 @@ Timelog: - merge_request_id - issue_id - user_id +- spent_at - created_at - updated_at ProjectAutoDevops: diff --git a/spec/lib/gitlab/multi_collection_paginator_spec.rb b/spec/lib/gitlab/multi_collection_paginator_spec.rb new file mode 100644 index 00000000000..68bd4f93159 --- /dev/null +++ b/spec/lib/gitlab/multi_collection_paginator_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::MultiCollectionPaginator do + subject(:paginator) { described_class.new(Project.all.order(:id), Group.all.order(:id), per_page: 3) } + + it 'combines both collections' do + project = create(:project) + group = create(:group) + + expect(paginator.paginate(1)).to eq([project, group]) + end + + it 'includes elements second collection if first collection is empty' do + group = create(:group) + + expect(paginator.paginate(1)).to eq([group]) + end + + context 'with a full first page' do + let!(:all_groups) { create_list(:group, 4) } + let!(:all_projects) { create_list(:project, 4) } + + it 'knows the total count of the collection' do + expect(paginator.total_count).to eq(8) + end + + it 'fills the first page with elements of the first collection' do + expect(paginator.paginate(1)).to eq(all_projects.take(3)) + end + + it 'fils the second page with a mixture of of the first & second collection' do + first_collection_element = all_projects.last + second_collection_elements = all_groups.take(2) + + expected_collection = [first_collection_element] + second_collection_elements + + expect(paginator.paginate(2)).to eq(expected_collection) + end + + it 'fils the last page with elements from the second collection' do + expected_collection = all_groups[-2..-1] + + expect(paginator.paginate(3)).to eq(expected_collection) + end + end +end diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb index 1f1c48ee9b5..f1f188cbfb5 100644 --- a/spec/lib/gitlab/path_regex_spec.rb +++ b/spec/lib/gitlab/path_regex_spec.rb @@ -213,7 +213,7 @@ describe Gitlab::PathRegex do it 'accepts group routes' do expect(subject).to match('activity/') expect(subject).to match('group_members/') - expect(subject).to match('subgroups/') + expect(subject).to match('labels/') end it 'is not case sensitive' do @@ -246,7 +246,7 @@ describe Gitlab::PathRegex do it 'accepts group routes' do expect(subject).to match('activity/') expect(subject).to match('group_members/') - expect(subject).to match('subgroups/') + expect(subject).to match('labels/') end end @@ -268,7 +268,7 @@ describe Gitlab::PathRegex do it 'accepts group routes' do expect(subject).to match('activity/more/') expect(subject).to match('group_members/more/') - expect(subject).to match('subgroups/more/') + expect(subject).to match('labels/more/') end end end @@ -292,7 +292,7 @@ describe Gitlab::PathRegex do it 'rejects group routes' do expect(subject).not_to match('root/activity/') expect(subject).not_to match('root/group_members/') - expect(subject).not_to match('root/subgroups/') + expect(subject).not_to match('root/labels/') end end @@ -314,7 +314,7 @@ describe Gitlab::PathRegex do it 'rejects group routes' do expect(subject).not_to match('root/activity/more/') expect(subject).not_to match('root/group_members/more/') - expect(subject).not_to match('root/subgroups/more/') + expect(subject).not_to match('root/labels/more/') end end end @@ -349,7 +349,7 @@ describe Gitlab::PathRegex do it 'accepts group routes' do expect(subject).to match('activity/') expect(subject).to match('group_members/') - expect(subject).to match('subgroups/') + expect(subject).to match('labels/') end it 'is not case sensitive' do @@ -382,7 +382,7 @@ describe Gitlab::PathRegex do it 'accepts group routes' do expect(subject).to match('root/activity/') expect(subject).to match('root/group_members/') - expect(subject).to match('root/subgroups/') + expect(subject).to match('root/labels/') end it 'is not case sensitive' do diff --git a/spec/lib/gitlab/quick_actions/spend_time_and_date_separator_spec.rb b/spec/lib/gitlab/quick_actions/spend_time_and_date_separator_spec.rb new file mode 100644 index 00000000000..8b58f0b3725 --- /dev/null +++ b/spec/lib/gitlab/quick_actions/spend_time_and_date_separator_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +describe Gitlab::QuickActions::SpendTimeAndDateSeparator do + subject { described_class } + + shared_examples 'arg line with invalid parameters' do + it 'return nil' do + expect(subject.new(invalid_arg).execute).to eq(nil) + end + end + + shared_examples 'arg line with valid parameters' do + it 'return time and date array' do + expect(subject.new(valid_arg).execute).to eq(expected_response) + end + end + + describe '#execute' do + context 'invalid paramenter in arg line' do + context 'empty arg line' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { '' } + end + end + + context 'future date in arg line' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { '10m 6023-02-02' } + end + end + + context 'unparseable date(invalid mixes of delimiters)' do + it_behaves_like 'arg line with invalid parameters' do + let(:invalid_arg) { '10m 2017.02-02' } + end + end + + context 'trash in arg line' do + let(:invalid_arg) { 'dfjkghdskjfghdjskfgdfg' } + + it 'return nil as time value' do + time_date_response = subject.new(invalid_arg).execute + + expect(time_date_response).to be_an_instance_of(Array) + expect(time_date_response.first).to eq(nil) + end + end + end + + context 'only time present in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:valid_arg) { '2m 3m 5m 1h' } + let(:time) { Gitlab::TimeTrackingFormatter.parse(valid_arg) } + let(:date) { DateTime.now.to_date } + let(:expected_response) { [time, date] } + end + end + + context 'simple time with date in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:raw_time) { '10m' } + let(:raw_date) { '2016-02-02' } + let(:valid_arg) { "#{raw_time} #{raw_date}" } + let(:date) { Date.parse(raw_date) } + let(:time) { Gitlab::TimeTrackingFormatter.parse(raw_time) } + let(:expected_response) { [time, date] } + end + end + + context 'composite time with date in arg line' do + it_behaves_like 'arg line with valid parameters' do + let(:raw_time) { '2m 10m 1h 3d' } + let(:raw_date) { '2016/02/02' } + let(:valid_arg) { "#{raw_time} #{raw_date}" } + let(:date) { Date.parse(raw_date) } + let(:time) { Gitlab::TimeTrackingFormatter.parse(raw_time) } + let(:expected_response) { [time, date] } + end + end + end +end diff --git a/spec/lib/gitlab/saml/auth_hash_spec.rb b/spec/lib/gitlab/saml/auth_hash_spec.rb new file mode 100644 index 00000000000..a555935aea3 --- /dev/null +++ b/spec/lib/gitlab/saml/auth_hash_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe Gitlab::Saml::AuthHash do + include LoginHelpers + + let(:raw_info_attr) { { 'groups' => %w(Developers Freelancers) } } + subject(:saml_auth_hash) { described_class.new(omniauth_auth_hash) } + + let(:info_hash) do + { + name: 'John', + email: 'john@mail.com' + } + end + + let(:omniauth_auth_hash) do + OmniAuth::AuthHash.new(uid: 'my-uid', + provider: 'saml', + info: info_hash, + extra: { raw_info: OneLogin::RubySaml::Attributes.new(raw_info_attr) } ) + end + + before do + stub_saml_group_config(%w(Developers Freelancers Designers)) + end + + describe '#groups' do + it 'returns array of groups' do + expect(saml_auth_hash.groups).to eq(%w(Developers Freelancers)) + end + + context 'raw info hash attributes empty' do + let(:raw_info_attr) { {} } + + it 'returns an empty array' do + expect(saml_auth_hash.groups).to be_a(Array) + end + end + end +end diff --git a/spec/lib/gitlab/saml/user_spec.rb b/spec/lib/gitlab/saml/user_spec.rb index 59923bfb14d..1c23fb5f285 100644 --- a/spec/lib/gitlab/saml/user_spec.rb +++ b/spec/lib/gitlab/saml/user_spec.rb @@ -2,13 +2,15 @@ require 'spec_helper' describe Gitlab::Saml::User do include LdapHelpers + include LoginHelpers let(:saml_user) { described_class.new(auth_hash) } let(:gl_user) { saml_user.gl_user } let(:uid) { 'my-uid' } let(:dn) { 'uid=user1,ou=People,dc=example' } let(:provider) { 'saml' } - let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash, extra: { raw_info: OneLogin::RubySaml::Attributes.new({ 'groups' => %w(Developers Freelancers Designers) }) }) } + let(:raw_info_attr) { { 'groups' => %w(Developers Freelancers Designers) } } + let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash, extra: { raw_info: OneLogin::RubySaml::Attributes.new(raw_info_attr) }) } let(:info_hash) do { name: 'John', @@ -18,22 +20,6 @@ describe Gitlab::Saml::User do let(:ldap_user) { Gitlab::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') } describe '#save' do - def stub_omniauth_config(messages) - allow(Gitlab.config.omniauth).to receive_messages(messages) - end - - def stub_ldap_config(messages) - allow(Gitlab::LDAP::Config).to receive_messages(messages) - end - - def stub_basic_saml_config - allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', args: {} } }) - end - - def stub_saml_group_config(groups) - allow(Gitlab::Saml::Config).to receive_messages({ options: { name: 'saml', groups_attribute: 'groups', external_groups: groups, args: {} } }) - end - before do stub_basic_saml_config end @@ -402,4 +388,16 @@ describe Gitlab::Saml::User do end end end + + describe '#find_user' do + context 'raw info hash attributes empty' do + let(:raw_info_attr) { {} } + + it 'does not mark user as external' do + stub_saml_group_config(%w(Freelancers)) + + expect(saml_user.find_user.external).to be_falsy + end + end + end end diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb index c2e77ef6b6c..884f27b212c 100644 --- a/spec/lib/gitlab/sidekiq_status_spec.rb +++ b/spec/lib/gitlab/sidekiq_status_spec.rb @@ -39,6 +39,18 @@ describe Gitlab::SidekiqStatus do end end + describe '.running?', :clean_gitlab_redis_shared_state do + it 'returns true if job is running' do + described_class.set('123') + + expect(described_class.running?('123')).to be(true) + end + + it 'returns false if job is not found' do + expect(described_class.running?('123')).to be(false) + end + end + describe '.num_running', :clean_gitlab_redis_shared_state do it 'returns 0 if all jobs have been completed' do expect(described_class.num_running(%w(123))).to eq(0) diff --git a/spec/lib/gitlab/sql/union_spec.rb b/spec/lib/gitlab/sql/union_spec.rb index 8026fba9f0a..fe6422c32b6 100644 --- a/spec/lib/gitlab/sql/union_spec.rb +++ b/spec/lib/gitlab/sql/union_spec.rb @@ -29,5 +29,12 @@ describe Gitlab::SQL::Union do expect(union.to_sql).to include('UNION ALL') end + + it 'returns `NULL` if all relations are empty' do + empty_relation = User.none + union = described_class.new([empty_relation, empty_relation]) + + expect(union.to_sql).to eq('NULL') + end end end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 777e9c8e21d..a7b65e94706 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -61,6 +61,8 @@ describe Gitlab::UsageData do deployments environments gcp_clusters + gcp_clusters_enabled + gcp_clusters_disabled in_review_folder groups issues diff --git a/spec/lib/gitlab/utils/merge_hash_spec.rb b/spec/lib/gitlab/utils/merge_hash_spec.rb new file mode 100644 index 00000000000..4fa7bb31301 --- /dev/null +++ b/spec/lib/gitlab/utils/merge_hash_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' +describe Gitlab::Utils::MergeHash do + describe '.crush' do + it 'can flatten a hash to each element' do + input = { hello: "world", this: { crushes: ["an entire", "hash"] } } + expected_result = [:hello, "world", :this, :crushes, "an entire", "hash"] + + expect(described_class.crush(input)).to eq(expected_result) + end + end + + describe '.elements' do + it 'deep merges an array of elements' do + input = [{ hello: ["world"] }, + { hello: "Everyone" }, + { hello: { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzień dobry'] } }, + "Goodbye", "Hallo"] + expected_output = [ + { + hello: + [ + "world", + "Everyone", + { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzień dobry'] } + ] + }, + "Goodbye" + ] + + expect(described_class.merge(input)).to eq(expected_output) + end + end +end |