diff options
Diffstat (limited to 'testament/specs.nim')
-rw-r--r-- | testament/specs.nim | 257 |
1 files changed, 147 insertions, 110 deletions
diff --git a/testament/specs.nim b/testament/specs.nim index 86fc8bed4..df12db543 100644 --- a/testament/specs.nim +++ b/testament/specs.nim @@ -9,21 +9,21 @@ import parseutils, strutils, os, osproc, streams, parsecfg - var compilerPrefix* = "compiler" / "nim" let isTravis* = existsEnv("TRAVIS") let isAppVeyor* = existsEnv("APPVEYOR") -proc cmdTemplate*(): string = - compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file" - type TTestAction* = enum actionRun = "run" actionCompile = "compile" actionReject = "reject" - actionRunNoSpec = "runNoSpec" + + TOutputCheck* = enum + ocIgnore = "ignore" + ocEqual = "equal" + ocSubstr = "substr" TResultEnum* = enum reNimcCrash, # nim compiler seems to have crashed @@ -38,8 +38,10 @@ type reExeNotFound, reInstallFailed # package installation failed reBuildFailed # package building failed - reIgnored, # test is ignored + reDisabled, # test is disabled + reJoined, # test is disabled because it was joined into the megatest reSuccess # test was successful + reInvalidSpec # test had problems to parse the spec TTarget* = enum targetC = "C" @@ -51,7 +53,9 @@ type action*: TTestAction file*, cmd*: string input*: string - outp*: string + outputCheck*: TOutputCheck + sortoutput*: bool + output*: string line*, column*: int tfile*: string tline*, tcolumn*: int @@ -60,9 +64,16 @@ type ccodeCheck*: string maxCodeSize*: int err*: TResultEnum - substr*, sortoutput*: bool targets*: set[TTarget] nimout*: string + parseErrors*: string # when the spec definition is invalid, this is not empty. + unjoinable*: bool + +proc getCmd*(s: TSpec): string = + if s.cmd.len == 0: + result = compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file" + else: + result = s.cmd const targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"] @@ -91,33 +102,6 @@ proc extractSpec(filename: string): string = when not defined(nimhygiene): {.pragma: inject.} -template parseSpecAux(fillResult: untyped) = - var ss = newStringStream(extractSpec(filename)) - var p {.inject.}: CfgParser - open(p, ss, filename, 1) - while true: - var e {.inject.} = next(p) - case e.kind - of cfgEof: break - of cfgSectionStart, cfgOption, cfgError: - echo ignoreMsg(p, e) - of cfgKeyValuePair: - fillResult - close(p) - -proc specDefaults*(result: var TSpec) = - result.msg = "" - result.outp = "" - result.nimout = "" - result.ccodeCheck = "" - result.cmd = cmdTemplate() - result.line = 0 - result.column = 0 - result.tfile = "" - result.tline = 0 - result.tcolumn = 0 - result.maxCodeSize = 0 - proc parseTargets*(value: string): set[TTarget] = for v in value.normalize.splitWhitespace: case v @@ -127,81 +111,134 @@ proc parseTargets*(value: string): set[TTarget] = of "js": result.incl(targetJS) else: echo "target ignored: " & v +proc addLine*(self: var string; a: string) = + self.add a + self.add "\n" + +proc addLine*(self: var string; a,b: string) = + self.add a + self.add b + self.add "\n" + proc parseSpec*(filename: string): TSpec = - specDefaults(result) result.file = filename - parseSpecAux: - case normalize(e.key) - of "action": - case e.value.normalize - of "compile": result.action = actionCompile - of "run": result.action = actionRun - of "reject": result.action = actionReject - else: echo ignoreMsg(p, e) - of "file": result.file = e.value - of "line": discard parseInt(e.value, result.line) - of "column": discard parseInt(e.value, result.column) - of "tfile": result.tfile = e.value - of "tline": discard parseInt(e.value, result.tline) - of "tcolumn": discard parseInt(e.value, result.tcolumn) - of "output": - result.action = actionRun - result.outp = e.value - of "input": - result.input = e.value - of "outputsub": - result.action = actionRun - result.outp = e.value - result.substr = true - of "sortoutput": - result.sortoutput = parseCfgBool(e.value) - of "exitcode": - discard parseInt(e.value, result.exitCode) - result.action = actionRun - of "msg": - result.msg = e.value - if result.action != actionRun: - result.action = actionCompile - of "errormsg", "errmsg": - result.msg = e.value - result.action = actionReject - of "nimout": - result.nimout = e.value - of "disabled": - case e.value.normalize - of "y", "yes", "true", "1", "on": result.err = reIgnored - of "n", "no", "false", "0", "off": discard - of "win", "windows": - when defined(windows): result.err = reIgnored - of "linux": - when defined(linux): result.err = reIgnored - of "bsd": - when defined(bsd): result.err = reIgnored - of "macosx": - when defined(macosx): result.err = reIgnored - of "unix": - when defined(unix): result.err = reIgnored - of "posix": - when defined(posix): result.err = reIgnored - of "travis": - if isTravis: result.err = reIgnored - of "appveyor": - if isAppVeyor: result.err = reIgnored - else: - raise newException(ValueError, "cannot interpret as a bool: " & e.value) - of "cmd": - if e.value.startsWith("nim "): - result.cmd = compilerPrefix & e.value[3..^1] + let specStr = extractSpec(filename) + var ss = newStringStream(specStr) + var p: CfgParser + open(p, ss, filename, 1) + while true: + var e = next(p) + case e.kind + of cfgKeyValuePair: + case normalize(e.key) + of "action": + case e.value.normalize + of "compile": + result.action = actionCompile + of "run": + result.action = actionRun + of "reject": + result.action = actionReject + else: + result.parseErrors.addLine "cannot interpret as action: ", e.value + of "file": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg or msg needs to be specified before file" + result.file = e.value + of "line": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg, msg or nimout needs to be specified before line" + discard parseInt(e.value, result.line) + of "column": + if result.msg.len == 0 and result.nimout.len == 0: + result.parseErrors.addLine "errormsg or msg needs to be specified before column" + discard parseInt(e.value, result.column) + of "tfile": + result.tfile = e.value + of "tline": + discard parseInt(e.value, result.tline) + of "tcolumn": + discard parseInt(e.value, result.tcolumn) + of "output": + result.outputCheck = ocEqual + result.output = strip(e.value) + of "input": + result.input = e.value + of "outputsub": + result.outputCheck = ocSubstr + result.output = strip(e.value) + of "sortoutput": + try: + result.sortoutput = parseCfgBool(e.value) + except: + result.parseErrors.addLine getCurrentExceptionMsg() + of "exitcode": + discard parseInt(e.value, result.exitCode) + result.action = actionRun + of "msg": + result.msg = e.value + if result.action != actionRun: + result.action = actionCompile + of "errormsg", "errmsg": + result.msg = e.value + result.action = actionReject + of "nimout": + result.nimout = e.value + of "joinable": + result.unjoinable = not parseCfgBool(e.value) + of "disabled": + case e.value.normalize + of "y", "yes", "true", "1", "on": result.err = reDisabled + of "n", "no", "false", "0", "off": discard + of "win", "windows": + when defined(windows): result.err = reDisabled + of "linux": + when defined(linux): result.err = reDisabled + of "bsd": + when defined(bsd): result.err = reDisabled + of "macosx": + when defined(macosx): result.err = reDisabled + of "unix": + when defined(unix): result.err = reDisabled + of "posix": + when defined(posix): result.err = reDisabled + of "travis": + if isTravis: result.err = reDisabled + of "appveyor": + if isAppVeyor: result.err = reDisabled + else: + result.parseErrors.addLine "cannot interpret as a bool: ", e.value + of "cmd": + if e.value.startsWith("nim "): + result.cmd = compilerPrefix & e.value[3..^1] + else: + result.cmd = e.value + of "ccodecheck": + result.ccodeCheck = e.value + of "maxcodesize": + discard parseInt(e.value, result.maxCodeSize) + of "target", "targets": + for v in e.value.normalize.splitWhitespace: + case v + of "c": + result.targets.incl(targetC) + of "cpp", "c++": + result.targets.incl(targetCpp) + of "objc": + result.targets.incl(targetObjC) + of "js": + result.targets.incl(targetJS) + else: + result.parseErrors.addLine "cannot interpret as a target: ", e.value else: - result.cmd = e.value - of "ccodecheck": result.ccodeCheck = e.value - of "maxcodesize": discard parseInt(e.value, result.maxCodeSize) - of "target", "targets": - for v in e.value.normalize.splitWhitespace: - case v - of "c": result.targets.incl(targetC) - of "cpp", "c++": result.targets.incl(targetCpp) - of "objc": result.targets.incl(targetObjC) - of "js": result.targets.incl(targetJS) - else: echo ignoreMsg(p, e) - else: echo ignoreMsg(p, e) + result.parseErrors.addLine "invalid key for test spec: ", e.key + + of cfgSectionStart: + result.parseErrors.addLine "section ignored: ", e.section + of cfgOption: + result.parseErrors.addLine "command ignored: ", e.key & ": " & e.value + of cfgError: + result.parseErrors.addLine e.msg + of cfgEof: + break + close(p) |