diff --git a/ruby/ci-queue.gemspec b/ruby/ci-queue.gemspec index 6b2c7387..3f4f69a9 100644 --- a/ruby/ci-queue.gemspec +++ b/ruby/ci-queue.gemspec @@ -41,9 +41,9 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'simplecov', '~> 0.12' spec.add_development_dependency 'minitest-reporters', '~> 1.1' + spec.add_development_dependency 'rexml' spec.add_development_dependency 'snappy' spec.add_development_dependency 'msgpack' spec.add_development_dependency 'benchmark' - spec.add_development_dependency 'rexml' spec.add_development_dependency 'rubocop' end diff --git a/ruby/lib/ci/queue/redis/worker.rb b/ruby/lib/ci/queue/redis/worker.rb index 004b6fe3..cf6366c6 100644 --- a/ruby/lib/ci/queue/redis/worker.rb +++ b/ruby/lib/ci/queue/redis/worker.rb @@ -13,6 +13,11 @@ class << self self.requeue_offset = 42 self.max_sleep_time = 2 + # Minimal wrapper returned by resolve_entry when neither @index nor entry_resolver + # is available. Provides the interface callers expect (.id, .queue_entry) so that + # downstream code doesn't crash with NoMethodError on a raw String. + UnresolvedEntry = Struct.new(:id, :queue_entry) + class Worker < Base attr_accessor :entry_resolver attr_reader :first_reserve_at @@ -295,7 +300,7 @@ def resolve_entry(entry) return entry_resolver.call(entry) if entry_resolver - entry + UnresolvedEntry.new(test_id, entry) end def still_streaming? diff --git a/ruby/lib/minitest/queue/queue_population_strategy.rb b/ruby/lib/minitest/queue/queue_population_strategy.rb index f3ed7765..9a461ab0 100644 --- a/ruby/lib/minitest/queue/queue_population_strategy.rb +++ b/ruby/lib/minitest/queue/queue_population_strategy.rb @@ -35,6 +35,7 @@ def populate_queue configure_lazy_queue queue.stream_populate(lazy_test_enumerator, random: ordering_seed, batch_size: queue_config.lazy_load_stream_batch_size) else + configure_lazy_queue queue.populate(Minitest.loaded_tests, random: ordering_seed) end end diff --git a/ruby/test/ci/queue/redis_test.rb b/ruby/test/ci/queue/redis_test.rb index 6e89798f..e3302621 100644 --- a/ruby/test/ci/queue/redis_test.rb +++ b/ruby/test/ci/queue/redis_test.rb @@ -358,6 +358,16 @@ def test_resolve_entry_falls_back_to_resolver assert_equal "resolved:MissingTest#test_bar#{DELIMITER}/tmp/missing.rb", resolved end + def test_resolve_entry_returns_unresolved_entry_without_index_or_resolver + queue = worker(1, populate: false) + + result = queue.send(:resolve_entry, "MissingTest#test_bar#{DELIMITER}/tmp/missing.rb") + + assert_instance_of CI::Queue::Redis::UnresolvedEntry, result + assert_equal "MissingTest#test_bar", result.id + assert_equal "MissingTest#test_bar#{DELIMITER}/tmp/missing.rb", result.queue_entry + end + def test_continuously_timing_out_tests 3.times do @redis.flushdb diff --git a/ruby/test/minitest/queue/queue_population_strategy_test.rb b/ruby/test/minitest/queue/queue_population_strategy_test.rb index 07975a2c..6f7ec7dc 100644 --- a/ruby/test/minitest/queue/queue_population_strategy_test.rb +++ b/ruby/test/minitest/queue/queue_population_strategy_test.rb @@ -59,6 +59,30 @@ def test_eager_mode_populates_loaded_tests Object.send(:remove_const, class_name) if class_name && Object.const_defined?(class_name) end + def test_eager_mode_sets_entry_resolver_as_fallback + queue = FakeQueue.new + config = CI::Queue::Configuration.new(lazy_load: false) + class_name = "StrategyEagerResolver#{Process.pid}#{rand(1000)}" + + Dir.mktmpdir do |dir| + file = File.join(dir, "strategy_eager_resolver_test.rb") + File.write(file, "class #{class_name} < Minitest::Test\n def test_resolver\n assert true\n end\nend\n") + strategy = QueuePopulationStrategy.new( + queue: queue, + queue_config: config, + argv: [file], + test_files_file: nil, + ordering_seed: Random.new(123), + ) + strategy.load_and_populate! + end + + assert_instance_of Minitest::Queue::LazyEntryResolver, queue.entry_resolver, + "eager mode should set entry_resolver as fallback for resolve_entry" + ensure + Object.send(:remove_const, class_name) if class_name && Object.const_defined?(class_name) + end + def test_preresolved_mode_streams_entries queue = FakeQueue.new config = CI::Queue::Configuration.new(lazy_load: true)