|
4 | 4 | import shutil |
5 | 5 | import tempfile |
6 | 6 | import unittest |
| 7 | +from unittest import mock |
7 | 8 | from collections import namedtuple |
8 | 9 | from pathlib import Path |
9 | 10 |
|
@@ -615,13 +616,43 @@ def test_export_file_html_has_line_numbers(self): |
615 | 616 | html_files = [f for f in os.listdir(output_path) |
616 | 617 | if f.startswith('file_') and f.endswith('.html')] |
617 | 618 |
|
618 | | - if html_files: |
619 | | - with open(os.path.join(output_path, html_files[0]), 'r', encoding='utf-8') as f: |
620 | | - content = f.read() |
| 619 | + self.assertEqual(len(html_files), 1) |
| 620 | + with open(os.path.join(output_path, html_files[0]), 'r', encoding='utf-8') as f: |
| 621 | + content = f.read() |
| 622 | + |
| 623 | + # Should have line-related content |
| 624 | + self.assertIn('line-', content) |
| 625 | + |
| 626 | + def test_export_skips_nonexistent_source(self): |
| 627 | + self.check_unavailable_source(os.path.join(self.test_dir, 'missing.py')) |
621 | 628 |
|
622 | | - # Should have line-related content |
623 | | - self.assertIn('line-', content) |
| 629 | + def test_export_skips_directory_source(self): |
| 630 | + self.check_unavailable_source(self.test_dir) |
624 | 631 |
|
| 632 | + @unittest.skipUnless(hasattr(os, 'mkfifo'), 'requires os.mkfifo') |
| 633 | + def test_export_skips_fifo_source(self): |
| 634 | + filename = os.path.join(self.test_dir, 'source.fifo') |
| 635 | + os.mkfifo(filename) |
| 636 | + self.check_unavailable_source(filename) |
| 637 | + |
| 638 | + def check_unavailable_source(self, filename): |
| 639 | + collector = HeatmapCollector(sample_interval_usec=100) |
| 640 | + frames = [(filename, (1, 1, -1, -1), 'f', None)] |
| 641 | + collector.process_frames(frames, thread_id=1) |
| 642 | + output_path = Path(self.test_dir) / 'unavailable_source' |
| 643 | + read_text = Path.read_text |
| 644 | + |
| 645 | + def check_read(path, *args, **kwargs): |
| 646 | + self.assertNotEqual(path, Path(filename), |
| 647 | + 'Non-regular source must not be opened') |
| 648 | + return read_text(path, *args, **kwargs) |
| 649 | + |
| 650 | + with (captured_stdout(), captured_stderr(), |
| 651 | + mock.patch.object(Path, 'read_text', check_read)): |
| 652 | + collector.export(output_path) |
| 653 | + content = (output_path / collector.file_index[filename]).read_text( |
| 654 | + encoding='utf-8') |
| 655 | + self.assertIn('Source file not available', content) |
625 | 656 |
|
626 | 657 | class MockFrameInfo: |
627 | 658 | """Mock FrameInfo for testing. |
|
0 commit comments