tparser.nim
1 # NimYAML - YAML implementation in Nim 2 # (c) Copyright 2015-2023 Felix Krause 3 # 4 # See the file "copying.txt", included in this 5 # distribution, for details about the copyright. 6 7 import os, terminal, strutils, streams, macros, unittest, sets 8 import testEventParser, commonTestUtils 9 import ../yaml/[ data, parser, stream ] 10 11 const 12 testSuiteFolder = "yaml-test-suite" 13 14 proc echoError(msg: string) = 15 styledWriteLine(stdout, fgRed, "[error] ", fgWhite, msg, resetStyle) 16 17 proc doParserTest(expected, actual: YamlStream, errorExpected: bool): bool = 18 var i = 1 19 try: 20 while true: 21 let actualEvent = actual.next() 22 let expectedEvent = expected.next() 23 if expectedEvent != actualEvent: 24 result = errorExpected 25 if not result: 26 echoError("At event #" & $i & 27 ": Actual events do not match expected events") 28 echo ".. expected event:" 29 echo " ", expectedEvent 30 echo ".. actual event:" 31 echo " ", actualEvent 32 echo ".. difference:" 33 when nimvm: discard 34 else: stdout.write(" ") 35 printDifference(expectedEvent, actualEvent) 36 37 return 38 i.inc() 39 if actualEvent.kind == yamlEndStream: 40 break 41 result = not errorExpected 42 if not result: 43 echo "Expected error, but parsed without error." 44 except CatchableError as e: 45 result = errorExpected 46 if not result: 47 echoError("Caught an exception at event #" & $i & 48 " test was not successful") 49 if e.parent of YamlParserError: 50 let pe = (ref YamlParserError)(e.parent) 51 echo "line ", pe.mark.line, ", column ", pe.mark.column, ": ", pe.msg 52 echo pe.lineContent 53 else: echo e.msg 54 55 proc parserTest(path: string, errorExpected : bool): bool = 56 var 57 parser: YamlParser 58 parser.init() 59 var 60 actualIn = newFileStream(path / "in.yaml") 61 actual = parser.parse(actualIn) 62 expectedIn = newFileStream(path / "test.event") 63 expected = parseEventStream(expectedIn) 64 defer: 65 actualIn.close() 66 expectedIn.close() 67 result = doParserTest(expected, actual, errorExpected) 68 69 macro genTests(): untyped = 70 let 71 pwd = staticExec("pwd").strip 72 absolutePath = '"' & (pwd / testSuiteFolder) & '"' 73 echo "[tparser] Generating tests from " & absolutePath 74 discard staticExec("git submodule init && git submodule update --remote") 75 76 var ignored = toHashSet([".git", "name", "tags", "meta"]) 77 78 proc genTest(target: var NimNode, dirPath: string, testId: string) {.compileTime.} = 79 let title = slurp(dirPath / "===") 80 let isErrorTest = fileExists(dirPath / "error") 81 let testName = strip(title) & " [" & testId & ']' 82 83 # TODO: this code executes the test at compile time. 84 # sadly it doesn't work currently since the VM doesn't support 85 # closure iterators (in parseEventStream). 86 # 87 #let staticIn = slurp(dirPath / "in.yaml") 88 #let staticExpected = slurp(dirPath / "test.event") 89 #var parser: YamlParser 90 #parser.init() 91 #var actual = parser.parse(staticIn) 92 #var expected = parseEventString(staticExpected) 93 # 94 #if not doParserTest(expected, actual, isErrorTest): 95 # target.add(newCall("test", newLit(testName & " [comptime]"), newCall("fail"))) 96 97 target.add(newCall("test", 98 newLit(testName), newCall("doAssert", newCall("parserTest", 99 newLit(dirPath), newLit(isErrorTest))))) 100 101 result = newStmtList() 102 103 # walkDir for some crude reason does not work with travis build 104 let dirItems = staticExec("ls -1d " & absolutePath / "*") 105 for dirPath in dirItems.splitLines(): 106 if dirPath.strip.len == 0: continue 107 let testId = dirPath[^4..^1] 108 if ignored.contains(testId): continue 109 if fileExists(dirPath / "==="): 110 genTest(result, dirPath, testId) 111 else: 112 let testItems = staticExec("ls -1d " & dirPath / "*") 113 var start = len(dirPath) + 1 114 for itemPath in testItems.splitLines(): 115 if itemPath.strip.len == 0: continue 116 let testItemId = testId / itemPath[start..^1] 117 if fileExists(itemPath / "==="): 118 genTest(result, itemPath, testItemId) 119 120 121 result = newCall("suite", newLit("Parser Tests (from yaml-test-suite)"), result) 122 123 genTests()