ci: freeze time in more specs (#643)

* ci: freeze time in more specs

* Introduce within_same_period helper method

---------

Co-authored-by: Gonzalo <456459+grzuy@users.noreply.github.com>
This commit is contained in:
Santiago Bartesaghi 2024-01-10 11:55:37 -03:00 committed by GitHub
parent 9b9f41c749
commit cb82b9f873
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 48 additions and 45 deletions

View file

@ -9,7 +9,6 @@ should_run =
if should_run if should_run
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "active_support/cache/dalli_store" require "active_support/cache/dalli_store"
require "timecop"
describe "ActiveSupport::Cache::DalliStore as a cache backend" do describe "ActiveSupport::Cache::DalliStore as a cache backend" do
before do before do

View file

@ -4,7 +4,6 @@ require_relative "../../spec_helper"
if defined?(::ConnectionPool) && defined?(::Dalli) if defined?(::ConnectionPool) && defined?(::Dalli)
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "ActiveSupport::Cache::MemCacheStore (pooled) as a cache backend" do describe "ActiveSupport::Cache::MemCacheStore (pooled) as a cache backend" do
before do before do

View file

@ -4,7 +4,6 @@ require_relative "../../spec_helper"
if defined?(::Dalli) if defined?(::Dalli)
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "ActiveSupport::Cache::MemCacheStore as a cache backend" do describe "ActiveSupport::Cache::MemCacheStore as a cache backend" do
before do before do

View file

@ -3,8 +3,6 @@
require_relative "../../spec_helper" require_relative "../../spec_helper"
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "ActiveSupport::Cache::MemoryStore as a cache backend" do describe "ActiveSupport::Cache::MemoryStore as a cache backend" do
before do before do
Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new

View file

@ -10,7 +10,6 @@ should_run =
if should_run if should_run
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "ActiveSupport::Cache::RedisCacheStore (pooled) as a cache backend" do describe "ActiveSupport::Cache::RedisCacheStore (pooled) as a cache backend" do
before do before do

View file

@ -9,7 +9,6 @@ should_run =
if should_run if should_run
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "ActiveSupport::Cache::RedisCacheStore as a cache backend" do describe "ActiveSupport::Cache::RedisCacheStore as a cache backend" do
before do before do

View file

@ -6,7 +6,6 @@ if defined?(::Dalli) && defined?(::ConnectionPool)
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "connection_pool" require "connection_pool"
require "dalli" require "dalli"
require "timecop"
describe "ConnectionPool with Dalli::Client as a cache backend" do describe "ConnectionPool with Dalli::Client as a cache backend" do
before do before do

View file

@ -5,7 +5,6 @@ require_relative "../../spec_helper"
if defined?(::Dalli) if defined?(::Dalli)
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "dalli" require "dalli"
require "timecop"
describe "Dalli::Client as a cache backend" do describe "Dalli::Client as a cache backend" do
before do before do

View file

@ -4,7 +4,6 @@ require_relative "../../spec_helper"
if defined?(::Redis) if defined?(::Redis)
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
require "timecop"
describe "Plain redis as a cache backend" do describe "Plain redis as a cache backend" do
before do before do

View file

@ -4,8 +4,6 @@ require_relative "../../spec_helper"
require_relative "../../support/cache_store_helper" require_relative "../../support/cache_store_helper"
if defined?(::Redis::Store) if defined?(::Redis::Store)
require "timecop"
describe "Redis::Store as a cache backend" do describe "Redis::Store as a cache backend" do
before do before do
Rack::Attack.cache.store = ::Redis::Store.new Rack::Attack.cache.store = ::Redis::Store.new

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative 'spec_helper' require_relative 'spec_helper'
require 'timecop' require_relative 'support/freeze_time_helper'
describe 'Rack::Attack.throttle' do describe 'Rack::Attack.throttle' do
before do before do
@ -16,7 +16,7 @@ describe 'Rack::Attack.throttle' do
describe 'a single request' do describe 'a single request' do
it 'should set the counter for one request' do it 'should set the counter for one request' do
Timecop.freeze do within_same_period do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
@ -41,7 +41,7 @@ describe 'Rack::Attack.throttle' do
describe "with 2 requests" do describe "with 2 requests" do
before do before do
Timecop.freeze do within_same_period do
2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' } 2.times { get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' }
end end
end end
@ -78,7 +78,7 @@ describe 'Rack::Attack.throttle with limit as proc' do
describe 'a single request' do describe 'a single request' do
it 'should set the counter for one request' do it 'should set the counter for one request' do
Timecop.freeze do within_same_period do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
@ -112,7 +112,7 @@ describe 'Rack::Attack.throttle with period as proc' do
describe 'a single request' do describe 'a single request' do
it 'should set the counter for one request' do it 'should set the counter for one request' do
Timecop.freeze do within_same_period do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
@ -147,7 +147,7 @@ describe 'Rack::Attack.throttle with block returning nil' do
describe 'a single request' do describe 'a single request' do
it 'should not set the counter' do it 'should not set the counter' do
Timecop.freeze do within_same_period do
get '/', {}, 'REMOTE_ADDR' => '1.2.3.4' get '/', {}, 'REMOTE_ADDR' => '1.2.3.4'
key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4" key = "rack::attack:#{Time.now.to_i / @period}:ip/sec:1.2.3.4"
@ -179,7 +179,7 @@ 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
Timecop.freeze do within_same_period do
post_logins post_logins
key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com" key = "rack::attack:#{Time.now.to_i / @period}:logins/email:person@example.com"
_(Rack::Attack.cache.store.read(key)).must_equal 3 _(Rack::Attack.cache.store.read(key)).must_equal 3
@ -191,7 +191,7 @@ 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
Timecop.freeze do within_same_period do
post_logins post_logins
@emails.each do |email| @emails.each do |email|
key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}" key = "rack::attack:#{Time.now.to_i / @period}:logins/email:#{email}"

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative 'freeze_time_helper'
class Minitest::Spec class Minitest::Spec
def self.it_works_for_cache_backed_features(options) def self.it_works_for_cache_backed_features(options)
fetch_from_store = options.fetch(:fetch_from_store) fetch_from_store = options.fetch(:fetch_from_store)
@ -9,11 +11,13 @@ class Minitest::Spec
request.ip request.ip
end end
get "/", {}, "REMOTE_ADDR" => "1.2.3.4" within_same_period do
assert_equal 200, last_response.status get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
assert_equal 200, last_response.status
get "/", {}, "REMOTE_ADDR" => "1.2.3.4" get "/", {}, "REMOTE_ADDR" => "1.2.3.4"
assert_equal 429, last_response.status assert_equal 429, last_response.status
end
end end
it "works for fail2ban" do it "works for fail2ban" do
@ -23,17 +27,19 @@ class Minitest::Spec
end end
end end
get "/" within_same_period do
assert_equal 200, last_response.status get "/"
assert_equal 200, last_response.status
get "/private-place" get "/private-place"
assert_equal 403, last_response.status assert_equal 403, last_response.status
get "/private-place" get "/private-place"
assert_equal 403, last_response.status assert_equal 403, last_response.status
get "/" get "/"
assert_equal 403, last_response.status assert_equal 403, last_response.status
end
end end
it "works for allow2ban" do it "works for allow2ban" do
@ -43,20 +49,22 @@ class Minitest::Spec
end end
end end
get "/" within_same_period do
assert_equal 200, last_response.status get "/"
assert_equal 200, last_response.status
get "/scarce-resource" get "/scarce-resource"
assert_equal 200, last_response.status assert_equal 200, last_response.status
get "/scarce-resource" get "/scarce-resource"
assert_equal 200, last_response.status assert_equal 200, last_response.status
get "/scarce-resource" get "/scarce-resource"
assert_equal 403, last_response.status assert_equal 403, last_response.status
get "/" get "/"
assert_equal 403, last_response.status assert_equal 403, last_response.status
end
end end
it "doesn't leak keys" do it "doesn't leak keys" do
@ -66,9 +74,7 @@ class Minitest::Spec
key = nil key = nil
# Freeze time during these statement to be sure that the key used by rack attack is the same within_same_period do
# we pre-calculate in local variable `key`
Timecop.freeze do
key = "rack::attack:#{Time.now.to_i}:by ip:1.2.3.4" key = "rack::attack:#{Time.now.to_i}:by ip:1.2.3.4"
get "/", {}, "REMOTE_ADDR" => "1.2.3.4" get "/", {}, "REMOTE_ADDR" => "1.2.3.4"

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
require "timecop"
class Minitest::Spec
def within_same_period(&block)
Timecop.freeze(&block)
end
end