<commit_before>require 'test/unit'
require 'yaml'

require 'dorothy'

class TestPrograms < Test::Unit::TestCase

  PROGRAMS_DIR = "#{File.dirname( __FILE__ )}/programs"

  Dir["#{PROGRAMS_DIR}/*.inf"].each do |fn|

    zf = "#{PROGRAMS_DIR}/#{File.basename( fn, '.inf' )}.z5"
    tm = "test_#{File.basename( fn, '.inf' )}"

    output_yaml, reading_output_yaml = "", nil
    open( fn, "r" ) do |f|
      while s = f.gets
        if s =~ /^\! output:/
          reading_output_yaml = true
        elsif reading_output_yaml 
          if s =~ /^\! (.*)/
            output_yaml += $1 + "\n"
          else
            reading_output_yaml = false
          end
        end
      end
    end

    expected_output = YAML::load( output_yaml ) if output_yaml

    if expected_output
      define_method( tm ) do
        __test_program( zf, expected_output )
      end
    end
  end


  def __test_program( filename, expected_output )
    m = Machine.new( filename )

    i = 0
   
    until m.finished? 
      m.step while m.output.empty? && ! m.finished?

      while s = m.output.shift

        assert( i < expected_output.length, "unexpected output #{s}, " +
                "only expecting #{expected_output.length} tokens.  " +
                "Trace: \n#{m.trace.join}" )

        assert_equal( expected_output[i], s, 
                      "output (token #{i}) doesn't match expected.  " +
                      "Trace: \n#{m.trace.join}" )

        i += 1
      end
    end

    assert_equal( expected_output.length, i,
                  "expected #{expected_output.length} output tokens, " +
                  "received #{i}.  Trace: \n#{m.trace.join}" )<commit_msg>Added support for input in unit tests.  Changed the way test programs are found (scan for .z? files and then check for the source code... so, only compiled test programs are run).<commit_after>require 'test/unit'
require 'yaml'

require 'dorothy'

class TestPrograms < Test::Unit::TestCase

  PROGRAMS_DIR = "#{File.dirname( __FILE__ )}/programs"

  Dir["#{PROGRAMS_DIR}/*.z?"].each do |zf|

    fn = "#{PROGRAMS_DIR}/#{File.basename( zf, File.extname( zf ) )}.inf"
    tm = "test_#{File.basename( fn, '.inf' )}"

    output_yaml, reading_output_yaml = "", nil
    input_yaml, reading_input_yaml = "", nil

    open( fn, "r" ) do |f|
      while s = f.gets
        if s =~ /^\! output:/
          reading_output_yaml = true
        elsif reading_output_yaml 
          if s =~ /^\! (.*)/
            output_yaml += $1 + "\n"
          else
            reading_output_yaml = false
          end
        elsif s =~ /^\! input:/
          reading_input_yaml = true
        elsif reading_input_yaml 
          if s =~ /^\! (.*)/
            input_yaml += $1 + "\n"
          else
            reading_input_yaml = false
          end
        end
      end
    end

    expected_output = YAML::load( output_yaml ) if output_yaml
    input = YAML::load( input_yaml ) if input_yaml

    if expected_output
      define_method( tm ) do
        __test_program( zf, expected_output, input )
      end
    end
  end


  def __test_program( filename, expected_output, input )
    m = Machine.new( filename )

    input.each { |s| m.keyboard << s }  if input

    i = 0
   
    until m.finished? 
      m.step while m.output.empty? && ! m.finished?

      while s = m.output.shift

        assert( i < expected_output.length, "unexpected output #{s}, " +
                "only expecting #{expected_output.length} tokens.  " +
                "Trace: \n#{m.trace.join}" )

        assert_equal( expected_output[i], s, 
                      "output (token #{i}) doesn't match expected.  " +
                      "Trace: \n#{m.trace.join}" )

        i += 1
      end
    end

    assert_equal( expected_output.length, i,
                  "expected #{expected_output.length} output tokens, " +
                  "received #{i}.  Trace: \n#{m.trace.join}" )
{'fraction_non_alphanumeric': 0.1301790281329923, 'fraction_numerical': 0.0020460358056265983, 'mean_word_length': 1.9164802386278896, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, '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': '2736598', 'n_tokens_mistral': 1294, 'n_tokens_neox': 1232, 'n_words': 318}