gitlab-org--gitlab-foss/spec/lib/gitlab/web_hooks/rate_limiter_spec.rb

124 lines
3.7 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::WebHooks::RateLimiter, :clean_gitlab_redis_rate_limiting do
let_it_be(:plan) { create(:default_plan) }
let_it_be_with_reload(:project_hook) { create(:project_hook) }
let_it_be_with_reload(:system_hook) { create(:system_hook) }
let_it_be_with_reload(:integration_hook) { create(:jenkins_integration).service_hook }
let_it_be(:limit) { 1 }
using RSpec::Parameterized::TableSyntax
describe '#rate_limit!' do
def rate_limit!(hook)
described_class.new(hook).rate_limit!
end
shared_examples 'a hook that is never rate limited' do
specify do
expect(Gitlab::ApplicationRateLimiter).not_to receive(:throttled?)
expect(rate_limit!(hook)).to eq(false)
end
end
context 'when there is no plan limit' do
where(:hook) { [ref(:project_hook), ref(:system_hook), ref(:integration_hook)] }
with_them { it_behaves_like 'a hook that is never rate limited' }
end
context 'when there is a plan limit' do
before_all do
create(:plan_limits, plan: plan, web_hook_calls: limit)
end
where(:hook, :limitless_hook_type) do
ref(:project_hook) | false
ref(:system_hook) | true
ref(:integration_hook) | true
end
with_them do
if params[:limitless_hook_type]
it_behaves_like 'a hook that is never rate limited'
else
it 'rate limits the hook, returning true when rate limited' do
expect(Gitlab::ApplicationRateLimiter).to receive(:throttled?)
.exactly(3).times
.and_call_original
freeze_time do
limit.times { expect(rate_limit!(hook)).to eq(false) }
expect(rate_limit!(hook)).to eq(true)
end
travel_to(1.day.from_now) do
expect(rate_limit!(hook)).to eq(false)
end
end
end
end
end
describe 'rate limit scope' do
it 'rate limits all hooks from the same namespace', :freeze_time do
create(:plan_limits, plan: plan, web_hook_calls: limit)
project_hook_in_different_namespace = create(:project_hook)
project_hook_in_same_namespace = create(:project_hook,
project: create(:project, namespace: project_hook.project.namespace)
)
limit.times { expect(rate_limit!(project_hook)).to eq(false) }
expect(rate_limit!(project_hook)).to eq(true)
expect(rate_limit!(project_hook_in_same_namespace)).to eq(true)
expect(rate_limit!(project_hook_in_different_namespace)).to eq(false)
end
end
end
describe '#rate_limited?' do
subject { described_class.new(hook).rate_limited? }
context 'when no plan limit has been defined' do
where(:hook) { [ref(:project_hook), ref(:system_hook), ref(:integration_hook)] }
with_them do
it { is_expected.to eq(false) }
end
end
context 'when there is a plan limit' do
before_all do
create(:plan_limits, plan: plan, web_hook_calls: limit)
end
context 'when hook is not rate-limited' do
where(:hook) { [ref(:project_hook), ref(:system_hook), ref(:integration_hook)] }
with_them do
it { is_expected.to eq(false) }
end
end
context 'when hook is rate-limited' do
before do
allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true)
end
where(:hook, :limitless_hook_type) do
ref(:project_hook) | false
ref(:system_hook) | true
ref(:integration_hook) | true
end
with_them do
it { is_expected.to eq(!limitless_hook_type) }
end
end
end
end
end