summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab
diff options
context:
space:
mode:
authorJose Ivan Vargas <jvargas@gitlab.com>2017-09-03 16:09:59 -0500
committerJose Ivan Vargas <jvargas@gitlab.com>2017-09-03 16:09:59 -0500
commitb623807682022a54344d8213d6f1c902be6ade37 (patch)
tree478ee3a25d67cb452aac09cfd42967fcfc7c22b9 /spec/lib/gitlab
parent28060caa0ade7566a38e3ed17f2db8bf9116dc1b (diff)
parent81002745184df28fc9d969afc524986279c653bb (diff)
downloadgitlab-ce-b623807682022a54344d8213d6f1c902be6ade37.tar.gz
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce
Diffstat (limited to 'spec/lib/gitlab')
-rw-r--r--spec/lib/gitlab/auth_spec.rb10
-rw-r--r--spec/lib/gitlab/git_access_spec.rb38
-rw-r--r--spec/lib/gitlab/i18n/metadata_entry_spec.rb51
-rw-r--r--spec/lib/gitlab/i18n/po_linter_spec.rb337
-rw-r--r--spec/lib/gitlab/i18n/translation_entry_spec.rb203
-rw-r--r--spec/lib/gitlab/key_fingerprint_spec.rb82
-rw-r--r--spec/lib/gitlab/sentry_spec.rb13
-rw-r--r--spec/lib/gitlab/ssh_public_key_spec.rb136
-rw-r--r--spec/lib/gitlab/utils_spec.rb8
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb17
10 files changed, 788 insertions, 107 deletions
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 4a498e79c87..f685bb83d0d 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -279,16 +279,6 @@ describe Gitlab::Auth do
gl_auth.find_with_user_password('ldap_user', 'password')
end
end
-
- context "with sign-in disabled" do
- before do
- stub_application_setting(password_authentication_enabled: false)
- end
-
- it "does not find user by valid login/password" do
- expect(gl_auth.find_with_user_password(username, password)).to be_nil
- end
- end
end
private
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 295a979da76..458627ee4de 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -155,6 +155,44 @@ describe Gitlab::GitAccess do
end
end
+ shared_examples '#check with a key that is not valid' do
+ before do
+ project.add_master(user)
+ end
+
+ context 'key is too small' do
+ before do
+ stub_application_setting(rsa_key_restriction: 4096)
+ end
+
+ it 'does not allow keys which are too small', aggregate_failures: true do
+ expect(actor).not_to be_valid
+ expect { pull_access_check }.to raise_unauthorized('Your SSH key must be at least 4096 bits.')
+ expect { push_access_check }.to raise_unauthorized('Your SSH key must be at least 4096 bits.')
+ end
+ end
+
+ context 'key type is not allowed' do
+ before do
+ stub_application_setting(rsa_key_restriction: ApplicationSetting::FORBIDDEN_KEY_VALUE)
+ end
+
+ it 'does not allow keys which are too small', aggregate_failures: true do
+ expect(actor).not_to be_valid
+ expect { pull_access_check }.to raise_unauthorized(/Your SSH key type is forbidden/)
+ expect { push_access_check }.to raise_unauthorized(/Your SSH key type is forbidden/)
+ end
+ end
+ end
+
+ it_behaves_like '#check with a key that is not valid' do
+ let(:actor) { build(:rsa_key_2048, user: user) }
+ end
+
+ it_behaves_like '#check with a key that is not valid' do
+ let(:actor) { build(:rsa_deploy_key_2048, user: user) }
+ end
+
describe '#check_project_moved!' do
before do
project.add_master(user)
diff --git a/spec/lib/gitlab/i18n/metadata_entry_spec.rb b/spec/lib/gitlab/i18n/metadata_entry_spec.rb
new file mode 100644
index 00000000000..ab71d6454a9
--- /dev/null
+++ b/spec/lib/gitlab/i18n/metadata_entry_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Gitlab::I18n::MetadataEntry do
+ describe '#expected_plurals' do
+ it 'returns the number of plurals' do
+ data = {
+ msgid: "",
+ msgstr: [
+ "",
+ "Project-Id-Version: gitlab 1.0.0\\n",
+ "Report-Msgid-Bugs-To: \\n",
+ "PO-Revision-Date: 2017-07-13 12:10-0500\\n",
+ "Language-Team: Spanish\\n",
+ "Language: es\\n",
+ "MIME-Version: 1.0\\n",
+ "Content-Type: text/plain; charset=UTF-8\\n",
+ "Content-Transfer-Encoding: 8bit\\n",
+ "Plural-Forms: nplurals=2; plural=n != 1;\\n",
+ "Last-Translator: Bob Van Landuyt <bob@gitlab.com>\\n",
+ "X-Generator: Poedit 2.0.2\\n"
+ ]
+ }
+ entry = described_class.new(data)
+
+ expect(entry.expected_plurals).to eq(2)
+ end
+
+ it 'returns 0 for the POT-metadata' do
+ data = {
+ msgid: "",
+ msgstr: [
+ "",
+ "Project-Id-Version: gitlab 1.0.0\\n",
+ "Report-Msgid-Bugs-To: \\n",
+ "PO-Revision-Date: 2017-07-13 12:10-0500\\n",
+ "Language-Team: Spanish\\n",
+ "Language: es\\n",
+ "MIME-Version: 1.0\\n",
+ "Content-Type: text/plain; charset=UTF-8\\n",
+ "Content-Transfer-Encoding: 8bit\\n",
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n",
+ "Last-Translator: Bob Van Landuyt <bob@gitlab.com>\\n",
+ "X-Generator: Poedit 2.0.2\\n"
+ ]
+ }
+ entry = described_class.new(data)
+
+ expect(entry.expected_plurals).to eq(0)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/i18n/po_linter_spec.rb b/spec/lib/gitlab/i18n/po_linter_spec.rb
new file mode 100644
index 00000000000..cd5c2b99751
--- /dev/null
+++ b/spec/lib/gitlab/i18n/po_linter_spec.rb
@@ -0,0 +1,337 @@
+require 'spec_helper'
+
+describe Gitlab::I18n::PoLinter do
+ let(:linter) { described_class.new(po_path) }
+ let(:po_path) { 'spec/fixtures/valid.po' }
+
+ describe '#errors' do
+ it 'only calls validation once' do
+ expect(linter).to receive(:validate_po).once.and_call_original
+
+ 2.times { linter.errors }
+ end
+ end
+
+ describe '#validate_po' do
+ subject(:errors) { linter.validate_po }
+
+ context 'for a fuzzy message' do
+ let(:po_path) { 'spec/fixtures/fuzzy.po' }
+
+ it 'has an error' do
+ is_expected.to include('PipelineSchedules|Remove variable row' => ['is marked fuzzy'])
+ end
+ end
+
+ context 'for a translations with newlines' do
+ let(:po_path) { 'spec/fixtures/newlines.po' }
+
+ it 'has an error for a normal string' do
+ message_id = "You are going to remove %{group_name}.\\nRemoved groups CANNOT be restored!\\nAre you ABSOLUTELY sure?"
+ expected_message = "is defined over multiple lines, this breaks some tooling."
+
+ expect(errors[message_id]).to include(expected_message)
+ end
+
+ it 'has an error when a translation is defined over multiple lines' do
+ message_id = "You are going to remove %{group_name}.\\nRemoved groups CANNOT be restored!\\nAre you ABSOLUTELY sure?"
+ expected_message = "has translations defined over multiple lines, this breaks some tooling."
+
+ expect(errors[message_id]).to include(expected_message)
+ end
+
+ it 'raises an error when a plural translation is defined over multiple lines' do
+ message_id = 'With plural'
+ expected_message = "has translations defined over multiple lines, this breaks some tooling."
+
+ expect(errors[message_id]).to include(expected_message)
+ end
+
+ it 'raises an error when the plural id is defined over multiple lines' do
+ message_id = 'multiline plural id'
+ expected_message = "plural is defined over multiple lines, this breaks some tooling."
+
+ expect(errors[message_id]).to include(expected_message)
+ end
+ end
+
+ context 'with an invalid po' do
+ let(:po_path) { 'spec/fixtures/invalid.po' }
+
+ it 'returns the error' do
+ is_expected.to include('PO-syntax errors' => a_kind_of(Array))
+ end
+
+ it 'does not validate entries' do
+ expect(linter).not_to receive(:validate_entries)
+
+ linter.validate_po
+ end
+ end
+
+ context 'with missing metadata' do
+ let(:po_path) { 'spec/fixtures/missing_metadata.po' }
+
+ it 'returns the an error' do
+ is_expected.to include('PO-syntax errors' => a_kind_of(Array))
+ end
+ end
+
+ context 'with a valid po' do
+ it 'parses the file' do
+ expect(linter).to receive(:parse_po).and_call_original
+
+ linter.validate_po
+ end
+
+ it 'validates the entries' do
+ expect(linter).to receive(:validate_entries).and_call_original
+
+ linter.validate_po
+ end
+
+ it 'has no errors' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'with missing plurals' do
+ let(:po_path) { 'spec/fixtures/missing_plurals.po' }
+
+ it 'has errors' do
+ is_expected.not_to be_empty
+ end
+ end
+
+ context 'with multiple plurals' do
+ let(:po_path) { 'spec/fixtures/multiple_plurals.po' }
+
+ it 'has errors' do
+ is_expected.not_to be_empty
+ end
+ end
+
+ context 'with unescaped chars' do
+ let(:po_path) { 'spec/fixtures/unescaped_chars.po' }
+
+ it 'contains an error' do
+ message_id = 'You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?'
+ expected_error = 'translation contains unescaped `%`, escape it using `%%`'
+
+ expect(errors[message_id]).to include(expected_error)
+ end
+ end
+ end
+
+ describe '#parse_po' do
+ context 'with a valid po' do
+ it 'fills in the entries' do
+ linter.parse_po
+
+ expect(linter.translation_entries).not_to be_empty
+ expect(linter.metadata_entry).to be_kind_of(Gitlab::I18n::MetadataEntry)
+ end
+
+ it 'does not have errors' do
+ expect(linter.parse_po).to be_nil
+ end
+ end
+
+ context 'with an invalid po' do
+ let(:po_path) { 'spec/fixtures/invalid.po' }
+
+ it 'contains an error' do
+ expect(linter.parse_po).not_to be_nil
+ end
+
+ it 'sets the entries to an empty array' do
+ linter.parse_po
+
+ expect(linter.translation_entries).to eq([])
+ end
+ end
+ end
+
+ describe '#validate_entries' do
+ it 'keeps track of errors for entries' do
+ fake_invalid_entry = Gitlab::I18n::TranslationEntry.new(
+ { msgid: "Hello %{world}", msgstr: "Bonjour %{monde}" }, 2
+ )
+ allow(linter).to receive(:translation_entries) { [fake_invalid_entry] }
+
+ expect(linter).to receive(:validate_entry)
+ .with(fake_invalid_entry)
+ .and_call_original
+
+ expect(linter.validate_entries).to include("Hello %{world}" => an_instance_of(Array))
+ end
+ end
+
+ describe '#validate_entry' do
+ it 'validates the flags, variable usage, newlines, and unescaped chars' do
+ fake_entry = double
+
+ expect(linter).to receive(:validate_flags).with([], fake_entry)
+ expect(linter).to receive(:validate_variables).with([], fake_entry)
+ expect(linter).to receive(:validate_newlines).with([], fake_entry)
+ expect(linter).to receive(:validate_number_of_plurals).with([], fake_entry)
+ expect(linter).to receive(:validate_unescaped_chars).with([], fake_entry)
+
+ linter.validate_entry(fake_entry)
+ end
+ end
+
+ describe '#validate_number_of_plurals' do
+ it 'validates when there are an incorrect number of translations' do
+ fake_metadata = double
+ allow(fake_metadata).to receive(:expected_plurals).and_return(2)
+ allow(linter).to receive(:metadata_entry).and_return(fake_metadata)
+
+ fake_entry = Gitlab::I18n::TranslationEntry.new(
+ { msgid: 'the singular', msgid_plural: 'the plural', 'msgstr[0]' => 'the singular' },
+ 2
+ )
+ errors = []
+
+ linter.validate_number_of_plurals(errors, fake_entry)
+
+ expect(errors).to include('should have 2 translations')
+ end
+ end
+
+ describe '#validate_variables' do
+ it 'validates both signular and plural in a pluralized string when the entry has a singular' do
+ pluralized_entry = Gitlab::I18n::TranslationEntry.new(
+ { msgid: 'Hello %{world}',
+ msgid_plural: 'Hello all %{world}',
+ 'msgstr[0]' => 'Bonjour %{world}',
+ 'msgstr[1]' => 'Bonjour tous %{world}' },
+ 2
+ )
+
+ expect(linter).to receive(:validate_variables_in_message)
+ .with([], 'Hello %{world}', 'Bonjour %{world}')
+ .and_call_original
+ expect(linter).to receive(:validate_variables_in_message)
+ .with([], 'Hello all %{world}', 'Bonjour tous %{world}')
+ .and_call_original
+
+ linter.validate_variables([], pluralized_entry)
+ end
+
+ it 'only validates plural when there is no separate singular' do
+ pluralized_entry = Gitlab::I18n::TranslationEntry.new(
+ { msgid: 'Hello %{world}',
+ msgid_plural: 'Hello all %{world}',
+ 'msgstr[0]' => 'Bonjour %{world}' },
+ 1
+ )
+
+ expect(linter).to receive(:validate_variables_in_message)
+ .with([], 'Hello all %{world}', 'Bonjour %{world}')
+
+ linter.validate_variables([], pluralized_entry)
+ end
+
+ it 'validates the message variables' do
+ entry = Gitlab::I18n::TranslationEntry.new(
+ { msgid: 'Hello', msgstr: 'Bonjour' },
+ 2
+ )
+
+ expect(linter).to receive(:validate_variables_in_message)
+ .with([], 'Hello', 'Bonjour')
+
+ linter.validate_variables([], entry)
+ end
+ end
+
+ describe '#validate_variables_in_message' do
+ it 'detects when a variables are used incorrectly' do
+ errors = []
+
+ expected_errors = ['<hello %{world} %d> is missing: [%{hello}]',
+ '<hello %{world} %d> is using unknown variables: [%{world}]',
+ 'is combining multiple unnamed variables']
+
+ linter.validate_variables_in_message(errors, '%{hello} world %d', 'hello %{world} %d')
+
+ expect(errors).to include(*expected_errors)
+ end
+ end
+
+ describe '#validate_translation' do
+ it 'succeeds with valid variables' do
+ errors = []
+
+ linter.validate_translation(errors, 'Hello %{world}', ['%{world}'])
+
+ expect(errors).to be_empty
+ end
+
+ it 'adds an error message when translating fails' do
+ errors = []
+
+ expect(FastGettext::Translation).to receive(:_) { raise 'broken' }
+
+ linter.validate_translation(errors, 'Hello', [])
+
+ expect(errors).to include('Failure translating to en with []: broken')
+ end
+
+ it 'adds an error message when translating fails when translating with context' do
+ errors = []
+
+ expect(FastGettext::Translation).to receive(:s_) { raise 'broken' }
+
+ linter.validate_translation(errors, 'Tests|Hello', [])
+
+ expect(errors).to include('Failure translating to en with []: broken')
+ end
+
+ it "adds an error when trying to translate with incorrect variables when using unnamed variables" do
+ errors = []
+
+ linter.validate_translation(errors, 'Hello %d', ['%s'])
+
+ expect(errors.first).to start_with("Failure translating to en with")
+ end
+
+ it "adds an error when trying to translate with named variables when unnamed variables are expected" do
+ errors = []
+
+ linter.validate_translation(errors, 'Hello %d', ['%{world}'])
+
+ expect(errors.first).to start_with("Failure translating to en with")
+ end
+
+ it 'adds an error when translated with incorrect variables using named variables' do
+ errors = []
+
+ linter.validate_translation(errors, 'Hello %{thing}', ['%d'])
+
+ expect(errors.first).to start_with("Failure translating to en with")
+ end
+ end
+
+ describe '#fill_in_variables' do
+ it 'builds an array for %d translations' do
+ result = linter.fill_in_variables(['%d'])
+
+ expect(result).to contain_exactly(a_kind_of(Integer))
+ end
+
+ it 'builds an array for %s translations' do
+ result = linter.fill_in_variables(['%s'])
+
+ expect(result).to contain_exactly(a_kind_of(String))
+ end
+
+ it 'builds a hash for named variables' do
+ result = linter.fill_in_variables(['%{hello}'])
+
+ expect(result).to be_a(Hash)
+ expect(result).to include('hello' => an_instance_of(String))
+ end
+ end
+end
diff --git a/spec/lib/gitlab/i18n/translation_entry_spec.rb b/spec/lib/gitlab/i18n/translation_entry_spec.rb
new file mode 100644
index 00000000000..f68bc8feff9
--- /dev/null
+++ b/spec/lib/gitlab/i18n/translation_entry_spec.rb
@@ -0,0 +1,203 @@
+require 'spec_helper'
+
+describe Gitlab::I18n::TranslationEntry do
+ describe '#singular_translation' do
+ it 'returns the normal `msgstr` for translations without plural' do
+ data = { msgid: 'Hello world', msgstr: 'Bonjour monde' }
+ entry = described_class.new(data, 2)
+
+ expect(entry.singular_translation).to eq('Bonjour monde')
+ end
+
+ it 'returns the first string for entries with plurals' do
+ data = {
+ msgid: 'Hello world',
+ msgid_plural: 'Hello worlds',
+ 'msgstr[0]' => 'Bonjour monde',
+ 'msgstr[1]' => 'Bonjour mondes'
+ }
+ entry = described_class.new(data, 2)
+
+ expect(entry.singular_translation).to eq('Bonjour monde')
+ end
+ end
+
+ describe '#all_translations' do
+ it 'returns all translations for singular translations' do
+ data = { msgid: 'Hello world', msgstr: 'Bonjour monde' }
+ entry = described_class.new(data, 2)
+
+ expect(entry.all_translations).to eq(['Bonjour monde'])
+ end
+
+ it 'returns all translations when including plural translations' do
+ data = {
+ msgid: 'Hello world',
+ msgid_plural: 'Hello worlds',
+ 'msgstr[0]' => 'Bonjour monde',
+ 'msgstr[1]' => 'Bonjour mondes'
+ }
+ entry = described_class.new(data, 2)
+
+ expect(entry.all_translations).to eq(['Bonjour monde', 'Bonjour mondes'])
+ end
+ end
+
+ describe '#plural_translations' do
+ it 'returns all translations if there is only one plural' do
+ data = {
+ msgid: 'Hello world',
+ msgid_plural: 'Hello worlds',
+ 'msgstr[0]' => 'Bonjour monde'
+ }
+ entry = described_class.new(data, 1)
+
+ expect(entry.plural_translations).to eq(['Bonjour monde'])
+ end
+
+ it 'returns all translations except for the first one if there are multiple' do
+ data = {
+ msgid: 'Hello world',
+ msgid_plural: 'Hello worlds',
+ 'msgstr[0]' => 'Bonjour monde',
+ 'msgstr[1]' => 'Bonjour mondes',
+ 'msgstr[2]' => 'Bonjour tous les mondes'
+ }
+ entry = described_class.new(data, 3)
+
+ expect(entry.plural_translations).to eq(['Bonjour mondes', 'Bonjour tous les mondes'])
+ end
+ end
+
+ describe '#has_singular_translation?' do
+ it 'has a singular when the translation is not pluralized' do
+ data = {
+ msgid: 'hello world',
+ msgstr: 'hello'
+ }
+ entry = described_class.new(data, 2)
+
+ expect(entry).to have_singular_translation
+ end
+
+ it 'has a singular when plural and singular are separately defined' do
+ data = {
+ msgid: 'hello world',
+ msgid_plural: 'hello worlds',
+ "msgstr[0]" => 'hello world',
+ "msgstr[1]" => 'hello worlds'
+ }
+ entry = described_class.new(data, 2)
+
+ expect(entry).to have_singular_translation
+ end
+
+ it 'does not have a separate singular if the plural string only has one translation' do
+ data = {
+ msgid: 'hello world',
+ msgid_plural: 'hello worlds',
+ "msgstr[0]" => 'hello worlds'
+ }
+ entry = described_class.new(data, 1)
+
+ expect(entry).not_to have_singular_translation
+ end
+ end
+
+ describe '#msgid_contains_newlines' do
+ it 'is true when the msgid is an array' do
+ data = { msgid: %w(hello world) }
+ entry = described_class.new(data, 2)
+
+ expect(entry.msgid_contains_newlines?).to be_truthy
+ end
+ end
+
+ describe '#plural_id_contains_newlines' do
+ it 'is true when the msgid is an array' do
+ data = { msgid_plural: %w(hello world) }
+ entry = described_class.new(data, 2)
+
+ expect(entry.plural_id_contains_newlines?).to be_truthy
+ end
+ end
+
+ describe '#translations_contain_newlines' do
+ it 'is true when the msgid is an array' do
+ data = { msgstr: %w(hello world) }
+ entry = described_class.new(data, 2)
+
+ expect(entry.translations_contain_newlines?).to be_truthy
+ end
+ end
+
+ describe '#contains_unescaped_chars' do
+ let(:data) { { msgid: '' } }
+ let(:entry) { described_class.new(data, 2) }
+ it 'is true when the msgid is an array' do
+ string = '「100%確定」'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_truthy
+ end
+
+ it 'is false when the `%` char is escaped' do
+ string = '「100%%確定」'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_falsy
+ end
+
+ it 'is false when using an unnamed variable' do
+ string = '「100%d確定」'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_falsy
+ end
+
+ it 'is false when using a named variable' do
+ string = '「100%{named}確定」'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_falsy
+ end
+
+ it 'is true when an unnamed variable is not closed' do
+ string = '「100%{named確定」'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_truthy
+ end
+
+ it 'is true when the string starts with a `%`' do
+ string = '%10'
+
+ expect(entry.contains_unescaped_chars?(string)).to be_truthy
+ end
+ end
+
+ describe '#msgid_contains_unescaped_chars' do
+ it 'is true when the msgid contains a `%`' do
+ data = { msgid: '「100%確定」' }
+ entry = described_class.new(data, 2)
+
+ expect(entry).to receive(:contains_unescaped_chars?).and_call_original
+ expect(entry.msgid_contains_unescaped_chars?).to be_truthy
+ end
+ end
+
+ describe '#plural_id_contains_unescaped_chars' do
+ it 'is true when the plural msgid contains a `%`' do
+ data = { msgid_plural: '「100%確定」' }
+ entry = described_class.new(data, 2)
+
+ expect(entry).to receive(:contains_unescaped_chars?).and_call_original
+ expect(entry.plural_id_contains_unescaped_chars?).to be_truthy
+ end
+ end
+
+ describe '#translations_contain_unescaped_chars' do
+ it 'is true when the translation contains a `%`' do
+ data = { msgstr: '「100%確定」' }
+ entry = described_class.new(data, 2)
+
+ expect(entry).to receive(:contains_unescaped_chars?).and_call_original
+ expect(entry.translations_contain_unescaped_chars?).to be_truthy
+ end
+ end
+end
diff --git a/spec/lib/gitlab/key_fingerprint_spec.rb b/spec/lib/gitlab/key_fingerprint_spec.rb
deleted file mode 100644
index d643dc5342d..00000000000
--- a/spec/lib/gitlab/key_fingerprint_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'spec_helper'
-
-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
-
- 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/sentry_spec.rb b/spec/lib/gitlab/sentry_spec.rb
new file mode 100644
index 00000000000..8c211d1c63f
--- /dev/null
+++ b/spec/lib/gitlab/sentry_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe Gitlab::Sentry do
+ describe '.context' do
+ it 'adds the locale to the tags' do
+ expect(described_class).to receive(:enabled?).and_return(true)
+
+ described_class.context(nil)
+
+ expect(Raven.tags_context[:locale]).to eq(I18n.locale.to_s)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ssh_public_key_spec.rb b/spec/lib/gitlab/ssh_public_key_spec.rb
new file mode 100644
index 00000000000..93d538141ce
--- /dev/null
+++ b/spec/lib/gitlab/ssh_public_key_spec.rb
@@ -0,0 +1,136 @@
+require 'spec_helper'
+
+describe Gitlab::SSHPublicKey, lib: true do
+ let(:key) { attributes_for(:rsa_key_2048)[:key] }
+ let(:public_key) { described_class.new(key) }
+
+ describe '.technology(name)' do
+ it 'returns nil for an unrecognised name' do
+ expect(described_class.technology(:foo)).to be_nil
+ end
+
+ where(:name) do
+ [:rsa, :dsa, :ecdsa, :ed25519]
+ end
+
+ with_them do
+ it { expect(described_class.technology(name).name).to eq(name) }
+ it { expect(described_class.technology(name.to_s).name).to eq(name) }
+ end
+ end
+
+ describe '.supported_sizes(name)' do
+ where(:name, :sizes) do
+ [
+ [:rsa, [1024, 2048, 3072, 4096]],
+ [:dsa, [1024, 2048, 3072]],
+ [:ecdsa, [256, 384, 521]],
+ [:ed25519, [256]]
+ ]
+ end
+
+ subject { described_class.supported_sizes(name) }
+
+ with_them do
+ it { expect(described_class.supported_sizes(name)).to eq(sizes) }
+ it { expect(described_class.supported_sizes(name.to_s)).to eq(sizes) }
+ end
+ end
+
+ describe '#valid?' do
+ subject { public_key }
+
+ context 'with a valid SSH key' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'with an invalid SSH key' do
+ let(:key) { 'this is not a key' }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ describe '#type' do
+ subject { public_key.type }
+
+ where(:factory, :type) do
+ [
+ [:rsa_key_2048, :rsa],
+ [:dsa_key_2048, :dsa],
+ [:ecdsa_key_256, :ecdsa],
+ [:ed25519_key_256, :ed25519]
+ ]
+ end
+
+ with_them do
+ let(:key) { attributes_for(factory)[:key] }
+
+ it { is_expected.to eq(type) }
+ end
+
+ context 'with an invalid SSH key' do
+ let(:key) { 'this is not a key' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#bits' do
+ subject { public_key.bits }
+
+ where(:factory, :bits) do
+ [
+ [:rsa_key_2048, 2048],
+ [:dsa_key_2048, 2048],
+ [:ecdsa_key_256, 256],
+ [:ed25519_key_256, 256]
+ ]
+ end
+
+ with_them do
+ let(:key) { attributes_for(factory)[:key] }
+
+ it { is_expected.to eq(bits) }
+ end
+
+ context 'with an invalid SSH key' do
+ let(:key) { 'this is not a key' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#fingerprint' do
+ subject { public_key.fingerprint }
+
+ where(:factory, :fingerprint) do
+ [
+ [:rsa_key_2048, '2e:ca:dc:e0:37:29:ed:fc:f0:1d:bf:66:d4:cd:51:b1'],
+ [:dsa_key_2048, 'bc:c1:a4:be:7e:8c:84:56:b3:58:93:53:c6:80:78:8c'],
+ [:ecdsa_key_256, '67:a3:a9:7d:b8:e1:15:d4:80:40:21:34:bb:ed:97:38'],
+ [:ed25519_key_256, 'e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73']
+ ]
+ end
+
+ with_them do
+ let(:key) { attributes_for(factory)[:key] }
+
+ it { is_expected.to eq(fingerprint) }
+ end
+
+ context 'with an invalid SSH key' do
+ let(:key) { 'this is not a key' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#key_text' do
+ let(:key) { 'this is not a key' }
+
+ it 'carries the unmodified key data' do
+ expect(public_key.key_text).to eq(key)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 92787bb262e..3137a72fdc4 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::Utils do
- delegate :to_boolean, :boolean_to_yes_no, :slugify, to: :described_class
+ delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, to: :described_class
describe '.slugify' do
{
@@ -53,4 +53,10 @@ describe Gitlab::Utils do
expect(boolean_to_yes_no(false)).to eq('No')
end
end
+
+ describe '.random_string' do
+ it 'generates a string' do
+ expect(random_string).to be_kind_of(String)
+ end
+ end
end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index b66afafa174..699184ad9fe 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -228,21 +228,10 @@ describe Gitlab::Workhorse do
let(:action) { 'git_upload_pack' }
let(:feature_flag) { :post_upload_pack }
- context 'when action is enabled by feature flag' do
- it 'includes Gitaly params in the returned value' do
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(true)
+ it 'includes Gitaly params in the returned value' do
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag).and_return(true)
- expect(subject).to include(gitaly_params)
- end
- end
-
- context 'when action is not enabled by feature flag' do
- it 'does not include Gitaly params in the returned value' do
- status_opt_out = Gitlab::GitalyClient::MigrationStatus::OPT_OUT
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).with(feature_flag, status: status_opt_out).and_return(false)
-
- expect(subject).not_to include(gitaly_params)
- end
+ expect(subject).to include(gitaly_params)
end
end