diff --git a/README.md b/README.md index 31a857b..870602c 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ - Customizable parser strictness including support for non-standard extensions - Well-defined handling of malformed / malicious inputs with configurable parsing limits - Fuzzing and comprehensive manual test coverage +- Since v0.4.4, compile time encode/decode is supported. This means you can initialize a const value using decode. It is also ok to use it inside a static block or other Nim VM code. diff --git a/json_serialization.nimble b/json_serialization.nimble index 685f038..53ba028 100644 --- a/json_serialization.nimble +++ b/json_serialization.nimble @@ -17,6 +17,7 @@ license = "Apache License 2.0" skipDirs = @["tests", "fuzzer"] requires "nim >= 1.6.0", + "faststreams >= 0.5.0", "serialization", "stew >= 0.2.0", "results" diff --git a/tests/test_lexer.nim b/tests/test_lexer.nim index 7f674d8..9cbe366 100644 --- a/tests/test_lexer.nim +++ b/tests/test_lexer.nim @@ -279,11 +279,7 @@ suite "lexer test suite": var conf = defaultJsonReaderConf conf.fractionDigitsLimit = 3 testScanNumber(".1234", ".123", error = errFracDigitLimit, conf = conf) - testScanNumber("1234.5555", "1234.5555") - - conf = defaultJsonReaderConf - conf.fractionDigitsLimit = 3 testScanNumber("1234.1234", "1234.123", error = errFracDigitLimit, conf = conf) test "scanNumber exponent part string": @@ -343,11 +339,7 @@ suite "lexer test suite": var conf = defaultJsonReaderConf conf.fractionDigitsLimit = 3 testScanNumber(".1234", JsonVoid(), error = errFracDigitLimit, conf = conf) - testScanNumber("1234.5555", JsonVoid()) - - conf = defaultJsonReaderConf - conf.fractionDigitsLimit = 3 testScanNumber("1234.1234", JsonVoid(), error = errFracDigitLimit, conf = conf) test "scanNumber exponent part JsonVoid": @@ -411,11 +403,7 @@ suite "lexer test suite": conf.fractionDigitsLimit = 3 testScanNumber(".1234", JsonNumber[string](fraction: "123"), error = errFracDigitLimit, conf = conf) - testScanNumber("1234.5555", JsonNumber[string](integer: "1234", fraction: "5555")) - - conf = defaultJsonReaderConf - conf.fractionDigitsLimit = 3 testScanNumber("1234.1234", JsonNumber[string](integer: "1234", fraction: "123"), error = errFracDigitLimit, conf = conf) @@ -501,7 +489,6 @@ suite "lexer test suite": testScanNumber("1234.5555", JsonNumber[uint64](integer: 1234, fraction: "5555")) - conf = defaultJsonReaderConf conf.fractionDigitsLimit = 3 testScanNumber("1234.1234", JsonNumber[uint64](integer: 1234, fraction: "123"), error = errFracDigitLimit, conf = conf) diff --git a/tests/test_parser.nim b/tests/test_parser.nim index 2a02785..d37b609 100644 --- a/tests/test_parser.nim +++ b/tests/test_parser.nim @@ -52,16 +52,18 @@ suite "Custom iterators": exponent == 789 test "customStringValueIt": - var text: string - var r = toReader "\"hello \\t world\"" - r.customStringValueIt: - text.add it - - expect JsonReaderError: - r.customStringValueIt(10): + proc customTest() = + var text: string + var r = toReader "\"hello \\t world\"" + r.customStringValueIt: text.add it - check text == "hello \t world" + expect JsonReaderError: + r.customStringValueIt(10): + text.add it + + check text == "hello \t world" + customTest() suite "Public parser": test "parseArray": @@ -222,16 +224,26 @@ suite "Public parser": val = r.parseFloat(float64) check val == -56009000.0 + proc inputFile(fileName: string): InputStream = + when nimvm: + let data = staticRead(pathRelativeTo(fileName, "tests")) + unsafeMemoryInput(data) + else: + memFileInput(fileName) + template testParseAsString(fileName: string) = try: - var stream = memFileInput(fileName) + var stream = inputFile(fileName) var r = JsonReader[DefaultFlavor].init(stream) let val = r.parseAsString() var xr = toReader val.string let xval = xr.parseAsString() check val == xval except JsonReaderError as ex: - debugEcho ex.formatMsg(fileName) + when nimvm: + debugEcho fileName, ex.msg + else: + debugEcho ex.formatMsg(fileName) check false test "parseAsString": diff --git a/tests/test_reader.nim b/tests/test_reader.nim index 1a3a8d5..49ff6c6 100644 --- a/tests/test_reader.nim +++ b/tests/test_reader.nim @@ -163,7 +163,10 @@ suite "JsonReader basic test": val.fourteen == SecondObject(one: "world", two: false) except JsonReaderError as ex: - debugEcho ex.formatMsg("jsonText3") + when nimvm: + debugEcho "jsonText3", ex.msg + else: + debugEcho ex.formatMsg("jsonText3") check false test "Special Types": diff --git a/tests/test_spec.nim b/tests/test_spec.nim index d0f9994..87ffa48 100644 --- a/tests/test_spec.nim +++ b/tests/test_spec.nim @@ -17,8 +17,15 @@ import include ../json_serialization/lexer -proc yCase(fileName, name: string): bool {.raises:[IOError].} = - var stream = memFileInput(fileName) +proc inputFile(fileName: string): InputStream {.raises: [IOError].} = + when nimvm: + let data = staticRead(pathRelativeTo(fileName, "tests")) + unsafeMemoryInput(data) + else: + memFileInput(fileName) + +proc yCase(fileName, name: string): bool {.raises: [IOError].} = + var stream = inputFile(fileName) var lex = init(JsonLexer, stream) var value: string lex.scanValue(value) @@ -28,8 +35,8 @@ proc yCase(fileName, name: string): bool {.raises:[IOError].} = return false true -proc nCase(fileName, name: string): bool {.raises:[IOError].} = - var stream = memFileInput(fileName) +proc nCase(fileName, name: string): bool {.raises: [IOError].} = + var stream = inputFile(fileName) var lex = init(JsonLexer, stream, {}) var value: string lex.scanValue(value) @@ -43,19 +50,33 @@ proc nCase(fileName, name: string): bool {.raises:[IOError].} = return false true -for fileName in walkDirRec(parsingPath): - let (_, name) = fileName.splitPath() - if name.startsWith("y_"): - doAssert yCase(fileName, name) - elif name.startsWith("n_"): - doAssert nCase(fileName, name) - # test cases starts with i_ are allowed to - # fail or success depending on the implementation details - elif name.startsWith("i_"): +proc test() {.raises: [OSError, IOError].} = + var checked = 0 + for fileName in walkDirRec(parsingPath): + let (_, name) = fileName.splitPath() + if name.startsWith("y_"): + doAssert yCase(fileName, name) + inc checked + elif name.startsWith("n_"): + doAssert nCase(fileName, name) + inc checked + # test cases starts with i_ are allowed to + # fail or success depending on the implementation details + elif name.startsWith("i_"): + if name notin allowedToFail: + doAssert yCase(fileName, name) + inc checked + + for fileName in walkDirRec(transformPath): + let (_, name) = fileName.splitPath() if name notin allowedToFail: doAssert yCase(fileName, name) + inc checked + + doAssert checked == 328, $checked -for fileName in walkDirRec(transformPath): - let (_, name) = fileName.splitPath() - if name notin allowedToFail: - doAssert yCase(fileName, name) +static: + test() + echo "static ok" +test() +echo "ok" diff --git a/tests/test_valueref.nim b/tests/test_valueref.nim index a4e3ba4..07856bf 100644 --- a/tests/test_valueref.nim +++ b/tests/test_valueref.nim @@ -18,7 +18,7 @@ func jsonBool(x: bool): JsonValueRef[uint64] = func jsonNull(): JsonValueRef[uint64] = JsonValueRef[uint64](kind: JsonValueKind.Null) -suite "Test JsonValueRef": +template valueRefVars() {.dirty.} = let objA = JsonValueRef[uint64]( kind: JsonValueKind.Object, objVal: [ @@ -105,7 +105,9 @@ suite "Test JsonValueRef": ].toOrderedTable ) +suite "Test JsonValueRef": test "Test table keys equality": + valueRefVars() check objA != objAB check objA == objA2 check objA != objABNull @@ -122,6 +124,7 @@ suite "Test JsonValueRef": check objInObjAB != objInObjABNull test "Test compare": + valueRefVars() check compare(objA, objAB) == false check compare(objA, objA2) == true check compare(objA, objABNull) == true diff --git a/tests/utils.nim b/tests/utils.nim index 58e785b..1639689 100644 --- a/tests/utils.nim +++ b/tests/utils.nim @@ -8,7 +8,7 @@ # those terms. import - strutils + strutils, os # `dedent` exists in newer Nim version and doesn't behave the same func test_dedent*(s: string): string = @@ -21,6 +21,12 @@ func test_dedent*(s: string): string = if indent < minIndent: minIndent = indent s.unindent(minIndent) +proc pathRelativeTo*(fileName, base: string): string = + try: + relativePath(fileName, base) + except Exception as err: + raise newException(Defect, err.msg) + const parsingPath* = "tests/test_vectors/test_parsing" transformPath* = "tests/test_vectors/test_transform"