mirror of https://github.com/japl-lang/japl.git
reimplementing some stuff better, still wip
This commit is contained in:
parent
4439a24a5b
commit
fff2739428
|
@ -24,7 +24,14 @@ import strformat
|
|||
var btvm = initVM()
|
||||
|
||||
try:
|
||||
discard btvm.interpret(stdin.readAll(), "")
|
||||
var source: string
|
||||
while true:
|
||||
let ch = stdin.readChar()
|
||||
if ch == char(4):
|
||||
break
|
||||
else:
|
||||
source &= ch
|
||||
discard btvm.interpret(source, "")
|
||||
quit(0)
|
||||
except:
|
||||
let error = getCurrentException()
|
||||
|
|
|
@ -21,3 +21,8 @@ const exceptions* = ["all.jpl", "for_with_function.jpl", "runtime_interning.jpl"
|
|||
var maxAliveTests* = 16 # number of tests that can run parallel
|
||||
const testWait* = 100 # number of milliseconds per cycle
|
||||
const timeout* = 100 # number of cycles after which a test is killed for timeout
|
||||
|
||||
var testRunner* = "jatr"
|
||||
|
||||
const outputStripReplaces* = [ "\[DEBUG.*\n", "[\n\r ]*$" ]
|
||||
const outputStripReplaceTargets* = [ "", "" ]
|
||||
|
|
|
@ -23,8 +23,6 @@ import streams
|
|||
import strformat
|
||||
import testconfig
|
||||
|
||||
|
||||
|
||||
proc evalTest(test: Test) =
|
||||
test.output = test.output.tuStrip()
|
||||
test.error = test.error.tuStrip()
|
||||
|
|
|
@ -14,13 +14,17 @@
|
|||
|
||||
# Test object and helpers
|
||||
|
||||
import re, strutils, osproc
|
||||
import testconfig
|
||||
|
||||
import re
|
||||
import strutils
|
||||
import osproc
|
||||
|
||||
# types
|
||||
|
||||
type
|
||||
TestResult* {.pure.} = enum
|
||||
Unstarted, Running, ToEval, Success, Skip, Mismatch, Crash
|
||||
Unstarted, Running, ToEval, Success, Skip, Mismatch, Crash, Killed
|
||||
|
||||
ExpectedLineKind* {.pure.} = enum
|
||||
Raw, Regex
|
||||
|
@ -107,6 +111,52 @@ proc skip*(test: Test) =
|
|||
|
||||
# Helpers for running tests
|
||||
|
||||
proc tuStrip*(input: string): string =
|
||||
return input.replace(re"\[DEBUG.*\n","\n").strip()
|
||||
proc start*(test: Test) =
|
||||
test.process = startProcess(testRunner, options = {})
|
||||
test.inputStream.write(test.source & $char(4) & test.input)
|
||||
test.inputStream.close() # this is advised against in the stdlib, but this is what gets the job
|
||||
# done. (Yes I tried flushing)
|
||||
test.result = TestResult.Running
|
||||
|
||||
proc finish*(test: Test) =
|
||||
# only call when the process has ended execution gracefully. Don't call after closing.
|
||||
# Don't call while it's running.
|
||||
test.output = test.outputStream.readAll()
|
||||
test.error = test.errorStream.readAll()
|
||||
if test.process.peekExitCode() == 0:
|
||||
test.result = TestResult.ToEval # also means "finished running" with a zero exit code
|
||||
else:
|
||||
test.result = TestResult.Crash # also means "finished running" with a non-zero exit code
|
||||
test.process.close()
|
||||
|
||||
proc kill*(test: Test) =
|
||||
# alternative to finish
|
||||
test.process.kill()
|
||||
discard test.process.waitForExit()
|
||||
test.result = TestResult.Killed
|
||||
|
||||
proc running*(test: Test): bool =
|
||||
test.result == TestResult.Running and test.process.running()
|
||||
|
||||
# Helpers for evaluating tests
|
||||
|
||||
proc toStrip(input: string): string =
|
||||
var text = input
|
||||
for i in countup(0, outputStripReplaces.high()):
|
||||
text = text.replace(outputStripReplaces[i], outputStripReplaceTargets[i])
|
||||
|
||||
|
||||
proc eval*(test: Test): bool =
|
||||
|
||||
test.output = test.output.toStrip()
|
||||
test.error = test.error.toStrip()
|
||||
|
||||
for line in test.expectedOutput:
|
||||
case line.kind:
|
||||
of ExpectedLineKind.Raw:
|
||||
# TODO HERE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,53 +19,28 @@ import logutils
|
|||
import testconfig
|
||||
|
||||
import strformat
|
||||
import os
|
||||
|
||||
|
||||
proc runTest(test: Test, runner: string) =
|
||||
proc runTest(test: Test) =
|
||||
log(LogLevel.Debug, &"Starting test {test.path}.")
|
||||
let process = startProcess(runner, args = @[test.path])
|
||||
test.process = process
|
||||
if test.input.len() > 0:
|
||||
var f: File
|
||||
let suc = f.open(process.inputHandle, fmWrite)
|
||||
if suc:
|
||||
f.write(test.input)
|
||||
f.close()
|
||||
else:
|
||||
log(LogLevel.Error, &"Stdin File handle could not be opened for test {test.path}")
|
||||
test.result = Crash
|
||||
|
||||
test.result = TestResult.Running
|
||||
|
||||
proc readOutputs(test: Test) =
|
||||
test.output = test.process.outputStream.readAll()
|
||||
test.error = test.process.errorStream.readAll()
|
||||
test.start()
|
||||
|
||||
proc tryFinishTest(test: Test): bool =
|
||||
if test.process.running():
|
||||
if test.running():
|
||||
return false
|
||||
test.readOutputs()
|
||||
if test.process.peekExitCode() == 0:
|
||||
test.result = TestResult.ToEval
|
||||
else:
|
||||
test.result = TestResult.Crash
|
||||
test.process.close()
|
||||
test.finish()
|
||||
log(LogLevel.Debug, &"Test {test.path} finished.")
|
||||
return true
|
||||
|
||||
|
||||
proc killTest(test: Test) =
|
||||
if test.process.running():
|
||||
test.process.kill()
|
||||
log(LogLevel.Debug, &"SIGKILL sent to {test.path}")
|
||||
discard test.process.waitForExit()
|
||||
test.result = TestResult.Crash
|
||||
if test.running():
|
||||
test.kill()
|
||||
log(LogLevel.Error, &"Test {test.path} was killed for taking too long.")
|
||||
|
||||
proc killTests*(tests: seq[Test]) =
|
||||
for test in tests:
|
||||
if test.result == TestResult.Running:
|
||||
killTest(test)
|
||||
if test.running():
|
||||
test.kill()
|
||||
|
||||
proc runTests*(tests: seq[Test], runner: string) =
|
||||
var
|
||||
|
@ -81,7 +56,7 @@ proc runTests*(tests: seq[Test], runner: string) =
|
|||
sleep(testWait)
|
||||
if aliveTests < maxAliveTests and currentTest < tests.len():
|
||||
if tests[currentTest].result == TestResult.Unstarted:
|
||||
tests[currentTest].runTest(runner)
|
||||
tests[currentTest].runTest()
|
||||
inc aliveTests
|
||||
inc currentTest
|
||||
else:
|
Loading…
Reference in New Issue