From 536ae08a44a8a78662be17628e59fe30dcf5d85d Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sun, 25 Feb 2024 15:14:22 -0800 Subject: [PATCH] cachable: make sure to clear caches between tests This adds a registry for all modules and classes that cachable is included in. The registry allows us to programmatically clear all caches in between tests so that we don't forget to do that when adding a new class or refactoring code. The goal here is to reduce the number of flaky tests in the future. --- Library/Homebrew/api/cask.rb | 4 +-- Library/Homebrew/api/formula.rb | 4 +-- Library/Homebrew/extend/cachable.rb | 41 +++++++++++++++++++++++++++- Library/Homebrew/readall.rb | 3 +- Library/Homebrew/test/spec_helper.rb | 21 ++------------ 5 files changed, 48 insertions(+), 25 deletions(-) diff --git a/Library/Homebrew/api/cask.rb b/Library/Homebrew/api/cask.rb index 17ca86b716..8d0274cda8 100644 --- a/Library/Homebrew/api/cask.rb +++ b/Library/Homebrew/api/cask.rb @@ -10,9 +10,9 @@ module Homebrew # # @api private module Cask - class << self - include Cachable + extend Cachable + class << self private :cache sig { params(token: String).returns(Hash) } diff --git a/Library/Homebrew/api/formula.rb b/Library/Homebrew/api/formula.rb index 8704ec6ad4..ba5a1de330 100644 --- a/Library/Homebrew/api/formula.rb +++ b/Library/Homebrew/api/formula.rb @@ -10,9 +10,9 @@ module Homebrew # # @api private module Formula - class << self - include Cachable + extend Cachable + class << self private :cache sig { params(name: String).returns(Hash) } diff --git a/Library/Homebrew/extend/cachable.rb b/Library/Homebrew/extend/cachable.rb index b124c638e6..9c65e1bc36 100644 --- a/Library/Homebrew/extend/cachable.rb +++ b/Library/Homebrew/extend/cachable.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # frozen_string_literal: true module Cachable @@ -11,4 +11,43 @@ module Cachable def clear_cache cache.clear end + + # Collect all classes that mix in Cachable so that those caches can be cleared in-between tests. + if ENV["HOMEBREW_TESTS"] + def self.included(klass) + raise ArgumentError, "Don't use Cachable with singleton classes" if klass.singleton_class? + + super if defined?(super) + end + + # Ignore classes that get inherited from a lot and that have + # caches that we don't need to clear on the class level. + IGNORE_INHERITED_CLASSES = %w[Formula Cask].freeze + private_constant :IGNORE_INHERITED_CLASSES + + def self.extended(klass) + Registry.list << klass + klass.extend(Inherited) unless IGNORE_INHERITED_CLASSES.include?(klass.name) + super if defined?(super) + end + + module Inherited + def inherited(klass) + # A class might inherit Cachable at the instance level + # and in that case we just want to skip registering it. + Registry.list << klass if klass.respond_to?(:clear_cache) + super if defined?(super) + end + end + + module Registry + def self.list + @list ||= [] + end + + def self.clear_all_caches + list.each(&:clear_cache) + end + end + end end diff --git a/Library/Homebrew/readall.rb b/Library/Homebrew/readall.rb index 91407529aa..778b10ca65 100644 --- a/Library/Homebrew/readall.rb +++ b/Library/Homebrew/readall.rb @@ -9,8 +9,9 @@ require "system_command" # # @api private module Readall + extend Cachable + class << self - include Cachable include SystemCommand::Mixin # TODO: remove this once the `MacOS` module is undefined on Linux diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index 9d2f2d10ee..f9ed707426 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -202,16 +202,7 @@ RSpec.configure do |config| config.around do |example| Homebrew.raise_deprecation_exceptions = true - Formulary.clear_cache - Tap.each(&:clear_cache) - Tap.clear_cache - DependencyCollector.clear_cache - Formula.clear_cache - Keg.clear_cache - Tab.clear_cache - Dependency.clear_cache - Requirement.clear_cache - Readall.clear_cache if defined?(Readall) + Cachable::Registry.clear_all_caches FormulaInstaller.clear_attempted FormulaInstaller.clear_installed FormulaInstaller.clear_fetched @@ -263,15 +254,7 @@ RSpec.configure do |config| @__stderr.close @__stdin.close - Formulary.clear_cache - Tap.clear_cache - DependencyCollector.clear_cache - Formula.clear_cache - Keg.clear_cache - Tab.clear_cache - Dependency.clear_cache - Requirement.clear_cache - Readall.clear_cache if defined?(Readall) + Cachable::Registry.clear_all_caches FileUtils.rm_rf [ *TEST_DIRECTORIES,