Added automatic test for quickstart snippets

* There are errors which indicate real bugs!
This commit is contained in:
Felix Krause 2016-10-08 23:35:33 +02:00
parent 5d4ec6c43f
commit 0f2e077b87
18 changed files with 165 additions and 32 deletions

2
.gitignore vendored
View File

@ -5,6 +5,7 @@ test/tdom
test/tserialization test/tserialization
test/tjson test/tjson
test/yamlTestSuite test/yamlTestSuite
test/tquickstart
test/*.exe test/*.exe
test/*.pdb test/*.pdb
test/*.ilk test/*.ilk
@ -19,4 +20,5 @@ bench/json
docout docout
doc/rstPreproc doc/rstPreproc
doc/tmp.rst doc/tmp.rst
doc/**/code
yaml-dev-kit yaml-dev-kit

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, streams
type Person = object type Person = object
name : string name : string
age : int32 age : int32

View File

@ -1,8 +1,8 @@
%YAML 1.2 %YAML 1.2
--- !nim:system:seq(nim:custom:Person) --- !nim:system:seq(nim:custom:Person)
- -
name: Karl Koch name: Karl Koch
age: 23 age: 23
- -
name: Peter Pan name: Peter Pan
age: 12 age: 12

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, streams
type Person = object type Person = object
name : string name : string
age : int32 age : int32

View File

@ -1,13 +1,13 @@
import yaml import yaml.serialization, yaml.presenter, streams
type Person = object type Person = object
name: string name: string
age: int32 age: int32
var personList: seq[Person] var personList = newSeq[Person]()
personList.add(Person(name: "Karl Koch", age: 23)) personList.add(Person(name: "Karl Koch", age: 23))
personList.add(Person(name: "Peter Pan", age: 12)) personList.add(Person(name: "Peter Pan", age: 12))
var s = newFileStream("out.yaml") var s = newFileStream("out.yaml", fmWrite)
dump(personList, s, options = defineOptions( dump(personList, s, options = defineOptions(
style = psCanonical, style = psCanonical,
indentationStep = 3, indentationStep = 3,

View File

@ -1,16 +1,16 @@
%YAML 1.1 %YAML 1.1
--- !nim:system:seq(nim:custom:Person) ---
[ !nim:system:seq(nim:custom:Person) [
!nim:custom:Person { !nim:custom:Person {
? !!str "name" ? !!str "name"
: !!str "Karl Koch", : !!str "Karl Koch",
? !!str "age" ? !!str "age"
: !nim:system:int32 "23" : !nim:system:int32 "23"
}, },
!nim:custom:Person { !nim:custom:Person {
? !!str "name" ? !!str "name"
: !!str "Peter Pan", : !!str "Peter Pan",
? !!str "age" ? !!str "age"
: !nim:system:int32 "12" : !nim:system:int32 "12"
} }
] ]

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, streams
type type
Node = ref NodeObj Node = ref NodeObj
NodeObj = object NodeObj = object

View File

@ -1,11 +1,11 @@
%YAML 1.2 %YAML 1.2
--- !nim:custom:NodeObj &a --- !nim:custom:NodeObj &a
name: Node 1 name: Node 1
left: left:
name: Node 2 name: Node 2
left: !!null ~ left: !!null ~
right: &b right: &b
name: Node 3 name: Node 3
left: *a left: *a
right: !!null ~ right: !!null ~
right: *b right: *b

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, streams
type type
Node = ref NodeObj Node = ref NodeObj
NodeObj = object NodeObj = object

View File

@ -1,4 +1,4 @@
import yaml import yaml, streams
type Mob = object type Mob = object
level, experience: int32 level, experience: int32
drops: seq[string] drops: seq[string]
@ -9,6 +9,5 @@ setTagUri(seq[string], "!Drops")
var mob = Mob(level: 42, experience: 1800, drops: var mob = Mob(level: 42, experience: 1800, drops:
@["Sword of Mob Slaying"]) @["Sword of Mob Slaying"])
var s = newFileStream("out.yaml", fmWrite) var s = newFileStream("out.yaml", fmWrite)
dump(mob, s, dump(mob, s, tagStyle = tsAll)
options = defineOptions(tagStyle = tsAll))
s.close() s.close()

View File

@ -1,5 +1,5 @@
%YAML 1.2 %YAML 1.2
--- !Mob --- !Mob
!nim:field level: !nim:system:int32 42 !nim:field level: !nim:system:int32 42
!nim:field experience: !nim:system:int32 1800 !nim:field experience: !nim:system:int32 1800
!nim:field drops: !Drops [!!str Sword of Mob Slaying] !nim:field drops: !Drops [!!str Sword of Mob Slaying]

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, yaml.presenter, streams
type Person = object type Person = object
name : string name : string
age : int32 age : int32

View File

@ -1,3 +1,4 @@
[ [
{ {
"name": "Karl Koch", "name": "Karl Koch",
@ -7,4 +8,4 @@
"name": "Peter Pan", "name": "Peter Pan",
"age": 12 "age": 12
} }
] ]

View File

@ -1,4 +1,4 @@
import yaml import yaml.serialization, streams
type Person = object type Person = object
name : string name : string
age : int32 age : int32

View File

@ -1,4 +1,4 @@
import yaml import yaml, streams
type type
Person = object Person = object
name: string name: string

View File

@ -1,4 +1,4 @@
import yaml import yaml, streams
type Person = object type Person = object
name: string name: string

128
test/tquickstart.nim Normal file
View File

@ -0,0 +1,128 @@
import unittest, os, osproc, macros, strutils, streams
proc inputTest(path: string): bool =
let
inFileOrig = path / "01-in.yaml"
inFileDest = path / "in.yaml"
codeFileOrig = path / "00-code.nim"
codeFileDest = path / "code.nim"
exeFileDest = when defined(windows): path / "code.exe" else: path / "code"
currentDir = getCurrentDir()
basePath = currentDir / ".."
absolutePath = currentDir / path
copyFile(inFileOrig, inFileDest)
copyFile(codeFileOrig, codeFileDest)
defer:
removeFile(inFileDest)
removeFile(codeFileDest)
var process = startProcess("nim c --hints:off -p:" & escape(basePath) &
" code.nim", path, [], nil, {poStdErrToStdOut, poEvalCommand})
setCurrentDir(currentDir) # workaround for https://github.com/nim-lang/Nim/issues/4867
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})
setCurrentDir(currentDir) # workaround for https://github.com/nim-lang/Nim/issues/4867
if process.waitForExit() != 0:
echo "executable output:"
echo "==================\n"
echo process.outputStream().readAll()
result = false
else: result = true
proc outputTest(path: string): bool =
let
codeFileOrig = path / "00-code.nim"
codeFileDest = path / "code.nim"
exeFileDest = when defined(windows): path / "code.exe" else: path / "code"
currentDir = getCurrentDir()
basePath = currentDir / ".."
absolutePath = currentDir / path
copyFile(codeFileOrig, codeFileDest)
defer: removeFile(codeFileDest)
var process = startProcess("nim c --hints:off -p:" & escape(basePath) &
" code.nim", path, [], nil, {poStdErrToStdOut, poEvalCommand})
defer: process.close()
setCurrentDir(currentDir) # workaround for https://github.com/nim-lang/Nim/issues/4867
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})
setCurrentDir(currentDir) # workaround for https://github.com/nim-lang/Nim/issues/4867
if process.waitForExit() != 0:
echo "executable output:"
echo "==================\n"
echo process.outputStream().readAll()
result = false
else:
var
expected = open(path / "01-out.yaml", fmRead)
actual = open(path / "out.yaml", fmRead)
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()
let title = titlePrefix & slurp(path / "title").splitLines()[0]
if fileExists(path / "00-code.nim"):
var test = newCall("test", newLit(title))
if fileExists(path / "01-in.yaml"):
test.add(newCall("doAssert", newCall("inputTest", newLit(path))))
elif fileExists(path / "01-out.yaml"):
test.add(newCall("doAssert", newCall("outputTest", newLit(path))))
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)
macro genTests(): untyped = testsFor("../doc/snippets/quickstart")
genTests()

View File

@ -18,6 +18,9 @@
import tables, typetraits, strutils, macros, streams import tables, typetraits, strutils, macros, streams
import parser, taglib, presenter, stream, ../private/internal, hints import parser, taglib, presenter, stream, ../private/internal, hints
export stream
# *something* in here needs externally visible `==`(x,y: AnchorId),
# but I cannot figure out what. binding it would be the better option.
type type
SerializationContext* = ref object SerializationContext* = ref object