More documentation

inputtest should really not be skipped, but fixed
This commit is contained in:
Productive2 2021-02-09 18:10:16 +01:00
parent 0a7db3ec0c
commit ffd3b9a542
4 changed files with 110 additions and 25 deletions

View File

@ -1,5 +1,4 @@
[Test: inputtesttwo]
[skip]
[source: raw]
print(readLine());
[end]

View File

@ -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")

View File

@ -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."

View File

@ -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