2525from clusterfuzz ._internal .bot .fuzzers import options
2626from clusterfuzz ._internal .bot .fuzzers .libFuzzer import \
2727 engine as libFuzzer_engine
28+ from clusterfuzz ._internal .bot .fuzzers .centipede import engine as centipede_engine
2829from clusterfuzz ._internal .bot .tasks import commands
2930from clusterfuzz ._internal .bot .tasks .utasks import corpus_pruning_task
3031from clusterfuzz ._internal .bot .tasks .utasks import uworker_io
@@ -384,132 +385,49 @@ def test_prune(self):
384385 self .assertCountEqual (['crash-7a8dc3985d2a90fb6e62e94910fc11d31949c348' ],
385386 quarantine )
386387
387-
388- class CorpusPruningTestUntrusted (
389- untrusted_runner_helpers . UntrustedRunnerIntegrationTest ):
390- """Tests for corpus pruning (untrusted) ."""
388+ @ test_utils . supported_platforms ( 'LINUX' )
389+ @ test_utils . with_cloud_emulators ( 'datastore' )
390+ class CorpusPruningTestCentipede ( unittest . TestCase , BaseTest ):
391+ """Tests for centipede corpus pruning."""
391392
392393 def setUp (self ):
393394 """Set up."""
394- super ().setUp ()
395- environment .set_value ('JOB_NAME' , 'libfuzzer_asan_job' )
396-
395+ BaseTest .setUp (self )
397396 helpers .patch (self , [
398- 'clusterfuzz._internal.bot.tasks.setup.get_fuzzer_directory' ,
399- 'clusterfuzz._internal.base.tasks.add_task' ,
400- 'clusterfuzz.fuzz.engine.get' ,
397+ 'clusterfuzz._internal.build_management.build_manager.setup_build' ,
398+ 'clusterfuzz._internal.base.utils.get_application_id' ,
399+ 'clusterfuzz._internal.datastore.data_handler.update_task_status' ,
400+ 'clusterfuzz._internal.datastore.data_handler.get_task_status' ,
401401 ])
402- self .mock .get .return_value = libFuzzer_engine .Engine ()
403- self .mock .get_fuzzer_directory .return_value = os .path .join (
404- environment .get_value ('ROOT_DIR' ), 'src' , 'clusterfuzz' , '_internal' ,
405- 'bot' , 'fuzzers' , 'libFuzzer' )
406- self .corpus_bucket = os .environ ['CORPUS_BUCKET' ]
407- self .quarantine_bucket = os .environ ['QUARANTINE_BUCKET' ]
408- self .backup_bucket = os .environ ['BACKUP_BUCKET' ]
409-
410- job = data_types .Job (
411- name = 'libfuzzer_asan_job' ,
412- environment_string = ('APP_NAME = test_fuzzer\n '
413- f'CORPUS_BUCKET = { self .corpus_bucket } \n '
414- f'QUARANTINE_BUCKET = { self .quarantine_bucket } \n '
415- f'BACKUP_BUCKET={ self .backup_bucket } \n '
416- 'RELEASE_BUILD_BUCKET_PATH = '
417- 'gs://clusterfuzz-test-data/test_libfuzzer_builds2/'
418- 'test-libfuzzer-build-([0-9]+).zip\n '
419- 'REVISION_VARS_URL = gs://clusterfuzz-test-data/'
420- 'test_libfuzzer_builds2/'
421- 'test-libfuzzer-build-%s.srcmap.json\n ' ))
422- job .put ()
423-
424- job = data_types .Job (
425- name = 'libfuzzer_asan_job2' ,
426- environment_string = ('APP_NAME = test2_fuzzer\n '
427- f'BACKUP_BUCKET = { self .backup_bucket } \n '
428- 'CORPUS_FUZZER_NAME_OVERRIDE = libfuzzer\n ' ))
429- job .put ()
430-
431- os .environ ['PROJECT_NAME' ] = 'oss-fuzz'
432- data_types .FuzzTarget (
433- engine = 'libFuzzer' , project = 'test' , binary = 'test_fuzzer' ).put ()
434- data_types .FuzzTargetJob (
435- fuzz_target_name = 'libFuzzer_test_fuzzer' ,
436- engine = 'libFuzzer' ,
437- job = 'libfuzzer_asan_job' ,
438- last_run = datetime .datetime .now ()).put ()
402+ self .mock .setup_build .side_effect = self ._mock_setup_build
403+ self .mock .get_application_id .return_value = 'project'
404+ self .mock .get .return_value = centipede_engine .Engine ()
405+ self .maxDiff = None
406+ self .backup_bucket = os .environ ['BACKUP_BUCKET' ] or ''
439407
440408 data_types .FuzzTarget (
441- engine = 'libFuzzer ' , project = 'test2 ' , binary = 'fuzzer ' ).put ()
409+ engine = 'centipede ' , binary = 'clusterfuzz_format_target ' , project = 'test-project ' ).put ()
442410 data_types .FuzzTargetJob (
443- fuzz_target_name = 'libFuzzer_test2_fuzzer' ,
444- engine = 'libFuzzer' ,
445- job = 'libfuzzer_asan_job2' ,
446- last_run = datetime .datetime .now ()).put ()
447-
448- # Set up remote corpora.
449- self .corpus = corpus_manager .FuzzTargetCorpus ('libFuzzer' , 'test_fuzzer' )
450- self .corpus .rsync_from_disk (os .path .join (TEST_DIR , 'corpus' ), delete = True )
451-
452- self .quarantine_corpus = corpus_manager .FuzzTargetCorpus (
453- 'libFuzzer' , 'test_fuzzer' , quarantine = True )
454- self .quarantine_corpus .rsync_from_disk (
455- os .path .join (TEST_DIR , 'quarantine' ), delete = True )
456-
457- data_types .DataBundle (
458- name = 'bundle' , bundle_name = TEST_GLOBAL_BUCKET ,
459- sync_to_worker = True ).put ()
460-
461- self .fuzzer = data_types .Fuzzer (
462- revision = 1 ,
463- file_size = 'builtin' ,
464- source = 'builtin' ,
465- name = 'libFuzzer' ,
466- max_testcases = 4 ,
467- builtin = True ,
468- data_bundle_name = 'bundle' )
469- self .fuzzer .put ()
470-
471- self .temp_dir = tempfile .mkdtemp ()
411+ fuzz_target_name = 'centipede_clusterfuzz_format_target' ,
412+ engine = 'centipede' ,
413+ job = 'centipede_asan_job' ).put ()
472414
473- # Copy corpus backup in the older date format.
474- corpus_backup_date = (
475- datetime .datetime .utcnow ().date () -
476- datetime .timedelta (days = data_types .CORPUS_BACKUP_PUBLIC_LOOKBACK_DAYS ))
477- gsutil .GSUtilRunner ().run_gsutil ([
478- 'cp' ,
479- f'gs://{ TEST2_BACKUP_BUCKET } /corpus/libfuzzer/test2_fuzzer/backup.zip' ,
480- (f'gs://{ self .backup_bucket } /corpus/libfuzzer/'
481- f'test2_fuzzer/{ corpus_backup_date } .zip' )
482- ])
483-
484- def tearDown (self ):
485- super ().tearDown ()
486- shutil .rmtree (self .temp_dir , ignore_errors = True )
487-
488- @unittest .skip ('Non-deterministic, impossible to tell why failing.' )
489415 def test_prune (self ):
490416 """Test pruning."""
491- self ._setup_env (job_type = 'libfuzzer_asan_job' )
492417 uworker_input = corpus_pruning_task .utask_preprocess (
493- job_type = 'libfuzzer_asan_job ' ,
494- fuzzer_name = 'libFuzzer_test_fuzzer ' ,
418+ job_type = 'centipede_asan_job ' ,
419+ fuzzer_name = 'centipede_clusterfuzz_format_target ' ,
495420 uworker_env = {})
496- corpus_pruning_task .utask_main (uworker_input )
497-
498- corpus_dir = os .path .join (self .temp_dir , 'corpus' )
499- os .mkdir (corpus_dir )
421+ # src/clusterfuzz/_internal/tests/core/bot/fuzzers/centipede/test_data/clusterfuzz_format_target
422+ output = corpus_pruning_task .utask_main (uworker_input )
423+ self .assertFalse (output .HasField ('error_type' ))
424+ output .uworker_input .CopyFrom (uworker_input )
425+ corpus_pruning_task .utask_postprocess (output )
500426
501- self . corpus . rsync_to_disk ( corpus_dir )
427+ corpus = os . listdir ( self . corpus_dir )
502428 self .assertCountEqual ([
503- '31836aeaab22dc49555a97edb4c753881432e01d' ,
504- '39e0574a4abfd646565a3e436c548eeb1684fb57' ,
505- ], os .listdir (corpus_dir ))
506-
507- quarantine_dir = os .path .join (self .temp_dir , 'quarantine' )
508- os .mkdir (quarantine_dir )
509- self .quarantine_corpus .rsync_to_disk (quarantine_dir )
510-
511- self .assertCountEqual (['crash-7acd6a2b3fe3c5ec97fa37e5a980c106367491fa' ],
512- os .listdir (quarantine_dir ))
429+ '7acd6a2b3fe3c5ec97fa37e5a980c106367491fa' ,
430+ ], corpus )
513431
514432 testcases = list (data_types .Testcase .query ())
515433 self .assertEqual (1 , len (testcases ))
@@ -518,24 +436,23 @@ def test_prune(self):
518436 self .assertEqual (1337 , testcases [0 ].crash_revision )
519437 self .assertEqual ('test_fuzzer' ,
520438 testcases [0 ].get_metadata ('fuzzer_binary_name' ))
521-
522- self .mock .add_task .assert_has_calls ([
523- mock .call ('minimize' , testcases [0 ].key .id (), 'libfuzzer_asan_job' ),
524- ])
439+ self .assertEqual ('label1,label2' , testcases [0 ].get_metadata ('issue_labels' ))
525440
526441 today = datetime .datetime .utcnow ().date ()
442+ # get_coverage_information on test_fuzzer rather than centipede_test_fuzzer
443+ # since the centipede_ prefix is removed when saving coverage info.
527444 coverage_info = data_handler .get_coverage_information ('test_fuzzer' , today )
528- coverage_info_without_backup = coverage_info .to_dict ()
529- del coverage_info_without_backup ['corpus_backup_location' ]
530445
531446 self .assertDictEqual (
532447 {
448+ 'corpus_backup_location' :
449+ uworker_input .corpus_pruning_task_input .dated_backup_gcs_url ,
533450 'corpus_location' :
534- f 'gs://{ self . corpus_bucket } /libFuzzer /test_fuzzer/' ,
451+ 'gs://bucket/centipede /test_fuzzer/' ,
535452 'corpus_size_bytes' :
536- 8 ,
537- 'corpus_size_units' :
538453 4 ,
454+ 'corpus_size_units' :
455+ 2 ,
539456 'date' :
540457 today ,
541458 # Coverage numbers are expected to be None as they come from fuzzer
@@ -550,20 +467,10 @@ def test_prune(self):
550467 None ,
551468 'fuzzer' :
552469 'test_fuzzer' ,
553- 'html_report_url' :
554- None ,
555- 'quarantine_location' :
556- f'gs://{ self .quarantine_bucket } /libFuzzer/test_fuzzer/' ,
557- 'quarantine_size_bytes' :
558- 2 ,
559- 'quarantine_size_units' :
560- 1 ,
561470 },
562- coverage_info_without_backup )
471+ coverage_info . to_dict () )
563472
564- self .assertEqual (
565- coverage_info .corpus_backup_location ,
566- f'gs://{ self .backup_bucket } /corpus/libFuzzer/test_fuzzer/{ today } .zip' )
473+ self .assertEqual (self .mock .unpack_seed_corpus_if_needed .call_count , 1 )
567474
568475 def get_mock_record_compare (self , project_qualified_name , sources ,
569476 initial_corpus_size , corpus_size ,
0 commit comments