diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-10 18:07:47 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-01-10 18:07:47 +0300 |
commit | 8b1228b0d409d7751f01d9fb72ebfbbf62399486 (patch) | |
tree | 1b4126fe48d7666a90c0d7ee26230cf8379b6410 /spec/lib | |
parent | 96b0c1245c93585a8b0fe23e22306d32ff4e4905 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/api/helpers/pagination_spec.rb | 70 | ||||
-rw-r--r-- | spec/lib/api/helpers/pagination_strategies_spec.rb | 97 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/job_spec.rb | 36 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/release/assets/link_spec.rb | 79 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/release/assets/links_spec.rb | 67 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/release/assets_spec.rb | 69 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/release_spec.rb | 114 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/root_spec.rb | 48 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/yaml_processor_spec.rb | 53 | ||||
-rw-r--r-- | spec/lib/gitlab/config/entry/attributable_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb | 77 | ||||
-rw-r--r-- | spec/lib/gitlab/pagination/keyset/page_spec.rb | 11 | ||||
-rw-r--r-- | spec/lib/gitlab/pagination/keyset/pager_spec.rb | 54 | ||||
-rw-r--r-- | spec/lib/gitlab/pagination/keyset/request_context_spec.rb | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/pagination/keyset_spec.rb | 16 |
15 files changed, 658 insertions, 139 deletions
diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb index 2d5bec2e752..796c753d6c4 100644 --- a/spec/lib/api/helpers/pagination_spec.rb +++ b/spec/lib/api/helpers/pagination_spec.rb @@ -5,70 +5,14 @@ require 'spec_helper' describe API::Helpers::Pagination do subject { Class.new.include(described_class).new } - let(:expected_result) { double("result", to_a: double) } - let(:relation) { double("relation") } - let(:params) { {} } + let(:paginator) { double('paginator') } + let(:relation) { double('relation') } + let(:expected_result) { double('expected result') } - before do - allow(subject).to receive(:params).and_return(params) - end - - describe '#paginate' do - let(:offset_pagination) { double("offset pagination") } - - it 'delegates to OffsetPagination' do - expect(::Gitlab::Pagination::OffsetPagination).to receive(:new).with(subject).and_return(offset_pagination) - expect(offset_pagination).to receive(:paginate).with(relation).and_return(expected_result) - - result = subject.paginate(relation) - - expect(result).to eq(expected_result) - end - end - - describe '#paginate_and_retrieve!' do - context 'for offset pagination' do - before do - allow(Gitlab::Pagination::Keyset).to receive(:available?).and_return(false) - end - - it 'delegates to paginate' do - expect(subject).to receive(:paginate).with(relation).and_return(expected_result) - - result = subject.paginate_and_retrieve!(relation) - - expect(result).to eq(expected_result.to_a) - end - end - - context 'for keyset pagination' do - let(:params) { { pagination: 'keyset' } } - let(:request_context) { double('request context') } - - before do - allow(Gitlab::Pagination::Keyset::RequestContext).to receive(:new).with(subject).and_return(request_context) - end - - context 'when keyset pagination is available' do - it 'delegates to KeysetPagination' do - expect(Gitlab::Pagination::Keyset).to receive(:available?).and_return(true) - expect(Gitlab::Pagination::Keyset).to receive(:paginate).with(request_context, relation).and_return(expected_result) - - result = subject.paginate_and_retrieve!(relation) - - expect(result).to eq(expected_result.to_a) - end - end - - context 'when keyset pagination is not available' do - it 'renders a 501 error if keyset pagination isnt available yet' do - expect(Gitlab::Pagination::Keyset).to receive(:available?).with(request_context, relation).and_return(false) - expect(Gitlab::Pagination::Keyset).not_to receive(:paginate) - expect(subject).to receive(:error!).with(/not yet available/, 405) + it 'delegates to OffsetPagination' do + expect(Gitlab::Pagination::OffsetPagination).to receive(:new).with(subject).and_return(paginator) + expect(paginator).to receive(:paginate).with(relation).and_return(expected_result) - subject.paginate_and_retrieve!(relation) - end - end - end + expect(subject.paginate(relation)).to eq(expected_result) end end diff --git a/spec/lib/api/helpers/pagination_strategies_spec.rb b/spec/lib/api/helpers/pagination_strategies_spec.rb new file mode 100644 index 00000000000..a418c09a824 --- /dev/null +++ b/spec/lib/api/helpers/pagination_strategies_spec.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe API::Helpers::PaginationStrategies do + subject { Class.new.include(described_class).new } + + let(:expected_result) { double("result") } + let(:relation) { double("relation") } + let(:params) { {} } + + before do + allow(subject).to receive(:params).and_return(params) + end + + describe '#paginate_with_strategies' do + let(:paginator) { double("paginator", paginate: expected_result, finalize: nil) } + + before do + allow(subject).to receive(:paginator).with(relation).and_return(paginator) + end + + it 'yields paginated relation' do + expect { |b| subject.paginate_with_strategies(relation, &b) }.to yield_with_args(expected_result) + end + + it 'calls #finalize with first value returned from block' do + return_value = double + expect(paginator).to receive(:finalize).with(return_value) + + subject.paginate_with_strategies(relation) do |records| + some_options = {} + [return_value, some_options] + end + end + + it 'returns whatever the block returns' do + return_value = [double, double] + + result = subject.paginate_with_strategies(relation) do |records| + return_value + end + + expect(result).to eq(return_value) + end + end + + describe '#paginator' do + context 'offset pagination' do + let(:paginator) { double("paginator") } + + before do + allow(subject).to receive(:keyset_pagination_enabled?).and_return(false) + end + + it 'delegates to OffsetPagination' do + expect(Gitlab::Pagination::OffsetPagination).to receive(:new).with(subject).and_return(paginator) + + expect(subject.paginator(relation)).to eq(paginator) + end + end + + context 'for keyset pagination' do + let(:params) { { pagination: 'keyset' } } + let(:request_context) { double('request context') } + let(:pager) { double('pager') } + + before do + allow(subject).to receive(:keyset_pagination_enabled?).and_return(true) + allow(Gitlab::Pagination::Keyset::RequestContext).to receive(:new).with(subject).and_return(request_context) + end + + context 'when keyset pagination is available' do + before do + allow(Gitlab::Pagination::Keyset).to receive(:available?).and_return(true) + allow(Gitlab::Pagination::Keyset::Pager).to receive(:new).with(request_context).and_return(pager) + end + + it 'delegates to Pager' do + expect(subject.paginator(relation)).to eq(pager) + end + end + + context 'when keyset pagination is not available' do + before do + allow(Gitlab::Pagination::Keyset).to receive(:available?).with(request_context, relation).and_return(false) + end + + it 'renders a 501 error' do + expect(subject).to receive(:error!).with(/not yet available/, 405) + + subject.paginator(relation) + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb index cc1ee63ff04..649689f7d3b 100644 --- a/spec/lib/gitlab/ci/config/entry/job_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb @@ -24,7 +24,7 @@ describe Gitlab::Ci::Config::Entry::Job do let(:result) do %i[before_script script stage type after_script cache image services only except rules needs variables artifacts - environment coverage retry interruptible timeout tags] + environment coverage retry interruptible timeout release tags] end it { is_expected.to match_array result } @@ -122,6 +122,21 @@ describe Gitlab::Ci::Config::Entry::Job do it { expect(entry).to be_valid } end + + context 'when it is a release' do + let(:config) do + { + script: ["make changelog | tee release_changelog.txt"], + release: { + tag_name: "v0.06", + name: "Release $CI_TAG_NAME", + description: "./release_changelog.txt" + } + } + end + + it { expect(entry).to be_valid } + end end end @@ -443,6 +458,25 @@ describe Gitlab::Ci::Config::Entry::Job do expect(entry.timeout).to eq('1m 1s') end end + + context 'when it is a release' do + context 'when `release:description` is missing' do + let(:config) do + { + script: ["make changelog | tee release_changelog.txt"], + release: { + tag_name: "v0.06", + name: "Release $CI_TAG_NAME" + } + } + end + + it "returns error" do + expect(entry).not_to be_valid + expect(entry.errors).to include "release description can't be blank" + end + end + end end end diff --git a/spec/lib/gitlab/ci/config/entry/release/assets/link_spec.rb b/spec/lib/gitlab/ci/config/entry/release/assets/link_spec.rb new file mode 100644 index 00000000000..0e346de3d9e --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/release/assets/link_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Release::Assets::Link do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) do + { + name: "cool-app.zip", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" + } + end + + describe '#value' do + it 'returns link configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when name is not a string' do + let(:config) { { name: 123, url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" } } + + it 'reports error' do + expect(entry.errors) + .to include 'link name should be a string' + end + end + + context 'when name is not present' do + let(:config) { { url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" } } + + it 'reports error' do + expect(entry.errors) + .to include "link name can't be blank" + end + end + + context 'when url is not addressable' do + let(:config) { { name: "cool-app.zip", url: "xyz" } } + + it 'reports error' do + expect(entry.errors) + .to include "link url is blocked: only allowed schemes are http, https" + end + end + + context 'when url is not present' do + let(:config) { { name: "cool-app.zip" } } + + it 'reports error' do + expect(entry.errors) + .to include "link url can't be blank" + end + end + + context 'when there is an unknown key present' do + let(:config) { { test: 100 } } + + it 'reports error' do + expect(entry.errors) + .to include 'link config contains unknown keys: test' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/release/assets/links_spec.rb b/spec/lib/gitlab/ci/config/entry/release/assets/links_spec.rb new file mode 100644 index 00000000000..d12e8d966ab --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/release/assets/links_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Release::Assets::Links do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) do + [ + { + name: "cool-app.zip", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" + }, + { + name: "cool-app.exe", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.exe" + } + ] + end + + describe '#value' do + it 'returns links configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when value of link is invalid' do + let(:config) { { link: 'xyz' } } + + it 'reports error' do + expect(entry.errors) + .to include 'links config should be a array' + end + end + + context 'when value of links link is empty' do + let(:config) { { link: [] } } + + it 'reports error' do + expect(entry.errors) + .to include "links config should be a array" + end + end + + context 'when there is an unknown key present' do + let(:config) { { test: 100 } } + + it 'reports error' do + expect(entry.errors) + .to include 'links config should be a array' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/release/assets_spec.rb b/spec/lib/gitlab/ci/config/entry/release/assets_spec.rb new file mode 100644 index 00000000000..08ad5764eaa --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/release/assets_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Release::Assets do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) do + { + links: [ + { + name: "cool-app.zip", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" + }, + { + name: "cool-app.exe", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.exe" + } + ] + } + end + + describe '#value' do + it 'returns assets configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when value of assets is invalid' do + let(:config) { { links: 'xyz' } } + + it 'reports error' do + expect(entry.errors) + .to include 'assets links should be an array of hashes' + end + end + + context 'when value of assets:links is empty' do + let(:config) { { links: [] } } + + it 'reports error' do + expect(entry.errors) + .to include "assets links can't be blank" + end + end + + context 'when there is an unknown key present' do + let(:config) { { test: 100 } } + + it 'reports error' do + expect(entry.errors) + .to include 'assets config contains unknown keys: test' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/release_spec.rb b/spec/lib/gitlab/ci/config/entry/release_spec.rb new file mode 100644 index 00000000000..500897569e9 --- /dev/null +++ b/spec/lib/gitlab/ci/config/entry/release_spec.rb @@ -0,0 +1,114 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Ci::Config::Entry::Release do + let(:entry) { described_class.new(config) } + + describe 'validation' do + context 'when entry config value is correct' do + let(:config) { { tag_name: 'v0.06', description: "./release_changelog.txt" } } + + describe '#value' do + it 'returns release configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context "when value includes 'assets' keyword" do + let(:config) do + { + tag_name: 'v0.06', + description: "./release_changelog.txt", + assets: [ + { + name: "cool-app.zip", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" + } + ] + } + end + + describe '#value' do + it 'returns release configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context "when value includes 'name' keyword" do + let(:config) do + { + tag_name: 'v0.06', + description: "./release_changelog.txt", + name: "Release $CI_TAG_NAME" + } + end + + describe '#value' do + it 'returns release configuration' do + expect(entry.value).to eq config + end + end + + describe '#valid?' do + it 'is valid' do + expect(entry).to be_valid + end + end + end + + context 'when entry value is not correct' do + describe '#errors' do + context 'when value of attribute is invalid' do + let(:config) { { description: 10 } } + + it 'reports error' do + expect(entry.errors) + .to include 'release description should be a string' + end + end + + context 'when release description is missing' do + let(:config) { { tag_name: 'v0.06' } } + + it 'reports error' do + expect(entry.errors) + .to include "release description can't be blank" + end + end + + context 'when release tag_name is missing' do + let(:config) { { description: "./release_changelog.txt" } } + + it 'reports error' do + expect(entry.errors) + .to include "release tag name can't be blank" + end + end + + context 'when there is an unknown key present' do + let(:config) { { test: 100 } } + + it 'reports error' do + expect(entry.errors) + .to include 'release config contains unknown keys: test' + end + end + end + end + end +end diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb index 43bd53b780f..95a5b8e88fb 100644 --- a/spec/lib/gitlab/ci/config/entry/root_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb @@ -27,16 +27,29 @@ describe Gitlab::Ci::Config::Entry::Root do context 'when configuration is valid' do context 'when top-level entries are defined' do let(:hash) do - { before_script: %w(ls pwd), + { + before_script: %w(ls pwd), image: 'ruby:2.2', default: {}, services: ['postgres:9.1', 'mysql:5.5'], variables: { VAR: 'value' }, after_script: ['make clean'], - stages: %w(build pages), + stages: %w(build pages release), cache: { key: 'k', untracked: true, paths: ['public/'] }, rspec: { script: %w[rspec ls] }, - spinach: { before_script: [], variables: {}, script: 'spinach' } } + spinach: { before_script: [], variables: {}, script: 'spinach' }, + release: { + stage: 'release', + before_script: [], + after_script: [], + script: ["make changelog | tee release_changelog.txt"], + release: { + tag_name: 'v0.06', + name: "Release $CI_TAG_NAME", + description: "./release_changelog.txt" + } + } + } end describe '#compose!' do @@ -87,7 +100,7 @@ describe Gitlab::Ci::Config::Entry::Root do describe '#stages_value' do context 'when stages key defined' do it 'returns array of stages' do - expect(root.stages_value).to eq %w[build pages] + expect(root.stages_value).to eq %w[build pages release] end end @@ -105,8 +118,9 @@ describe Gitlab::Ci::Config::Entry::Root do describe '#jobs_value' do it 'returns jobs configuration' do - expect(root.jobs_value).to eq( - rspec: { name: :rspec, + expect(root.jobs_value.keys).to eq([:rspec, :spinach, :release]) + expect(root.jobs_value[:rspec]).to eq( + { name: :rspec, script: %w[rspec ls], before_script: %w(ls pwd), image: { name: 'ruby:2.2' }, @@ -116,8 +130,10 @@ describe Gitlab::Ci::Config::Entry::Root do variables: {}, ignore: false, after_script: ['make clean'], - only: { refs: %w[branches tags] } }, - spinach: { name: :spinach, + only: { refs: %w[branches tags] } } + ) + expect(root.jobs_value[:spinach]).to eq( + { name: :spinach, before_script: [], script: %w[spinach], image: { name: 'ruby:2.2' }, @@ -129,6 +145,20 @@ describe Gitlab::Ci::Config::Entry::Root do after_script: ['make clean'], only: { refs: %w[branches tags] } } ) + expect(root.jobs_value[:release]).to eq( + { name: :release, + stage: 'release', + before_script: [], + script: ["make changelog | tee release_changelog.txt"], + release: { name: "Release $CI_TAG_NAME", tag_name: 'v0.06', description: "./release_changelog.txt" }, + image: { name: "ruby:2.2" }, + services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }], + cache: { key: "k", untracked: true, paths: ["public/"], policy: "pull-push" }, + only: { refs: %w(branches tags) }, + variables: {}, + after_script: [], + ignore: false } + ) end end end @@ -261,7 +291,7 @@ describe Gitlab::Ci::Config::Entry::Root do # despite the fact, that key is present. See issue #18775 for more # details. # - context 'when entires specified but not defined' do + context 'when entries are specified but not defined' do before do root.compose! end diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index 2e470d59345..9dea74f6345 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -1285,6 +1285,59 @@ module Gitlab end end + describe "release" do + let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) } + let(:config) do + { + stages: ["build", "test", "release"], # rubocop:disable Style/WordArray + release: { + stage: "release", + only: ["tags"], + script: ["make changelog | tee release_changelog.txt"], + release: { + tag_name: "$CI_COMMIT_TAG", + name: "Release $CI_TAG_NAME", + description: "./release_changelog.txt", + assets: { + links: [ + { + name: "cool-app.zip", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.zip" + }, + { + name: "cool-app.exe", + url: "http://my.awesome.download.site/1.0-$CI_COMMIT_SHORT_SHA.exe" + } + ] + } + } + } + } + end + + context 'with feature flag active' do + before do + stub_feature_flags(ci_release_generation: true) + end + + it "returns release info" do + expect(processor.stage_builds_attributes('release').first[:options]) + .to eq(config[:release].except(:stage, :only)) + end + end + + context 'with feature flag inactive' do + before do + stub_feature_flags(ci_release_generation: false) + end + + it "returns release info" do + expect(processor.stage_builds_attributes('release').first[:options].include?(config[:release])) + .to be false + end + end + end + describe '#environment' do let(:config) do { diff --git a/spec/lib/gitlab/config/entry/attributable_spec.rb b/spec/lib/gitlab/config/entry/attributable_spec.rb index 6b548d5c4a8..bc29a194181 100644 --- a/spec/lib/gitlab/config/entry/attributable_spec.rb +++ b/spec/lib/gitlab/config/entry/attributable_spec.rb @@ -59,7 +59,7 @@ describe Gitlab::Config::Entry::Attributable do end end - expectation.to raise_error(ArgumentError, 'Method already defined!') + expectation.to raise_error(ArgumentError, 'Method already defined: length') end end end diff --git a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb index 474240cf620..9b29046fce9 100644 --- a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb +++ b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb @@ -53,30 +53,46 @@ describe Gitlab::Git::RuggedImpl::UseRugged, :seed_helper do allow(Feature).to receive(:persisted?).with(feature_flag).and_return(false) end - it 'returns true when gitaly matches disk' do - expect(subject.use_rugged?(repository, feature_flag_name)).to be true + context 'when running puma with multiple threads' do + before do + allow(subject).to receive(:running_puma_with_multiple_threads?).and_return(true) + end + + it 'returns false' do + expect(subject.use_rugged?(repository, feature_flag_name)).to be false + end end - it 'returns false when disk access fails' do - allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return("/fake/path/doesnt/exist") + context 'when not running puma with multiple threads' do + before do + allow(subject).to receive(:running_puma_with_multiple_threads?).and_return(false) + end - expect(subject.use_rugged?(repository, feature_flag_name)).to be false - end + it 'returns true when gitaly matches disk' do + expect(subject.use_rugged?(repository, feature_flag_name)).to be true + end - it "returns false when gitaly doesn't match disk" do - allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return(temp_gitaly_metadata_file) + it 'returns false when disk access fails' do + allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return("/fake/path/doesnt/exist") - expect(subject.use_rugged?(repository, feature_flag_name)).to be_falsey + expect(subject.use_rugged?(repository, feature_flag_name)).to be false + end - File.delete(temp_gitaly_metadata_file) - end + it "returns false when gitaly doesn't match disk" do + allow(Gitlab::GitalyClient).to receive(:storage_metadata_file_path).and_return(temp_gitaly_metadata_file) - it "doesn't lead to a second rpc call because gitaly client should use the cached value" do - expect(subject.use_rugged?(repository, feature_flag_name)).to be true + expect(subject.use_rugged?(repository, feature_flag_name)).to be_falsey - expect(Gitlab::GitalyClient).not_to receive(:filesystem_id) + File.delete(temp_gitaly_metadata_file) + end - subject.use_rugged?(repository, feature_flag_name) + it "doesn't lead to a second rpc call because gitaly client should use the cached value" do + expect(subject.use_rugged?(repository, feature_flag_name)).to be true + + expect(Gitlab::GitalyClient).not_to receive(:filesystem_id) + + subject.use_rugged?(repository, feature_flag_name) + end end end @@ -99,6 +115,37 @@ describe Gitlab::Git::RuggedImpl::UseRugged, :seed_helper do end end + describe '#running_puma_with_multiple_threads?' do + context 'when using Puma' do + before do + stub_const('::Puma', class_double('Puma')) + allow(Gitlab::Runtime).to receive(:puma?).and_return(true) + end + + it 'returns false for single thread Puma' do + allow(::Puma).to receive_message_chain(:cli_config, :options).and_return(max_threads: 1) + + expect(subject.running_puma_with_multiple_threads?).to be false + end + + it 'returns true for multi-threaded Puma' do + allow(::Puma).to receive_message_chain(:cli_config, :options).and_return(max_threads: 2) + + expect(subject.running_puma_with_multiple_threads?).to be true + end + end + + context 'when not using Puma' do + before do + allow(Gitlab::Runtime).to receive(:puma?).and_return(false) + end + + it 'returns false' do + expect(subject.running_puma_with_multiple_threads?).to be false + end + end + end + def create_temporary_gitaly_metadata_file tmp = Tempfile.new('.gitaly-metadata') gitaly_metadata = { diff --git a/spec/lib/gitlab/pagination/keyset/page_spec.rb b/spec/lib/gitlab/pagination/keyset/page_spec.rb index 5c03224c05a..c5ca27231d8 100644 --- a/spec/lib/gitlab/pagination/keyset/page_spec.rb +++ b/spec/lib/gitlab/pagination/keyset/page_spec.rb @@ -30,16 +30,14 @@ describe Gitlab::Pagination::Keyset::Page do end describe '#next' do - let(:page) { described_class.new(order_by: order_by, lower_bounds: lower_bounds, per_page: per_page, end_reached: end_reached) } - subject { page.next(new_lower_bounds, new_end_reached) } + let(:page) { described_class.new(order_by: order_by, lower_bounds: lower_bounds, per_page: per_page) } + subject { page.next(new_lower_bounds) } let(:order_by) { { id: :desc } } let(:lower_bounds) { { id: 42 } } let(:per_page) { 10 } - let(:end_reached) { false } let(:new_lower_bounds) { { id: 21 } } - let(:new_end_reached) { true } it 'copies over order_by' do expect(subject.order_by).to eq(page.order_by) @@ -57,10 +55,5 @@ describe Gitlab::Pagination::Keyset::Page do expect(subject.lower_bounds).to eq(new_lower_bounds) expect(page.lower_bounds).to eq(lower_bounds) end - - it 'sets end_reached only on new instance' do - expect(subject.end_reached?).to eq(new_end_reached) - expect(page.end_reached?).to eq(end_reached) - end end end diff --git a/spec/lib/gitlab/pagination/keyset/pager_spec.rb b/spec/lib/gitlab/pagination/keyset/pager_spec.rb index 6d23fe2adcc..3ad1bee7225 100644 --- a/spec/lib/gitlab/pagination/keyset/pager_spec.rb +++ b/spec/lib/gitlab/pagination/keyset/pager_spec.rb @@ -15,15 +15,37 @@ describe Gitlab::Pagination::Keyset::Pager do describe '#paginate' do subject { described_class.new(request).paginate(relation) } - it 'loads the result relation only once' do + it 'does not execute a query' do expect do subject - end.not_to exceed_query_limit(1) + end.not_to exceed_query_limit(0) end + it 'applies a LIMIT' do + expect(subject.limit_value).to eq(page.per_page) + end + + it 'returns the limited relation' do + expect(subject).to eq(relation.limit(page.per_page)) + end + + context 'validating the order clause' do + let(:page) { Gitlab::Pagination::Keyset::Page.new(order_by: { created_at: :asc }, per_page: 3) } + + it 'raises an error if has a different order clause than the page' do + expect { subject }.to raise_error(ArgumentError, /order_by does not match/) + end + end + end + + describe '#finalize' do + let(:records) { relation.limit(page.per_page).load } + + subject { described_class.new(request).finalize(records) } + it 'passes information about next page to request' do - lower_bounds = relation.limit(page.per_page).last.slice(:id) - expect(page).to receive(:next).with(lower_bounds, false).and_return(next_page) + lower_bounds = records.last.slice(:id) + expect(page).to receive(:next).with(lower_bounds).and_return(next_page) expect(request).to receive(:apply_headers).with(next_page) subject @@ -32,10 +54,10 @@ describe Gitlab::Pagination::Keyset::Pager do context 'when retrieving the last page' do let(:relation) { Project.where('id > ?', Project.maximum(:id) - page.per_page).order(id: :asc) } - it 'indicates this is the last page' do - expect(request).to receive(:apply_headers) do |next_page| - expect(next_page.end_reached?).to be_truthy - end + it 'indicates there is another (likely empty) page' do + lower_bounds = records.last.slice(:id) + expect(page).to receive(:next).with(lower_bounds).and_return(next_page) + expect(request).to receive(:apply_headers).with(next_page) subject end @@ -45,24 +67,10 @@ describe Gitlab::Pagination::Keyset::Pager do let(:relation) { Project.where('id > ?', Project.maximum(:id) + 1).order(id: :asc) } it 'indicates this is the last page' do - expect(request).to receive(:apply_headers) do |next_page| - expect(next_page.end_reached?).to be_truthy - end + expect(request).not_to receive(:apply_headers) subject end end - - it 'returns an array with the loaded records' do - expect(subject).to eq(relation.limit(page.per_page).to_a) - end - - context 'validating the order clause' do - let(:page) { Gitlab::Pagination::Keyset::Page.new(order_by: { created_at: :asc }, per_page: 3) } - - it 'raises an error if has a different order clause than the page' do - expect { subject }.to raise_error(ArgumentError, /order_by does not match/) - end - end end end diff --git a/spec/lib/gitlab/pagination/keyset/request_context_spec.rb b/spec/lib/gitlab/pagination/keyset/request_context_spec.rb index 344ef90efa3..6cd5ccc3c19 100644 --- a/spec/lib/gitlab/pagination/keyset/request_context_spec.rb +++ b/spec/lib/gitlab/pagination/keyset/request_context_spec.rb @@ -53,7 +53,7 @@ describe Gitlab::Pagination::Keyset::RequestContext do let(:request) { double('request', url: "http://#{Gitlab.config.gitlab.host}/api/v4/projects?foo=bar") } let(:params) { { foo: 'bar' } } let(:request_context) { double('request context', params: params, request: request) } - let(:next_page) { double('next page', order_by: { id: :asc }, lower_bounds: { id: 42 }, end_reached?: false) } + let(:next_page) { double('next page', order_by: { id: :asc }, lower_bounds: { id: 42 }) } subject { described_class.new(request_context).apply_headers(next_page) } @@ -92,7 +92,7 @@ describe Gitlab::Pagination::Keyset::RequestContext do end context 'with descending order' do - let(:next_page) { double('next page', order_by: { id: :desc }, lower_bounds: { id: 42 }, end_reached?: false) } + let(:next_page) { double('next page', order_by: { id: :desc }, lower_bounds: { id: 42 }) } it 'sets Links header with a link to the next page' do orig_uri = URI.parse(request_context.request.url) diff --git a/spec/lib/gitlab/pagination/keyset_spec.rb b/spec/lib/gitlab/pagination/keyset_spec.rb index 5c2576d7b45..bde280c5fca 100644 --- a/spec/lib/gitlab/pagination/keyset_spec.rb +++ b/spec/lib/gitlab/pagination/keyset_spec.rb @@ -3,22 +3,6 @@ require 'spec_helper' describe Gitlab::Pagination::Keyset do - describe '.paginate' do - subject { described_class.paginate(request_context, relation) } - - let(:request_context) { double } - let(:relation) { double } - let(:pager) { double } - let(:result) { double } - - it 'uses Pager to paginate the relation' do - expect(Gitlab::Pagination::Keyset::Pager).to receive(:new).with(request_context).and_return(pager) - expect(pager).to receive(:paginate).with(relation).and_return(result) - - expect(subject).to eq(result) - end - end - describe '.available?' do subject { described_class } |