More comprehensive test suite; Depends on Fixes in Nim 1.2

This commit is contained in:
Zahary Karadjov 2020-03-25 17:54:27 +02:00 committed by zah
parent 0eab8cfeee
commit 68e9ef7901
2 changed files with 77 additions and 50 deletions

View File

@ -122,7 +122,7 @@ macro enumAllSerializedFieldsImpl(T: type, body: untyped): untyped =
# TODO: This is a work-around for a classic Nim issue:
type `FieldTypeSym` {.used.} = type(`field`)
`body`
i += 1
template enumAllSerializedFields*(T: type, body): untyped =
@ -181,21 +181,20 @@ proc makeFieldReadersTable(RecordType, Reader: distinct type):
when RecordType is tuple:
const i = fieldName.parseInt
try:
type F = FieldTag[RecordType, fieldName, type(FieldType)]
when RecordType is not tuple:
obj.field(fieldName) = readFieldIMPL(F, reader)
else:
when RecordType is tuple:
obj[i] = readFieldIMPL(F, reader)
else:
field(obj, fieldName) = readFieldIMPL(F, reader)
except SerializationError:
raise
except CatchableError as err:
when RecordType is not tuple:
let field = obj.field(fieldName)
else:
let field = obj[i]
reader.handleReadException(`RecordType`, fieldName,
field, err)
reader.handleReadException(
`RecordType`,
fieldName,
when RecordType is tuple: obj[i] else: field(obj, fieldName),
err)
result.add((fieldName, readField))
proc fieldReadersTable*(RecordType, Reader: distinct type):

View File

@ -14,30 +14,40 @@ type
ignored*: int
Transaction* = object
amount: int
time: DateTime
sender: string
receiver: string
amount*: int
time*: DateTime
sender*: string
receiver*: string
DerivedFromRoot* = object of RootObj
a*: string
b*: int
DerivedFromRootRef = ref DerivedFromRoot
RefTypeDerivedFromRoot* = ref object of RootObj
a*: int
b*: string
Foo = object
x: uint64
y: string
z: seq[int]
x*: uint64
y*: string
z*: seq[int]
Bar = object
b: string
f: Foo
ListOfLists = object
lists: seq[ListOfLists]
b*: string
f*: Foo
# Baz should use custom serialization
# The `i` field should be multiplied by two while deserializing and
# `ignored` field should be set to 10
Baz = object
f: Foo
i: int
ignored {.dontSerialize.}: int
f*: Foo
i*: int
ignored* {.dontSerialize.}: int
ListOfLists = object
lists*: seq[ListOfLists]
NoExpectedResult = distinct int
@ -46,7 +56,7 @@ type
B
CaseObject* = object
case kind: ObjectKind:
case kind*: ObjectKind:
of A:
a*: int
other*: CaseObjectRef
@ -55,6 +65,9 @@ type
CaseObjectRef* = ref CaseObject
HoldsCaseObject* = object
value: CaseObject
HoldsSet* = object
a*: int
s*: HashSet[string]
@ -111,22 +124,30 @@ func caseObjectEquals(a, b: CaseObject): bool =
func `==`*(a, b: CaseObject): bool =
caseObjectEquals(a, b)
template maybeDefer(x: auto): auto =
when type(x) is ref:
x[]
else:
x
template roundtripChecks*(Format: type, value: auto, expectedResult: auto) =
let v = value
let serialized = encode(Format, v)
let origValue = value
let serialized = encode(Format, origValue)
checkpoint "(encoded value): " & $serialized
when not (expectedResult is NoExpectedResult):
check serialized == expectedResult
try:
let decoded = Format.decode(serialized, type(v))
let decoded = Format.decode(serialized, type(origValue))
checkpoint "(decoded value): " & repr(decoded)
let decodedValueMatchesOriginal = decoded == v
check decodedValueMatchesOriginal
let success = maybeDefer(decoded) == maybeDefer(origValue)
check success
except SerializationError as err:
checkpoint "(serialization error): " & err.formatMsg("(encoded value)")
fail()
except:
when compiles($value):
checkpoint "unexpected failure in roundtrip test for " & $value
@ -158,11 +179,8 @@ proc executeRoundtripTests*(Format: type) =
template intTests(T: untyped) =
roundtrip low(T)
roundtrip high(T)
when false:
# TODO:
# rand(low..high) produces an overflow error in Nim 1.0.2
for i in 0..1000:
roundtrip rand(low(T)..(high(T) div 2))
for i in 0..1000:
roundtrip rand(T)
intTests int8
intTests int16
@ -194,9 +212,8 @@ proc executeRoundtripTests*(Format: type) =
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300]))
roundtrip b
when false:
# TODO: This requires the test suite of each format to implement
# support for the DateTime type.
when false and supports(Format, Transaction):
# Some formats may not support the DateTime type.
var t = Transaction(time: now(), amount: 1000, sender: "Alice", receiver: "Bob")
roundtrip t
@ -205,21 +222,32 @@ proc executeRoundtripTests*(Format: type) =
# and give it a more proper name. The custom serialization demands
# that the `ignored` field is populated with a value depending on
# the `i` value. `i` itself is doubled on deserialization.
var origVal = Baz(f: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
bytes = Format.encode(origVal)
var restored = Format.decode(bytes, Baz)
let
origVal = Baz(f: Foo(x: 10'u64, y: "y", z: @[]), ignored: 5)
encoded = Format.encode(origVal)
restored = Format.decode(encoded, Baz)
check:
origVal.f.x == restored.f.x
origVal.f.i == restored.f.i div 2
origVal.f.y.len == restored.f.y.len
origVal.i == restored.i div 2
restored.ignored == 10
block:
let
a = DerivedFromRoot(a: "test", b: -1000)
b = DerivedFromRootRef(a: "another test", b: 2000)
c = RefTypeDerivedFromRoot(a: high(int), b: "")
roundtrip a
roundtrip b
roundtrip c
test "case objects":
var
c1 = CaseObjectRef(kind: B, b: 100)
c2 = CaseObjectRef(kind: A, a: 80, other: CaseObjectRef(kind: B))
c3 = CaseObject(kind: A, a: 60, other: nil)
c3 = HoldsCaseObject(value: CaseObject(kind: A, a: 60, other: c1))
roundtrip c1
roundtrip c2
@ -263,11 +291,11 @@ proc executeRoundtripTests*(Format: type) =
roundtrip s1
roundtrip s2
test "tuple":
var t = (0, "e")
var namedT = (a: 0, b: "e")
roundtrip t
roundtrip namedT
test "tuple":
var t = (0, "e")
var namedT = (a: 0, b: "e")
roundtrip t
roundtrip namedT
proc executeReaderWriterTests*(Format: type) =
mixin init, ReaderType, WriterType