mirror of https://github.com/japl-lang/japl.git
More documentation
inputtest should really not be skipped, but fixed
This commit is contained in:
parent
0a7db3ec0c
commit
ffd3b9a542
|
@ -1,5 +1,4 @@
|
|||
[Test: inputtesttwo]
|
||||
[skip]
|
||||
[source: raw]
|
||||
print(readLine());
|
||||
[end]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Just Another Test Suite for running JAPL tests
|
||||
## Just Another Test Suite for running JAPL tests
|
||||
|
||||
import nim/nimtests
|
||||
import testobject
|
||||
|
@ -33,21 +33,31 @@ import re
|
|||
type
|
||||
Action {.pure.} = enum
|
||||
Run, Help, Version
|
||||
## The action JATS takes.
|
||||
|
||||
DebugAction {.pure.} = enum
|
||||
Interactive, Stdout
|
||||
## The action JATS takes with the Debug Log output.
|
||||
|
||||
QuitValue {.pure.} = enum
|
||||
Success, Failure, ArgParseErr, Unreachable, Interrupt, JatrNotFound, UncaughtException
|
||||
Success, Failure, ArgParseErr, Unreachable, Interrupt, JatrNotFound,
|
||||
UncaughtException
|
||||
## The enum that specifies what each exit code means
|
||||
|
||||
when isMainModule:
|
||||
# command line option parser
|
||||
var optparser = initOptParser(commandLineParams())
|
||||
|
||||
# variables that define what JATS does
|
||||
var action: Action = Action.Run
|
||||
var debugActions: seq[DebugAction]
|
||||
var targetFiles: seq[string]
|
||||
var verbose = true
|
||||
var crash = false
|
||||
|
||||
var quitVal = QuitValue.Success
|
||||
|
||||
proc evalKey(key: string) =
|
||||
## Modifies the globals that define what JATS does based on the
|
||||
## provided key/flag
|
||||
let key = key.toLower()
|
||||
if key == "h" or key == "help":
|
||||
action = Action.Help
|
||||
|
@ -57,8 +67,6 @@ when isMainModule:
|
|||
debugActions.add(DebugAction.Interactive)
|
||||
elif key == "s" or key == "silent":
|
||||
verbose = false
|
||||
elif key == "crash":
|
||||
crash = true
|
||||
elif key == "stdout":
|
||||
debugActions.add(DebugAction.Stdout)
|
||||
else:
|
||||
|
@ -68,6 +76,8 @@ when isMainModule:
|
|||
|
||||
|
||||
proc evalKeyVal(key: string, val: string) =
|
||||
## Modifies the globals that specify what JATS does based on
|
||||
## the provided key/value pair
|
||||
let key = key.toLower()
|
||||
if key == "o" or key == "output":
|
||||
targetFiles.add(val)
|
||||
|
@ -85,10 +95,12 @@ when isMainModule:
|
|||
|
||||
|
||||
proc evalArg(key: string) =
|
||||
## Modifies what JATS does based on a provided argument
|
||||
echo &"Unexpected argument"
|
||||
action = Action.Help
|
||||
quitVal = QuitValue.ArgParseErr
|
||||
|
||||
# parse arguments
|
||||
while true:
|
||||
optparser.next()
|
||||
case optparser.kind:
|
||||
|
@ -103,6 +115,7 @@ when isMainModule:
|
|||
|
||||
|
||||
proc printUsage =
|
||||
## Prints JATS usage/help information to the terminal
|
||||
echo """
|
||||
JATS - Just Another Test Suite
|
||||
|
||||
|
@ -120,8 +133,11 @@ Flags:
|
|||
"""
|
||||
|
||||
proc printVersion =
|
||||
## Prints JATS version information to the terminal
|
||||
echo &"JATS - Just Another Test Suite version {jatsVersion}"
|
||||
|
||||
# execute the action defined. Run is executed below, so not quitting
|
||||
# runs it.
|
||||
if action == Action.Help:
|
||||
printUsage()
|
||||
quit int(quitVal)
|
||||
|
@ -133,29 +149,45 @@ Flags:
|
|||
else:
|
||||
echo &"Unknown action {action}, please contact the devs to fix this."
|
||||
quit int(QuitValue.Unreachable)
|
||||
|
||||
|
||||
# action Run
|
||||
|
||||
# define globals in logutils
|
||||
setVerbosity(verbose)
|
||||
setLogfiles(targetFiles)
|
||||
# start of JATS
|
||||
|
||||
# run the test suite
|
||||
try:
|
||||
if crash:
|
||||
raise newException(CatchableError, "Crash.")
|
||||
log(LogLevel.Debug, &"Welcome to JATS")
|
||||
|
||||
# the first half of the test suite defined in ~japl/tests/nim
|
||||
runNimTests()
|
||||
|
||||
# the second half of the test suite defined in ~japl/tests/japl
|
||||
# Find ~japl/tests/japl and the test runner JATR
|
||||
var jatr = "jatr"
|
||||
var testDir = "japl"
|
||||
if not fileExists(jatr):
|
||||
if fileExists("tests" / jatr):
|
||||
log(LogLevel.Debug, &"Must be in root: prepending \"tests\" to paths")
|
||||
log(LogLevel.Debug,
|
||||
&"Must be in root: prepending \"tests\" to paths")
|
||||
jatr = "tests" / jatr
|
||||
testDir = "tests" / testDir
|
||||
else:
|
||||
# only those two dirs are realistically useful for now,
|
||||
echo "The tests directory couldn't be found."
|
||||
quit int(QuitValue.JatrNotFound)
|
||||
|
||||
# set the global var which specifies the path to the test runner
|
||||
testRunner = jatr
|
||||
log(LogLevel.Info, &"Running JAPL tests.")
|
||||
log(LogLevel.Info, &"Building tests...")
|
||||
# build tests (see testbuilder.nim)
|
||||
let tests: seq[Test] = buildTests(testDir)
|
||||
log(LogLevel.Debug, &"Tests built.")
|
||||
# define interrupt (only here, because it's a closure over tests, so
|
||||
# they can be killed)
|
||||
proc ctrlc() {.noconv.} =
|
||||
showCursor()
|
||||
tests.killTests()
|
||||
|
@ -163,30 +195,43 @@ Flags:
|
|||
quit(int(QuitValue.Interrupt))
|
||||
setControlCHook(ctrlc)
|
||||
log(LogLevel.Info, &"Running tests...")
|
||||
# run tests (see testrun.nim)
|
||||
tests.runTests(jatr)
|
||||
log(LogLevel.Debug, &"Tests ran.")
|
||||
log(LogLevel.Debug, &"Evaluating tests...")
|
||||
# evaluate tests (see testeval.nim)
|
||||
tests.evalTests()
|
||||
log(LogLevel.Debug, &"Tests evaluated.")
|
||||
# print test results (see testeval.nim)
|
||||
if not tests.printResults():
|
||||
quitVal = QuitValue.Failure
|
||||
log(LogLevel.Debug, &"Quitting JATS.")
|
||||
# special options to view the entire debug log
|
||||
except FatalError:
|
||||
# a fatal raised by some code
|
||||
writeLine stderr, getCurrentExceptionMsg()
|
||||
quit(int(QuitValue.UncaughtException))
|
||||
except:
|
||||
errorDisplay()
|
||||
writeLine stdout, getCurrentExceptionMsg()
|
||||
# write the current exception message
|
||||
writeLine stdout, getCurrentExceptionMessage()
|
||||
writeLine stdout, getCurrentException().getStackTrace()
|
||||
quit(int(QuitValue.UncaughtException))
|
||||
|
||||
finally:
|
||||
# Always show logs, even if there's a crash
|
||||
let logs = getTotalLog()
|
||||
for action in debugActions:
|
||||
case action:
|
||||
of DebugAction.Interactive:
|
||||
# try to find 'more' and 'less' as pagers
|
||||
let lessExe = findExe("less", extensions = @[""])
|
||||
let moreExe = findExe("more", extensions = @[""])
|
||||
# prioritize 'less' if found, otherwise go for more
|
||||
# or if both are "" = not found, then inform the lack
|
||||
# of a recognized terminal pager
|
||||
var viewer = if lessExe == "": moreExe else: lessExe
|
||||
if viewer != "":
|
||||
# more reliable than pipes
|
||||
writeFile("testresults.txt", logs) # yes, testresults.txt is reserved
|
||||
discard execShellCmd(viewer & " testresults.txt") # this way because of pipe buffer sizes
|
||||
removeFile("testresults.txt")
|
||||
|
|
|
@ -22,10 +22,11 @@ when language == 1:
|
|||
const bb* = "VXd1IFdlIG1hZGUgYSBmKmNreSB3dWNreSEhIEEgd2l0dGxlIGYqY2tvIGJvaW5nbyE="
|
||||
const cc* = "VGhlIGNvZGUgbW9ua2V5cyBhdCBvdXIgaGVhZHF1YXJ0ZXJzIGFyZSB3b3JraW5nIFZFV1kgSEFXRCB0byBmaXggdGhpcyEK"
|
||||
|
||||
proc errorDisplay* =
|
||||
proc getCurrentExceptionMessage*: string =
|
||||
when language == 1:
|
||||
echo decode aa
|
||||
echo decode bb
|
||||
echo decode cc
|
||||
return getCurrentExceptionMsg()
|
||||
else:
|
||||
echo "Unsupported language."
|
||||
|
|
|
@ -12,36 +12,67 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
# logging stuff
|
||||
## A quick library for writing debug logs, errors, fatals and progress bars
|
||||
## for the test suite.
|
||||
##
|
||||
## Global variables:
|
||||
##
|
||||
## totalLog (can be written to with the proc log)
|
||||
## verbose (can be set with the proc setVerbosity)
|
||||
## logfiles (can be set with the proc setLogfiles)
|
||||
##
|
||||
## The rationale behind all three is that they have one value accross
|
||||
## one jats process/instance, and they would bloat up every single proc
|
||||
## signature, because they are needed for the proc log to work.
|
||||
|
||||
import terminal
|
||||
import strformat
|
||||
import times
|
||||
import strutils
|
||||
|
||||
|
||||
type LogLevel* {.pure.} = enum
|
||||
## All the different possible log levels
|
||||
Debug, # always written to file only (large outputs, such as the entire output of the failing test or stacktrace)
|
||||
Info, # important information about the progress of the test suite
|
||||
Error, # failing tests (printed with yellow)
|
||||
Fatal # always printed with red, halts the entire suite (test parsing errors, printed with red)
|
||||
|
||||
# don't move this to testglobals/testconfig
|
||||
# log config: which log levels to show, show in silent mode and save to the
|
||||
# detailed debug logs
|
||||
const echoedLogs = {LogLevel.Info, LogLevel.Error, LogLevel.Fatal}
|
||||
const echoedLogsSilent = {LogLevel.Error, LogLevel.Fatal} # will be echoed even if test suite is silent
|
||||
const echoedLogsSilent = {LogLevel.Fatal} # will be echoed even if test suite is silent
|
||||
const savedLogs = {LogLevel.Debug, LogLevel.Info, LogLevel.Error, LogLevel.Fatal}
|
||||
|
||||
# aesthetic config:
|
||||
# progress bar length
|
||||
const progbarLength = 25
|
||||
# log level colors
|
||||
const logColors = [LogLevel.Debug: fgDefault, LogLevel.Info: fgGreen,
|
||||
LogLevel.Error: fgYellow, LogLevel.Fatal: fgRed]
|
||||
|
||||
const logColors = [LogLevel.Debug: fgDefault, LogLevel.Info: fgGreen, LogLevel.Error: fgYellow, LogLevel.Fatal: fgRed]
|
||||
|
||||
# global vars for the proc log
|
||||
var totalLog = ""
|
||||
var verbose = true
|
||||
var logfiles: seq[string]
|
||||
|
||||
# simple interfaces with the globals
|
||||
proc setVerbosity*(verb: bool) =
|
||||
## Sets the logging verbosity
|
||||
verbose = verb
|
||||
|
||||
proc getTotalLog*: string =
|
||||
## Returns all the detailed logs in ever logged in the jats instance
|
||||
totalLog
|
||||
|
||||
proc setLogfiles*(files: seq[string]) =
|
||||
## Sets files to write logs to
|
||||
logfiles = files
|
||||
|
||||
# main logging command
|
||||
proc log*(level: LogLevel, msg: string) =
|
||||
## Adds a line to the total logs/stdout depending on config, together
|
||||
## with the timestamp
|
||||
let msg = &"[{$level} - {$getTime()}] {msg}"
|
||||
if level in savedLogs:
|
||||
totalLog &= msg & "\n"
|
||||
|
@ -55,26 +86,32 @@ proc log*(level: LogLevel, msg: string) =
|
|||
echo msg
|
||||
setForegroundColor(fgDefault)
|
||||
|
||||
|
||||
type FatalError* = ref object of CatchableError
|
||||
|
||||
proc fatal*(msg: string) =
|
||||
## Creates a fatal error, logs it and raises it as an exception
|
||||
log(LogLevel.Fatal, msg)
|
||||
let e = new(FatalError)
|
||||
e.msg = msg
|
||||
raise e
|
||||
|
||||
proc getTotalLog*: string =
|
||||
totalLog
|
||||
|
||||
# progress bar stuff
|
||||
|
||||
type Buffer* = ref object
|
||||
## Represents an updateable line on the terminal
|
||||
contents: string
|
||||
previous: string
|
||||
|
||||
proc newBuffer*: Buffer =
|
||||
# hideCursor()
|
||||
## Creates a Buffer, hides the cursor
|
||||
hideCursor()
|
||||
new(result)
|
||||
|
||||
proc updateProgressBar*(buf: Buffer, text: string, total: int, current: int) =
|
||||
## Fills a buffer with a progress bar with label (text) total cells (total)
|
||||
## and filled cells (current)
|
||||
if total <= 0:
|
||||
return
|
||||
var newline = ""
|
||||
|
@ -93,6 +130,9 @@ proc updateProgressBar*(buf: Buffer, text: string, total: int, current: int) =
|
|||
buf.contents = newline
|
||||
|
||||
proc clearLineAndWrite(text: string, oldsize: int) =
|
||||
## writes text to the beginning of the line
|
||||
# oldsize is there for history, and so that the implementation
|
||||
# of line clearing is flexible
|
||||
write stdout, "\r" & text & "\r"
|
||||
|
||||
proc render*(buf: Buffer) =
|
||||
|
@ -101,7 +141,7 @@ proc render*(buf: Buffer) =
|
|||
buf.previous = buf.contents
|
||||
|
||||
proc endBuffer*(buf: Buffer) =
|
||||
## Ends the existence of a buffer
|
||||
## restores terminal status for good scrolling experience
|
||||
showCursor()
|
||||
|
||||
proc setLogfiles*(files: seq[string]) =
|
||||
logfiles = files
|
||||
|
|
Loading…
Reference in New Issue