Files
BitLogger/src/parsed_library_logger_test.mbt
T
Nanaloveyuki b18dcf972d 🧪 relocate test logs
2026-07-17 18:22:04 +08:00

318 lines
11 KiB
MoonBit

///|
test "library logger can be parsed and built from config text" {
let logger = parse_and_build_library_logger(
"{\"min_level\":\"warn\",\"target\":\"lib.json\",\"sink\":{\"kind\":\"console\"}}",
)
let full = logger.to_logger()
inspect(logger.is_enabled(Level::Error), content="true")
inspect(logger.is_enabled(Level::Info), content="false")
inspect(full.target, content="lib.json")
}
///|
test "parsed library logger log supports per-call target override through facade" {
let captured_target : Ref[String] = Ref("")
let captured_message : Ref[String] = Ref("")
let captured_fields : Ref[Array[Field]] = Ref([])
let logger = parse_and_build_library_logger(
"{\"min_level\":\"warn\",\"target\":\"lib.json.default\",\"sink\":{\"kind\":\"console\"}}",
)
.to_logger()
.with_patch(fn(rec) {
captured_target.val = rec.target
captured_message.val = rec.message
captured_fields.val = rec.fields
rec
})
.to_library_logger()
.bind([field("service", "bitlogger")])
logger.log(
Level::Error,
"override",
fields=[field("mode", "test")],
target="lib.json.override",
)
inspect(captured_target.val, content="lib.json.override")
inspect(captured_message.val, content="override")
inspect(captured_fields.val.length(), content="2")
inspect(captured_fields.val[0].key, content="service")
inspect(captured_fields.val[0].value, content="bitlogger")
inspect(captured_fields.val[1].key, content="mode")
inspect(captured_fields.val[1].value, content="test")
logger.log(Level::Error, "default")
inspect(captured_target.val, content="lib.json.default")
inspect(captured_message.val, content="default")
inspect(captured_fields.val.length(), content="1")
inspect(captured_fields.val[0].key, content="service")
}
///|
test "parsed library logger severity helpers use stored target without override" {
let captured_levels : Ref[Array[String]] = Ref([])
let captured_targets : Ref[Array[String]] = Ref([])
let captured_fields : Ref[Array[Array[Field]]] = Ref([])
let logger = parse_and_build_library_logger(
"{\"min_level\":\"info\",\"target\":\"lib.json.helpers\",\"sink\":{\"kind\":\"console\"}}",
)
.to_logger()
.with_patch(fn(rec) {
captured_levels.val.push(rec.level.label())
captured_targets.val.push(rec.target)
captured_fields.val.push(rec.fields)
rec
})
.to_library_logger()
.bind([field("service", "bitlogger")])
logger.info("info", fields=[field("mode", "info")])
logger.warn("warn", fields=[field("mode", "warn")])
logger.error("error", fields=[field("mode", "error")])
inspect(captured_levels.val.length(), content="3")
inspect(captured_levels.val[0], content="INFO")
inspect(captured_levels.val[1], content="WARN")
inspect(captured_levels.val[2], content="ERROR")
inspect(captured_targets.val.length(), content="3")
inspect(captured_targets.val[0], content="lib.json.helpers")
inspect(captured_targets.val[1], content="lib.json.helpers")
inspect(captured_targets.val[2], content="lib.json.helpers")
inspect(captured_fields.val[0].length(), content="2")
inspect(captured_fields.val[1].length(), content="2")
inspect(captured_fields.val[2].length(), content="2")
inspect(captured_fields.val[0][0].key, content="service")
inspect(captured_fields.val[0][1].value, content="info")
inspect(captured_fields.val[1][0].key, content="service")
inspect(captured_fields.val[1][1].value, content="warn")
inspect(captured_fields.val[2][0].key, content="service")
inspect(captured_fields.val[2][1].value, content="error")
}
///|
test "library logger parse-build unwrap matches parsed direct builder behavior" {
let raw = "{\"min_level\":\"warn\",\"target\":\"lib.json.same-build\",\"timestamp\":true,\"queue\":{\"max_pending\":2,\"overflow\":\"DropNewest\"},\"sink\":{\"kind\":\"console\"}}"
let logger = parse_and_build_library_logger(raw)
let full = logger.to_logger()
let configured = parse_and_build_logger(raw)
inspect(full.target, content=configured.target)
inspect(full.timestamp == configured.timestamp, content="true")
inspect(
logger.is_enabled(Level::Error) == configured.is_enabled(Level::Error),
content="true",
)
inspect(
logger.is_enabled(Level::Info) == configured.is_enabled(Level::Info),
content="true",
)
let full_sink_kind = match full.sink {
RuntimeSink::QueuedConsole(_) => "QueuedConsole"
RuntimeSink::QueuedJsonConsole(_) => "QueuedJsonConsole"
RuntimeSink::QueuedTextConsole(_) => "QueuedTextConsole"
RuntimeSink::QueuedFile(_) => "QueuedFile"
RuntimeSink::Console(_) => "Console"
RuntimeSink::JsonConsole(_) => "JsonConsole"
RuntimeSink::TextConsole(_) => "TextConsole"
RuntimeSink::File(_) => "File"
}
let configured_sink_kind = match configured.sink {
RuntimeSink::QueuedConsole(_) => "QueuedConsole"
RuntimeSink::QueuedJsonConsole(_) => "QueuedJsonConsole"
RuntimeSink::QueuedTextConsole(_) => "QueuedTextConsole"
RuntimeSink::QueuedFile(_) => "QueuedFile"
RuntimeSink::Console(_) => "Console"
RuntimeSink::JsonConsole(_) => "JsonConsole"
RuntimeSink::TextConsole(_) => "TextConsole"
RuntimeSink::File(_) => "File"
}
inspect(full_sink_kind == configured_sink_kind, content="true")
full.error("one")
full.error("two")
full.error("three")
configured.error("one")
configured.error("two")
configured.error("three")
inspect(full.pending_count() == configured.pending_count(), content="true")
inspect(full.dropped_count() == configured.dropped_count(), content="true")
inspect(full.flush() == configured.flush(), content="true")
inspect(full.pending_count() == configured.pending_count(), content="true")
}
///|
test "library logger parse-build unwrap preserves file runtime helpers" {
let raw = "{\"min_level\":\"warn\",\"target\":\"lib.json.file.same-build\",\"queue\":{\"max_pending\":2,\"overflow\":\"DropOldest\"},\"sink\":{\"kind\":\"file\",\"path\":\"logs/lib-json-file-same-build.log\"}}"
let logger = parse_and_build_library_logger(raw)
let full = logger.to_logger()
let configured = parse_and_build_logger(raw)
full.error("one")
full.error("two")
full.error("three")
configured.error("one")
configured.error("two")
configured.error("three")
inspect(full.pending_count() == configured.pending_count(), content="true")
inspect(full.dropped_count() == configured.dropped_count(), content="true")
inspect(full.file_available() == configured.file_available(), content="true")
inspect(
full.file_append_mode() == configured.file_append_mode(),
content="true",
)
inspect(
full.file_auto_flush() == configured.file_auto_flush(),
content="true",
)
let full_state = full.file_state()
let configured_state = configured.file_state()
inspect(full_state.path == configured_state.path, content="true")
inspect(full_state.available == configured_state.available, content="true")
inspect(full_state.append == configured_state.append, content="true")
inspect(full_state.auto_flush == configured_state.auto_flush, content="true")
inspect(
full_state.open_failures == configured_state.open_failures,
content="true",
)
inspect(
full_state.write_failures == configured_state.write_failures,
content="true",
)
inspect(
full_state.flush_failures == configured_state.flush_failures,
content="true",
)
inspect(
full_state.rotation_failures == configured_state.rotation_failures,
content="true",
)
match (full.file_runtime_state(), configured.file_runtime_state()) {
(Some(snapshot), Some(other)) => {
inspect(snapshot.file.path == other.file.path, content="true")
inspect(snapshot.file.available == other.file.available, content="true")
inspect(snapshot.queued == other.queued, content="true")
inspect(snapshot.pending_count == other.pending_count, content="true")
inspect(snapshot.dropped_count == other.dropped_count, content="true")
}
_ => inspect(false, content="true")
}
inspect(full.file_flush() == configured.file_flush(), content="true")
inspect(full.pending_count() == configured.pending_count(), content="true")
inspect(full.file_close() == configured.file_close(), content="true")
}
///|
test "library logger parse-build unwrap preserves file controls" {
let raw = "{\"min_level\":\"warn\",\"target\":\"lib.json.file.controls.same-build\",\"sink\":{\"kind\":\"file\",\"path\":\"logs/lib-json-file-controls-same-build.log\"}}"
let logger = parse_and_build_library_logger(raw)
let full = logger.to_logger()
let configured = parse_and_build_logger(raw)
inspect(
full.file_set_append_mode(false) == configured.file_set_append_mode(false),
content="true",
)
inspect(
full.file_append_mode() == configured.file_append_mode(),
content="true",
)
inspect(
full.file_set_auto_flush(false) == configured.file_set_auto_flush(false),
content="true",
)
inspect(
full.file_auto_flush() == configured.file_auto_flush(),
content="true",
)
let rotation = Some(file_rotation(40, max_backups=2))
inspect(
full.file_set_rotation(rotation) == configured.file_set_rotation(rotation),
content="true",
)
inspect(
full.file_rotation_enabled() == configured.file_rotation_enabled(),
content="true",
)
inspect(
full.file_reopen(append=Some(false)) ==
configured.file_reopen(append=Some(false)),
content="true",
)
inspect(
full.file_append_mode() == configured.file_append_mode(),
content="true",
)
inspect(
full.file_reopen_append() == configured.file_reopen_append(),
content="true",
)
inspect(
full.file_append_mode() == configured.file_append_mode(),
content="true",
)
inspect(
full.file_clear_rotation() == configured.file_clear_rotation(),
content="true",
)
inspect(
full.file_rotation_enabled() == configured.file_rotation_enabled(),
content="true",
)
inspect(
full.file_reset_policy() == configured.file_reset_policy(),
content="true",
)
inspect(
full.file_policy_matches_default() ==
configured.file_policy_matches_default(),
content="true",
)
inspect(
full.file_reset_failure_counters() ==
configured.file_reset_failure_counters(),
content="true",
)
inspect(full.file_close() == configured.file_close(), content="true")
}
///|
test "parsed library logger unwrap preserves configured runtime path" {
let logger = parse_and_build_library_logger(
"{\"min_level\":\"warn\",\"target\":\"lib.json.runtime\",\"timestamp\":true,\"queue\":{\"max_pending\":3,\"overflow\":\"DropNewest\"},\"sink\":{\"kind\":\"console\"}}",
)
let full = logger.to_logger()
inspect(logger.is_enabled(Level::Error), content="true")
inspect(logger.is_enabled(Level::Info), content="false")
inspect(full.target, content="lib.json.runtime")
inspect(full.timestamp, content="true")
full.error("one")
full.error("two")
inspect(
match full.sink {
RuntimeSink::QueuedConsole(_) => "QueuedConsole"
RuntimeSink::QueuedJsonConsole(_) => "QueuedJsonConsole"
RuntimeSink::QueuedTextConsole(_) => "QueuedTextConsole"
RuntimeSink::QueuedFile(_) => "QueuedFile"
_ => "Other"
},
content="QueuedConsole",
)
inspect(full.sink.pending_count(), content="2")
inspect(full.sink.dropped_count(), content="0")
inspect(full.sink.drain(max_items=1), content="1")
inspect(full.sink.pending_count(), content="1")
inspect(full.sink.flush(), content="1")
inspect(full.sink.pending_count(), content="0")
}
///|