debian-mirror-gitlab/spec/lib/gitlab/error_tracking/processor/sidekiq_processor_spec.rb
2021-09-04 01:27:46 +05:30

182 lines
6 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
require 'rspec-parameterized'
RSpec.describe Gitlab::ErrorTracking::Processor::SidekiqProcessor do
after do
if described_class.instance_variable_defined?(:@permitted_arguments_for_worker)
described_class.remove_instance_variable(:@permitted_arguments_for_worker)
end
end
describe '.filter_arguments' do
it 'returns a lazy enumerator' do
filtered = described_class.filter_arguments([1, 'string'], 'TestWorker')
expect(filtered).to be_a(Enumerator::Lazy)
expect(filtered.to_a).to eq([1, described_class::FILTERED_STRING])
end
context 'arguments filtering' do
using RSpec::Parameterized::TableSyntax
where(:klass, :expected) do
'UnknownWorker' | [1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING]
'NoPermittedArguments' | [1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING]
'OnePermittedArgument' | [1, 'string', described_class::FILTERED_STRING, described_class::FILTERED_STRING]
'AllPermittedArguments' | [1, 'string', [1, 2], { a: 1 }]
end
with_them do
before do
stub_const('NoPermittedArguments', double(loggable_arguments: []))
stub_const('OnePermittedArgument', double(loggable_arguments: [1]))
stub_const('AllPermittedArguments', double(loggable_arguments: [0, 1, 2, 3]))
end
it do
expect(described_class.filter_arguments([1, 'string', [1, 2], { a: 1 }], klass).to_a)
.to eq(expected)
end
end
end
end
describe '.permitted_arguments_for_worker' do
it 'returns the loggable_arguments for a worker class as a set' do
stub_const('TestWorker', double(loggable_arguments: [1, 1]))
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq([1].to_set)
end
it 'returns an empty set when the worker class does not exist' do
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'returns an empty set when the worker class does not respond to loggable_arguments' do
stub_const('TestWorker', 1)
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'returns an empty set when loggable_arguments cannot be converted to a set' do
stub_const('TestWorker', double(loggable_arguments: 1))
expect(described_class.permitted_arguments_for_worker('TestWorker'))
.to eq(Set.new)
end
it 'memoizes the results' do
worker_class = double
stub_const('TestWorker', worker_class)
expect(worker_class).to receive(:loggable_arguments).once.and_return([])
described_class.permitted_arguments_for_worker('TestWorker')
described_class.permitted_arguments_for_worker('TestWorker')
end
end
describe '.loggable_arguments' do
it 'filters and limits the arguments, then converts to strings' do
half_limit = Gitlab::Utils::LogLimitedArray::MAXIMUM_ARRAY_LENGTH / 2
args = [[1, 2], 'a' * half_limit, 'b' * half_limit, 'c' * half_limit, 'd']
stub_const('LoggableArguments', double(loggable_arguments: [0, 1, 3, 4]))
expect(described_class.loggable_arguments(args, 'LoggableArguments'))
.to eq(['[1, 2]', 'a' * half_limit, '[FILTERED]', '...'])
end
end
describe '.call' do
let(:required_options) do
{
configuration: Raven.configuration,
context: Raven.context,
breadcrumbs: Raven.breadcrumbs
}
end
let(:event) { Raven::Event.new(required_options.merge(wrapped_value)) }
let(:result_hash) { described_class.call(event).to_hash }
context 'when there is Sidekiq data' do
let(:wrapped_value) { { extra: { sidekiq: value } } }
shared_examples 'Sidekiq arguments' do |args_in_job_hash: true|
let(:path) { [:extra, :sidekiq, args_in_job_hash ? :job : nil, 'args'].compact }
let(:args) { [1, 'string', { a: 1 }, [1, 2]] }
context 'for an unknown worker' do
let(:value) do
hash = { 'args' => args, 'class' => 'UnknownWorker' }
args_in_job_hash ? { job: hash } : hash
end
it 'only allows numeric arguments for an unknown worker' do
expect(result_hash.dig(*path))
.to eq([1, described_class::FILTERED_STRING, described_class::FILTERED_STRING, described_class::FILTERED_STRING])
end
end
context 'for a permitted worker' do
let(:value) do
hash = { 'args' => args, 'class' => 'PostReceive' }
args_in_job_hash ? { job: hash } : hash
end
it 'allows all argument types for a permitted worker' do
expect(result_hash.dig(*path)).to eq(args)
end
end
end
context 'when processing via the default error handler' do
include_examples 'Sidekiq arguments', args_in_job_hash: true
end
context 'when processing via Gitlab::ErrorTracking' do
include_examples 'Sidekiq arguments', args_in_job_hash: false
end
context 'when a jobstr field is present' do
let(:value) do
{
job: { 'args' => [1] },
jobstr: { 'args' => [1] }.to_json
}
end
it 'removes the jobstr' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value.except(:jobstr))
end
end
context 'when no jobstr value is present' do
let(:value) { { job: { 'args' => [1] } } }
it 'does nothing' do
expect(result_hash.dig(:extra, :sidekiq)).to eq(value)
end
end
end
context 'when there is no Sidekiq data' do
let(:value) { { tags: { foo: 'bar', baz: 'quux' } } }
let(:wrapped_value) { value }
it 'does nothing' do
expect(result_hash).to include(value)
expect(result_hash.dig(:extra, :sidekiq)).to be_nil
end
end
end
end