diff options
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/banzai/filter/milestone_reference_filter_spec.rb | 196 | ||||
-rw-r--r-- | spec/lib/gitlab/bitbucket_import/importer_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/daemon_spec.rb | 103 | ||||
-rw-r--r-- | spec/lib/gitlab/git/blob_spec.rb | 71 | ||||
-rw-r--r-- | spec/lib/gitlab/import_sources_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/key_fingerprint_spec.rb | 84 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/influx_sampler_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/sidekiq_metrics_exporter_spec.rb | 101 | ||||
-rw-r--r-- | spec/lib/gitlab/project_template_spec.rb | 63 | ||||
-rw-r--r-- | spec/lib/gitlab/shell_spec.rb | 90 |
10 files changed, 629 insertions, 85 deletions
diff --git a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb index 5db77566513..ebd6c79077e 100644 --- a/spec/lib/banzai/filter/milestone_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/milestone_reference_filter_spec.rb @@ -3,57 +3,57 @@ require 'spec_helper' describe Banzai::Filter::MilestoneReferenceFilter do include FilterSpecHelper - let(:project) { create(:project, :public) } - let(:milestone) { create(:milestone, project: project) } - let(:reference) { milestone.to_reference } + let(:group) { create(:group, :public) } + let(:project) { create(:project, :public, group: group) } it 'requires project context' do expect { described_class.call('') }.to raise_error(ArgumentError, /:project/) end - %w(pre code a style).each do |elem| - it "ignores valid references contained inside '#{elem}' element" do - exp = act = "<#{elem}>milestone #{milestone.to_reference}</#{elem}>" - expect(reference_filter(act).to_html).to eq exp + shared_examples 'reference parsing' do + %w(pre code a style).each do |elem| + it "ignores valid references contained inside '#{elem}' element" do + exp = act = "<#{elem}>milestone #{reference}</#{elem}>" + expect(reference_filter(act).to_html).to eq exp + end end - end - it 'includes default classes' do - doc = reference_filter("Milestone #{reference}") - expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone has-tooltip' - end + it 'includes default classes' do + doc = reference_filter("Milestone #{reference}") - it 'includes a data-project attribute' do - doc = reference_filter("Milestone #{reference}") - link = doc.css('a').first + expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-milestone has-tooltip' + end - expect(link).to have_attribute('data-project') - expect(link.attr('data-project')).to eq project.id.to_s - end + it 'includes a data-project attribute' do + doc = reference_filter("Milestone #{reference}") + link = doc.css('a').first - it 'includes a data-milestone attribute' do - doc = reference_filter("See #{reference}") - link = doc.css('a').first + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end - expect(link).to have_attribute('data-milestone') - expect(link.attr('data-milestone')).to eq milestone.id.to_s - end + it 'includes a data-milestone attribute' do + doc = reference_filter("See #{reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-milestone') + expect(link.attr('data-milestone')).to eq milestone.id.to_s + end - it 'supports an :only_path context' do - doc = reference_filter("Milestone #{reference}", only_path: true) - link = doc.css('a').first.attr('href') + it 'supports an :only_path context' do + doc = reference_filter("Milestone #{reference}", only_path: true) + link = doc.css('a').first.attr('href') - expect(link).not_to match %r(https?://) - expect(link).to eq urls - .project_milestone_path(project, milestone) + expect(link).not_to match %r(https?://) + expect(link).to eq urls.milestone_path(milestone) + end end - context 'Integer-based references' do + shared_examples 'Integer-based references' do it 'links to a valid reference' do doc = reference_filter("See #{reference}") - expect(doc.css('a').first.attr('href')).to eq urls - .project_milestone_url(project, milestone) + expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone) end it 'links with adjacent text' do @@ -68,15 +68,17 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - context 'String-based single-word references' do - let(:milestone) { create(:milestone, name: 'gfm', project: project) } + shared_examples 'String-based single-word references' do let(:reference) { "#{Milestone.reference_prefix}#{milestone.name}" } + before do + milestone.update!(name: 'gfm') + end + it 'links to a valid reference' do doc = reference_filter("See #{reference}") - expect(doc.css('a').first.attr('href')).to eq urls - .project_milestone_url(project, milestone) + expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone) expect(doc.text).to eq 'See gfm' end @@ -92,15 +94,17 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - context 'String-based multi-word references in quotes' do - let(:milestone) { create(:milestone, name: 'gfm references', project: project) } + shared_examples 'String-based multi-word references in quotes' do let(:reference) { milestone.to_reference(format: :name) } + before do + milestone.update!(name: 'gfm references') + end + it 'links to a valid reference' do doc = reference_filter("See #{reference}") - expect(doc.css('a').first.attr('href')).to eq urls - .project_milestone_url(project, milestone) + expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone) expect(doc.text).to eq 'See gfm references' end @@ -116,23 +120,27 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - describe 'referencing a milestone in a link href' do - let(:reference) { %Q{<a href="#{milestone.to_reference}">Milestone</a>} } + shared_examples 'referencing a milestone in a link href' do + let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" } + let(:link_reference) { %Q{<a href="#{unquoted_reference}">Milestone</a>} } + + before do + milestone.update!(name: 'gfm') + end it 'links to a valid reference' do - doc = reference_filter("See #{reference}") + doc = reference_filter("See #{link_reference}") - expect(doc.css('a').first.attr('href')).to eq urls - .project_milestone_url(project, milestone) + expect(doc.css('a').first.attr('href')).to eq urls.milestone_url(milestone) end it 'links with adjacent text' do - doc = reference_filter("Milestone (#{reference}.)") + doc = reference_filter("Milestone (#{link_reference}.)") expect(doc.to_html).to match(%r(\(<a.+>Milestone</a>\.\))) end it 'includes a data-project attribute' do - doc = reference_filter("Milestone #{reference}") + doc = reference_filter("Milestone #{link_reference}") link = doc.css('a').first expect(link).to have_attribute('data-project') @@ -140,7 +148,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do end it 'includes a data-milestone attribute' do - doc = reference_filter("See #{reference}") + doc = reference_filter("See #{link_reference}") link = doc.css('a').first expect(link).to have_attribute('data-milestone') @@ -148,7 +156,35 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - describe 'cross-project / cross-namespace complete reference' do + shared_examples 'linking to a milestone as the entire link' do + let(:unquoted_reference) { "#{Milestone.reference_prefix}#{milestone.name}" } + let(:link) { urls.milestone_url(milestone) } + let(:link_reference) { %Q{<a href="#{link}">#{link}</a>} } + + it 'replaces the link text with the milestone reference' do + doc = reference_filter("See #{link}") + + expect(doc.css('a').first.text).to eq(unquoted_reference) + end + + it 'includes a data-project attribute' do + doc = reference_filter("Milestone #{link_reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-project') + expect(link.attr('data-project')).to eq project.id.to_s + end + + it 'includes a data-milestone attribute' do + doc = reference_filter("See #{link_reference}") + link = doc.css('a').first + + expect(link).to have_attribute('data-milestone') + expect(link.attr('data-milestone')).to eq milestone.id.to_s + end + end + + shared_examples 'cross-project / cross-namespace complete reference' do let(:namespace) { create(:namespace) } let(:another_project) { create(:project, :public, namespace: namespace) } let(:milestone) { create(:milestone, project: another_project) } @@ -184,7 +220,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - describe 'cross-project / same-namespace complete reference' do + shared_examples 'cross-project / same-namespace complete reference' do let(:namespace) { create(:namespace) } let(:project) { create(:project, :public, namespace: namespace) } let(:another_project) { create(:project, :public, namespace: namespace) } @@ -221,7 +257,7 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - describe 'cross project shorthand reference' do + shared_examples 'cross project shorthand reference' do let(:namespace) { create(:namespace) } let(:project) { create(:project, :public, namespace: namespace) } let(:another_project) { create(:project, :public, namespace: namespace) } @@ -258,27 +294,53 @@ describe Banzai::Filter::MilestoneReferenceFilter do end end - describe 'cross project milestone references' do - let(:another_project) { create(:project, :public) } - let(:project_path) { another_project.full_path } - let(:milestone) { create(:milestone, project: another_project) } - let(:reference) { milestone.to_reference(project) } + context 'project milestones' do + let(:milestone) { create(:milestone, project: project) } + let(:reference) { milestone.to_reference } - let!(:result) { reference_filter("See #{reference}") } + include_examples 'reference parsing' - it 'points to referenced project milestone page' do - expect(result.css('a').first.attr('href')).to eq urls - .project_milestone_url(another_project, milestone) + it_behaves_like 'Integer-based references' + it_behaves_like 'String-based single-word references' + it_behaves_like 'String-based multi-word references in quotes' + it_behaves_like 'referencing a milestone in a link href' + it_behaves_like 'cross-project / cross-namespace complete reference' + it_behaves_like 'cross-project / same-namespace complete reference' + it_behaves_like 'cross project shorthand reference' + end + + context 'group milestones' do + let(:milestone) { create(:milestone, group: group) } + let(:reference) { milestone.to_reference(format: :name) } + + include_examples 'reference parsing' + + it_behaves_like 'String-based single-word references' + it_behaves_like 'String-based multi-word references in quotes' + it_behaves_like 'referencing a milestone in a link href' + + it 'does not support references by IID' do + doc = reference_filter("See #{Milestone.reference_prefix}#{milestone.iid}") + + expect(doc.css('a')).to be_empty end - it 'contains cross project content' do - expect(result.css('a').first.text).to eq "#{milestone.name} in #{project_path}" + it 'does not support references by link' do + doc = reference_filter("See #{urls.milestone_url(milestone)}") + + expect(doc.css('a').first.text).to eq(urls.milestone_url(milestone)) end - it 'escapes the name attribute' do - allow_any_instance_of(Milestone).to receive(:title).and_return(%{"></a>whatever<a title="}) - doc = reference_filter("See #{reference}") - expect(doc.css('a').first.text).to eq "#{milestone.name} in #{project_path}" + it 'does not support cross-project references' do + another_group = create(:group) + another_project = create(:project, :public, group: group) + project_reference = another_project.to_reference(project) + + milestone.update!(group: another_group) + + doc = reference_filter("See #{project_reference}#{reference}") + + expect(doc.css('a')).to be_empty end end end diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb index d7d6a37f7cf..a66347ead76 100644 --- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb @@ -54,7 +54,7 @@ describe Gitlab::BitbucketImport::Importer do create( :project, import_source: project_identifier, - import_data: ProjectImportData.new(credentials: data) + import_data_attributes: { credentials: data } ) end diff --git a/spec/lib/gitlab/daemon_spec.rb b/spec/lib/gitlab/daemon_spec.rb new file mode 100644 index 00000000000..c519984a267 --- /dev/null +++ b/spec/lib/gitlab/daemon_spec.rb @@ -0,0 +1,103 @@ +require 'spec_helper' + +describe Gitlab::Daemon do + subject { described_class.new } + + before do + allow(subject).to receive(:start_working) + allow(subject).to receive(:stop_working) + end + + describe '.instance' do + before do + allow(Kernel).to receive(:at_exit) + end + + after(:each) do + described_class.instance_variable_set(:@instance, nil) + end + + it 'provides instance of Daemon' do + expect(described_class.instance).to be_instance_of(described_class) + end + + it 'subsequent invocations provide the same instance' do + expect(described_class.instance).to eq(described_class.instance) + end + + it 'creates at_exit hook when instance is created' do + expect(described_class.instance).not_to be_nil + + expect(Kernel).to have_received(:at_exit) + end + end + + describe 'when Daemon is enabled' do + before do + allow(subject).to receive(:enabled?).and_return(true) + end + + describe 'when Daemon is stopped' do + describe '#start' do + it 'starts the Daemon' do + expect { subject.start.join }.to change { subject.thread? }.from(false).to(true) + + expect(subject).to have_received(:start_working) + end + end + + describe '#stop' do + it "doesn't shutdown stopped Daemon" do + expect { subject.stop }.not_to change { subject.thread? } + + expect(subject).not_to have_received(:start_working) + end + end + end + + describe 'when Daemon is running' do + before do + subject.start.join + end + + describe '#start' do + it "doesn't start running Daemon" do + expect { subject.start.join }.not_to change { subject.thread? } + + expect(subject).to have_received(:start_working).once + end + end + + describe '#stop' do + it 'shutdowns Daemon' do + expect { subject.stop }.to change { subject.thread? }.from(true).to(false) + + expect(subject).to have_received(:stop_working) + end + end + end + end + + describe 'when Daemon is disabled' do + before do + allow(subject).to receive(:enabled?).and_return(false) + end + + describe '#start' do + it "doesn't start working" do + expect(subject.start).to be_nil + expect { subject.start }.not_to change { subject.thread? } + + expect(subject).not_to have_received(:start_working) + end + end + + describe '#stop' do + it "doesn't stop working" do + expect { subject.stop }.not_to change { subject.thread? } + + expect(subject).not_to have_received(:stop_working) + end + end + end +end diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb index 18320bb23b9..dfab0c2fe85 100644 --- a/spec/lib/gitlab/git/blob_spec.rb +++ b/spec/lib/gitlab/git/blob_spec.rb @@ -152,6 +152,77 @@ describe Gitlab::Git::Blob, seed_helper: true do end end + describe '.batch' do + let(:blob_references) do + [ + [SeedRepo::Commit::ID, "files/ruby/popen.rb"], + [SeedRepo::Commit::ID, 'six'] + ] + end + + subject { described_class.batch(repository, blob_references) } + + it { expect(subject.size).to eq(blob_references.size) } + + context 'first blob' do + let(:blob) { subject[0] } + + it { expect(blob.id).to eq(SeedRepo::RubyBlob::ID) } + it { expect(blob.name).to eq(SeedRepo::RubyBlob::NAME) } + it { expect(blob.path).to eq("files/ruby/popen.rb") } + it { expect(blob.commit_id).to eq(SeedRepo::Commit::ID) } + it { expect(blob.data[0..10]).to eq(SeedRepo::RubyBlob::CONTENT[0..10]) } + it { expect(blob.size).to eq(669) } + it { expect(blob.mode).to eq("100644") } + end + + context 'second blob' do + let(:blob) { subject[1] } + + it { expect(blob.id).to eq('409f37c4f05865e4fb208c771485f211a22c4c2d') } + it { expect(blob.data).to eq('') } + it 'does not mark the blob as binary' do + expect(blob).not_to be_binary + end + end + + context 'limiting' do + subject { described_class.batch(repository, blob_references, blob_size_limit: blob_size_limit) } + + context 'default' do + let(:blob_size_limit) { nil } + + it 'limits to MAX_DATA_DISPLAY_SIZE' do + stub_const('Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE', 100) + + expect(subject.first.data.size).to eq(100) + end + end + + context 'positive' do + let(:blob_size_limit) { 10 } + + it { expect(subject.first.data.size).to eq(10) } + end + + context 'zero' do + let(:blob_size_limit) { 0 } + + it { expect(subject.first.data).to eq('') } + end + + context 'negative' do + let(:blob_size_limit) { -1 } + + it 'ignores MAX_DATA_DISPLAY_SIZE' do + stub_const('Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE', 100) + + expect(subject.first.data.size).to eq(669) + end + end + end + end + describe 'encoding' do context 'file with russian text' do let(:blob) { Gitlab::Git::Blob.find(repository, SeedRepo::Commit::ID, "encoding/russian.rb") } diff --git a/spec/lib/gitlab/import_sources_spec.rb b/spec/lib/gitlab/import_sources_spec.rb index b3b5e5e7e33..c5725f47453 100644 --- a/spec/lib/gitlab/import_sources_spec.rb +++ b/spec/lib/gitlab/import_sources_spec.rb @@ -56,7 +56,7 @@ describe Gitlab::ImportSources do describe '.importer' do import_sources = { - 'github' => Gitlab::GithubImport::Importer, + 'github' => Github::Import, 'bitbucket' => Gitlab::BitbucketImport::Importer, 'gitlab' => Gitlab::GitlabImport::Importer, 'google_code' => Gitlab::GoogleCodeImport::Importer, diff --git a/spec/lib/gitlab/key_fingerprint_spec.rb b/spec/lib/gitlab/key_fingerprint_spec.rb index d7bebaca675..f5fd5a96bc9 100644 --- a/spec/lib/gitlab/key_fingerprint_spec.rb +++ b/spec/lib/gitlab/key_fingerprint_spec.rb @@ -1,12 +1,82 @@ -require "spec_helper" +require 'spec_helper' -describe Gitlab::KeyFingerprint do - let(:key) { "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" } - let(:fingerprint) { "3f:a2:ee:de:b5:de:53:c3:aa:2f:9c:45:24:4c:47:7b" } +describe Gitlab::KeyFingerprint, lib: true do + KEYS = { + rsa: + 'example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5z65PwQ1GE6foJgwk' \ + '9rmQi/glaXbUeVa5uvQpnZ3Z5+forcI7aTngh3aZ/H2UDP2L70TGy7kKNyp0J3a8/OdG' \ + 'Z08y5yi3JlbjFARO1NyoFEjw2H1SJxeJ43L6zmvTlu+hlK1jSAlidl7enS0ufTlzEEj4' \ + 'iJcuTPKdVzKRgZuTRVm9woWNVKqIrdRC0rJiTinERnfSAp/vNYERMuaoN4oJt8p/NEek' \ + 'rmFoDsQOsyDW5RAnCnjWUU+jFBKDpfkJQ1U2n6BjJewC9dl6ODK639l3yN4WOLZEk4tN' \ + 'UysfbGeF3rmMeflaD6O1Jplpv3YhwVGFNKa7fMq6k3Z0tszTJPYh', + ecdsa: + 'example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAI' \ + 'bmlzdHAyNTYAAABBBKTJy43NZzJSfNxpv/e2E6Zy3qoHoTQbmOsU5FEfpWfWa1MdTeXQ' \ + 'YvKOi+qz/1AaNx6BK421jGu74JCDJtiZWT8=', + ed25519: + '@revoked example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjq' \ + 'uxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf', + dss: + 'example.com ssh-dss AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdS' \ + 'PO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f' \ + '6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iID' \ + 'GZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhX' \ + 'uXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwW' \ + 'eotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6A' \ + 'e1UlZAFMO/7PSSoAAACBAJcQ4JODqhuGbXIEpqxetm7PWbdbCcr3y/GzIZ066pRovpL6' \ + 'qm3qCVIym4cyChxWwb8qlyCIi+YRUUWm1z/wiBYT2Vf3S4FXBnyymCkKEaV/EY7+jd4X' \ + '1bXI58OD2u+bLCB/sInM4fGB8CZUIWT9nJH0Ve9jJUge2ms348/QOJ1+' + }.freeze - describe "#fingerprint" do - it "generates the key's fingerprint" do - expect(described_class.new(key).fingerprint).to eq(fingerprint) + MD5_FINGERPRINTS = { + rsa: '06:b2:8a:92:df:0e:11:2c:ca:7b:8f:a4:ba:6e:4b:fd', + ecdsa: '45:ff:5b:98:9a:b6:8a:41:13:c1:30:8b:09:5e:7b:4e', + ed25519: '2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16', + dss: '57:98:86:02:5f:9c:f4:9b:ad:5a:1e:51:92:0e:fd:2b' + }.freeze + + BIT_COUNTS = { + rsa: 2048, + ecdsa: 256, + ed25519: 256, + dss: 1024 + }.freeze + + describe '#type' do + KEYS.each do |type, key| + it "calculates the type of #{type} keys" do + calculated_type = described_class.new(key).type + + expect(calculated_type).to eq(type.to_s.upcase) + end + end + end + + describe '#fingerprint' do + KEYS.each do |type, key| + it "calculates the MD5 fingerprint for #{type} keys" do + fp = described_class.new(key).fingerprint + + expect(fp).to eq(MD5_FINGERPRINTS[type]) + end + end + end + + describe '#bits' do + KEYS.each do |type, key| + it "calculates the number of bits in #{type} keys" do + bits = described_class.new(key).bits + + expect(bits).to eq(BIT_COUNTS[type]) + end + end + end + + describe '#key' do + it 'carries the unmodified key data' do + key = described_class.new(KEYS[:rsa]).key + + expect(key).to eq(KEYS[:rsa]) end end end diff --git a/spec/lib/gitlab/metrics/influx_sampler_spec.rb b/spec/lib/gitlab/metrics/influx_sampler_spec.rb index 0bc68d64276..999a9536d82 100644 --- a/spec/lib/gitlab/metrics/influx_sampler_spec.rb +++ b/spec/lib/gitlab/metrics/influx_sampler_spec.rb @@ -11,7 +11,7 @@ describe Gitlab::Metrics::InfluxSampler do it 'runs once and gathers a sample at a given interval' do expect(sampler).to receive(:sleep).with(a_kind_of(Numeric)).twice expect(sampler).to receive(:sample).once - expect(sampler).to receive(:running).and_return(false, true, false) + expect(sampler).to receive(:running).and_return(true, false) sampler.start.join end diff --git a/spec/lib/gitlab/metrics/sidekiq_metrics_exporter_spec.rb b/spec/lib/gitlab/metrics/sidekiq_metrics_exporter_spec.rb new file mode 100644 index 00000000000..6721e02fb85 --- /dev/null +++ b/spec/lib/gitlab/metrics/sidekiq_metrics_exporter_spec.rb @@ -0,0 +1,101 @@ +require 'spec_helper' + +describe Gitlab::Metrics::SidekiqMetricsExporter do + let(:exporter) { described_class.new } + let(:server) { double('server') } + + before do + allow(::WEBrick::HTTPServer).to receive(:new).and_return(server) + allow(server).to receive(:mount) + allow(server).to receive(:start) + allow(server).to receive(:shutdown) + end + + describe 'when exporter is enabled' do + before do + allow(Settings.monitoring.sidekiq_exporter).to receive(:enabled).and_return(true) + end + + describe 'when exporter is stopped' do + describe '#start' do + it 'starts the exporter' do + expect { exporter.start.join }.to change { exporter.thread? }.from(false).to(true) + + expect(server).to have_received(:start) + end + + describe 'with custom settings' do + let(:port) { 99999 } + let(:address) { 'sidekiq_exporter_address' } + + before do + allow(Settings.monitoring.sidekiq_exporter).to receive(:port).and_return(port) + allow(Settings.monitoring.sidekiq_exporter).to receive(:address).and_return(address) + end + + it 'starts server with port and address from settings' do + exporter.start.join + + expect(::WEBrick::HTTPServer).to have_received(:new).with( + Port: port, + BindAddress: address + ) + end + end + end + + describe '#stop' do + it "doesn't shutdown stopped server" do + expect { exporter.stop }.not_to change { exporter.thread? } + + expect(server).not_to have_received(:shutdown) + end + end + end + + describe 'when exporter is running' do + before do + exporter.start.join + end + + describe '#start' do + it "doesn't start running server" do + expect { exporter.start.join }.not_to change { exporter.thread? } + + expect(server).to have_received(:start).once + end + end + + describe '#stop' do + it 'shutdowns server' do + expect { exporter.stop }.to change { exporter.thread? }.from(true).to(false) + + expect(server).to have_received(:shutdown) + end + end + end + end + + describe 'when exporter is disabled' do + before do + allow(Settings.monitoring.sidekiq_exporter).to receive(:enabled).and_return(false) + end + + describe '#start' do + it "doesn't start" do + expect(exporter.start).to be_nil + expect { exporter.start }.not_to change { exporter.thread? } + + expect(server).not_to have_received(:start) + end + end + + describe '#stop' do + it "doesn't shutdown" do + expect { exporter.stop }.not_to change { exporter.thread? } + + expect(server).not_to have_received(:shutdown) + end + end + end +end diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb new file mode 100644 index 00000000000..12e75cdd5d0 --- /dev/null +++ b/spec/lib/gitlab/project_template_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe Gitlab::ProjectTemplate do + describe '.all' do + it 'returns a all templates' do + expected = [ + described_class.new('rails', 'Ruby on Rails') + ] + + expect(described_class.all).to be_an(Array) + expect(described_class.all).to eq(expected) + end + end + + describe '.find' do + subject { described_class.find(query) } + + context 'when there is a match' do + let(:query) { :rails } + + it { is_expected.to be_a(described_class) } + end + + context 'when there is no match' do + let(:query) { 'no-match' } + + it { is_expected.to be(nil) } + end + end + + describe 'instance methods' do + subject { described_class.new('phoenix', 'Phoenix Framework') } + + it { is_expected.to respond_to(:logo, :file, :archive_path) } + end + + describe 'validate all templates' do + set(:admin) { create(:admin) } + + described_class.all.each do |template| + it "#{template.name} has a valid archive" do + archive = template.archive_path + + expect(File.exist?(archive)).to be(true) + end + + context 'with valid parameters' do + it 'can be imported' do + params = { + template_name: template.name, + namespace_id: admin.namespace.id, + path: template.name + } + + project = Projects::CreateFromTemplateService.new(admin, params).execute + + expect(project).to be_valid + expect(project).to be_persisted + end + end + end + end +end diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb index b90d8dede0f..2345874cf10 100644 --- a/spec/lib/gitlab/shell_spec.rb +++ b/spec/lib/gitlab/shell_spec.rb @@ -174,20 +174,94 @@ describe Gitlab::Shell do end describe '#fetch_remote' do + def fetch_remote(ssh_auth = nil) + gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage', ssh_auth: ssh_auth) + end + + def expect_popen(vars = {}) + popen_args = [ + projects_path, + 'fetch-remote', + 'current/storage', + 'project/path.git', + 'new/storage', + Gitlab.config.gitlab_shell.git_timeout.to_s + ] + + expect(Gitlab::Popen).to receive(:popen).with(popen_args, nil, popen_vars.merge(vars)) + end + + def build_ssh_auth(opts = {}) + defaults = { + ssh_import?: true, + ssh_key_auth?: false, + ssh_known_hosts: nil, + ssh_private_key: nil + } + + double(:ssh_auth, defaults.merge(opts)) + end + it 'returns true when the command succeeds' do - expect(Gitlab::Popen).to receive(:popen) - .with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800'], - nil, popen_vars).and_return([nil, 0]) + expect_popen.and_return([nil, 0]) - expect(gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage')).to be true + expect(fetch_remote).to be_truthy end it 'raises an exception when the command fails' do - expect(Gitlab::Popen).to receive(:popen) - .with([projects_path, 'fetch-remote', 'current/storage', 'project/path.git', 'new/storage', '800'], - nil, popen_vars).and_return(["error", 1]) + expect_popen.and_return(["error", 1]) + + expect { fetch_remote }.to raise_error(Gitlab::Shell::Error, "error") + end + + context 'SSH auth' do + it 'passes the SSH key if specified' do + expect_popen('GITLAB_SHELL_SSH_KEY' => 'foo').and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_key_auth?: true, ssh_private_key: 'foo') + + expect(fetch_remote(ssh_auth)).to be_truthy + end + + it 'does not pass an empty SSH key' do + expect_popen.and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_key_auth: true, ssh_private_key: '') + + expect(fetch_remote(ssh_auth)).to be_truthy + end + + it 'does not pass the key unless SSH key auth is to be used' do + expect_popen.and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_key_auth: false, ssh_private_key: 'foo') + + expect(fetch_remote(ssh_auth)).to be_truthy + end + + it 'passes the known_hosts data if specified' do + expect_popen('GITLAB_SHELL_KNOWN_HOSTS' => 'foo').and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_known_hosts: 'foo') + + expect(fetch_remote(ssh_auth)).to be_truthy + end + + it 'does not pass empty known_hosts data' do + expect_popen.and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_known_hosts: '') + + expect(fetch_remote(ssh_auth)).to be_truthy + end + + it 'does not pass known_hosts data unless SSH is to be used' do + expect_popen(popen_vars).and_return([nil, 0]) + + ssh_auth = build_ssh_auth(ssh_import?: false, ssh_known_hosts: 'foo') - expect { gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage') }.to raise_error(Gitlab::Shell::Error, "error") + expect(fetch_remote(ssh_auth)).to be_truthy + end end end |