|
1 | | -# test_performance_logger.py |
2 | | -import unittest |
| 1 | +import time |
| 2 | +import tempfile |
3 | 3 | import os |
| 4 | +import pytest |
4 | 5 | import pandas as pd |
5 | | -from UTILS.perfmonitor.performance_logger import PerformanceLogger, default_plot_config, default_summary_config |
6 | | - |
7 | | -class TestPerformanceLogger(unittest.TestCase): |
8 | | - def setUp(self): |
9 | | - self.log_path = "test_log.txt" |
10 | | - self.logger = PerformanceLogger(self.log_path) |
11 | | - # Ensure the log file is empty before each test |
12 | | - if os.path.exists(self.log_path): |
13 | | - os.remove(self.log_path) |
14 | | - |
15 | | - def tearDown(self): |
16 | | - # Clean up the log file after each test |
17 | | - if os.path.exists(self.log_path): |
18 | | - os.remove(self.log_path) |
19 | | - |
20 | | - def test_log(self): |
21 | | - self.logger.log("TestStep") |
22 | | - self.assertTrue(os.path.exists(self.log_path)) |
23 | | - with open(self.log_path, "r") as f: |
24 | | - lines = f.readlines() |
25 | | - self.assertEqual(len(lines), 1) |
26 | | - self.assertIn("TestStep", lines[0]) |
27 | | - |
28 | | - def test_log_to_dataframe(self): |
29 | | - self.logger.log("TestStep") |
30 | | - df = PerformanceLogger.log_to_dataframe(self.log_path) |
31 | | - self.assertEqual(len(df), 1) |
32 | | - self.assertEqual(df.iloc[0]["step"], "TestStep") |
33 | | - |
34 | | - def test_summarize_with_config(self): |
35 | | - self.logger.log("Step1") |
36 | | - self.logger.log("Step2") |
37 | | - df = PerformanceLogger.log_to_dataframe(self.log_path) |
38 | | - summary = PerformanceLogger.summarize_with_config(df, default_summary_config["summary_by_step"]) |
39 | | - self.assertIn("elapsed_sec", summary.columns) |
40 | | - self.assertIn("rss_gb", summary.columns) |
41 | | - |
42 | | - def test_plot(self): |
43 | | - self.logger.log("Step1") |
44 | | - self.logger.log("Step2") |
45 | | - df = PerformanceLogger.log_to_dataframe(self.log_path) |
46 | | - try: |
47 | | - PerformanceLogger.plot(df, default_plot_config) |
48 | | - except Exception as e: |
49 | | - self.fail(f"Plotting failed with exception: {e}") |
50 | | - |
51 | | -if __name__ == "__main__": |
52 | | - unittest.main() |
| 6 | +from perfmonitor.performance_logger import ( |
| 7 | + PerformanceLogger, |
| 8 | + default_summary_config, |
| 9 | + default_plot_config, |
| 10 | +) |
53 | 11 |
|
| 12 | +def test_basic_logging_and_parsing(): |
| 13 | + with tempfile.NamedTemporaryFile(delete=False, mode='w+', suffix=".txt") as tmp: |
| 14 | + log_path = tmp.name |
| 15 | + |
| 16 | + logger = PerformanceLogger(log_path) |
| 17 | + logger.log("start") |
| 18 | + time.sleep(0.1) |
| 19 | + logger.log("step::loop", index=[0]) |
| 20 | + time.sleep(0.1) |
| 21 | + logger.log("step::loop", index=[1, 2]) |
| 22 | + |
| 23 | + df = PerformanceLogger.log_to_dataframe([log_path]) |
| 24 | + assert not df.empty |
| 25 | + assert "step" in df.columns |
| 26 | + assert "elapsed_sec" in df.columns |
| 27 | + assert "rss_gb" in df.columns |
| 28 | + assert df["step"].str.contains("step::loop").any() |
| 29 | + assert "index_1" in df.columns # tests index parsing |
| 30 | + |
| 31 | + os.remove(log_path) |
| 32 | + |
| 33 | + |
| 34 | +def test_missing_log_file_handling(): |
| 35 | + df = PerformanceLogger.log_to_dataframe(["nonexistent_file.txt"]) |
| 36 | + assert isinstance(df, pd.DataFrame) |
| 37 | + assert df.empty |
| 38 | + |
| 39 | + |
| 40 | +def test_plot_and_summary(tmp_path): |
| 41 | + log_path = tmp_path / "log.txt" |
| 42 | + logger = PerformanceLogger(log_path) |
| 43 | + logger.log("init") |
| 44 | + time.sleep(0.05) |
| 45 | + for i in range(3): |
| 46 | + logger.log("step::loop", index=[i]) |
| 47 | + time.sleep(0.01) |
| 48 | + |
| 49 | + df = PerformanceLogger.log_to_dataframe([str(log_path)]) |
| 50 | + |
| 51 | + summary = PerformanceLogger.summarize_with_config(df, default_summary_config) |
| 52 | + assert isinstance(summary, dict) |
| 53 | + assert "summary_by_step" in summary |
| 54 | + |
| 55 | + # Test plotting (non-crashing) |
| 56 | + PerformanceLogger.plot(df, default_plot_config) |
| 57 | + |
| 58 | + |
| 59 | +def test_multiple_files(): |
| 60 | + paths = [] |
| 61 | + for i in range(2): |
| 62 | + with tempfile.NamedTemporaryFile(delete=False, suffix=".txt") as tmp: |
| 63 | + path = tmp.name |
| 64 | + logger = PerformanceLogger(path) |
| 65 | + logger.log(f"file{i}::start") |
| 66 | + paths.append(path) |
| 67 | + |
| 68 | + df = PerformanceLogger.log_to_dataframe(paths) |
| 69 | + assert len(df) == 2 |
| 70 | + assert "logfile" in df.columns |
| 71 | + for path in paths: |
| 72 | + os.remove(path) |
| 73 | + |
| 74 | + |
| 75 | +def test_custom_summary(): |
| 76 | + with tempfile.NamedTemporaryFile(delete=False) as tmp: |
| 77 | + log_path = tmp.name |
| 78 | + |
| 79 | + logger = PerformanceLogger(log_path) |
| 80 | + for i in range(3): |
| 81 | + logger.log("step::measure", index=[i]) |
| 82 | + time.sleep(0.01) |
| 83 | + |
| 84 | + df = PerformanceLogger.log_to_dataframe([log_path]) |
| 85 | + config = { |
| 86 | + "by_index": { |
| 87 | + "by": ["index_0"], |
| 88 | + "stats": ["mean", "count"] |
| 89 | + } |
| 90 | + } |
| 91 | + summary = PerformanceLogger.summarize_with_config(df, config) |
| 92 | + assert "by_index" in summary |
| 93 | + os.remove(log_path) |
0 commit comments