diff options
Diffstat (limited to 'spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb')
-rw-r--r-- | spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb new file mode 100644 index 00000000000..3140686c908 --- /dev/null +++ b/spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb @@ -0,0 +1,253 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::SidekiqMiddleware::SizeLimiter::Validator do + let(:worker_class) do + Class.new do + def self.name + "TestSizeLimiterWorker" + end + + include ApplicationWorker + + def perform(*args); end + end + end + + before do + stub_const("TestSizeLimiterWorker", worker_class) + end + + describe '#initialize' do + context 'when the input mode is valid' do + it 'does not log a warning message' do + expect(::Sidekiq.logger).not_to receive(:warn) + + described_class.new(TestSizeLimiterWorker, {}, mode: 'track') + described_class.new(TestSizeLimiterWorker, {}, mode: 'raise') + end + end + + context 'when the input mode is invalid' do + it 'defaults to track mode and logs a warning message' do + expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter mode: invalid. Fallback to track mode.') + + validator = described_class.new(TestSizeLimiterWorker, {}, mode: 'invalid') + + expect(validator.mode).to eql('track') + end + end + + context 'when the input mode is empty' do + it 'defaults to track mode' do + expect(::Sidekiq.logger).not_to receive(:warn) + + validator = described_class.new(TestSizeLimiterWorker, {}) + + expect(validator.mode).to eql('track') + end + end + + context 'when the size input is valid' do + it 'does not log a warning message' do + expect(::Sidekiq.logger).not_to receive(:warn) + + described_class.new(TestSizeLimiterWorker, {}, size_limit: 300) + described_class.new(TestSizeLimiterWorker, {}, size_limit: 0) + end + end + + context 'when the size input is invalid' do + it 'defaults to 0 and logs a warning message' do + expect(::Sidekiq.logger).to receive(:warn).with('Invalid Sidekiq size limiter limit: -1') + + described_class.new(TestSizeLimiterWorker, {}, size_limit: -1) + end + end + + context 'when the size input is empty' do + it 'defaults to 0' do + expect(::Sidekiq.logger).not_to receive(:warn) + + validator = described_class.new(TestSizeLimiterWorker, {}) + + expect(validator.size_limit).to be(0) + end + end + end + + shared_examples 'validate limit job payload size' do + context 'in track mode' do + let(:mode) { 'track' } + + context 'when size limit negative' do + let(:size_limit) { -1 } + + it 'does not track jobs' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) + end + + it 'does not raise exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + end + end + + context 'when size limit is 0' do + let(:size_limit) { 0 } + + it 'does not track jobs' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) + end + + it 'does not raise exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + end + end + + context 'when job size is bigger than size limit' do + let(:size_limit) { 50 } + + it 'tracks job' do + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + be_a(Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError) + ) + + validate.call(TestSizeLimiterWorker, { a: 'a' * 100 }) + end + + it 'does not raise an exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + end + + context 'when the worker has big_payload attribute' do + before do + worker_class.big_payload! + end + + it 'does not track jobs' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) + validate.call('TestSizeLimiterWorker', { a: 'a' * 300 }) + end + + it 'does not raise an exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + expect { validate.call('TestSizeLimiterWorker', { a: 'a' * 300 }) }.not_to raise_error + end + end + end + + context 'when job size is less than size limit' do + let(:size_limit) { 50 } + + it 'does not track job' do + expect(Gitlab::ErrorTracking).not_to receive(:track_exception) + + validate.call(TestSizeLimiterWorker, { a: 'a' }) + end + + it 'does not raise an exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' }) }.not_to raise_error + end + end + end + + context 'in raise mode' do + let(:mode) { 'raise' } + + context 'when size limit is negative' do + let(:size_limit) { -1 } + + it 'does not raise exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + end + end + + context 'when size limit is 0' do + let(:size_limit) { 0 } + + it 'does not raise exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + end + end + + context 'when job size is bigger than size limit' do + let(:size_limit) { 50 } + + it 'raises an exception' do + expect do + validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) + end.to raise_error( + Gitlab::SidekiqMiddleware::SizeLimiter::ExceedLimitError, + /TestSizeLimiterWorker job exceeds payload size limit/i + ) + end + + context 'when the worker has big_payload attribute' do + before do + worker_class.big_payload! + end + + it 'does not raise an exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' * 300 }) }.not_to raise_error + expect { validate.call('TestSizeLimiterWorker', { a: 'a' * 300 }) }.not_to raise_error + end + end + end + + context 'when job size is less than size limit' do + let(:size_limit) { 50 } + + it 'does not raise an exception' do + expect { validate.call(TestSizeLimiterWorker, { a: 'a' }) }.not_to raise_error + end + end + end + end + + describe '#validate!' do + context 'when calling SizeLimiter.validate!' do + let(:validate) { ->(worker_clas, job) { described_class.validate!(worker_class, job) } } + + before do + stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_MODE', mode) + stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES', size_limit) + end + + it_behaves_like 'validate limit job payload size' + end + + context 'when creating an instance with the related ENV variables' do + let(:validate) do + ->(worker_clas, job) do + validator = described_class.new(worker_class, job, mode: mode, size_limit: size_limit) + validator.validate! + end + end + + before do + stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_MODE', mode) + stub_env('GITLAB_SIDEKIQ_SIZE_LIMITER_LIMIT_BYTES', size_limit) + end + + it_behaves_like 'validate limit job payload size' + end + + context 'when creating an instance with mode and size limit' do + let(:validate) do + ->(worker_clas, job) do + validator = described_class.new(worker_class, job, mode: mode, size_limit: size_limit) + validator.validate! + end + end + + it_behaves_like 'validate limit job payload size' + end + end +end |