|
20 | 20 | import shutil |
21 | 21 | import tempfile |
22 | 22 | import unittest |
23 | | -from unittest.mock import patch |
| 23 | +from unittest.mock import MagicMock, patch |
24 | 24 |
|
25 | 25 | from clusterfuzz._internal.bot.fuzzers import options |
26 | 26 | from clusterfuzz._internal.bot.fuzzers.centipede import \ |
|
30 | 30 | from clusterfuzz._internal.bot.tasks import commands |
31 | 31 | from clusterfuzz._internal.bot.tasks.utasks import corpus_pruning_task |
32 | 32 | from clusterfuzz._internal.bot.tasks.utasks import uworker_io |
| 33 | +from clusterfuzz._internal.metrics import logs |
33 | 34 | from clusterfuzz._internal.datastore import data_handler |
34 | 35 | from clusterfuzz._internal.datastore import data_types |
35 | 36 | from clusterfuzz._internal.google_cloud_utils import blobs |
@@ -584,3 +585,35 @@ def tearDown(self): |
584 | 585 | shutil.rmtree('a') |
585 | 586 | shutil.rmtree('c') |
586 | 587 | shutil.rmtree(self.temp_dir) |
| 588 | + |
| 589 | + |
| 590 | +class CorpusPruningDedupTest(unittest.TestCase): |
| 591 | + """Tests for corpus pruning error deduplication.""" |
| 592 | + |
| 593 | + def test_minimize_corpus_error_dedup(self): |
| 594 | + """Test that corpus minimization errors are deduplicated.""" |
| 595 | + runner = MagicMock() |
| 596 | + runner.get_fuzzer_flags.return_value = [] |
| 597 | + runner.target_path = '/tmp/target' |
| 598 | + runner.context = MagicMock() |
| 599 | + |
| 600 | + # We need a predictable repr for the error |
| 601 | + err = engine.Error("Variable error content 12345") |
| 602 | + runner.minimize_corpus.side_effect = err |
| 603 | + |
| 604 | + pruner = corpus_pruning_task.CorpusPrunerBase(runner) |
| 605 | + |
| 606 | + with patch('clusterfuzz._internal.system.shell.get_directory_file_count', return_value=1), \ |
| 607 | + patch('clusterfuzz._internal.bot.fuzzers.engine_common.unpack_seed_corpus_if_needed'), \ |
| 608 | + patch('clusterfuzz._internal.system.environment.reset_current_memory_tool_options'), \ |
| 609 | + patch('clusterfuzz._internal.metrics.logs.warning') as mock_log_warning, \ |
| 610 | + patch('clusterfuzz._internal.metrics.logs.info'): |
| 611 | + |
| 612 | + with self.assertRaises(corpus_pruning_task.CorpusPruningError) as cm: |
| 613 | + pruner.run('/tmp/initial', '/tmp/minimized', '/tmp/bad') |
| 614 | + |
| 615 | + # This is the expected behavior AFTER fix. |
| 616 | + self.assertEqual(str(cm.exception), "Corpus pruning failed to minimize corpus") |
| 617 | + |
| 618 | + # Check detailed log |
| 619 | + mock_log_warning.assert_called_with("Corpus pruning failed to minimize corpus\n" + repr(err)) |
0 commit comments