From 0f2e077b871730602c41f0e1fc5157ce90756315 Mon Sep 17 00:00:00 2001 From: Felix Krause Date: Sat, 8 Oct 2016 23:35:33 +0200 Subject: [PATCH] Added automatic test for quickstart snippets * There are errors which indicate real bugs! --- .gitignore | 2 + doc/snippets/quickstart/00/00-code.nim | 2 +- doc/snippets/quickstart/00/01-out.yaml | 8 +- doc/snippets/quickstart/01/00-code.nim | 2 +- doc/snippets/quickstart/02/00-code.nim | 6 +- doc/snippets/quickstart/02/01-out.yaml | 14 +-- doc/snippets/quickstart/03/00-code.nim | 2 +- doc/snippets/quickstart/03/01-out.yaml | 8 +- doc/snippets/quickstart/04/00-code.nim | 2 +- doc/snippets/quickstart/05/00-code.nim | 5 +- doc/snippets/quickstart/05/01-out.yaml | 4 +- doc/snippets/quickstart/06/00-code.nim | 2 +- doc/snippets/quickstart/06/01-out.yaml | 3 +- doc/snippets/quickstart/07/00-code.nim | 2 +- doc/snippets/quickstart/08/00/00-code.nim | 2 +- doc/snippets/quickstart/08/01/00-code.nim | 2 +- test/tquickstart.nim | 128 ++++++++++++++++++++++ yaml/serialization.nim | 3 + 18 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 test/tquickstart.nim diff --git a/.gitignore b/.gitignore index a345654..704e960 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ test/tdom test/tserialization test/tjson test/yamlTestSuite +test/tquickstart test/*.exe test/*.pdb test/*.ilk @@ -19,4 +20,5 @@ bench/json docout doc/rstPreproc doc/tmp.rst +doc/**/code yaml-dev-kit diff --git a/doc/snippets/quickstart/00/00-code.nim b/doc/snippets/quickstart/00/00-code.nim index b1bec26..6354883 100644 --- a/doc/snippets/quickstart/00/00-code.nim +++ b/doc/snippets/quickstart/00/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, streams type Person = object name : string age : int32 diff --git a/doc/snippets/quickstart/00/01-out.yaml b/doc/snippets/quickstart/00/01-out.yaml index 46d0583..207ff5c 100644 --- a/doc/snippets/quickstart/00/01-out.yaml +++ b/doc/snippets/quickstart/00/01-out.yaml @@ -1,8 +1,8 @@ %YAML 1.2 ---- !nim:system:seq(nim:custom:Person) -- +--- !nim:system:seq(nim:custom:Person) +- name: Karl Koch age: 23 -- +- name: Peter Pan - age: 12 \ No newline at end of file + age: 12 diff --git a/doc/snippets/quickstart/01/00-code.nim b/doc/snippets/quickstart/01/00-code.nim index 3ceb4ce..19bff02 100644 --- a/doc/snippets/quickstart/01/00-code.nim +++ b/doc/snippets/quickstart/01/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, streams type Person = object name : string age : int32 diff --git a/doc/snippets/quickstart/02/00-code.nim b/doc/snippets/quickstart/02/00-code.nim index 2e80785..1743b07 100644 --- a/doc/snippets/quickstart/02/00-code.nim +++ b/doc/snippets/quickstart/02/00-code.nim @@ -1,13 +1,13 @@ -import yaml +import yaml.serialization, yaml.presenter, streams type Person = object name: string age: int32 -var personList: seq[Person] +var personList = newSeq[Person]() personList.add(Person(name: "Karl Koch", age: 23)) personList.add(Person(name: "Peter Pan", age: 12)) -var s = newFileStream("out.yaml") +var s = newFileStream("out.yaml", fmWrite) dump(personList, s, options = defineOptions( style = psCanonical, indentationStep = 3, diff --git a/doc/snippets/quickstart/02/01-out.yaml b/doc/snippets/quickstart/02/01-out.yaml index 76b4fc0..ac7ffcd 100644 --- a/doc/snippets/quickstart/02/01-out.yaml +++ b/doc/snippets/quickstart/02/01-out.yaml @@ -1,16 +1,16 @@ %YAML 1.1 ---- !nim:system:seq(nim:custom:Person) -[ - !nim:custom:Person { +--- +!nim:system:seq(nim:custom:Person) [ + !nim:custom:Person { ? !!str "name" : !!str "Karl Koch", ? !!str "age" : !nim:system:int32 "23" - }, - !nim:custom:Person { + }, + !nim:custom:Person { ? !!str "name" : !!str "Peter Pan", ? !!str "age" : !nim:system:int32 "12" - } -] \ No newline at end of file + } +] diff --git a/doc/snippets/quickstart/03/00-code.nim b/doc/snippets/quickstart/03/00-code.nim index 0e97b6c..e812eca 100644 --- a/doc/snippets/quickstart/03/00-code.nim +++ b/doc/snippets/quickstart/03/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, streams type Node = ref NodeObj NodeObj = object diff --git a/doc/snippets/quickstart/03/01-out.yaml b/doc/snippets/quickstart/03/01-out.yaml index 25e569e..4762270 100644 --- a/doc/snippets/quickstart/03/01-out.yaml +++ b/doc/snippets/quickstart/03/01-out.yaml @@ -1,11 +1,11 @@ %YAML 1.2 ---- !nim:custom:NodeObj &a +--- !nim:custom:NodeObj &a name: Node 1 -left: +left: name: Node 2 left: !!null ~ - right: &b + right: &b name: Node 3 left: *a right: !!null ~ -right: *b \ No newline at end of file +right: *b diff --git a/doc/snippets/quickstart/04/00-code.nim b/doc/snippets/quickstart/04/00-code.nim index 983ae94..c698008 100644 --- a/doc/snippets/quickstart/04/00-code.nim +++ b/doc/snippets/quickstart/04/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, streams type Node = ref NodeObj NodeObj = object diff --git a/doc/snippets/quickstart/05/00-code.nim b/doc/snippets/quickstart/05/00-code.nim index 411fb58..f2b7d9f 100644 --- a/doc/snippets/quickstart/05/00-code.nim +++ b/doc/snippets/quickstart/05/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml, streams type Mob = object level, experience: int32 drops: seq[string] @@ -9,6 +9,5 @@ setTagUri(seq[string], "!Drops") var mob = Mob(level: 42, experience: 1800, drops: @["Sword of Mob Slaying"]) var s = newFileStream("out.yaml", fmWrite) -dump(mob, s, - options = defineOptions(tagStyle = tsAll)) +dump(mob, s, tagStyle = tsAll) s.close() \ No newline at end of file diff --git a/doc/snippets/quickstart/05/01-out.yaml b/doc/snippets/quickstart/05/01-out.yaml index cf6deba..b3c155a 100644 --- a/doc/snippets/quickstart/05/01-out.yaml +++ b/doc/snippets/quickstart/05/01-out.yaml @@ -1,5 +1,5 @@ %YAML 1.2 ---- !Mob +--- !Mob !nim:field level: !nim:system:int32 42 !nim:field experience: !nim:system:int32 1800 -!nim:field drops: !Drops [!!str Sword of Mob Slaying] \ No newline at end of file +!nim:field drops: !Drops [!!str Sword of Mob Slaying] diff --git a/doc/snippets/quickstart/06/00-code.nim b/doc/snippets/quickstart/06/00-code.nim index 7b91553..babe9f3 100644 --- a/doc/snippets/quickstart/06/00-code.nim +++ b/doc/snippets/quickstart/06/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, yaml.presenter, streams type Person = object name : string age : int32 diff --git a/doc/snippets/quickstart/06/01-out.yaml b/doc/snippets/quickstart/06/01-out.yaml index 3be727c..06befc2 100644 --- a/doc/snippets/quickstart/06/01-out.yaml +++ b/doc/snippets/quickstart/06/01-out.yaml @@ -1,3 +1,4 @@ + [ { "name": "Karl Koch", @@ -7,4 +8,4 @@ "name": "Peter Pan", "age": 12 } -] \ No newline at end of file +] diff --git a/doc/snippets/quickstart/07/00-code.nim b/doc/snippets/quickstart/07/00-code.nim index cf86f03..1312ee5 100644 --- a/doc/snippets/quickstart/07/00-code.nim +++ b/doc/snippets/quickstart/07/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml.serialization, streams type Person = object name : string age : int32 diff --git a/doc/snippets/quickstart/08/00/00-code.nim b/doc/snippets/quickstart/08/00/00-code.nim index 323c410..4bf5947 100644 --- a/doc/snippets/quickstart/08/00/00-code.nim +++ b/doc/snippets/quickstart/08/00/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml, streams type Person = object name: string diff --git a/doc/snippets/quickstart/08/01/00-code.nim b/doc/snippets/quickstart/08/01/00-code.nim index e1ada99..59b0f84 100644 --- a/doc/snippets/quickstart/08/01/00-code.nim +++ b/doc/snippets/quickstart/08/01/00-code.nim @@ -1,4 +1,4 @@ -import yaml +import yaml, streams type Person = object name: string diff --git a/test/tquickstart.nim b/test/tquickstart.nim new file mode 100644 index 0000000..fd88c43 --- /dev/null +++ b/test/tquickstart.nim @@ -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() \ No newline at end of file diff --git a/yaml/serialization.nim b/yaml/serialization.nim index df95ac5..756b52e 100644 --- a/yaml/serialization.nim +++ b/yaml/serialization.nim @@ -18,6 +18,9 @@ import tables, typetraits, strutils, macros, streams 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 SerializationContext* = ref object