mirror of
https://github.com/waku-org/nwaku.git
synced 2025-01-16 09:55:07 +00:00
359 lines
9.7 KiB
Nim
359 lines
9.7 KiB
Nim
# toml-serialization
|
|
# Copyright (c) 2020 Status Research & Development GmbH
|
|
# Licensed and distributed under either of
|
|
# * MIT license: [LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT
|
|
# * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
import
|
|
unittest2, os, strutils, tables,
|
|
../toml_serialization,
|
|
../toml_serialization/lexer,
|
|
stint
|
|
|
|
type
|
|
Owner = object
|
|
name: string
|
|
dob: TomlDateTime
|
|
cap: float64
|
|
dobToml: string
|
|
|
|
FakeOwner = tuple[name: string, cap: float64]
|
|
|
|
Server = object
|
|
ip: string
|
|
port: int
|
|
name: string
|
|
|
|
Encoding = object
|
|
name: string
|
|
charset: string
|
|
|
|
HoldDateTime = object
|
|
dt: TomlDateTime
|
|
|
|
HoldString = object
|
|
name: string
|
|
multiLine: bool
|
|
literal: bool
|
|
|
|
DateString = object
|
|
date: string
|
|
|
|
HoldFloat = object
|
|
data: string
|
|
sign: Sign
|
|
|
|
HoldInt = object
|
|
data: int
|
|
|
|
Features = enum
|
|
ParseInt
|
|
ParseEnum
|
|
ParseFloat
|
|
ParseString
|
|
|
|
HoldEnum = object
|
|
data: Features
|
|
|
|
HoldValue = object
|
|
data: TomlValueRef
|
|
|
|
HoldTable = object
|
|
data: Table[string, int]
|
|
|
|
proc readValue*(r: var TomlReader, value: var UInt256) =
|
|
var z: string
|
|
let (sign, base) = r.parseNumber(z)
|
|
|
|
if sign == Sign.Neg:
|
|
raiseTomlErr(r.lex, errNegateUint)
|
|
|
|
case base
|
|
of base10: value = parse(z, UInt256, 10)
|
|
of base16: value = parse(z, UInt256, 16)
|
|
of base8: value = parse(z, UInt256, 8)
|
|
of base2: value = parse(z, UInt256, 2)
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldDateTime) =
|
|
value.dt = r.parseDateTime()
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldString) =
|
|
(value.multiLine, value.literal) = r.parseString(value.name)
|
|
|
|
proc readValue*(r: var TomlReader, value: var DateString) =
|
|
value.date = r.parseAsString
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldFloat) =
|
|
value.sign = r.parseFloat(value.data)
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldInt) =
|
|
value.data = r.parseInt(type value.data)
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldEnum) =
|
|
value.data = r.parseEnum(type value.data)
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldValue) =
|
|
value.data = r.parseValue()
|
|
|
|
proc readValue*(r: var TomlReader, value: var Table) =
|
|
parseTable(r, key):
|
|
value[key] = r.parseInt(int)
|
|
|
|
type
|
|
HoldArray = object
|
|
data: array[3, int]
|
|
|
|
HoldSeq = object
|
|
data: seq[int]
|
|
|
|
WelderFlag = enum
|
|
TIG
|
|
MIG
|
|
MMA
|
|
|
|
Welder = object
|
|
flags: set[WelderFlag]
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldArray) =
|
|
r.parseList(i):
|
|
value.data[i] = r.parseInt(int)
|
|
|
|
proc readValue*(r: var TomlReader, value: var HoldSeq) =
|
|
r.parseList:
|
|
let lastPos = value.data.len
|
|
value.data.setLen(lastPos + 1)
|
|
readValue(r, value.data[lastPos])
|
|
|
|
proc readValue*(r: var TomlReader, value: var Welder) =
|
|
r.parseList:
|
|
value.flags.incl r.parseEnum(WelderFlag)
|
|
|
|
suite "features test suite":
|
|
let rawToml = readFile("tests" / "tomls" / "example.toml")
|
|
let rawCase = readFile("tests" / "tomls" / "case.toml")
|
|
|
|
test "case sensitive":
|
|
let server = Toml.decode(rawToml, string, "database.server")
|
|
check server == "192.168.1.1"
|
|
|
|
let owner = Toml.decode(rawToml, string, "owner.name")
|
|
check owner == "Tom Preston-Werner"
|
|
|
|
let serverName = Toml.decode(rawCase, string, "SeRveR.nAmE")
|
|
check serverName == "Toml"
|
|
|
|
expect TomlError:
|
|
discard Toml.decode(rawToml, string, "Fruit")
|
|
|
|
test "case insensitive":
|
|
let fruit = Toml.decode(rawCase, string, "fruit.name", TomlCaseInsensitive)
|
|
check fruit == "banana"
|
|
|
|
let animal = Toml.decode(rawCase, string, "animal.name", TomlCaseInsensitive)
|
|
check animal == "Elephant"
|
|
|
|
test "case nim style":
|
|
let fruit = Toml.decode(rawCase, string, "Fruit.Name", TomlCaseNim)
|
|
check fruit == "banana"
|
|
|
|
let vehicle = Toml.decode(rawCase, string, "Vehicle.Name", TomlCaseNim)
|
|
check vehicle == "hovercraft"
|
|
|
|
let server = Toml.decode(rawCase, string, "Server.name", TomlCaseNim)
|
|
check server == "Toml"
|
|
|
|
test "allowUnknownFields":
|
|
expect TomlError:
|
|
discard Toml.decode(rawToml, Owner, "owner")
|
|
|
|
var owner = Toml.decode(rawToml, Owner, "owner", TomlCaseInsensitive, {TomlUnknownFields})
|
|
check owner.name == "Tom Preston-Werner"
|
|
|
|
var fakeOwner = Toml.decode(rawToml, FakeOwner, "owner", TomlCaseInsensitive, {TomlUnknownFields})
|
|
check fakeOwner.name == "Tom Preston-Werner"
|
|
|
|
type
|
|
NoName = object
|
|
age: int
|
|
|
|
let toml = readFile("tests" / "tomls" / "nested_object.toml")
|
|
let y = Toml.decode(toml, NoName, "someone.noname", {TomlUnknownFields})
|
|
check y.age == 30
|
|
|
|
test "newline in inline table":
|
|
let toml = readFile("tests" / "tomls" / "inline-table-newline.toml")
|
|
|
|
expect TomlError:
|
|
discard Toml.decode(toml, Server, "server")
|
|
|
|
var server = Toml.decode(toml, Server, "server", TomlCaseInsensitive, {TomlInlineTableNewline})
|
|
check server.port == 8005
|
|
|
|
var z = Toml.decode(toml, Encoding, "encoding", TomlCaseInsensitive, {TomlInlineTableNewline})
|
|
check z.name == "TOML"
|
|
|
|
var w = Toml.decode(toml, TomlValueRef, {TomlInlineTableNewline})
|
|
check w.tableVal["server"].kind == TomlKind.InlineTable
|
|
|
|
expect TomlError:
|
|
discard Toml.decode(toml, TomlValueRef)
|
|
|
|
test "bignum":
|
|
var z = Toml.decode("bignum = 1234567890_1234567890", UInt256, "bignum")
|
|
check $z == "12345678901234567890"
|
|
|
|
test "helper functions":
|
|
var u = Toml.decode("val = 1970-08-08 07:10:11", HoldDateTime, "val")
|
|
check u.dt.date.isSome
|
|
|
|
var v = Toml.decode("val = \'Toml Literal\'", HoldString, "val")
|
|
check:
|
|
v.name == "Toml Literal"
|
|
v.multiLine == false
|
|
v.literal == true
|
|
|
|
var w = Toml.decode("val = 1970-08-08 07:10:11", DateString, "val")
|
|
check w.date == "1970-08-08 07:10:11"
|
|
|
|
var z = Toml.decode("val = -123.123", HoldFloat, "val")
|
|
check z.sign == Sign.Neg
|
|
check z.data == "-123.123"
|
|
|
|
var x = Toml.decode("val = 768", HoldInt, "val")
|
|
check x.data == 768
|
|
|
|
var y = Toml.decode("val = 1", HoldEnum, "val")
|
|
check y.data == ParseEnum
|
|
|
|
y = Toml.decode("val = 'ParseInt'", HoldEnum, "val")
|
|
check y.data == ParseInt
|
|
|
|
y = Toml.decode("val = \"ParseFloat\"", HoldEnum, "val")
|
|
check y.data == ParseFloat
|
|
|
|
expect TomlError:
|
|
discard Toml.decode("val = '''ParseString'''", HoldEnum, "val")
|
|
|
|
expect TomlError:
|
|
discard Toml.decode("val = \"\"\"ParseString\"\"\"", HoldEnum, "val")
|
|
|
|
var p = Toml.decode("val = 1", HoldValue, "val")
|
|
check p.data == TomlValueRef(kind: TomlKind.Int, intVal: 1)
|
|
|
|
test "hex escape sequence":
|
|
var x = Toml.decode("val = \"H\\x45X\"", string, "val", TomlCaseSensitive, {TomlHexEscape})
|
|
check x == "HEX"
|
|
|
|
expect TomlError:
|
|
discard Toml.decode("val = \"H\\x45X\"", string, "val")
|
|
|
|
var z = Toml.decode("val = \"H\\x45X\" \n name = \"skip hex\"",
|
|
string, "name", TomlCaseSensitive, {TomlHexEscape})
|
|
check z == "skip hex"
|
|
|
|
expect TomlError:
|
|
discard Toml.decode("val = \"H\\x45X\" \n name = \"skip hex\"", string, "name")
|
|
|
|
test "api test":
|
|
var x = Toml.decode("val = \"H\\x45X\"", string, "val", {TomlHexEscape})
|
|
check x == "HEX"
|
|
|
|
var w = Toml.decode("Val = \"HEX\"", string, "Val", TomlCaseSensitive)
|
|
check w == "HEX"
|
|
|
|
var u = Toml.decode("val = 123456", int, "val")
|
|
check u == 123456
|
|
|
|
let file = "tests" / "tomls" / "example.toml"
|
|
var z = Toml.loadFile(file, bool, "database.enabled")
|
|
check z == true
|
|
|
|
let toml = "tests" / "tomls" / "case.toml"
|
|
var v = Toml.loadFile(toml, string, "animal.name", TomlCaseInsensitive)
|
|
check v == "Elephant"
|
|
|
|
test "unsupported keyed mode":
|
|
let table = "tests" / "tomls" / "inline-table-newline.toml"
|
|
expect TomlError:
|
|
discard Toml.loadFile(table, int, "server.port", {TomlInlineTableNewline})
|
|
|
|
test "date time reader":
|
|
var x = Toml.decode("x = 12:13:14", TomlTime, "x")
|
|
check x.hour == 12
|
|
check x.minute == 13
|
|
check x.second == 14
|
|
|
|
var y = Toml.decode("x = 2020-08-16", TomlDate, "x")
|
|
check y.year == 2020
|
|
check y.month == 8
|
|
check y.day == 16
|
|
|
|
test "TomlHourMinute flags":
|
|
expect TomlError:
|
|
discard Toml.decode("x = 12:13", TomlTime, "x")
|
|
|
|
var x = Toml.decode("x = 12:13", TomlTime, "x", {TomlHourMinute})
|
|
check x.hour == 12
|
|
check x.minute == 13
|
|
check x.second == 0
|
|
|
|
suite "helper parsers":
|
|
test "parseTable":
|
|
var q = Toml.decode("p = 1\nq = 2\nr = 3", Table[string, int])
|
|
check:
|
|
q["p"] == 1
|
|
q["q"] == 2
|
|
q["r"] == 3
|
|
|
|
var r = Toml.decode("[data]\np = 1\nq = 2\nr = 3", HoldTable)
|
|
check:
|
|
r.data["p"] == 1
|
|
r.data["q"] == 2
|
|
r.data["r"] == 3
|
|
|
|
var s = Toml.decode("data = {p = 1, q = 2, r = 3}", HoldTable)
|
|
check:
|
|
s.data["p"] == 1
|
|
s.data["q"] == 2
|
|
s.data["r"] == 3
|
|
|
|
test "parseList":
|
|
let x = Toml.decode("x = [1, 2, 3]", HoldArray, "x")
|
|
check x.data == [1, 2, 3]
|
|
|
|
let y = Toml.decode("x = [1, 2, 3]", HoldSeq, "x")
|
|
check y.data == @[1, 2, 3]
|
|
|
|
let z = Toml.decode("x = ['MMA', 'MIG']", Welder, "x")
|
|
check:
|
|
MMA in z.flags
|
|
MIG in z.flags
|
|
|
|
type
|
|
Fruits = enum
|
|
Apple
|
|
Banana
|
|
Orange
|
|
|
|
FruitBasket = object
|
|
fruit1: Fruits
|
|
fruit2: Fruits
|
|
fruit3: Fruits
|
|
|
|
proc writeValue*(w: var TomlWriter, val: Fruits) =
|
|
w.writeValue $val
|
|
|
|
suite "enums examples":
|
|
test "read enums":
|
|
var x = Toml.loadFile("tests" / "tomls" / "fruits.toml", FruitBasket)
|
|
check x.fruit1 == Apple
|
|
check x.fruit2 == Banana
|
|
check x.fruit3 == Orange
|
|
|
|
test "write enums":
|
|
let z = FruitBasket(fruit1: Apple, fruit2: Banana, fruit3: Orange)
|
|
let res = Toml.encode(z)
|
|
let want = "fruit1 = \"Apple\"\nfruit2 = \"Banana\"\nfruit3 = \"Orange\"\n"
|
|
check res == want
|