ci: freeze time to fix flakey specs (#640)

This commit is contained in:
Jonathan del Strother 2023-11-21 13:22:01 +00:00 committed by GitHub
parent d9fedfae4f
commit d3b3da44c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,10 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative 'spec_helper' require_relative 'spec_helper'
require 'timecop'
describe 'Rack::Attack.throttle' do describe 'Rack::Attack.throttle' do
before do before do
@period = 60 # Use a long period; failures due to cache key rotation less likely @period = 60
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip } Rack::Attack.throttle('ip/sec', limit: 1, period: @period) { |req| req.ip }
end end
@ -14,14 +15,18 @@ describe 'Rack::Attack.throttle' do
it_allows_ok_requests it_allows_ok_requests
describe 'a single request' do describe 'a single request' do
before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
it 'should set the counter for one request' do it 'should set the counter for one request' do
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" Timecop.freeze do
_(Rack::Attack.cache.store.read(key)).must_equal 1 get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
_(Rack::Attack.cache.store.read(key)).must_equal 1
end
end end
it 'should populate throttle data' do it 'should populate throttle data' do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
data = { data = {
count: 1, count: 1,
limit: 1, limit: 1,
@ -36,7 +41,9 @@ describe 'Rack::Attack.throttle' do
describe "with 2 requests" do describe "with 2 requests" do
before do before do
2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } Timecop.freeze do
2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
end
end end
it 'should block the last request' do it 'should block the last request' do
@ -62,7 +69,7 @@ end
describe 'Rack::Attack.throttle with limit as proc' do describe 'Rack::Attack.throttle with limit as proc' do
before do before do
@period = 60 # Use a long period; failures due to cache key rotation less likely @period = 60
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: @period) { |req| req.ip } Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: @period) { |req| req.ip }
end end
@ -70,14 +77,17 @@ describe 'Rack::Attack.throttle with limit as proc' do
it_allows_ok_requests it_allows_ok_requests
describe 'a single request' do describe 'a single request' do
before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
it 'should set the counter for one request' do it 'should set the counter for one request' do
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" Timecop.freeze do
_(Rack::Attack.cache.store.read(key)).must_equal 1 get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
_(Rack::Attack.cache.store.read(key)).must_equal 1
end
end end
it 'should populate throttle data' do it 'should populate throttle data' do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
data = { data = {
count: 1, count: 1,
limit: 1, limit: 1,
@ -93,7 +103,7 @@ end
describe 'Rack::Attack.throttle with period as proc' do describe 'Rack::Attack.throttle with period as proc' do
before do before do
@period = 60 # Use a long period; failures due to cache key rotation less likely @period = 60
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: lambda { |_req| @period }) { |req| req.ip } Rack::Attack.throttle('ip/sec', limit: lambda { |_req| 1 }, period: lambda { |_req| @period }) { |req| req.ip }
end end
@ -101,14 +111,18 @@ describe 'Rack::Attack.throttle with period as proc' do
it_allows_ok_requests it_allows_ok_requests
describe 'a single request' do describe 'a single request' do
before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
it 'should set the counter for one request' do it 'should set the counter for one request' do
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" Timecop.freeze do
_(Rack::Attack.cache.store.read(key)).must_equal 1 get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
_(Rack::Attack.cache.store.read(key)).must_equal 1
end
end end
it 'should populate throttle data' do it 'should populate throttle data' do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
data = { data = {
count: 1, count: 1,
limit: 1, limit: 1,
@ -122,7 +136,7 @@ describe 'Rack::Attack.throttle with period as proc' do
end end
end end
describe 'Rack::Attack.throttle with block retuning nil' do describe 'Rack::Attack.throttle with block returning nil' do
before do before do
@period = 60 @period = 60
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
@ -132,14 +146,17 @@ describe 'Rack::Attack.throttle with block retuning nil' do
it_allows_ok_requests it_allows_ok_requests
describe 'a single request' do describe 'a single request' do
before { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
it 'should not set the counter' do it 'should not set the counter' do
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" Timecop.freeze do
assert_nil Rack::Attack.cache.store.read(key) get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
assert_nil Rack::Attack.cache.store.read(key)
end
end end
it 'should not populate throttle data' do it 'should not populate throttle data' do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
assert_nil last_request.env['rack.attack.throttle_data'] assert_nil last_request.env['rack.attack.throttle_data']
end end
end end
@ -162,9 +179,11 @@ describe 'Rack::Attack.throttle with throttle_discriminator_normalizer' do
end end
it 'should not differentiate requests when throttle_discriminator_normalizer is enabled' do it 'should not differentiate requests when throttle_discriminator_normalizer is enabled' do
post_logins Timecop.freeze do
key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com" post_logins
_(Rack::Attack.cache.store.read(key)).must_equal 3 key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com"
_(Rack::Attack.cache.store.read(key)).must_equal 3
end
end end
it 'should differentiate requests when throttle_discriminator_normalizer is disabled' do it 'should differentiate requests when throttle_discriminator_normalizer is disabled' do
@ -172,10 +191,12 @@ describe 'Rack::Attack.throttle with throttle_discriminator_normalizer' do
prev = Rack::Attack.throttle_discriminator_normalizer prev = Rack::Attack.throttle_discriminator_normalizer
Rack::Attack.throttle_discriminator_normalizer = nil Rack::Attack.throttle_discriminator_normalizer = nil
post_logins Timecop.freeze do
@emails.each do |email| post_logins
key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}" @emails.each do |email|
_(Rack::Attack.cache.store.read(key)).must_equal 1 key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}"
_(Rack::Attack.cache.store.read(key)).must_equal 1
end
end end
ensure ensure
Rack::Attack.throttle_discriminator_normalizer = prev Rack::Attack.throttle_discriminator_normalizer = prev