lib/test_queue/iterator.rb in test-queue-0.2.13 vs lib/test_queue/iterator.rb in test-queue-0.3.0

- old
+ new

@@ -1,54 +1,74 @@ module TestQueue class Iterator - attr_reader :stats, :sock + attr_reader :sock - def initialize(sock, suites, filter=nil) + def initialize(test_framework, sock, filter=nil, early_failure_limit: nil) + @test_framework = test_framework @done = false - @stats = {} + @suite_stats = [] @procline = $0 @sock = sock - @suites = suites @filter = filter if @sock =~ /^(.+):(\d+)$/ @tcp_address = $1 @tcp_port = $2.to_i end + @failures = 0 + @early_failure_limit = early_failure_limit end def each fail "already used this iterator. previous caller: #@done" if @done while true - client = connect_to_master('POP') + # If we've hit too many failures in one worker, assume the entire + # test suite is broken, and notify master so the run + # can be immediately halted. + if @early_failure_limit && @failures >= @early_failure_limit + connect_to_master("KABOOM") + break + else + client = connect_to_master('POP') + end break if client.nil? - r, w, e = IO.select([client], nil, [client], nil) + _r, _w, e = IO.select([client], nil, [client], nil) break if !e.empty? if data = client.read(65536) client.close item = Marshal.load(data) break if item.nil? || item.empty? - suite = @suites[item] + if item == "WAIT" + $0 = "#{@procline} - Waiting for work" + sleep 0.1 + next + end + suite_name, path = item + suite = load_suite(suite_name, path) + # Maybe we were told to load a suite that doesn't exist anymore. + next unless suite + $0 = "#{@procline} - #{suite.respond_to?(:description) ? suite.description : suite}" start = Time.now if @filter @filter.call(suite){ yield suite } else yield suite end - @stats[suite.to_s] = Time.now - start + @suite_stats << TestQueue::Stats::Suite.new(suite_name, path, Time.now - start, Time.now) + @failures += suite.failure_count if suite.respond_to? :failure_count else break end end rescue Errno::ENOENT, Errno::ECONNRESET, Errno::ECONNREFUSED ensure @done = caller.first - File.open("/tmp/test_queue_worker_#{$$}_stats", "wb") do |f| - f.write Marshal.dump(@stats) + File.open("/tmp/test_queue_worker_#{$$}_suites", "wb") do |f| + Marshal.dump(@suite_stats, f) end end def connect_to_master(cmd) sock = @@ -65,8 +85,19 @@ include Enumerable def empty? false + end + + def load_suite(suite_name, path) + @loaded_suites ||= {} + suite = @loaded_suites[suite_name] + return suite if suite + + @test_framework.suites_from_file(path).each do |name, suite| + @loaded_suites[name] = suite + end + @loaded_suites[suite_name] end end end