<commit_before>require "yaml"
require "pathname"
require "test/unit/ui/console/testrunner"

module Nestor
  module Strategies
    module Test
      class Unit
        def initialize(root)
          @root = Pathname.new(root).realpath
        end

        # Logs a message to STDOUT.  This implementation forks, so the #log method also
        # provides the PID of the logger.
        def log(message)
          STDOUT.printf "[%d] %s - %s\n", Process.pid, Time.now.strftime("%H:%M:%S"), message
          STDOUT.flush
        end

        # Runs absolutely all tests as found by walking test/.
        def run_all
          fork do
            log "Run all tests"
            Dir["test/**/*_test.rb"].each {|f| log(f); load f}

            ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
            test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
            result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
              autorunner.runner = lambda { test_runner }
            end

            report(test_runner)
          end
        end

        # Runs only the named files, and optionally focuses on only a couple of tests
        # within the loaded test cases.
        def run(test_files, focuses=[])
          fork do
            log "Running #{focuses.length} focused tests"
            test_files.each {|f| log(f); load f}

            ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
            test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
            result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
              autorunner.runner = lambda { test_runner }
              autorunner.filters << proc{|t| focuses.include?(t.method_name)} unless focuses.empty?
            end

            report(test_runner)
          end
        end

        private

        # Since we forked, we can't call into the Machine from the child process.  Upstream
        # communications is implemented by writing new files to the filesystem and letting
        # the parent process catch the changes.
        def report(test_runner)
          info = {"status" => test_runner.passed? ? "successful" : "failed", "failures" => {}}
          failures = info["failures"]
          test_runner.faults.each do |failure|
            filename = if failure.respond_to?(:location) then
                         loc = failure.location.first[1..-1]
                         loc.split(":", 2).first
                       elsif failure.respond_to?(:exception) then
                         loc = failure.exception.backtrace.first
                         loc.split(":", 2).first
                       else
                         raise "Unknown object type received as failure: #{failure.inspect} doesn't have #exception or #location methods."
                       end

            filename = Pathname.new(filename)
            filename = filename.realpath.relative_path_from(@root)
            failures[failure.test_name.split("(", 2).first.strip] = filename
          end
<commit_msg>Attempt to extract the filename from the test name.<commit_after>require "yaml"
require "pathname"
require "test/unit/ui/console/testrunner"

module Nestor
  module Strategies
    module Test
      class Unit
        def initialize(root)
          @root = Pathname.new(root).realpath
        end

        # Logs a message to STDOUT.  This implementation forks, so the #log method also
        # provides the PID of the logger.
        def log(message)
          STDOUT.printf "[%d] %s - %s\n", Process.pid, Time.now.strftime("%H:%M:%S"), message
          STDOUT.flush
        end

        # Runs absolutely all tests as found by walking test/.
        def run_all
          fork do
            log "Run all tests"
            test_files = Dir["test/**/*_test.rb"]
            test_files.each {|f| log(f); load f}

            ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
            test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
            result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
              autorunner.runner = lambda { test_runner }
            end

            report(test_runner, test_files)
          end
        end

        # Runs only the named files, and optionally focuses on only a couple of tests
        # within the loaded test cases.
        def run(test_files, focuses=[])
          fork do
            log "Running #{focuses.length} focused tests"
            test_files.each {|f| log(f); load f}

            ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
            test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
            result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
              autorunner.runner = lambda { test_runner }
              autorunner.filters << proc{|t| focuses.include?(t.method_name)} unless focuses.empty?
            end

            report(test_runner, test_files)
          end
        end

        private

        # Since we forked, we can't call into the Machine from the child process.  Upstream
        # communications is implemented by writing new files to the filesystem and letting
        # the parent process catch the changes.
        def report(test_runner, test_files)
          info = {"status" => test_runner.passed? ? "successful" : "failed", "failures" => {}}
          failures = info["failures"]
          test_runner.faults.each do |failure|
            filename = if failure.respond_to?(:location) then
                         failure.location.detect do |loc|
                           filename = loc.split(":", 2).first
                           test_files.detect {|tf| filename.include?(tf)}
                         end
                       elsif failure.respond_to?(:exception) then
                         failure.exception.backtrace.detect do |loc|
                           filename = loc.split(":", 2).first
                           test_files.detect {|tf| filename.include?(tf)}
                         end
                       else
                         raise "Unknown object type received as failure: #{failure.inspect} doesn't have #exception or #location methods."
                       end

            test_name = failure.test_name.split("(", 2).first.strip
            if filename.nil? then
              log("Could not map #{failure.test_name.inspect} to a specific test file: mapping to #{test_files.length}")
              test_files.each do |tf|
                failures[test_name] = tf
              end
            else
              log("Failed #{failure.test_name.inspect} in #{filename.inspect}")
              failures[test_name] = filename
            end
          end

{'fraction_non_alphanumeric': 0.09812877560041255, 'fraction_numerical': 0.0011787240312361867, 'mean_word_length': 1.8318731748018355, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, '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': '6593741', 'n_tokens_mistral': 1796, 'n_tokens_neox': 1758, 'n_words': 508}