<commit_before># MiniTest adaptor for tapout.

require 'minitest/unit'
require 'stringio'

# Becuase of some wierdness in MiniTest
#debug, $DEBUG = $DEBUG, false
#require 'minitest/unit'
#$DEBUG = debug

module MiniTest

  # Base class for TapY and TapJ runners.
  # 
  # This is a heavily refactored version of the built-in MiniTest runner. It's
  # about the same speed, from what I can tell, but is significantly easier to
  # extend.
  # 
  # Based upon <NAME> of Seattle.rb's MiniTest (MIT License).
  # 
  # @see https://github.com/seattlerb/minitest MiniTest
  #
  class MiniTap < ::MiniTest::Unit

    # TAP-Y/J Revision
    REVISION = 2

    attr_accessor :suite_start_time, :test_start_time, :reporters
    
    def initialize
      self.report = {}
      self.errors = 0
      self.failures = 0
      self.skips = 0
      self.test_count = 0
      self.assertion_count = 0
      self.verbose = false
      self.reporters = []

      @_source_cache = {}
    end

    # Top level driver, controls all output and filtering.
    def _run args = []
      self.options = process_args(args)

      self.class.plugins.each do |plugin|
        send plugin
        break unless report.empty?
      end

      return failures + errors if @test_count > 0 # or return nil...
    rescue Interrupt
      abort 'Interrupted'
    end

    #
    def _run_anything(type)
      self.start_time = Time.now
      
      suites = suites_of_type(type)
      tests = suites.inject({}) do |acc, suite|
        acc[suite] = filtered_tests(suite, type)
        acc
      end
      
      self.test_count = tests.inject(0) { |acc, suite| acc + suite[1].length }
      
      if test_count > 0
        trigger(:before_suites, suites, type)
        
        fix_sync do
          suites.each { |suite| _run_suite(suite, tests[suite]) }
        end
        
        trigger(:after_suites, suites, type)
      end
    end
    
    def _run_suite(suite, tests)
      unless tests.empty?
        begin
          self.suite_start_time = Time.now
          
          trigger(:before_suite, suite)
          suite.startup if suite.respond_to?(:startup)
          
          tests.each { |test| _run_test(suite, test) }
        ensure
          suite.shutdown if suite.respond_to?(:shutdown)
          trigger(:after_suite, suite)
        end
      end
    end
    
    #
    def _run_test(suite, test)
      self.test_start_time = Time.now

      trigger(:before_test, suite, test)
      
      test_runner = TestRunner.new(suite, test)
      test_runner.run
      add_test_result(suite, test, test_runner)
      
      trigger(test_runner.result, suite, test, test_runner)
    end
    
    #
    def trigger(callback, *args)
      send("tapout_#{callback}", *args)
    end

    private

    #    
    def filtered_tests(suite, type)
      filter = options[:filter] || '/./'
      filter = Regexp.new($1) if filter =~ /\/(.*)\//
      suite.send("#{type}_methods").grep(filter)
    end
    
    #
    def suites_of_type(type)
      TestCase.send("#{type}_suites")
    end
    
    #
    def add_test_result(suite, test, test_runner)
      self.report[suite] ||= {}
      self.report[suite][test.to_sym] = test_runner
      
      self.assertion_count += test_runner.assertions
      
      case test_runner.result
      when :skip then self.skips += 1
      when :failure then self.failures += 1
      when :error then self.errors += 1
      end
    end

    #
    def fix_sync
      sync = output.respond_to?(:'sync=') # stupid emacs
      old_sync, output.sync = output.sync, true if sync
      yield
      output.sync = old_sync if sync
    end

    #
    def tapout_before_suites(suites, type)
      doc = {
        'type'  => 'suite',
        'start' => self.start_time.strftime('%Y-%m-%d %H:%M:%S'),
        'count' => self.test_count,
        'seed'  => self.options[:seed],
        'rev'   => REVISION
      }
      return doc
    end

    #
    def tapout_after_suites(suites, type)
      doc = {
        'type' => 'tally',
        'time' => Time.now - self.test_start_time,
        'counts' => {<commit_msg>Update to revision 3 of TAP-Y/J spec.<commit_after># MiniTest adaptor for tapout.

require 'minitest/unit'
require 'stringio'

# Becuase of some wierdness in MiniTest
#debug, $DEBUG = $DEBUG, false
#require 'minitest/unit'
#$DEBUG = debug

module MiniTest

  # Base class for TapY and TapJ runners.
  # 
  # This is a heavily refactored version of the built-in MiniTest runner. It's
  # about the same speed, from what I can tell, but is significantly easier to
  # extend.
  # 
  # Based upon <NAME> of Seattle.rb's MiniTest (MIT License).
  # 
  # @see https://github.com/seattlerb/minitest MiniTest
  #
  class MiniTap < ::MiniTest::Unit

    # TAP-Y/J Revision
    REVISION = 2

    attr_accessor :suite_start_time, :test_start_time, :reporters
    
    def initialize
      self.report = {}
      self.errors = 0
      self.failures = 0
      self.skips = 0
      self.test_count = 0
      self.assertion_count = 0
      self.verbose = false
      self.reporters = []

      @_source_cache = {}
    end

    # Top level driver, controls all output and filtering.
    def _run args = []
      self.options = process_args(args)

      self.class.plugins.each do |plugin|
        send plugin
        break unless report.empty?
      end

      return failures + errors if @test_count > 0 # or return nil...
    rescue Interrupt
      abort 'Interrupted'
    end

    #
    def _run_anything(type)
      self.start_time = Time.now
      
      suites = suites_of_type(type)
      tests = suites.inject({}) do |acc, suite|
        acc[suite] = filtered_tests(suite, type)
        acc
      end
      
      self.test_count = tests.inject(0) { |acc, suite| acc + suite[1].length }
      
      if test_count > 0
        trigger(:before_suites, suites, type)
        
        fix_sync do
          suites.each { |suite| _run_suite(suite, tests[suite]) }
        end
        
        trigger(:after_suites, suites, type)
      end
    end
    
    def _run_suite(suite, tests)
      unless tests.empty?
        begin
          self.suite_start_time = Time.now
          
          trigger(:before_suite, suite)
          suite.startup if suite.respond_to?(:startup)
          
          tests.each { |test| _run_test(suite, test) }
        ensure
          suite.shutdown if suite.respond_to?(:shutdown)
          trigger(:after_suite, suite)
        end
      end
    end
    
    #
    def _run_test(suite, test)
      self.test_start_time = Time.now

      trigger(:before_test, suite, test)
      
      test_runner = TestRunner.new(suite, test)
      test_runner.run
      add_test_result(suite, test, test_runner)
      
      trigger(test_runner.result, suite, test, test_runner)
    end
    
    #
    def trigger(callback, *args)
      send("tapout_#{callback}", *args)
    end

    private

    #    
    def filtered_tests(suite, type)
      filter = options[:filter] || '/./'
      filter = Regexp.new($1) if filter =~ /\/(.*)\//
      suite.send("#{type}_methods").grep(filter)
    end
    
    #
    def suites_of_type(type)
      TestCase.send("#{type}_suites")
    end
    
    #
    def add_test_result(suite, test, test_runner)
      self.report[suite] ||= {}
      self.report[suite][test.to_sym] = test_runner
      
      self.assertion_count += test_runner.assertions
      
      case test_runner.result
      when :skip then self.skips += 1
      when :failure then self.failures += 1
      when :error then self.errors += 1
      end
    end

    #
    def fix_sync
      sync = output.respond_to?(:'sync=') # stupid emacs
      old_sync, output.sync = output.sync, true if sync
      yield
      output.sync = old_sync if sync
    end

    #
    def tapout_before_suites(suites, type)
      doc = {
        'type'  => 'suite',
        'start' => self.start_time.strftime('%Y-%m-%d %H:%M:%S'),
        'count' => self.test_count,
        'seed'  => self.options[:seed],
        'rev'   => REVISION
      }
      return doc
    end

    #
    def tapout_after_suites(suites, type)
      doc = {
        'type' => 'final',
        'time' => Time.now - self.test_start_time,
        'counts' => {
{'fraction_non_alphanumeric': 0.10882281257616379, 'fraction_numerical': 0.0035339995125517913, 'mean_word_length': 2.0509293680297396, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '601750', 'n_tokens_mistral': 2736, 'n_tokens_neox': 2646, 'n_words': 640}