File size: 3,448 Bytes
7e83939 5cb8ae8 7e83939 5cb8ae8 7e83939 5cb8ae8 7e83939 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import datetime
from minecraft_stack import _server_performance
def test_tick_lag_and_movement_are_distinct():
now = datetime.datetime(2026, 9, 27, 16, 30, 0)
lines = [
"[2026-09-27 16:24:00] minecraft> [Server thread/WARN]: Can't keep up! Is the server overloaded? Running 9000ms or 180 ticks behind",
"[2026-09-27 16:27:00] minecraft> [Server thread/WARN]: IffyBinkie6134 moved too quickly!",
"[2026-09-27 16:29:00] minecraft> [Server thread/WARN]: Can't keep up! Is the server overloaded? Running 321ms or 6 ticks behind",
"[2026-09-27 16:29:10] minecraft> [Server thread/WARN]: IffyBinkie6134 moved wrongly!",
]
result = _server_performance(lines, now)
assert result == {
"window_seconds": 300,
"tick_lag_events": 1,
"max_reported_tick_delay_ms": 321,
"movement_warnings": 2,
"movement_warning_samples": [
"[2026-09-27 16:27:00] minecraft> [Server thread/WARN]: IffyBinkie6134 moved too quickly!",
"[2026-09-27 16:29:10] minecraft> [Server thread/WARN]: IffyBinkie6134 moved wrongly!",
],
"last_tick_lag_at": "2026-09-27 16:29:00",
}
assert _server_performance(lines[:1], now)["max_reported_tick_delay_ms"] is None
def test_movement_samples_name_the_entity_behind_the_burst():
# Measured: the counter went 0 -> 107 in under a minute and then stopped. A
# count cannot say whether one entity joining caused it or the whole server is
# degrading, so the entity has to be in the payload.
now = datetime.datetime(2026, 9, 29, 10, 30, 0)
lines = [
f"[2026-09-29 10:29:{second:02d}] minecraft> [Server thread/WARN]: Naldo_Bot moved too quickly! 12.5,0.0,-8.25"
for second in range(0, 40)
]
result = _server_performance(lines, now)
assert result["movement_warnings"] == 40
# The burst carries a distinct timestamp per entry, so the samples must
# collapse on the message: one entity, one problem, one sample.
assert result["movement_warning_samples"] == [
"[2026-09-29 10:29:00] minecraft> [Server thread/WARN]: Naldo_Bot moved too quickly! 12.5,0.0,-8.25"
], "a burst from one entity must not fill the payload with copies"
assert "Naldo_Bot" in result["movement_warning_samples"][0]
def test_movement_samples_are_bounded():
now = datetime.datetime(2026, 9, 29, 10, 30, 0)
lines = [
f"[2026-09-29 10:29:{second:02d}] minecraft> [Server thread/WARN]: Bot{second} moved wrongly!"
for second in range(0, 20)
]
result = _server_performance(lines, now)
assert result["movement_warnings"] == 20
assert len(result["movement_warning_samples"]) == 5, "the payload must stay small"
assert all(len(sample) <= 200 for sample in result["movement_warning_samples"])
def test_samples_are_empty_when_nothing_moved_wrongly():
now = datetime.datetime(2026, 9, 29, 10, 30, 0)
result = _server_performance(
["[2026-09-29 10:29:00] minecraft> [Server thread/INFO]: Done (1.2s)!"], now
)
assert result["movement_warnings"] == 0
assert result["movement_warning_samples"] == []
if __name__ == "__main__":
test_tick_lag_and_movement_are_distinct()
test_movement_samples_name_the_entity_behind_the_burst()
test_movement_samples_are_bounded()
test_samples_are_empty_when_nothing_moved_wrongly()
print("PASS bounded vanilla tick-lag and movement diagnostics")
|