require "./web/examples.rb"
require "./test/collect_tests.rb"
require "./run.rb"

`ghc -O engine.hs`

def run(prog, input, pp)
  File.open("prog.iog", "w"){|f| f << prog }
  File.open("input.txt", "w"){|f| f << input }
  if Array === input
    `(ruby main.rb prog.iog -e #{pp ? "-p" : ""} > test.ism && engine test.ism #{input.map{|i|"'"+i+"'"}*" "}) 2>&1`
  else
    `(ruby main.rb prog.iog -e #{pp ? "-p" : ""} > test.ism && engine test.ism < input.txt) 2>&1`
  end
end

tests = ExamplesAndTests

small_tests = collect_tests

# engine_test.rb batches tests into one engine run for speed, so it can only cover
# non-erroring, standard-input cases. Here we pick up the exact complement of that
# filter and run each through the engine individually, since these "couldn't be tested
# in bulk": an erroring case would abort a batched run, and non-standard inputs can't
# share one stdin. This is what guarantees Ruby<->engine parity for error messages and
# for varied input formats - so there is no engine coverage gap, just a split for speed.
tests.concat small_tests.filter{|source,expected,from,input,no_pp|
  expected[/^\s*ERROR/] || !(input=="" || input=="777" || input==nil)
}.map{|source,expected,from,input,no_pp|
  [source, source.strip, input||"", expected.strip,!no_pp]
}

pass = true
tests.each{|name, prog, input, expected, pp|
  next if name == "iterate * >" # this ones infinite loop hangs in haskell

  found = run(prog, input, pp)
  found.gsub!(/engine: (?:\e\[31m)?ERROR: (?:\e\[0m)?/,'ERROR: ') # (color is tty gated)
  found.gsub!(/\nCallStack.*/m,'')
  found.gsub!(/ +$/,'')
  if expected['...']
    found = found[0,expected.index("...")] + "..."
  end


  if found.chomp != expected.chomp
    STDERR.puts "FAIL: #{name}"
    STDERR.puts prog
    STDERR.puts "expected:"
    STDERR.puts expected
    STDERR.puts "found:"
    STDERR.puts found
    pass = false
    exit
  end
}
`rm prog.iog input.txt test.ism`

puts "PASS #{tests.size} examples engine" if pass
