nim-codex/tests/codex/testlogutils.nim

235 lines
7.7 KiB
Nim
Raw Normal View History

feat: create logging proxy (#663) * implement a logging proxy The logging proxy: - prevents the need to import chronicles (as well as export except toJson), - prevents the need to override `writeValue` or use or import nim-json-seralization elsewhere in the codebase, allowing for sole use of utils/json for de/serialization, - and handles json formatting correctly in chronicles json sinks * Rename logging -> logutils to avoid ambiguity with common names * clean up * add setProperty for JsonRecord, remove nim-json-serialization conflict * Allow specifying textlines and json format separately Not specifying a LogFormat will apply the formatting to both textlines and json sinks. Specifying a LogFormat will apply the formatting to only that sink. * remove unneeded usages of std/json We only need to import utils/json instead of std/json * move serialization from rest/json to utils/json so it can be shared * fix NoColors ambiguity Was causing unit tests to fail on Windows. * Remove nre usage to fix Windows error Windows was erroring with `could not load: pcre64.dll`. Instead of fixing that error, remove the pcre usage :) * Add logutils module doc * Shorten logutils.formatIt for `NBytes` Both json and textlines formatIt were not needed, and could be combined into one formatIt * remove debug integration test config debug output and logformat of json for integration test logs * Use ## module doc to support docgen * bump nim-poseidon2 to export fromBytes Before the changes in this branch, fromBytes was likely being resolved by nim-stew, or other dependency. With the changes in this branch, that dependency was removed and fromBytes could no longer be resolved. By exporting fromBytes from nim-poseidon, the correct resolution is now happening. * fixes to get compiling after rebasing master * Add support for Result types being logged using formatIt
2024-01-23 07:35:03 +00:00
import std/options
import std/strutils
import std/unittest
import pkg/codex/blocktype
import pkg/codex/conf
import pkg/codex/contracts/requests
import pkg/codex/logutils
import pkg/codex/purchasing/purchaseid
import pkg/codex/units
import pkg/libp2p/cid
import pkg/libp2p/multiaddress
import pkg/questionable
import pkg/questionable/results
import pkg/stew/byteutils
import pkg/stint
import ../checktest
export logutils
logStream testlines[textlines[nocolors,notimestamps,dynamic]]
logStream testjson[json[nocolors,notimestamps,dynamic]]
type
ObjectType = object
a: string
DistinctType {.borrow: `.`.} = distinct ObjectType
RefType = ref object
a: string
AnotherType = object
a: int
# must be defined at the top-level
proc `$`*(t: ObjectType): string = "used `$`"
func `%`*(t: RefType): JsonNode = % t.a
logutils.formatIt(LogFormat.textLines, ObjectType): "formatted_" & it.a
logutils.formatIt(LogFormat.textLines, RefType): "formatted_" & it.a
logutils.formatIt(LogFormat.textLines, DistinctType): "formatted_" & it.a
logutils.formatIt(LogFormat.json, ObjectType): "formatted_" & it.a
logutils.formatIt(LogFormat.json, RefType): %it
logutils.formatIt(LogFormat.json, DistinctType): "formatted_" & it.a
logutils.formatIt(AnotherType): it.a
checksuite "Test logging output":
var outputLines: string
var outputJson: string
proc writeToLines(logLevel: LogLevel, msg: LogOutputStr) =
outputLines &= msg
proc writeToJson(logLevel: LogLevel, msg: LogOutputStr) =
outputJson &= msg
setup:
outputLines = ""
outputJson = ""
testlines.outputs[0].writer = writeToLines
testjson.outputs[0].writer = writeToJson
template logged(prop, expected): auto =
let toFind = prop & "=" & expected
outputLines.contains(toFind)
template loggedJson(prop, expected): auto =
let json = $ parseJson(outputJson){prop}
json == expected
template log(val) =
testlines.trace "test", val
testjson.trace "test", val
test "logs objects":
let t = ObjectType(a: "a")
log t
check logged("t", "formatted_a")
check loggedJson("t", "\"formatted_a\"")
test "logs sequences of objects":
let t1 = ObjectType(a: "a")
let t2 = ObjectType(a: "b")
let t = @[t1, t2]
log t
check logged("t", "\"@[formatted_a, formatted_b]\"")
check loggedJson("t", "[\"formatted_a\",\"formatted_b\"]")
test "logs ref types":
let t = RefType(a: "a")
log t
check logged("t", "formatted_a")
check loggedJson("t", "\"a\"")
test "logs sequences of ref types":
let t1 = RefType(a: "a")
let t2 = RefType(a: "b")
let t = @[t1, t2]
log t
check logged("t", "\"@[formatted_a, formatted_b]\"")
check loggedJson("t", "[\"a\",\"b\"]")
test "logs distinct types":
let t = DistinctType(ObjectType(a: "a"))
log t
check logged("t", "formatted_a")
check loggedJson("t", "\"formatted_a\"")
test "logs sequences of distinct types":
let t1 = DistinctType(ObjectType(a: "a"))
let t2 = DistinctType(ObjectType(a: "b"))
let t = @[t1, t2]
log t
check logged("t", "\"@[formatted_a, formatted_b]\"")
check loggedJson("t", "[\"formatted_a\",\"formatted_b\"]")
test "formatIt can return non-string types":
let t = AnotherType(a: 1)
log t
check logged("t", "1")
check loggedJson("t", "1")
test "logs Option types":
let t = some ObjectType(a: "a")
log t
check logged("t", "some(formatted_a)")
check loggedJson("t", "\"formatted_a\"")
test "logs sequences of Option types":
let t1 = some ObjectType(a: "a")
let t2 = none ObjectType
let t = @[t1, t2]
log t
check logged("t", "\"@[some(formatted_a), none(ObjectType)]\"")
check loggedJson("t", """["formatted_a",null]""")
test "logs Result types -- success with string property":
let t: ?!ObjectType = success ObjectType(a: "a")
log t
check logged("t", "formatted_a")
check loggedJson("t", "\"formatted_a\"")
test "logs Result types -- success with int property":
let t: ?!AnotherType = success AnotherType(a: 1)
log t
check logged("t", "1")
check loggedJson("t", "1")
test "logs Result types -- failure":
let t: ?!ObjectType = ObjectType.failure newException(ValueError, "some error")
log t
check logged("t", "\"Error: some error\"")
check loggedJson("t", """{"error":"some error"}""")
test "can define `$` override for T":
let o = ObjectType()
check $o == "used `$`"
test "logs NByte correctly":
let nb = 12345.NBytes
log nb
check logged("nb", "12345\'NByte")
check loggedJson("nb", "\"12345\'NByte\"")
test "logs BlockAddress correctly":
let cid = Cid.init("zb2rhgsDE16rLtbwTFeNKbdSobtKiWdjJPvKEuPgrQAfndjU1").tryGet
let ba = BlockAddress.init(cid, 0)
log ba
check logged("ba", "\"treeCid: zb2*fndjU1, index: 0\"")
check loggedJson("ba", """{"treeCid":"zb2rhgsDE16rLtbwTFeNKbdSobtKiWdjJPvKEuPgrQAfndjU1","index":0}""")
test "logs Cid correctly":
let cid = Cid.init("zb2rhmfWaXASbyi15iLqbz5yp3awnSyecpt9jcFnc2YA5TgiD").tryGet
log cid
check logged("cid", "zb2*A5TgiD")
check loggedJson("cid", "\"zb2rhmfWaXASbyi15iLqbz5yp3awnSyecpt9jcFnc2YA5TgiD\"")
test "logs StUint correctly":
let stint = 12345678901234.u256
log stint
check logged("stint", "12345678901234")
check loggedJson("stint", "\"12345678901234\"")
test "logs int correctly":
let int = 123
log int
check logged("int", "123")
check loggedJson("int", "123")
test "logs EthAddress correctly":
let address = EthAddress.fromHex("0xf75e076f650cd51dbfa0fd9c465d5037f22e1b1b")
log address
check logged("address", "0xf75e..1b1b")
check loggedJson("address", "\"0xf75e076f650cd51dbfa0fd9c465d5037f22e1b1b\"")
test "logs PurchaseId correctly":
let id = PurchaseId.fromHex("0x712003bdfc0db9abf21e7fbb7119cd52ff221c96714d21d39e782d7c744d3dea")
log id
check logged("id", "0x7120..3dea")
test "logs RequestId correctly":
let id = RequestId.fromHex("0x712003bdfc0db9abf21e7fbb7119cd52ff221c96714d21d39e782d7c744d3dea")
log id
check logged("id", "0x7120..3dea")
check loggedJson("id", "\"0x712003bdfc0db9abf21e7fbb7119cd52ff221c96714d21d39e782d7c744d3dea\"")
test "logs seq[RequestId] correctly":
let id = RequestId.fromHex("0x712003bdfc0db9abf21e7fbb7119cd52ff221c96714d21d39e782d7c744d3dea")
let id2 = RequestId.fromHex("0x9ab2c4d102a95d990facb022d67b3c9b39052597c006fddf122bed2cb594c282")
let ids = @[id, id2]
log ids
check logged("ids", "\"@[0x7120..3dea, 0x9ab2..c282]\"")
check loggedJson("ids", """["0x712003bdfc0db9abf21e7fbb7119cd52ff221c96714d21d39e782d7c744d3dea","0x9ab2c4d102a95d990facb022d67b3c9b39052597c006fddf122bed2cb594c282"]""")
test "logs SlotId correctly":
let id = SlotId.fromHex("0x9ab2c4d102a95d990facb022d67b3c9b39052597c006fddf122bed2cb594c282")
log id
check logged("id", "0x9ab2..c282")
check loggedJson("id", "\"0x9ab2c4d102a95d990facb022d67b3c9b39052597c006fddf122bed2cb594c282\"")
test "logs Nonce correctly":
let n = Nonce.fromHex("ce88f368a7b776172ebd29a212456eb66acb60f169ee76eae91935e7fafad6ea")
log n
check logged("n", "0xce88..d6ea")
check loggedJson("n", "\"0xce88f368a7b776172ebd29a212456eb66acb60f169ee76eae91935e7fafad6ea\"")
test "logs MultiAddress correctly":
let ma = MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet
log ma
check logged("ma", "/ip4/127.0.0.1/tcp/0")
check loggedJson("ma", "\"/ip4/127.0.0.1/tcp/0\"")
test "logs seq[MultiAddress] correctly":
let ma = @[MultiAddress.init("/ip4/127.0.0.1/tcp/0").tryGet,
MultiAddress.init("/ip4/127.0.0.2/tcp/1").tryGet]
log ma
check logged("ma", "\"@[/ip4/127.0.0.1/tcp/0, /ip4/127.0.0.2/tcp/1]\"")
check loggedJson("ma", "[\"/ip4/127.0.0.1/tcp/0\",\"/ip4/127.0.0.2/tcp/1\"]")