|
2 | 2 | Unit tests for the utilities module. |
3 | 3 | """ |
4 | 4 |
|
| 5 | +import json |
5 | 6 | import os |
| 7 | +from unittest.mock import MagicMock, patch |
6 | 8 |
|
7 | 9 | from funannotate2.utilities import ( |
8 | 10 | create_tmpdir, |
9 | 11 | merge_coordinates, |
10 | 12 | naming_slug, |
11 | 13 | readBlocks, |
| 14 | + runSubprocess, |
12 | 15 | ) |
13 | 16 |
|
14 | 17 |
|
@@ -134,3 +137,94 @@ def test_read_blocks_no_pattern(self): |
134 | 137 | blocks = list(readBlocks(source, "#")) |
135 | 138 | assert len(blocks) == 1 |
136 | 139 | assert blocks[0] == ["Line 1", "Line 2", "Line 3"] |
| 140 | + |
| 141 | + |
| 142 | +class TestRunSubprocess: |
| 143 | + """Regression tests for subprocess logging behavior.""" |
| 144 | + |
| 145 | + @patch("funannotate2.utilities.subprocess.Popen") |
| 146 | + @patch("funannotate2.memory.MemoryMonitor") |
| 147 | + def test_monitoring_keeps_memory_report_out_of_callable_logs( |
| 148 | + self, mock_monitor_cls, mock_popen, tmp_path, monkeypatch |
| 149 | + ): |
| 150 | + """Memory monitoring should not emit formatted reports via callable logs.""" |
| 151 | + process = MagicMock() |
| 152 | + process.pid = 12345 |
| 153 | + process.returncode = 0 |
| 154 | + process.stdout = "" |
| 155 | + process.stderr = "" |
| 156 | + mock_popen.return_value = process |
| 157 | + |
| 158 | + mock_monitor = mock_monitor_cls.return_value |
| 159 | + mock_monitor.monitor_process.return_value = { |
| 160 | + "process_name": "snap-scaffold_1.fasta", |
| 161 | + "duration_seconds": 1.5, |
| 162 | + "peak_rss_mb": 10.0, |
| 163 | + "peak_vms_mb": 20.0, |
| 164 | + "avg_rss_mb": 9.0, |
| 165 | + "avg_vms_mb": 19.0, |
| 166 | + "sample_count": 2, |
| 167 | + "samples": [], |
| 168 | + } |
| 169 | + |
| 170 | + messages = [] |
| 171 | + monkeypatch.setenv("FUNANNOTATE2_OUTPUT_DIR", str(tmp_path)) |
| 172 | + |
| 173 | + runSubprocess( |
| 174 | + ["snap", "input.fasta"], |
| 175 | + messages.append, |
| 176 | + cwd=str(tmp_path), |
| 177 | + monitor_memory=True, |
| 178 | + process_name="snap-scaffold_1.fasta", |
| 179 | + ) |
| 180 | + |
| 181 | + assert messages == [] |
| 182 | + |
| 183 | + memory_log = tmp_path / "logfiles" / "predict-abinitio-memory-monitoring.jsonl" |
| 184 | + assert memory_log.exists() |
| 185 | + |
| 186 | + records = [json.loads(line) for line in memory_log.read_text().splitlines()] |
| 187 | + assert len(records) == 1 |
| 188 | + assert records[0]["process_name"] == "snap-scaffold_1.fasta" |
| 189 | + assert records[0]["tool_name"] == "snap" |
| 190 | + assert records[0]["memory_stats"]["peak_rss_mb"] == 10.0 |
| 191 | + |
| 192 | + @patch("funannotate2.utilities.subprocess.Popen") |
| 193 | + @patch("funannotate2.memory.MemoryMonitor") |
| 194 | + def test_monitoring_does_not_debug_log_formatted_memory_report( |
| 195 | + self, mock_monitor_cls, mock_popen, tmp_path, monkeypatch |
| 196 | + ): |
| 197 | + """Detailed memory reports should stay out of the normal logfile path.""" |
| 198 | + process = MagicMock() |
| 199 | + process.pid = 12345 |
| 200 | + process.returncode = 0 |
| 201 | + process.stdout = "" |
| 202 | + process.stderr = "" |
| 203 | + mock_popen.return_value = process |
| 204 | + |
| 205 | + mock_monitor = mock_monitor_cls.return_value |
| 206 | + mock_monitor.monitor_process.return_value = { |
| 207 | + "process_name": "snap-scaffold_1.fasta", |
| 208 | + "duration_seconds": 1.5, |
| 209 | + "peak_rss_mb": 10.0, |
| 210 | + "peak_vms_mb": 20.0, |
| 211 | + "avg_rss_mb": 9.0, |
| 212 | + "avg_vms_mb": 19.0, |
| 213 | + "sample_count": 2, |
| 214 | + "samples": [], |
| 215 | + } |
| 216 | + |
| 217 | + logger = MagicMock() |
| 218 | + monkeypatch.setenv("FUNANNOTATE2_OUTPUT_DIR", str(tmp_path)) |
| 219 | + |
| 220 | + runSubprocess( |
| 221 | + ["snap", "input.fasta"], |
| 222 | + logger, |
| 223 | + cwd=str(tmp_path), |
| 224 | + monitor_memory=True, |
| 225 | + process_name="snap-scaffold_1.fasta", |
| 226 | + ) |
| 227 | + |
| 228 | + debug_messages = [call.args[0] for call in logger.debug.call_args_list] |
| 229 | + assert "snap input.fasta" in debug_messages |
| 230 | + assert not any("Memory usage for" in message for message in debug_messages) |
0 commit comments