import json
import pytest
import denet
from tests.python.test_helpers import create_sample_metrics
class TestSummaryFromMetricsJson:
def test_basic_summary_generation(self):
metrics = create_sample_metrics(3)
metrics_json = [json.dumps(metric) for metric in metrics]
elapsed_time = (metrics[-1]["ts_ms"] - metrics[0]["ts_ms"]) / 1000.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert isinstance(summary, dict)
expected_fields = [
"total_time_secs",
"sample_count",
"max_processes",
"max_threads",
"total_disk_read_bytes",
"total_disk_write_bytes",
"total_sys_net_rx_bytes",
"total_sys_net_tx_bytes",
"peak_mem_rss_kb",
"avg_cpu_usage",
]
for field in expected_fields:
assert field in summary, f"Missing field: {field}"
assert summary["sample_count"] == 3
assert summary["total_time_secs"] == elapsed_time
assert summary["max_processes"] >= 1
assert summary["avg_cpu_usage"] > 0
def test_single_metric_summary(self):
metric = create_sample_metrics(1)[0]
metrics_json = [json.dumps(metric)]
elapsed_time = 0.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["sample_count"] == 1
assert summary["total_time_secs"] == elapsed_time
def test_empty_metrics_summary(self):
summary_json = denet.generate_summary_from_metrics_json([], 0.0)
summary = json.loads(summary_json)
assert summary["sample_count"] == 0
assert summary["total_time_secs"] == 0.0
def test_tree_metrics_summary(self):
tree_metric = {
"ts_ms": 1000,
"parent": {
"ts_ms": 1000,
"cpu_usage": 10.0,
"mem_rss_kb": 5000,
"mem_vms_kb": 10000,
"disk_read_bytes": 1024,
"disk_write_bytes": 2048,
"net_rx_bytes": 512,
"net_tx_bytes": 256,
"thread_count": 2,
"uptime_secs": 10,
},
"children": [],
"aggregated": {
"ts_ms": 1000,
"cpu_usage": 15.0,
"mem_rss_kb": 8000,
"mem_vms_kb": 16000,
"disk_read_bytes": 2048,
"disk_write_bytes": 4096,
"net_rx_bytes": 1024,
"net_tx_bytes": 512,
"thread_count": 3,
"process_count": 2,
"uptime_secs": 10,
},
}
metrics_json = [json.dumps(tree_metric)]
elapsed_time = 1.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["sample_count"] == 1
assert summary["avg_cpu_usage"] == 15.0 assert summary["peak_mem_rss_kb"] == 8000
def test_mixed_regular_and_tree_metrics(self):
regular_metric = create_sample_metrics(1)[0]
tree_metric = {
"ts_ms": 2000,
"aggregated": {
"ts_ms": 2000,
"cpu_usage": 25.0,
"mem_rss_kb": 10000,
"mem_vms_kb": 20000,
"disk_read_bytes": 4096,
"disk_write_bytes": 8192,
"net_rx_bytes": 2048,
"net_tx_bytes": 1024,
"thread_count": 4,
"process_count": 3,
"uptime_secs": 20,
},
}
metrics_json = [json.dumps(regular_metric), json.dumps(tree_metric)]
elapsed_time = (tree_metric["ts_ms"] - regular_metric["ts_ms"]) / 1000.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["sample_count"] >= 1
assert summary["peak_mem_rss_kb"] == 10000
def test_invalid_json_handling(self):
valid_metric = json.dumps(create_sample_metrics(1)[0])
invalid_json = "invalid json string"
summary_json = denet.generate_summary_from_metrics_json([valid_metric, invalid_json], 1.0)
summary = json.loads(summary_json)
assert summary["sample_count"] >= 0
class TestSummaryFromFile:
def test_basic_file_summary(self, tmp_path):
metrics = create_sample_metrics(3)
temp_file = tmp_path / "test_metrics.jsonl"
with open(temp_file, "w") as f:
for metric in metrics:
f.write(json.dumps(metric) + "\n")
summary_json = denet.generate_summary_from_file(str(temp_file))
summary = json.loads(summary_json)
assert summary["sample_count"] == 3
assert summary["avg_cpu_usage"] > 0
assert summary["peak_mem_rss_kb"] > 0
def test_empty_file_summary(self, tmp_path):
temp_file = tmp_path / "empty_metrics.jsonl"
temp_file.touch()
with pytest.raises(OSError):
denet.generate_summary_from_file(str(temp_file))
def test_file_with_mixed_content(self, tmp_path):
metrics = create_sample_metrics(2)
temp_file = tmp_path / "mixed_content.jsonl"
with open(temp_file, "w") as f:
f.write(json.dumps(metrics[0]) + "\n")
metadata = {"pid": 12345, "cmd": ["test"], "executable": "/usr/bin/test", "t0_ms": 1000}
f.write(json.dumps(metadata) + "\n")
f.write(json.dumps(metrics[1]) + "\n")
f.write("invalid json line\n")
summary_json = denet.generate_summary_from_file(str(temp_file))
summary = json.loads(summary_json)
assert summary["sample_count"] == 2
def test_nonexistent_file(self):
with pytest.raises((FileNotFoundError, OSError)):
denet.generate_summary_from_file("/nonexistent/path/file.jsonl")
class TestSummaryDataIntegrity:
def test_cpu_usage_calculation(self):
metrics = [
{
"ts_ms": 1000,
"cpu_usage": 10.0,
"mem_rss_kb": 5000,
"mem_vms_kb": 10000,
"disk_read_bytes": 1024,
"disk_write_bytes": 2048,
"net_rx_bytes": 512,
"net_tx_bytes": 256,
"thread_count": 2,
"uptime_secs": 10,
},
{
"ts_ms": 2000,
"cpu_usage": 20.0,
"mem_rss_kb": 6000,
"mem_vms_kb": 12000,
"disk_read_bytes": 2048,
"disk_write_bytes": 4096,
"net_rx_bytes": 1024,
"net_tx_bytes": 512,
"thread_count": 3,
"uptime_secs": 20,
},
]
metrics_json = [json.dumps(metric) for metric in metrics]
elapsed_time = 1.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["avg_cpu_usage"] == 15.0
def test_memory_peak_calculation(self):
metrics = [
{
"ts_ms": 1000,
"cpu_usage": 10.0,
"mem_rss_kb": 5000,
"mem_vms_kb": 10000,
"disk_read_bytes": 1024,
"disk_write_bytes": 2048,
"net_rx_bytes": 512,
"net_tx_bytes": 256,
"thread_count": 2,
"uptime_secs": 10,
},
{
"ts_ms": 2000,
"cpu_usage": 20.0,
"mem_rss_kb": 8000, "mem_vms_kb": 16000,
"disk_read_bytes": 2048,
"disk_write_bytes": 4096,
"net_rx_bytes": 1024,
"net_tx_bytes": 512,
"thread_count": 3,
"uptime_secs": 20,
},
{
"ts_ms": 3000,
"cpu_usage": 15.0,
"mem_rss_kb": 6000,
"mem_vms_kb": 12000,
"disk_read_bytes": 3072,
"disk_write_bytes": 6144,
"net_rx_bytes": 1536,
"net_tx_bytes": 768,
"thread_count": 2,
"uptime_secs": 30,
},
]
metrics_json = [json.dumps(metric) for metric in metrics]
elapsed_time = 2.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["peak_mem_rss_kb"] == 8000
def test_time_calculation(self):
metrics = [
{
"ts_ms": 1000,
"cpu_usage": 10.0,
"mem_rss_kb": 5000,
"mem_vms_kb": 10000,
"disk_read_bytes": 1024,
"disk_write_bytes": 2048,
"net_rx_bytes": 512,
"net_tx_bytes": 256,
"thread_count": 2,
"uptime_secs": 10,
},
{
"ts_ms": 3500,
"cpu_usage": 20.0,
"mem_rss_kb": 6000,
"mem_vms_kb": 12000,
"disk_read_bytes": 2048,
"disk_write_bytes": 4096,
"net_rx_bytes": 1024,
"net_tx_bytes": 512,
"thread_count": 3,
"uptime_secs": 25,
},
]
metrics_json = [json.dumps(metric) for metric in metrics]
elapsed_time = 2.5
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["total_time_secs"] == elapsed_time
def test_cumulative_values(self):
metrics = [
{
"ts_ms": 1000,
"cpu_usage": 10.0,
"mem_rss_kb": 5000,
"mem_vms_kb": 10000,
"disk_read_bytes": 1024,
"disk_write_bytes": 2048,
"net_rx_bytes": 512,
"net_tx_bytes": 256,
"thread_count": 2,
"uptime_secs": 10,
},
{
"ts_ms": 2000,
"cpu_usage": 20.0,
"mem_rss_kb": 6000,
"mem_vms_kb": 12000,
"disk_read_bytes": 4096, "disk_write_bytes": 8192,
"net_rx_bytes": 2048,
"net_tx_bytes": 1024,
"thread_count": 3,
"uptime_secs": 20,
},
]
metrics_json = [json.dumps(metric) for metric in metrics]
elapsed_time = 1.0
summary_json = denet.generate_summary_from_metrics_json(metrics_json, elapsed_time)
summary = json.loads(summary_json)
assert summary["total_disk_read_bytes"] == 4096
assert summary["total_disk_write_bytes"] == 8192
assert summary["total_sys_net_rx_bytes"] == 2048
assert summary["total_sys_net_tx_bytes"] == 1024