Zum Inhalt

tests/test_gui_cpu_sample.py

# tests/test_gui_cpu_sample.py
import touchstone.sampler as sampler_mod
from touchstone.merge import load_samples_jsonl
from touchstone.models import ResourceSample
from touchstone.sampler import HostSampler


def test_resource_sample_has_cpu_pct_defaulting_none():
    s = ResourceSample(
        ts=1.0,
        sys_used_mb=1.0,
        sys_available_mb=1.0,
        swap_used_mb=0.0,
        server_rss_mb=None,
        mem_pressure_level="normal",
        throttled=False,
    )
    assert s.cpu_pct is None  # last field, defaulted → old code constructs unchanged


def test_old_resources_jsonl_loads_without_cpu(tmp_path):
    p = tmp_path / "resources.jsonl"
    p.write_text(
        '{"ts":1.0,"sys_used_mb":1.0,"sys_available_mb":1.0,"swap_used_mb":0.0,'
        '"server_rss_mb":null,"mem_pressure_level":"normal","throttled":false}\n',
        encoding="utf-8",
    )
    samples = load_samples_jsonl(p)
    assert samples[0].cpu_pct is None  # missing key → default


def test_load_samples_jsonl_tolerates_half_line(tmp_path):
    """MAJOR 4: a truncated final line (crashed/resumed bundle) is skipped, not fatal."""
    p = tmp_path / "resources.jsonl"
    good = (
        '{"ts":1.0,"sys_used_mb":1.0,"sys_available_mb":1.0,"swap_used_mb":0.0,'
        '"server_rss_mb":null,"mem_pressure_level":"normal","throttled":false,"cpu_pct":42.0}'
    )
    p.write_text(good + "\n" + '{"ts":2.0,"sys_used_mb":', encoding="utf-8")
    samples = load_samples_jsonl(p)
    assert len(samples) == 1
    assert samples[0].cpu_pct == 42.0


def test_host_sampler_cpu_pct_primed_and_sampled(monkeypatch):
    """MAJOR 5: start() consumes the prime cpu_percent call; sample_once reports the real %.

    Injects a cpu_percent stub returning [0.0 (prime, discarded), 42.0]; makes the rest of
    sample_once hermetic so the asserted value is solely the sampler's cpu handling.
    """
    cpu_values = iter([0.0, 42.0])
    primed: list[bool] = []

    def fake_cpu_percent(interval=None):
        v = next(cpu_values)
        if not primed:  # first ever call is the prime in start()
            primed.append(True)
        return v

    class _VM:
        used = 0
        available = 0

    class _SW:
        used = 0

    monkeypatch.setattr(sampler_mod.psutil, "cpu_percent", fake_cpu_percent)
    monkeypatch.setattr(sampler_mod.psutil, "virtual_memory", lambda: _VM())
    monkeypatch.setattr(sampler_mod.psutil, "swap_memory", lambda: _SW())
    monkeypatch.setattr(sampler_mod, "server_rss_mb", lambda match: None)

    s = HostSampler(powermetrics=False)
    s.start()
    assert primed == [True]  # the prime call happened in start()
    sample = s.sample_once()
    assert sample.cpu_pct == 42.0  # the prime 0.0 was discarded