2016-10-08 21:35:33 +00:00
|
|
|
import unittest, os, osproc, macros, strutils, streams
|
|
|
|
|
2017-02-06 20:41:43 +00:00
|
|
|
const baseDir = parentDir(staticExec("pwd"))
|
|
|
|
let (nimPathRaw, nimPathRet) =
|
|
|
|
execCmdEx("which nim", {poStdErrToStdOut, poUsePath})
|
|
|
|
if nimPathRet != 0: quit "could not locate nim executable:\n" & nimPathRaw
|
|
|
|
let nimPath =
|
|
|
|
if nimPathRaw[0] == '/': nimPathRaw.strip else: baseDir / nimPathRaw.strip
|
|
|
|
|
|
|
|
proc inputTest(basePath, path: string): bool =
|
2016-10-08 21:35:33 +00:00
|
|
|
let
|
2016-10-09 13:05:18 +00:00
|
|
|
absolutePath = basePath / path
|
|
|
|
inFileOrig = absolutePath / "01-in.yaml"
|
|
|
|
inFileDest = absolutePath / "in.yaml"
|
|
|
|
codeFileOrig = absolutePath / "00-code.nim"
|
|
|
|
codeFileDest = absolutePath / "code.nim"
|
|
|
|
exeFileDest = when defined(windows): absolutePath / "code.exe" else:
|
|
|
|
absolutePath / "code"
|
2016-10-08 21:35:33 +00:00
|
|
|
copyFile(inFileOrig, inFileDest)
|
|
|
|
copyFile(codeFileOrig, codeFileDest)
|
|
|
|
defer:
|
|
|
|
removeFile(inFileDest)
|
|
|
|
removeFile(codeFileDest)
|
2016-10-09 13:21:27 +00:00
|
|
|
var process = startProcess(nimPath & " c --hints:off -p:" & escape(basePath) &
|
2016-10-09 13:05:18 +00:00
|
|
|
" code.nim", absolutePath, [], nil, {poStdErrToStdOut, poEvalCommand})
|
2016-10-08 21:35:33 +00:00
|
|
|
defer:
|
|
|
|
process.close()
|
|
|
|
if process.waitForExit() != 0:
|
|
|
|
echo "compiler output:"
|
|
|
|
echo "================\n"
|
|
|
|
echo process.outputStream().readAll()
|
|
|
|
result = false
|
|
|
|
else:
|
|
|
|
defer: removeFile(exeFileDest)
|
|
|
|
process.close()
|
|
|
|
process = startProcess(absolutePath / "code", absolutePath, [], nil,
|
|
|
|
{poStdErrToStdOut, poEvalCommand})
|
|
|
|
if process.waitForExit() != 0:
|
|
|
|
echo "executable output:"
|
|
|
|
echo "==================\n"
|
|
|
|
echo process.outputStream().readAll()
|
|
|
|
result = false
|
|
|
|
else: result = true
|
|
|
|
|
2017-02-06 20:41:43 +00:00
|
|
|
proc outputTest(basePath, path: string): bool =
|
2016-10-08 21:35:33 +00:00
|
|
|
let
|
2016-10-09 13:05:18 +00:00
|
|
|
absolutePath = basePath / path
|
|
|
|
codeFileOrig = absolutePath / "00-code.nim"
|
|
|
|
codeFileDest = absolutePath / "code.nim"
|
|
|
|
exeFileDest = when defined(windows): absolutePath / "code.exe" else:
|
|
|
|
absolutePath / "code"
|
|
|
|
outFileExpected = absolutePath / "01-out.yaml"
|
|
|
|
outFileActual = absolutePath / "out.yaml"
|
2016-10-08 21:35:33 +00:00
|
|
|
copyFile(codeFileOrig, codeFileDest)
|
|
|
|
defer: removeFile(codeFileDest)
|
2016-10-09 13:21:27 +00:00
|
|
|
var process = startProcess(nimPath & " c --hints:off -p:" & escape(basePath) &
|
2016-10-09 13:05:18 +00:00
|
|
|
" code.nim", absolutePath, [], nil, {poStdErrToStdOut, poEvalCommand})
|
2016-10-08 21:35:33 +00:00
|
|
|
defer: process.close()
|
|
|
|
if process.waitForExit() != 0:
|
|
|
|
echo "compiler output:"
|
|
|
|
echo "================\n"
|
|
|
|
echo process.outputStream().readAll()
|
|
|
|
result = false
|
|
|
|
else:
|
|
|
|
defer: removeFile(exeFileDest)
|
|
|
|
process.close()
|
|
|
|
process = startProcess(absolutePath / "code", absolutePath, [], nil,
|
|
|
|
{poStdErrToStdOut, poEvalCommand})
|
|
|
|
if process.waitForExit() != 0:
|
|
|
|
echo "executable output:"
|
|
|
|
echo "==================\n"
|
|
|
|
echo process.outputStream().readAll()
|
|
|
|
result = false
|
|
|
|
else:
|
2016-10-09 09:48:52 +00:00
|
|
|
defer: removeFile(outFileActual)
|
2016-10-08 21:35:33 +00:00
|
|
|
var
|
2016-10-09 09:48:52 +00:00
|
|
|
expected = open(outFileExpected, fmRead)
|
|
|
|
actual = open(outFileActual, fmRead)
|
2016-10-08 21:35:33 +00:00
|
|
|
lineNumber = 1
|
|
|
|
defer:
|
|
|
|
expected.close()
|
|
|
|
actual.close()
|
|
|
|
var
|
|
|
|
expectedLine = ""
|
|
|
|
actualLine = ""
|
|
|
|
while true:
|
|
|
|
if expected.readLine(expectedLine):
|
|
|
|
if actual.readLine(actualLine):
|
|
|
|
if expectedLine != actualLine:
|
|
|
|
echo "difference at line #", lineNumber, ':'
|
|
|
|
echo "expected: ", escape(expectedLine)
|
|
|
|
echo " actual: ", escape(actualLine)
|
|
|
|
return false
|
|
|
|
else:
|
|
|
|
echo "actual output has fewer lines than expected; ",
|
|
|
|
"first missing line: #", lineNumber
|
|
|
|
echo "expected: ", escape(expectedLine)
|
|
|
|
return false
|
|
|
|
else:
|
|
|
|
if actual.readLine(actualLine):
|
|
|
|
echo "actual output has more lines than expected; ",
|
|
|
|
"first unexpected line: #", lineNumber
|
|
|
|
echo "content: ", escape(actualLine)
|
|
|
|
return false
|
|
|
|
else: break
|
|
|
|
lineNumber.inc()
|
|
|
|
result = true
|
|
|
|
|
|
|
|
proc testsFor(path: string, root: bool = true, titlePrefix: string = ""):
|
|
|
|
NimNode {.compileTime.} =
|
|
|
|
result = newStmtList()
|
2016-10-09 13:05:18 +00:00
|
|
|
let
|
|
|
|
title = titlePrefix & slurp(baseDir / path / "title").splitLines()[0]
|
2016-10-08 21:35:33 +00:00
|
|
|
if fileExists(path / "00-code.nim"):
|
|
|
|
var test = newCall("test", newLit(title))
|
|
|
|
if fileExists(path / "01-in.yaml"):
|
2016-10-09 13:05:18 +00:00
|
|
|
test.add(newCall("doAssert", newCall("inputTest", newLit(baseDir),
|
2017-02-06 20:41:43 +00:00
|
|
|
newLit(path))))
|
2016-10-08 21:35:33 +00:00
|
|
|
elif fileExists(path / "01-out.yaml"):
|
2016-10-09 13:05:18 +00:00
|
|
|
test.add(newCall("doAssert", newCall("outputTest", newLit(baseDir),
|
2017-02-06 20:41:43 +00:00
|
|
|
newLit(path))))
|
2016-10-08 21:35:33 +00:00
|
|
|
else:
|
|
|
|
echo "Error: neither 01-in.yaml nor 01-out.yaml exists in " & path & '!'
|
|
|
|
quit 1
|
|
|
|
result.add(test)
|
|
|
|
for kind, childPath in walkDir(path):
|
|
|
|
if kind == pcDir:
|
|
|
|
if childPath != path / "nimcache":
|
|
|
|
result.add(testsFor(childPath, false, if root: "" else: title & ' '))
|
|
|
|
if root:
|
|
|
|
result = newCall("suite", newLit(title), result)
|
|
|
|
|
2016-10-09 13:05:18 +00:00
|
|
|
macro genTests(): untyped = testsFor("doc/snippets/quickstart")
|
2016-10-08 21:35:33 +00:00
|
|
|
|
|
|
|
genTests()
|