The wording fix a commit ago was written by hand in two files and the same mislabel was still sitting in four others -- traits, chain, modifier install and node schema all reported a thing that loaded, recognised its work and then raised as one that "did not load", sending a reader after an import error that never happened. Three hand-written strings would have drifted, so log.broke() now says it once and every site calls it. Two of the new tests were vacuous when first written -- "nothing said did not load" is also true where nothing ran at all, and picking the first provider found lands on one whose traits exclude the test's model. Both assert the line is present before asserting the wrong line is not. One finding, confirmed, plus four sites it did not name.
143 lines
4.5 KiB
Python
143 lines
4.5 KiB
Python
"""The log: a severity, a source, and a message.
|
|
|
|
The format is the contract -- the app will parse it and a person will scan it --
|
|
so it is pinned rather than left to drift line by line.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from core import log, run
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def clean():
|
|
log._reset()
|
|
run._reset()
|
|
yield
|
|
log._reset()
|
|
run._reset()
|
|
|
|
|
|
def test_the_shape_is_label_severity_source_message():
|
|
assert log.line("Warning", "FunPack LoRA Loader", "style.safetensors is empty") == (
|
|
"[Log] Warning: FunPack LoRA Loader | style.safetensors is empty")
|
|
|
|
|
|
def test_a_message_with_no_source_does_not_print_an_empty_one():
|
|
assert log.line("Info", "", "ready") == "[Log] Info: ready"
|
|
|
|
|
|
@pytest.mark.parametrize("fn,level", [
|
|
(log.info, "Info"), (log.alert, "Alert"),
|
|
(log.warning, "Warning"), (log.critical, "Critical"),
|
|
])
|
|
def test_each_level_records_itself(fn, level):
|
|
fn("somewhere", "something")
|
|
entry = log.history()[-1]
|
|
assert entry["level"] == level
|
|
assert entry["source"] == "somewhere"
|
|
assert entry["message"] == "something"
|
|
|
|
|
|
def test_a_record_carries_the_run_it_happened_in():
|
|
"""So a report can say which generation a line belongs to, and two runs in
|
|
one session can be told apart."""
|
|
log.info("before", "no run yet")
|
|
assert log.history()[-1]["run"] is None
|
|
|
|
first = run.start()
|
|
log.info("during", "inside a run")
|
|
assert log.history()[-1]["run"] == first
|
|
|
|
second = run.start()
|
|
log.info("during", "inside the next one")
|
|
assert log.history()[-1]["run"] == second
|
|
assert first != second
|
|
|
|
|
|
def test_history_can_be_filtered_to_one_run():
|
|
first = run.start()
|
|
log.info("a", "one")
|
|
run.start()
|
|
log.info("b", "two")
|
|
assert [r["source"] for r in log.history(run=first)] == ["a"]
|
|
|
|
|
|
def test_starting_a_run_clears_what_was_said_once():
|
|
run.start()
|
|
log.once("k", log.ALERT, "src", "inert")
|
|
run.start()
|
|
log.once("k", log.ALERT, "src", "inert")
|
|
assert len(log.history()) == 2
|
|
|
|
|
|
def test_it_prints_as_well_as_records(capsys):
|
|
log.warning("loader", "a file went missing")
|
|
assert "[Log] Warning: loader | a file went missing" in capsys.readouterr().err
|
|
|
|
|
|
def test_history_can_be_filtered_by_level():
|
|
log.info("a", "one")
|
|
log.warning("b", "two")
|
|
log.info("c", "three")
|
|
assert [r["source"] for r in log.history(log.INFO)] == ["a", "c"]
|
|
|
|
|
|
def test_the_history_is_bounded():
|
|
"""A long rental session must not turn the log into a memory leak."""
|
|
for i in range(log.HISTORY + 50):
|
|
log.info("loop", str(i))
|
|
assert len(log.history()) == log.HISTORY
|
|
assert log.history()[-1]["message"] == str(log.HISTORY + 49)
|
|
|
|
|
|
def test_failed_is_a_warning_because_it_means_a_feature_is_absent():
|
|
log.failed("some.module", ValueError("bad"))
|
|
entry = log.history()[-1]
|
|
assert entry["level"] == log.WARNING
|
|
assert "ValueError" in entry["message"] and "bad" in entry["message"]
|
|
|
|
|
|
def test_broke_says_it_worked_and_then_did_not_which_is_a_different_search():
|
|
"""The distinction, stated where it is defined.
|
|
|
|
"did not load" points a reader at an import; "failed while ..." points at
|
|
the work. Something that loaded, recognised its model and then raised was
|
|
reported as absent in three separate files before anyone noticed, which is
|
|
why this is one function and not three hand-written strings.
|
|
"""
|
|
log.broke("some.module", ValueError("bad"), "building this model's latent")
|
|
entry = log.history()[-1]
|
|
assert entry["level"] == log.WARNING
|
|
assert "did not load" not in entry["message"]
|
|
assert "failed while building this model's latent" in entry["message"]
|
|
assert "ValueError" in entry["message"] and "bad" in entry["message"]
|
|
|
|
|
|
def test_broke_still_says_something_useful_with_no_description():
|
|
log.broke("some.module", ValueError("bad"))
|
|
assert "failed while working" in log.history()[-1]["message"]
|
|
|
|
|
|
# --- once, and what "once" means -------------------------------------------
|
|
|
|
def test_once_says_it_a_single_time():
|
|
for _ in range(10):
|
|
log.once("k", log.ALERT, "src", "inert")
|
|
assert len(log.history()) == 1
|
|
|
|
|
|
def test_once_is_per_run_not_per_process():
|
|
"""v4 deduped for the life of the interpreter, so a session reported the
|
|
first generation that went inert and stayed quiet for every one after."""
|
|
log.once("k", log.ALERT, "src", "inert")
|
|
log.new_run()
|
|
log.once("k", log.ALERT, "src", "inert")
|
|
assert len(log.history()) == 2
|
|
|
|
|
|
def test_different_keys_are_independent():
|
|
log.once("a", log.ALERT, "src", "one")
|
|
log.once("b", log.ALERT, "src", "two")
|
|
assert len(log.history()) == 2
|