Files
2026-07-13 13:05:14 +08:00

88 lines
2.8 KiB
Python

"""Tests for the `FileSink` / `save` / `stdout` `write_footer` opt-out."""
from __future__ import annotations
from typing import TYPE_CHECKING
import rerun as rr
if TYPE_CHECKING:
import pathlib
APP_ID = "rerun_example_test_file_sink"
# The trailing RRD `StreamFooter` frame always ends with the bytes `RRF2` followed by
# `FOOT`, located at `file_len - 12 .. file_len - 4`.
# See `re_log_encoding::rrd::frames::StreamFooter` for the definition.
_STREAM_FOOTER_FOURCC = b"RRF2"
_STREAM_FOOTER_IDENTIFIER = b"FOOT"
def _has_stream_footer(path: pathlib.Path) -> bool:
"""Return True if the file at `path` ends with a valid RRD `StreamFooter` trailer."""
data = path.read_bytes()
if len(data) < 12:
return False
return data[-12:-8] == _STREAM_FOOTER_FOURCC and data[-8:-4] == _STREAM_FOOTER_IDENTIFIER
def _log_some(rec: rr.RecordingStream) -> None:
for i in range(10):
rec.log("signal", rr.Scalars(float(i)))
def test_save_default_writes_footer(tmp_path: pathlib.Path) -> None:
"""`RecordingStream.save(path)` defaults to writing a footer."""
rrd = tmp_path / "default.rrd"
rec = rr.RecordingStream(APP_ID)
rec.save(rrd)
_log_some(rec)
rec.disconnect()
assert _has_stream_footer(rrd), "default save() must produce a footer-bearing file"
def test_save_write_footer_false_omits_footer(tmp_path: pathlib.Path) -> None:
"""`RecordingStream.save(path, write_footer=False)` produces a footer-less file."""
rrd = tmp_path / "no_footer.rrd"
rec = rr.RecordingStream(APP_ID)
rec.save(rrd, write_footer=False)
_log_some(rec)
rec.disconnect()
assert not _has_stream_footer(rrd), "save(…, write_footer=False) must produce a footer-less file"
def test_module_save_write_footer_false(tmp_path: pathlib.Path) -> None:
"""The module-level `rr.save(…, write_footer=False)` honours the flag."""
rrd = tmp_path / "module_no_footer.rrd"
rr.init(APP_ID + "_module")
rr.save(rrd, write_footer=False)
for i in range(10):
rr.log("signal", rr.Scalars(float(i)))
rr.disconnect()
assert not _has_stream_footer(rrd)
def test_filesink_class_default_writes_footer(tmp_path: pathlib.Path) -> None:
"""The `rr.FileSink(path)` class defaults to writing a footer (legacy call shape)."""
rrd = tmp_path / "filesink_default.rrd"
rec = rr.RecordingStream(APP_ID)
rec.set_sinks(rr.FileSink(rrd))
_log_some(rec)
rec.disconnect()
assert _has_stream_footer(rrd)
def test_filesink_class_write_footer_false(tmp_path: pathlib.Path) -> None:
"""The `rr.FileSink(path, write_footer=False)` class honours the kw-only flag."""
rrd = tmp_path / "filesink_no_footer.rrd"
rec = rr.RecordingStream(APP_ID)
rec.set_sinks(rr.FileSink(rrd, write_footer=False))
_log_some(rec)
rec.disconnect()
assert not _has_stream_footer(rrd)