"""Cross-day interval unattributed-byte preservation (issue #88). Verifies that a cross-hour interval spanning midnight is stored ONCE as shared boundary evidence, not duplicated into both days. Seam: derive._add_unattributed_bytes() → day_aggregates.unattributed_bytes_* """ import sqlite3 from datetime import datetime, timedelta, timezone from pathlib import Path import pytest import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from fenris.collector import run_collection from fenris.store import init_store from fenris.monitoring_periods import ensure_period_open def _make_smartctl(duw: int, dur: int): return { "json_format_version": [1, 0], "smartctl": {"version": [7, 3], "svn_revision": "5155", "build_info": "(local build)"}, "nvme_smart_health_information_log": { "critical_warning": 0, "temperature": 35, "available_spare": 100, "available_spare_threshold": 10, "percentage_used": 5, "data_units_written": duw, "data_units_read": dur, "power_on_hours": 8765, "power_cycles": 1234, "unsafe_shutdowns": 5, "media_errors": 0, "num_err_log_entries": 0, }, "user_capacity": {"bytes": 1024000000000, "units": "bytes"}, "model_name": "Samsung SSD 970 EVO Plus 1TB", "serial_number": "S4EWNX0N123456", "firmware_version": "2B2QEXM7", } @pytest.fixture def sysfs_tree(tmp_path: Path) -> Path: ctrl_dir = tmp_path / "sys" / "class" / "nvme" / "nvme0" ctrl_dir.mkdir(parents=True) (ctrl_dir / "subsysnqn").write_text( "nqn.2014-08.org.nvmexpress:uuid:12345678-1234-1234-1234-123456789abc\n" ) (ctrl_dir / "model").write_text("Samsung SSD 970 EVO Plus 1TB\n") (ctrl_dir / "serial").write_text("S4EWNX0N123456\n") (ctrl_dir / "firmware_rev").write_text("2B2QEXM7\n") transport_dir = ctrl_dir / "transport" transport_dir.mkdir() (transport_dir / "address").write_text("0000:03:00.0") (transport_dir / "trstring").write_text("pcie") return tmp_path class _Clock: def __init__(self, initial): self.now = initial def utcnow(self): return self.now class TestCrossDayUnattributedNoDuplication: """Unattributed bytes from a midnight-spanning interval must be stored once, not duplicated into both days (issue #88).""" def test_midnight_spanning_interval_not_duplicated( self, tmp_path, sysfs_tree, ): """Two samples spanning midnight: 23:55 UTC day1 → 00:05 UTC day2. The unattributed bytes should appear once, not in both days. """ store = str(tmp_path / "obs.db") cfg = {"device": "/dev/nvme0", "store_path": store} sysfs_nvme = sysfs_tree / "sys" / "class" / "nvme" / "nvme0" t1 = datetime(2026, 9, 1, 23, 55, 0, tzinfo=timezone.utc) t2 = datetime(2026, 9, 2, 0, 5, 0, tzinfo=timezone.utc) # +100 DUW, +60 DUR across midnight r1 = run_collection(_make_smartctl(10000000, 8000000), sysfs_nvme, cfg, _Clock(t1)) assert r1["ok"] r2 = run_collection(_make_smartctl(10000100, 8000060), sysfs_nvme, cfg, _Clock(t2)) assert r2["ok"] conn = sqlite3.connect(store) # Get unattributed bytes for each day unattr_w_day1 = conn.execute( "SELECT unattributed_bytes_written FROM day_aggregates WHERE day = ?", ("2026-09-01",) ).fetchone() unattr_w_day2 = conn.execute( "SELECT unattributed_bytes_written FROM day_aggregates WHERE day = ?", ("2026-09-02",) ).fetchone() unattr_r_day1 = conn.execute( "SELECT unattributed_bytes_read FROM day_aggregates WHERE day = ?", ("2026-09-01",) ).fetchone() unattr_r_day2 = conn.execute( "SELECT unattributed_bytes_read FROM day_aggregates WHERE day = ?", ("2026-09-02",) ).fetchone() expected_bw = 100 * 512000 # 51200000 expected_br = 60 * 512000 # 30720000 # BUG: Current code adds the SAME bytes to BOTH days. # After fix: only ONE day should have the unattributed bytes. # The spec says: preserve once as shared boundary evidence. # At least one day must have the unattributed bytes total_unattr_w = (unattr_w_day1[0] if unattr_w_day1 else 0) + (unattr_w_day2[0] if unattr_w_day2 else 0) total_unattr_r = (unattr_r_day1[0] if unattr_r_day1 else 0) + (unattr_r_day2[0] if unattr_r_day2 else 0) # The total unattributed bytes across both days must equal # the actual delta (not double) assert total_unattr_w == expected_bw, ( f"Unattributed writes across both days should be {expected_bw}, " f"got {total_unattr_w} (duplication detected)" ) assert total_unattr_r == expected_br, ( f"Unattributed reads across both days should be {expected_br}, " f"got {total_unattr_r} (duplication detected)" ) # Neither day should have MORE than the actual delta for day_label, uw, ur in [ ("day1", unattr_w_day1, unattr_r_day1), ("day2", unattr_w_day2, unattr_r_day2), ]: if uw is not None: assert uw[0] <= expected_bw, ( f"{day_label} unattributed writes {uw[0]} exceeds delta {expected_bw}" ) if ur is not None: assert ur[0] <= expected_br, ( f"{day_label} unattributed reads {ur[0]} exceeds delta {expected_br}" ) conn.close()