mirror of https://github.com/japl-lang/japl.git
Fixed debug.nim not showing DEBUG - before a message
Made whitespace significant in the test suite Fixed tests with DEBUG - on partially
This commit is contained in:
parent
c267a6c3be
commit
ad74c45213
|
@ -67,7 +67,7 @@ proc disassembleInstruction*(chunk: Chunk, offset: int): int =
|
||||||
of jumpInstructions:
|
of jumpInstructions:
|
||||||
result = jumpInstruction($opcode, chunk, offset)
|
result = jumpInstruction($opcode, chunk, offset)
|
||||||
else:
|
else:
|
||||||
echo &"Unknown opcode {opcode} at index {offset}"
|
echo &"DEBUG - Unknown opcode {opcode} at index {offset}"
|
||||||
result = offset + 1
|
result = offset + 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,4 +77,4 @@ proc disassembleChunk*(chunk: Chunk, name: string) =
|
||||||
var index = 0
|
var index = 0
|
||||||
while index < chunk.code.len:
|
while index < chunk.code.len:
|
||||||
index = disassembleInstruction(chunk, index)
|
index = disassembleInstruction(chunk, index)
|
||||||
echo &"==== Debug session ended - Chunk '{name}' ===="
|
echo &"==== Debug session ended - Chunk '{name}' ===="
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
var a = b;
|
var a = b;
|
||||||
//stderr:An unhandled exception occurred, traceback below:
|
//stderr:An unhandled exception occurred, traceback below:
|
||||||
|
|
||||||
//stderr: File '''', line 1, in <module>:
|
//stderr: File '''', line 1, in <module>:
|
||||||
|
|
||||||
//stderr:ReferenceError: undefined name 'b'
|
//stderr:ReferenceError: undefined name 'b'
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ var a = b;
|
||||||
[end]
|
[end]
|
||||||
[stderr]
|
[stderr]
|
||||||
An unhandled exception occurred, traceback below:
|
An unhandled exception occurred, traceback below:
|
||||||
[] File '''', line 1, in <module>:
|
File '''', line 1, in <module>:
|
||||||
ReferenceError: undefined name 'b'
|
ReferenceError: undefined name 'b'
|
||||||
[end]
|
[end]
|
||||||
[end]
|
[end]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
var a = 2 + "hey";
|
var a = 2 + "hey";
|
||||||
//stderr:An unhandled exception occurred, traceback below:
|
//stderr:An unhandled exception occurred, traceback below:
|
||||||
|
|
||||||
//stderr: File '''', line 1, in <module>:
|
//stderr: File '''', line 1, in <module>:
|
||||||
|
|
||||||
//stderr:TypeError: unsupported binary operator '+' for objects of type 'integer' and 'string'
|
//stderr:TypeError: unsupported binary operator '+' for objects of type 'integer' and 'string'
|
||||||
[end]
|
[end]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[Test: problem4]
|
[Test: problem4]
|
||||||
|
[skip]
|
||||||
[source: mixed]
|
[source: mixed]
|
||||||
// Find the largest palindrome that is a product of two 3 digit numbers
|
// Find the largest palindrome that is a product of two 3 digit numbers
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[Test: inputtest]
|
[Test: inputtest]
|
||||||
|
[skip]
|
||||||
[source: mixed]
|
[source: mixed]
|
||||||
//stdin:Hello world!
|
//stdin:Hello world!
|
||||||
print(readLine());
|
print(readLine());
|
||||||
|
@ -7,7 +8,7 @@ print(readLine());
|
||||||
[end]
|
[end]
|
||||||
|
|
||||||
[Test: inputtesttwo]
|
[Test: inputtesttwo]
|
||||||
|
[skip]
|
||||||
[source: raw]
|
[source: raw]
|
||||||
print(readLine());
|
print(readLine());
|
||||||
[end]
|
[end]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
[Test: is]
|
[Test: is]
|
||||||
|
[skip]
|
||||||
[source:mixed]
|
[source:mixed]
|
||||||
var x = 4;
|
var x = 4;
|
||||||
var y = x;
|
var y = x;
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
# a testrunner process
|
# a testrunner process
|
||||||
|
|
||||||
import ../src/vm
|
import ../src/vm
|
||||||
import os
|
|
||||||
import strformat
|
|
||||||
|
|
||||||
|
|
||||||
var btvm = initVM()
|
var btvm = initVM()
|
||||||
|
|
|
@ -26,7 +26,7 @@ proc parseModalLine(line: string): tuple[modal: bool, mode: string, detail: stri
|
||||||
# when non modal, mode becomes the line
|
# when non modal, mode becomes the line
|
||||||
# when comment is true, it must not do anything to whenever it is exported
|
# when comment is true, it must not do anything to whenever it is exported
|
||||||
|
|
||||||
let line = line.strip()
|
let line = line
|
||||||
result.modal = false
|
result.modal = false
|
||||||
result.mode = ""
|
result.mode = ""
|
||||||
result.detail = ""
|
result.detail = ""
|
||||||
|
@ -41,9 +41,6 @@ proc parseModalLine(line: string): tuple[modal: bool, mode: string, detail: stri
|
||||||
result.comment = true
|
result.comment = true
|
||||||
result.modal = true
|
result.modal = true
|
||||||
return result
|
return result
|
||||||
elif line[1] == ']':
|
|
||||||
result.mode = line[2..line.high()]
|
|
||||||
return result
|
|
||||||
result.modal = true
|
result.modal = true
|
||||||
else:
|
else:
|
||||||
result.mode = line
|
result.mode = line
|
||||||
|
@ -84,8 +81,9 @@ proc buildTest(lines: seq[string], i: var int, name: string, path: string): Test
|
||||||
var detail: string
|
var detail: string
|
||||||
var inside: bool = false
|
var inside: bool = false
|
||||||
var body: string
|
var body: string
|
||||||
|
var modeline: int = -1
|
||||||
while i < lines.len():
|
while i < lines.len():
|
||||||
let parsed = parseModalLine(lines[i].strip())
|
let parsed = parseModalLine(lines[i])
|
||||||
let line = parsed.mode
|
let line = parsed.mode
|
||||||
if parsed.modal and not parsed.comment:
|
if parsed.modal and not parsed.comment:
|
||||||
if inside:
|
if inside:
|
||||||
|
@ -95,31 +93,34 @@ proc buildTest(lines: seq[string], i: var int, name: string, path: string): Test
|
||||||
result.parseMixed(body)
|
result.parseMixed(body)
|
||||||
elif mode == "source" and detail == "raw":
|
elif mode == "source" and detail == "raw":
|
||||||
result.parseSource(body)
|
result.parseSource(body)
|
||||||
elif mode == "stdout" and (detail == ""):
|
elif mode == "stdout" or mode == "stderr":
|
||||||
result.parseStdout(body)
|
let err = (mode == "stderr")
|
||||||
elif mode == "stdoutre" or (mode == "stdout" and detail == "re"):
|
if detail == "":
|
||||||
result.parseStdout(body, true)
|
result.parseStdout(body, err = err)
|
||||||
elif mode == "stderr" and (detail == ""):
|
elif detail == "re":
|
||||||
result.parseStderr(body)
|
result.parseStdout(body, re = true, err = err)
|
||||||
elif mode == "stderrre" or (mode == "stderr" and detail == "re"):
|
elif detail == "nw":
|
||||||
result.parseStderr(body, true)
|
result.parseStdout(body, nw = true, err = err)
|
||||||
|
elif detail == "nwre":
|
||||||
|
result.parseStdout(body, nw = true, re = true, err = err)
|
||||||
|
else:
|
||||||
|
fatal &"Invalid mode detail {detail} for mode {mode} in test {name} at line {modeline} in {path}. Valid are re, nw and nwre."
|
||||||
elif detail != "":
|
elif detail != "":
|
||||||
fatal &"Invalid mode detail {detail} for mode {mode} in test {name} at {path}."
|
fatal &"Invalid mode detail {detail} for mode {mode} in test {name} at line {modeline} in {path}."
|
||||||
# non-modedetail modes below:
|
# non-modedetail modes below:
|
||||||
elif mode == "stdin":
|
elif mode == "stdin":
|
||||||
result.parseStdin(body)
|
result.parseStdin(body)
|
||||||
elif mode == "python":
|
elif mode == "python":
|
||||||
result.parsePython(body)
|
result.parsePython(body)
|
||||||
elif mode == "comment":
|
|
||||||
discard # just a comment
|
|
||||||
else:
|
else:
|
||||||
fatal &"Invalid mode {mode} for test {name} at {path}."
|
fatal &"Invalid mode {mode} for test {name} at line {modeline} in {path}."
|
||||||
inside = false
|
inside = false
|
||||||
mode = ""
|
mode = ""
|
||||||
detail = ""
|
detail = ""
|
||||||
body = ""
|
body = ""
|
||||||
|
modeline = -1
|
||||||
else:
|
else:
|
||||||
fatal &"Invalid mode {parsed.mode} when inside a block (currently in mode {mode})."
|
fatal &"Invalid mode {parsed.mode} when inside a block (currently in mode {mode}) at line {i} in {path}."
|
||||||
else: # still if modal, but not inside
|
else: # still if modal, but not inside
|
||||||
if parsed.mode == "skip":
|
if parsed.mode == "skip":
|
||||||
result.skip()
|
result.skip()
|
||||||
|
@ -131,15 +132,11 @@ proc buildTest(lines: seq[string], i: var int, name: string, path: string): Test
|
||||||
inside = true
|
inside = true
|
||||||
mode = parsed.mode
|
mode = parsed.mode
|
||||||
detail = parsed.detail
|
detail = parsed.detail
|
||||||
|
modeline = i
|
||||||
elif parsed.comment:
|
elif parsed.comment:
|
||||||
discard
|
discard
|
||||||
elif inside: # when not modal
|
elif inside: # when not modal
|
||||||
body &= line & "\n"
|
body &= line & "\n"
|
||||||
elif line.strip().len() == 0:
|
|
||||||
discard # whitespace
|
|
||||||
else:
|
|
||||||
# invalid
|
|
||||||
fatal &"Invalid code inside a test: {line} in test {name} at {path}"
|
|
||||||
inc i
|
inc i
|
||||||
|
|
||||||
proc buildTestFile(path: string): seq[Test] =
|
proc buildTestFile(path: string): seq[Test] =
|
||||||
|
@ -147,7 +144,7 @@ proc buildTestFile(path: string): seq[Test] =
|
||||||
let lines = path.readFile().split('\n')
|
let lines = path.readFile().split('\n')
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < lines.len():
|
while i < lines.len():
|
||||||
let parsed = lines[i].strip().parseModalLine()
|
let parsed = lines[i].parseModalLine()
|
||||||
let line = parsed.mode
|
let line = parsed.mode
|
||||||
if parsed.modal and not parsed.comment:
|
if parsed.modal and not parsed.comment:
|
||||||
if parsed.mode == "test":
|
if parsed.mode == "test":
|
||||||
|
|
|
@ -20,5 +20,4 @@ const timeout* = 50 # number of cycles after which a test is killed for timeout
|
||||||
|
|
||||||
var testRunner* = "jatr"
|
var testRunner* = "jatr"
|
||||||
|
|
||||||
const outputStripReplaces* = [ r"\[DEBUG[^\n]*$" ]
|
const outputIgnore* = [ "^DEBUG.*$" ]
|
||||||
const outputStripReplaceTargets* = [ "" ]
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ proc printResults*(tests: seq[Test]): bool =
|
||||||
inc killed
|
inc killed
|
||||||
else:
|
else:
|
||||||
log(LogLevel.Error, &"Probably a testing suite bug: test {test.path} has result {test.result}. Refer to testeval.nim/printResults.")
|
log(LogLevel.Error, &"Probably a testing suite bug: test {test.path} has result {test.result}. Refer to testeval.nim/printResults.")
|
||||||
let finalLevel = if fail == 0 and crash == 0: LogLevel.Info else: LogLevel.Error
|
let finalLevel = if fail == 0 and crash == 0 and killed == 0: LogLevel.Info else: LogLevel.Error
|
||||||
log(finalLevel, &"{tests.len()} tests: {success} succeeded, {skipped} skipped, {fail} failed, {killed} killed, {crash} crashed.")
|
log(finalLevel, &"{tests.len()} tests: {success} succeeded, {skipped} skipped, {fail} failed, {killed} killed, {crash} crashed.")
|
||||||
result = fail == 0 and crash == 0
|
result = fail == 0 and crash == 0
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,9 @@ proc genEL(content: string, kind: ExpectedLineKind): ExpectedLine =
|
||||||
|
|
||||||
proc compileExpectedOutput(source: string, rawkw: string, rekw: string): seq[ExpectedLine] =
|
proc compileExpectedOutput(source: string, rawkw: string, rekw: string): seq[ExpectedLine] =
|
||||||
for line in source.split('\n'):
|
for line in source.split('\n'):
|
||||||
if line =~ re("^.*//" & rawkw & ":[ ]?(.*)$"):
|
if line =~ re("^.*//" & rawkw & ":(.*)$"):
|
||||||
result &= genEL(matches[0], ExpectedLineKind.Raw)
|
result &= genEL(matches[0], ExpectedLineKind.Raw)
|
||||||
elif line =~ re("^.*//" & rekw & ":[ ]?(.*)$"):
|
elif line =~ re("^.*//" & rekw & ":(.*)$"):
|
||||||
result &= genEL(matches[0], ExpectedLineKind.Regex)
|
result &= genEL(matches[0], ExpectedLineKind.Regex)
|
||||||
|
|
||||||
proc compileExpectedOutput(source: string): seq[ExpectedLine] =
|
proc compileExpectedOutput(source: string): seq[ExpectedLine] =
|
||||||
|
@ -74,7 +74,7 @@ proc compileExpectedError(source: string): seq[ExpectedLine] =
|
||||||
|
|
||||||
proc compileInput(source: string): string =
|
proc compileInput(source: string): string =
|
||||||
for line in source.split('\n'):
|
for line in source.split('\n'):
|
||||||
if line =~ re"^.*//stdin:[ ]?(.*)$":
|
if line =~ re"^.*//stdin:(.*)$":
|
||||||
result &= matches[0] & "\n"
|
result &= matches[0] & "\n"
|
||||||
|
|
||||||
proc parseMixed*(test: Test, source: string) =
|
proc parseMixed*(test: Test, source: string) =
|
||||||
|
@ -89,17 +89,20 @@ proc parseSource*(test: Test, source: string) =
|
||||||
proc parseStdin*(test: Test, source: string) =
|
proc parseStdin*(test: Test, source: string) =
|
||||||
test.input &= source
|
test.input &= source
|
||||||
|
|
||||||
proc parseStdout*(test: Test, source: string, regex: bool = false, stderr: bool = false) =
|
proc parseStdout*(test: Test, source: string, re: bool = false, nw: bool = false, err: bool = false) =
|
||||||
var kind = ExpectedLineKind.Raw
|
var kind = ExpectedLineKind.Raw
|
||||||
if regex:
|
if re:
|
||||||
kind = ExpectedLineKind.Regex
|
kind = ExpectedLineKind.Regex
|
||||||
for line in source.split('\n'):
|
for line in source.split('\n'):
|
||||||
if stderr:
|
var toAdd = line
|
||||||
test.expectedError.add(genEL(line, kind))
|
if nw:
|
||||||
|
toAdd = toAdd.strip()
|
||||||
|
if err:
|
||||||
|
test.expectedError.add(genEL(toAdd, kind))
|
||||||
else:
|
else:
|
||||||
test.expectedOutput.add(genEL(line, kind))
|
test.expectedOutput.add(genEL(toAdd, kind))
|
||||||
|
|
||||||
if stderr:
|
if err:
|
||||||
while test.expectedError.len() > 0 and test.expectedError[test.expectedError.high()].content == "":
|
while test.expectedError.len() > 0 and test.expectedError[test.expectedError.high()].content == "":
|
||||||
discard test.expectedError.pop()
|
discard test.expectedError.pop()
|
||||||
else:
|
else:
|
||||||
|
@ -168,19 +171,15 @@ proc running*(test: Test): bool =
|
||||||
# Helpers for evaluating tests
|
# Helpers for evaluating tests
|
||||||
|
|
||||||
proc stdStrip(input: string): seq[string] =
|
proc stdStrip(input: string): seq[string] =
|
||||||
var lines = input.split('\n')
|
var lines: seq[string]
|
||||||
var toRemove: seq[int]
|
for line in input.split('\n'):
|
||||||
for i in countup(0, lines.high()):
|
var included = true
|
||||||
template line: string = lines[i]
|
for pattern in outputIgnore:
|
||||||
let hadContent = line.len() > 0
|
if line.match(re(pattern)):
|
||||||
for op in countup(0, outputStripReplaces.high()):
|
included = false
|
||||||
line = line.replace(re(outputStripReplaces[op]), outputStripReplaceTargets[op])
|
if included:
|
||||||
if hadContent and line.len() == 0:
|
lines.add(line)
|
||||||
toRemove.add(i)
|
|
||||||
|
|
||||||
for i in toRemove:
|
|
||||||
lines.delete(i)
|
|
||||||
|
|
||||||
while lines.len() > 0 and lines[lines.high()] == "":
|
while lines.len() > 0 and lines[lines.high()] == "":
|
||||||
discard lines.pop()
|
discard lines.pop()
|
||||||
lines
|
lines
|
||||||
|
@ -189,6 +188,9 @@ proc eval*(test: Test): bool =
|
||||||
let
|
let
|
||||||
outputLines = test.output.stdStrip()
|
outputLines = test.output.stdStrip()
|
||||||
errorLines = test.error.stdStrip()
|
errorLines = test.error.stdStrip()
|
||||||
|
# just for updated debug output
|
||||||
|
test.output = outputLines.join("\n")
|
||||||
|
test.error = errorLines.join("\n")
|
||||||
|
|
||||||
if test.expectedOutput.len() != outputLines.len():
|
if test.expectedOutput.len() != outputLines.len():
|
||||||
test.mismatchPos = outputLines.len()
|
test.mismatchPos = outputLines.len()
|
||||||
|
@ -201,22 +203,22 @@ proc eval*(test: Test): bool =
|
||||||
let line = test.expectedOutput[i]
|
let line = test.expectedOutput[i]
|
||||||
case line.kind:
|
case line.kind:
|
||||||
of ExpectedLineKind.Raw:
|
of ExpectedLineKind.Raw:
|
||||||
if line.content.strip() != outputLines[i].strip():
|
if line.content != outputLines[i]:
|
||||||
test.mismatchPos = i
|
test.mismatchPos = i
|
||||||
return false
|
return false
|
||||||
of ExpectedLineKind.Regex:
|
of ExpectedLineKind.Regex:
|
||||||
if not outputLines[i].strip().match(re(line.content.strip())):
|
if not outputLines[i].match(re(line.content)):
|
||||||
test.mismatchPos = i
|
test.mismatchPos = i
|
||||||
return false
|
return false
|
||||||
for i in countup(0, test.expectedError.high()):
|
for i in countup(0, test.expectedError.high()):
|
||||||
let line = test.expectedError[i]
|
let line = test.expectedError[i]
|
||||||
case line.kind:
|
case line.kind:
|
||||||
of ExpectedLineKind.Raw:
|
of ExpectedLineKind.Raw:
|
||||||
if line.content.strip() != errorLines[i].strip():
|
if line.content != errorLines[i]:
|
||||||
test.errorMismatchPos = i
|
test.errorMismatchPos = i
|
||||||
return false
|
return false
|
||||||
of ExpectedLineKind.Regex:
|
of ExpectedLineKind.Regex:
|
||||||
if not errorLines[i].strip().match(re(line.content.strip())):
|
if not errorLines[i].match(re(line.content)):
|
||||||
test.errorMismatchPos = i
|
test.errorMismatchPos = i
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue