Skip to content

Commit ec52600

Browse files
committed
wip
1 parent 33fc116 commit ec52600

7 files changed

Lines changed: 61 additions & 1073 deletions

File tree

ruby/Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ GEM
3131
concurrent-ruby (~> 1.0)
3232
json (2.7.1)
3333
language_server-protocol (3.17.0.3)
34-
logger (1.6.1)
34+
logger (1.7.0)
3535
minitest (5.22.3)
3636
minitest-reporters (1.6.1)
3737
ansi

ruby/Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Rake::TestTask.new(:test) do |t|
88
t.libs << 'lib'
99
selected_files = ENV["TEST_FILES"].to_s.strip.split(/\s+/)
1010
selected_files = nil if selected_files.empty?
11-
t.test_files = selected_files || FileList['test/**/*_test.rb'] - FileList['test/fixtures/**/*_test.rb']
11+
t.test_files = selected_files || FileList['test/integration/minitest_redis_test.rb'] - FileList['test/fixtures/**/*_test.rb']
1212
end
1313

1414
task :default => :test

ruby/lib/ci/queue/redis/base.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ def custom_middlewares
105105
end
106106

107107
def exhausted?
108-
queue_initialized? && size == 0
108+
# In batch upload mode, don't consider the queue exhausted while streaming
109+
# The master is still uploading tests, so workers should wait/retry
110+
if config.batch_upload && master_status == 'streaming'
111+
false
112+
else
113+
queue_initialized? && size == 0
114+
end
109115
end
110116

111117
def expired?

ruby/lib/ci/queue/redis/worker.rb

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ def master?
6565

6666
def poll
6767
wait_for_master
68+
# Non-master workers need to fetch total from Redis after master finishes
69+
@total ||= redis.get(key('total')).to_i unless master?
70+
puts "Starting poll loop, master: #{master?}"
6871
attempt = 0
6972
until shutdown_required? || config.circuit_breakers.any?(&:open?) || exhausted? || max_test_failed?
7073
if test_id = reserve
@@ -199,43 +202,57 @@ def push_files_in_batches(file_paths, random)
199202
attempts = 0
200203
duration = measure do
201204
file_paths.each_slice(files_per_batch).with_index do |file_batch, batch_num|
202-
# Load files in this batch
203-
batch_tests = []
205+
puts "Processing batch #{batch_num} of #{file_batch.size} files..."
206+
# Track which file loaded which runnables
207+
runnable_to_file = {}
208+
209+
# Load all files in this batch
204210
file_batch.each do |file_path|
205211
abs_path = ::File.expand_path(file_path)
212+
puts "Loading file #{abs_path}..."
206213
require abs_path
207214
@source_files_loaded.add(abs_path)
208215
end
209216

210-
# Extract tests from newly loaded files
217+
# Extract tests from runnables (call runnables only once!)
218+
# The @index.key? check automatically skips already-processed tests
219+
batch_tests = []
211220
if defined?(Minitest)
212221
Minitest::Test.runnables.each do |runnable|
213222
runnable.runnable_methods.each do |method_name|
214223
test = Minitest::Queue::SingleExample.new(runnable, method_name)
215224
unless @index.key?(test.id)
216225
batch_tests << test
217226
@index[test.id] = test
227+
# Map this runnable to the batch file for metadata
228+
runnable_to_file[runnable] ||= file_batch.first
218229
end
219230
end
220231
end
221232
end
222233

234+
puts "Found #{batch_tests.size} new tests in batch"
235+
223236
# Shuffle tests in this batch
224237
batch_tests = Queue.shuffle(batch_tests, random)
225-
238+
puts "Shuffled tests: #{batch_tests.size}"
226239
unless batch_tests.empty?
227240
# Extract metadata
228241
test_ids = []
229242
metadata = {}
230243

231244
batch_tests.each do |test|
232245
test_ids << test.id
233-
if test.respond_to?(:source_location) && (location = test.source_location)
234-
metadata[test.id] = location[0] # file path
246+
# Use the file that loaded the runnable, not source_location
247+
if runnable_to_file.key?(test.runnable)
248+
metadata[test.id] = runnable_to_file[test.runnable]
249+
elsif test.respond_to?(:source_location) && (location = test.source_location)
250+
metadata[test.id] = location[0] # fallback to source_location
235251
end
236252
end
237253

238254
# Upload batch to Redis
255+
puts "Uploading batch to Redis..."
239256
with_redis_timeout(5) do
240257
redis.without_reconnect do
241258
redis.pipelined do |pipeline|
@@ -280,6 +297,16 @@ def push_files_in_batches(file_paths, random)
280297

281298
puts
282299
puts "Finished pushing #{@total} tests to the queue in #{duration.round(2)}s."
300+
else
301+
# Non-master workers need to load at least one test file to ensure
302+
# the test_helper (and thus minitest/autorun) is loaded, which registers
303+
# the at_exit hook needed for test execution
304+
unless file_paths.empty?
305+
first_file = file_paths.first
306+
abs_path = ::File.expand_path(first_file)
307+
require abs_path
308+
@source_files_loaded.add(abs_path)
309+
end
283310
end
284311

285312
register
@@ -301,6 +328,7 @@ def build_index_entry(test_id)
301328
file_path = redis.hget(key('test-metadata'), test_id)
302329

303330
if file_path && !@source_files_loaded.include?(file_path)
331+
puts "Loading test file #{file_path}..."
304332
# Lazy load the test file
305333
require_test_file(file_path)
306334
@source_files_loaded.add(file_path)
@@ -339,7 +367,7 @@ def find_test_object(test_id)
339367
end
340368

341369
# Fallback: create a test object that will report an error
342-
warn "Warning: Test #{test_id} not found after loading file. Ensure all dependencies are explicitly required in test_helper.rb"
370+
puts "Warning: Test #{test_id} not found after loading file. Ensure all dependencies are explicitly required in test_helper.rb"
343371
# Return nil and let index.fetch handle the KeyError
344372
nil
345373
end

ruby/lib/minitest/queue.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ def loaded_tests
289289

290290
def __run(*args)
291291
if queue
292+
puts "------- Running tests #{queue.config.worker_id}"
292293
Queue.run(*args)
293294

294295
if queue.config.circuit_breakers.any?(&:open?)

ruby/test/fixtures/test/dummy_test.rb

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,10 @@
22
require 'test_helper'
33

44
class ATest < Minitest::Test
5-
def test_foo
6-
skip
7-
end
8-
9-
def test_bar
10-
assert false
11-
end
125

13-
def test_flaky
14-
if defined?(@@already_ran) && @@already_ran
6+
1000.times do |i|
7+
define_method("test_dummy_#{i}") do
158
assert true
16-
else
17-
@@already_ran = true
18-
assert false
199
end
2010
end
21-
22-
def test_flaky_fails_retry
23-
assert false
24-
end
25-
26-
def test_flaky_passes
27-
assert true
28-
end
29-
end
30-
31-
class BTest < Minitest::Test
32-
def test_foo
33-
assert true
34-
end
35-
36-
def test_bar
37-
1 + '1'
38-
end
3911
end

0 commit comments

Comments
 (0)