Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added tests/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
import pytest

FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")


@pytest.fixture
def active_log():
return os.path.join(FIXTURES_DIR, "vmstat_active.log")


@pytest.fixture
def standard_log():
return os.path.join(FIXTURES_DIR, "vmstat_standard.log")


@pytest.fixture
def no_header_log():
return os.path.join(FIXTURES_DIR, "vmstat_no_header.log")
7 changes: 7 additions & 0 deletions tests/fixtures/vmstat_active.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free inact active si so bi bo in cs us sy id wa st gu
3 0 0 523 128 1059 0 0 4 1 71 111 0 0 99 0 0 0 2025-08-01 10:06:32
1 0 0 523 128 1059 0 0 0 0 1815 3452 4 1 96 0 0 0 2025-08-01 10:06:33
1 0 0 523 128 1059 0 0 0 16 2530 4711 4 3 93 0 0 0 2025-08-01 10:06:34
1 0 0 523 128 1059 0 0 0 0 2061 3776 4 2 94 0 0 0 2025-08-01 10:06:35
2 0 0 523 128 1059 0 0 0 16 1906 3617 4 1 95 0 0 0 2025-08-01 10:06:36
3 changes: 3 additions & 0 deletions tests/fixtures/vmstat_no_header.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
3 0 0 523 128 1059 0 0 4 1 71 111 0 0 99 0 0 0 2025-08-01 10:06:32
1 0 0 523 128 1059 0 0 0 0 1815 3452 4 1 96 0 0 0 2025-08-01 10:06:33
1 0 0 523 128 1059 0 0 0 16 2530 4711 4 3 93 0 0 0 2025-08-01 10:06:34
7 changes: 7 additions & 0 deletions tests/fixtures/vmstat_standard.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 0 0 523 64 995 0 0 4 1 71 111 0 0 99 0 0 2025-08-01 10:06:32
1 0 0 523 64 995 0 0 0 0 1815 3452 4 1 96 0 0 2025-08-01 10:06:33
1 0 0 523 64 995 0 0 0 16 2530 4711 4 3 93 0 0 2025-08-01 10:06:34
1 0 0 523 64 995 0 0 0 0 2061 3776 4 2 94 0 0 2025-08-01 10:06:35
2 0 0 523 64 995 0 0 0 16 1906 3617 4 1 95 0 0 2025-08-01 10:06:36
110 changes: 110 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""Tests for the vmstat parser."""

import pytest
from vmstat_visualizer.parser.parser import Parser


class TestParserActiveFormat:
"""Tests for vmstat -a output (inact/active columns) with header lines."""

def test_parse_entry_count(self, active_log):
p = Parser(active_log)
p.parse()
assert len(p.timeseries) == 5

def test_first_entry_time(self, active_log):
p = Parser(active_log)
p.parse()
assert p.timeseries[0].time == "2025-08-01 10:06:32"

def test_first_entry_cpu(self, active_log):
p = Parser(active_log)
p.parse()
entry = p.timeseries[0]
assert entry.user_cpu_percent == "0"
assert entry.system_cpu_percent == "0"
assert entry.idle_cpu_percent == "99"

def test_first_entry_memory(self, active_log):
p = Parser(active_log)
p.parse()
entry = p.timeseries[0]
assert entry.free_memory_kb == "523"

def test_last_entry_time(self, active_log):
p = Parser(active_log)
p.parse()
assert p.timeseries[-1].time == "2025-08-01 10:06:36"


class TestParserNoHeader:
"""Tests for log files without header lines (legacy format)."""

def test_parse_entry_count(self, no_header_log):
p = Parser(no_header_log)
p.parse()
assert len(p.timeseries) == 3

def test_first_entry_values(self, no_header_log):
p = Parser(no_header_log)
p.parse()
entry = p.timeseries[0]
assert entry.time == "2025-08-01 10:06:32"
assert entry.run_queue == "3"
assert entry.free_memory_kb == "523"

def test_empty_lines_skipped(self, tmp_path):
log = tmp_path / "empty.log"
log.write_text("\n\n\n")
p = Parser(str(log))
p.parse()
assert len(p.timeseries) == 0

def test_header_only_file(self, tmp_path):
log = tmp_path / "header_only.log"
log.write_text(
"procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----\n"
" r b swpd free inact active si so bi bo in cs us sy id wa st\n"
)
p = Parser(str(log))
p.parse()
assert len(p.timeseries) == 0


class TestPlotMetrics:
"""Tests for the PlotMetrics inner class."""

def test_time_format(self, active_log):
p = Parser(active_log)
p.parse()
pm = p.PlotMetrics(p.timeseries)
assert len(pm.t) == 5
assert pm.t[0] == "06:32"

def test_relative_time(self, active_log):
p = Parser(active_log)
p.parse()
pm = p.PlotMetrics(p.timeseries, relative_time=True)
assert pm.t == [0, 1, 2, 3, 4]

def test_cpu_extraction(self, active_log):
p = Parser(active_log)
p.parse()
pm = p.PlotMetrics(p.timeseries)
assert pm.user_cpu_percent[0] == "0"
assert pm.idle_cpu_percent[0] == "99"
assert len(pm.user_cpu_percent) == 5

def test_memory_extraction(self, active_log):
p = Parser(active_log)
p.parse()
pm = p.PlotMetrics(p.timeseries)
assert pm.free_memory_kb[0] == "523"
assert len(pm.free_memory_kb) == 5

def test_io_extraction(self, active_log):
p = Parser(active_log)
p.parse()
pm = p.PlotMetrics(p.timeseries)
assert pm.blocks_in[0] == "4"
assert pm.blocks_out[0] == "1"
44 changes: 44 additions & 0 deletions tests/test_timeseries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Tests for the Timeseries data model."""

from vmstat_visualizer.parser.timeseries import Timeseries


class TestTimeseriesCommit:
"""Test commit_raw_data with the default (vmstat -a) header list."""

def test_commit_default_headers(self):
ts = Timeseries()
data = ["1", "0", "0", "256", "128", "2048",
"0", "0", "0", "0", "50", "100",
"10", "2", "88", "0", "0", "0", "2025-01-01 12:00:01"]
ts.add_data_point(data)
ts.commit_raw_data()

assert ts.run_queue == "1"
assert ts.free_memory_kb == "256"
assert ts.inactive_memory_kb == "128"
assert ts.active_memory_kb == "2048"
assert ts.user_cpu_percent == "10"
assert ts.idle_cpu_percent == "88"
assert ts.time == "2025-01-01 12:00:01"

def test_add_data_point_stores_raw(self):
ts = Timeseries()
data = ["a", "b", "c"]
ts.add_data_point(data)
assert ts.raw_data == data

def test_repr_contains_key_fields(self):
ts = Timeseries()
ts.time = "2025-01-01 12:00:00"
ts.run_queue = "3"
r = repr(ts)
assert "time=2025-01-01 12:00:00" in r
assert "run_queue=3" in r

def test_initial_values_are_none(self):
ts = Timeseries()
assert ts.time is None
assert ts.run_queue is None
assert ts.user_cpu_percent is None
assert ts.free_memory_kb is None