From 8c4ad095e93d2d2909a762ed920b174926700177 Mon Sep 17 00:00:00 2001 From: jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com> Date: Wed, 26 May 2021 09:45:22 -0700 Subject: [PATCH] [CIFuzz] Refactor in preparation for filestore (#5841) 1. Moving the _create_config and create_config functions from build_fuzzers_test.py and run_fuzzers_test.py into test_helpers.py (which is now part of cifuzz instead of infra) and share code between them. 2. Rename artifacts_dir to crashes_dir in run_fuzzers.py. "artifacts" is ambiguous. 3. Make some small changes to pytest.ini to improve debugging. --- infra/base-images/base-runner/run_fuzzer | 2 +- infra/cifuzz/actions/run_fuzzers/action.yml | 9 ++ infra/cifuzz/build_fuzzers_test.py | 126 +++++++++----------- infra/cifuzz/clusterfuzz_deployment_test.py | 13 +- infra/cifuzz/config_utils.py | 11 +- infra/cifuzz/fuzz_target_test.py | 13 +- infra/cifuzz/run_fuzzers.py | 15 ++- infra/cifuzz/run_fuzzers_test.py | 73 +++++------- infra/{ => cifuzz}/test_helpers.py | 28 +++++ infra/pytest.ini | 3 +- infra/retry.py | 6 +- 11 files changed, 146 insertions(+), 153 deletions(-) rename infra/{ => cifuzz}/test_helpers.py (55%) diff --git a/infra/base-images/base-runner/run_fuzzer b/infra/base-images/base-runner/run_fuzzer index 17cfac0c9..c27f8a330 100755 --- a/infra/base-images/base-runner/run_fuzzer +++ b/infra/base-images/base-runner/run_fuzzer @@ -112,7 +112,7 @@ if [[ "$FUZZING_ENGINE" = afl ]]; then # If $OUT/afl++.dict we load it as a dictionary for afl-fuzz. test -e "$OUT/afl++.dict" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -x $OUT/afl++.dict" # Ensure timeout is a bit larger than 1sec as some of the OSS-Fuzz fuzzers - # are slower than this. + # are slower than this. AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -t 5000+" # AFL expects at least 1 file in the input dir. echo input > ${CORPUS_DIR}/input diff --git a/infra/cifuzz/actions/run_fuzzers/action.yml b/infra/cifuzz/actions/run_fuzzers/action.yml index d1c03c833..da9022214 100644 --- a/infra/cifuzz/actions/run_fuzzers/action.yml +++ b/infra/cifuzz/actions/run_fuzzers/action.yml @@ -30,6 +30,14 @@ inputs: "batch" is in alpha and should not be used in production. required: false default: 'ci' + github-token: + description: | + Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET + You should use "secrets.GITHUB_TOKEN" in your workflow file, do not + hardcode the token. + TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361): + Document locking this down. + required: false runs: using: 'docker' image: '../../../run_fuzzers.Dockerfile' @@ -44,4 +52,5 @@ runs: # for running because we use it to distinguish OSS-Fuzz from non-OSS-Fuzz. # We should do something explicit instead. BUILD_INTEGRATION_PATH: ${{ inputs.build-integration-path }} + GITHUB_TOKEN: ${{ inputs.github-token }} LOW_DISK_SPACE: 'True' diff --git a/infra/cifuzz/build_fuzzers_test.py b/infra/cifuzz/build_fuzzers_test.py index ea52b2ca2..5dfe4f0f8 100644 --- a/infra/cifuzz/build_fuzzers_test.py +++ b/infra/cifuzz/build_fuzzers_test.py @@ -28,7 +28,6 @@ sys.path.append(INFRA_DIR) OSS_FUZZ_DIR = os.path.dirname(INFRA_DIR) import build_fuzzers -import config_utils import continuous_integration import repo_manager import test_helpers @@ -57,22 +56,6 @@ EXAMPLE_BUILD_FUZZER = 'do_stuff_fuzzer' # pylint: disable=no-self-use,protected-access,too-few-public-methods -def create_config(**kwargs): - """Creates a config object and then sets every attribute that is a key in - |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an - attribute of Config.""" - with mock.patch('os.path.basename', return_value=None), mock.patch( - 'config_utils.get_project_src_path', - return_value=None), mock.patch('config_utils._is_dry_run', - return_value=True): - config = config_utils.BuildFuzzersConfig() - - for key, value in kwargs.items(): - assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key - setattr(config, key, value) - return config - - class BuildFuzzersTest(unittest.TestCase): """Unit tests for build_fuzzers.""" @@ -86,10 +69,10 @@ class BuildFuzzersTest(unittest.TestCase): with tempfile.TemporaryDirectory() as tmp_dir: build_fuzzers.build_fuzzers( - create_config(project_name=EXAMPLE_PROJECT, - project_repo_name=EXAMPLE_PROJECT, - workspace=tmp_dir, - pr_ref='refs/pull/1757/merge')) + test_helpers.create_build_config(project_name=EXAMPLE_PROJECT, + project_repo_name=EXAMPLE_PROJECT, + workspace=tmp_dir, + pr_ref='refs/pull/1757/merge')) docker_run_command = mocked_docker_run.call_args_list[0][0][0] def command_has_env_var_arg(command, env_var_arg): @@ -114,13 +97,14 @@ class InternalGithubBuildTest(unittest.TestCase): def _create_builder(self, tmp_dir): """Creates an InternalGithubBuilder and returns it.""" - config = create_config(project_name=self.PROJECT_NAME, - project_repo_name=self.PROJECT_REPO_NAME, - workspace=tmp_dir, - sanitizer=self.SANITIZER, - commit_sha=self.COMMIT_SHA, - pr_ref=self.PR_REF, - is_github=True) + config = test_helpers.create_build_config( + project_name=self.PROJECT_NAME, + project_repo_name=self.PROJECT_REPO_NAME, + workspace=tmp_dir, + sanitizer=self.SANITIZER, + commit_sha=self.COMMIT_SHA, + pr_ref=self.PR_REF, + is_github=True) ci_system = continuous_integration.get_ci(config) return build_fuzzers.Builder(config, ci_system) @@ -164,14 +148,15 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): git_url = 'https://github.com/jonathanmetzman/cifuzz-external-example.git' # This test is dependant on the state of # github.com/jonathanmetzman/cifuzz-external-example. - config = create_config(project_name=project_name, - project_repo_name=project_name, - workspace=self.workspace, - build_integration_path=build_integration_path, - git_url=git_url, - commit_sha='HEAD', - is_github=True, - base_commit='HEAD^1') + config = test_helpers.create_build_config( + project_name=project_name, + project_repo_name=project_name, + workspace=self.workspace, + build_integration_path=build_integration_path, + git_url=git_url, + commit_sha='HEAD', + is_github=True, + base_commit='HEAD^1') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) @@ -187,21 +172,22 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): 'https://github.com/jonathanmetzman/cifuzz-external-example', self.tmp_dir_obj.name) project_src_path = manager.repo_dir - config = create_config(project_name=project_name, - project_repo_name=project_name, - workspace=self.workspace, - build_integration_path=build_integration_path, - git_url=git_url, - commit_sha='HEAD', - project_src_path=project_src_path, - base_commit='HEAD^1') + config = test_helpers.create_build_config( + project_name=project_name, + project_repo_name=project_name, + workspace=self.workspace, + build_integration_path=build_integration_path, + git_url=git_url, + commit_sha='HEAD', + project_src_path=project_src_path, + base_commit='HEAD^1') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_valid_commit(self): """Tests building fuzzers with valid inputs.""" - config = create_config( + config = test_helpers.create_build_config( project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=self.workspace, @@ -215,29 +201,29 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): def test_valid_pull_request(self): """Tests building fuzzers with valid pull request.""" # TODO(metzman): What happens when this branch closes? - config = create_config(project_name=EXAMPLE_PROJECT, - project_repo_name='oss-fuzz', - workspace=self.workspace, - pr_ref='refs/pull/1757/merge', - base_ref='master', - is_github=True) + config = test_helpers.create_build_config(project_name=EXAMPLE_PROJECT, + project_repo_name='oss-fuzz', + workspace=self.workspace, + pr_ref='refs/pull/1757/merge', + base_ref='master', + is_github=True) self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_invalid_pull_request(self): """Tests building fuzzers with invalid pull request.""" - config = create_config(project_name=EXAMPLE_PROJECT, - project_repo_name='oss-fuzz', - workspace=self.workspace, - pr_ref='ref-1/merge', - base_ref='master', - is_github=True) + config = test_helpers.create_build_config(project_name=EXAMPLE_PROJECT, + project_repo_name='oss-fuzz', + workspace=self.workspace, + pr_ref='ref-1/merge', + base_ref='master', + is_github=True) self.assertTrue(build_fuzzers.build_fuzzers(config)) def test_invalid_project_name(self): """Tests building fuzzers with invalid project name.""" - config = create_config( + config = test_helpers.create_build_config( project_name='not_a_valid_project', project_repo_name='oss-fuzz', workspace=self.workspace, @@ -246,7 +232,7 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): def test_invalid_repo_name(self): """Tests building fuzzers with invalid repo name.""" - config = create_config( + config = test_helpers.create_build_config( project_name=EXAMPLE_PROJECT, project_repo_name='not-real-repo', workspace=self.workspace, @@ -255,17 +241,17 @@ class BuildFuzzersIntegrationTest(unittest.TestCase): def test_invalid_commit_sha(self): """Tests building fuzzers with invalid commit SHA.""" - config = create_config(project_name=EXAMPLE_PROJECT, - project_repo_name='oss-fuzz', - workspace=self.workspace, - commit_sha='', - is_github=True) + config = test_helpers.create_build_config(project_name=EXAMPLE_PROJECT, + project_repo_name='oss-fuzz', + workspace=self.workspace, + commit_sha='', + is_github=True) with self.assertRaises(AssertionError): build_fuzzers.build_fuzzers(config) def test_invalid_workspace(self): """Tests building fuzzers with invalid workspace.""" - config = create_config( + config = test_helpers.create_build_config( project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=os.path.join(self.workspace, 'not', 'a', 'dir'), @@ -329,11 +315,11 @@ class BuildSantizerIntegrationTest(unittest.TestCase): @classmethod def _create_config(cls, tmp_dir, sanitizer): - return create_config(project_name=cls.PROJECT_NAME, - project_repo_name=cls.PROJECT_NAME, - workspace=tmp_dir, - pr_ref=cls.PR_REF, - sanitizer=sanitizer) + return test_helpers.create_build_config(project_name=cls.PROJECT_NAME, + project_repo_name=cls.PROJECT_NAME, + workspace=tmp_dir, + pr_ref=cls.PR_REF, + sanitizer=sanitizer) @parameterized.parameterized.expand([('memory',), ('undefined',)]) def test_valid_project_curl(self, sanitizer): diff --git a/infra/cifuzz/clusterfuzz_deployment_test.py b/infra/cifuzz/clusterfuzz_deployment_test.py index 06ff78476..d4a991194 100644 --- a/infra/cifuzz/clusterfuzz_deployment_test.py +++ b/infra/cifuzz/clusterfuzz_deployment_test.py @@ -21,7 +21,7 @@ import urllib.error from pyfakefs import fake_filesystem_unittest import clusterfuzz_deployment -import config_utils +import test_helpers # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. @@ -40,16 +40,7 @@ def _create_config(**kwargs): if default_key not in kwargs: kwargs[default_key] = default_value - with mock.patch('os.path.basename', return_value=None), mock.patch( - 'config_utils.get_project_src_path', - return_value=None), mock.patch('config_utils._is_dry_run', - return_value=True): - config = config_utils.RunFuzzersConfig() - - for key, value in kwargs.items(): - assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key - setattr(config, key, value) - return config + return test_helpers.create_run_config(**kwargs) def _create_deployment(**kwargs): diff --git a/infra/cifuzz/config_utils.py b/infra/cifuzz/config_utils.py index 941feb7d4..9237c293b 100644 --- a/infra/cifuzz/config_utils.py +++ b/infra/cifuzz/config_utils.py @@ -21,8 +21,10 @@ import json import environment -def _get_project_repo_name(): - return os.path.basename(environment.get('GITHUB_REPOSITORY', '')) +def _get_project_repo_owner_and_name(): + # Includes owner and repo name. + github_repository = os.getenv('GITHUB_REPOSITORY', '') + return os.path.split(github_repository) def _get_pr_ref(event): @@ -93,6 +95,8 @@ class BaseConfig: def __init__(self): self.workspace = os.getenv('GITHUB_WORKSPACE') self.project_name = _get_project_name() + self.project_repo_owner, self.project_repo_name = ( + _get_project_repo_owner_and_name()) # Check if failures should not be reported. self.dry_run = _is_dry_run() self.sanitizer = _get_sanitizer() @@ -104,6 +108,8 @@ class BaseConfig: # TODO(metzman): Parse env like we do in ClusterFuzz. self.low_disk_space = environment.get('LOW_DISK_SPACE', False) + self.github_token = os.environ.get('GITHUB_TOKEN') + @property def is_internal(self): """Returns True if this is an OSS-Fuzz project.""" @@ -162,7 +168,6 @@ class BuildFuzzersConfig(BaseConfig): # TODO(metzman): Some of this config is very CI-specific. Move it into the # CI class. super().__init__() - self.project_repo_name = _get_project_repo_name() self.commit_sha = os.getenv('GITHUB_SHA') event = os.getenv('GITHUB_EVENT_NAME') diff --git a/infra/cifuzz/fuzz_target_test.py b/infra/cifuzz/fuzz_target_test.py index 8bec234dc..22c5ac83c 100644 --- a/infra/cifuzz/fuzz_target_test.py +++ b/infra/cifuzz/fuzz_target_test.py @@ -22,8 +22,8 @@ import parameterized from pyfakefs import fake_filesystem_unittest import clusterfuzz_deployment -import config_utils import fuzz_target +import test_helpers # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. @@ -48,16 +48,7 @@ def _create_config(**kwargs): if default_key not in kwargs: kwargs[default_key] = default_value - with mock.patch('os.path.basename', return_value=None), mock.patch( - 'config_utils.get_project_src_path', - return_value=None), mock.patch('config_utils._is_dry_run', - return_value=True): - config = config_utils.RunFuzzersConfig() - - for key, value in kwargs.items(): - assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key - setattr(config, key, value) - return config + return test_helpers.create_run_config(**kwargs) def _create_deployment(**kwargs): diff --git a/infra/cifuzz/run_fuzzers.py b/infra/cifuzz/run_fuzzers.py index 513cfb6fa..a6f552ec7 100644 --- a/infra/cifuzz/run_fuzzers.py +++ b/infra/cifuzz/run_fuzzers.py @@ -46,7 +46,7 @@ class BaseFuzzTargetRunner: # Set by the initialize method. self.out_dir = None self.fuzz_target_paths = None - self.artifacts_dir = None + self.crashes_dir = None def initialize(self): """Initialization method. Must be called before calling run_fuzz_targets. @@ -69,13 +69,12 @@ class BaseFuzzTargetRunner: logging.error('Out directory: %s does not exist.', self.out_dir) return False - self.artifacts_dir = os.path.join(self.out_dir, 'artifacts') - if not os.path.exists(self.artifacts_dir): - os.mkdir(self.artifacts_dir) - elif (not os.path.isdir(self.artifacts_dir) or - os.listdir(self.artifacts_dir)): + self.crashes_dir = os.path.join(self.out_dir, 'artifacts') + if not os.path.exists(self.crashes_dir): + os.mkdir(self.crashes_dir) + elif (not os.path.isdir(self.crashes_dir) or os.listdir(self.crashes_dir)): logging.error('Artifacts path: %s exists and is not an empty directory.', - self.artifacts_dir) + self.crashes_dir) return False self.fuzz_target_paths = utils.get_fuzz_targets(self.out_dir) @@ -108,7 +107,7 @@ class BaseFuzzTargetRunner: target_name=target.target_name, sanitizer=self.config.sanitizer, artifact_name=artifact_name) - return os.path.join(self.artifacts_dir, artifact_name) + return os.path.join(self.crashes_dir, artifact_name) def create_fuzz_target_obj(self, target_path, run_seconds): """Returns a fuzz target object.""" diff --git a/infra/cifuzz/run_fuzzers_test.py b/infra/cifuzz/run_fuzzers_test.py index b2659903c..82d97f254 100644 --- a/infra/cifuzz/run_fuzzers_test.py +++ b/infra/cifuzz/run_fuzzers_test.py @@ -22,7 +22,6 @@ from unittest import mock import parameterized from pyfakefs import fake_filesystem_unittest -import config_utils import fuzz_target import run_fuzzers @@ -49,22 +48,6 @@ UNDEFINED_FUZZER = 'curl_fuzzer_undefined' FUZZ_SECONDS = 10 -def _create_config(**kwargs): - """Creates a config object and then sets every attribute that is a key in - |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an - attribute of Config.""" - with mock.patch('os.path.basename', return_value=None), mock.patch( - 'config_utils.get_project_src_path', - return_value=None), mock.patch('config_utils._is_dry_run', - return_value=True): - config = config_utils.RunFuzzersConfig() - - for key, value in kwargs.items(): - assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key - setattr(config, key, value) - return config - - class RunFuzzerIntegrationTestMixin: # pylint: disable=too-few-public-methods,invalid-name """Mixin for integration test classes that runbuild_fuzzers on builds of a specific sanitizer.""" @@ -76,10 +59,10 @@ class RunFuzzerIntegrationTestMixin: # pylint: disable=too-few-public-methods,i """Calls run_fuzzers on fuzzer_dir and |sanitizer| and asserts the run succeeded and that no bug was found.""" with test_helpers.temp_dir_copy(fuzzer_dir) as fuzzer_dir_copy: - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=fuzzer_dir_copy, - project_name='curl', - sanitizer=sanitizer) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=fuzzer_dir_copy, + project_name='curl', + sanitizer=sanitizer) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND) @@ -119,7 +102,7 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase): if default_key not in kwargs: kwargs[default_key] = default_value - config = _create_config(**kwargs) + config = test_helpers.create_run_config(**kwargs) return run_fuzzers.BaseFuzzTargetRunner(config) def _test_initialize_fail(self, expected_error_args, **create_runner_kwargs): @@ -219,8 +202,8 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase): def test_get_fuzz_target_artifact(self): """Tests that get_fuzz_target_artifact works as intended.""" runner = self._create_runner() - artifacts_dir = 'artifacts-dir' - runner.artifacts_dir = artifacts_dir + crashes_dir = 'crashes-dir' + runner.crashes_dir = crashes_dir artifact_name = 'artifact-name' target = mock.MagicMock() target_name = 'target_name' @@ -228,7 +211,7 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase): fuzz_target_artifact = runner.get_fuzz_target_artifact( target, artifact_name) expected_fuzz_target_artifact = ( - 'artifacts-dir/target_name-address-artifact-name') + 'crashes-dir/target_name-address-artifact-name') self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact) @@ -248,9 +231,9 @@ class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): workspace = 'workspace' out_path = os.path.join(workspace, 'out') self.fs.create_dir(out_path) - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=workspace, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=workspace, + project_name=EXAMPLE_PROJECT) runner = run_fuzzers.CiFuzzTargetRunner(config) mocked_get_fuzz_targets.return_value = ['target1', 'target2'] @@ -264,7 +247,7 @@ class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): magic_mock.target_name = 'target1' mocked_create_fuzz_target_obj.return_value = magic_mock self.assertTrue(runner.run_fuzz_targets()) - self.assertIn('target1-address-testcase', os.listdir(runner.artifacts_dir)) + self.assertIn('target1-address-testcase', os.listdir(runner.crashes_dir)) self.assertEqual(mocked_run_fuzz_target.call_count, 1) @@ -284,9 +267,9 @@ class BatchFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): workspace = 'workspace' out_path = os.path.join(workspace, 'out') self.fs.create_dir(out_path) - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=workspace, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=workspace, + project_name=EXAMPLE_PROJECT) runner = run_fuzzers.BatchFuzzTargetRunner(config) mocked_get_fuzz_targets.return_value = ['target1', 'target2'] @@ -314,7 +297,7 @@ class BatchFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): mocked_create_fuzz_target_obj.return_value = magic_mock self.assertTrue(runner.run_fuzz_targets()) self.assertIn('target1-address-testcase-aaa', - os.listdir(runner.artifacts_dir)) + os.listdir(runner.crashes_dir)) self.assertEqual(mocked_run_fuzz_target.call_count, 2) @@ -336,9 +319,9 @@ class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin, with tempfile.TemporaryDirectory() as tmp_dir: workspace = os.path.join(tmp_dir, 'workspace') shutil.copytree(TEST_DATA_PATH, workspace) - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=workspace, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=workspace, + project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.BUG_FOUND) build_dir = os.path.join(workspace, 'out', self.BUILD_DIR_NAME) @@ -350,15 +333,15 @@ class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin, side_effect=[True, True]) def test_old_bug_found(self, _): """Tests run_fuzzers with a bug found in OSS-Fuzz before.""" - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=TEST_DATA_PATH, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=TEST_DATA_PATH, + project_name=EXAMPLE_PROJECT) with tempfile.TemporaryDirectory() as tmp_dir: workspace = os.path.join(tmp_dir, 'workspace') shutil.copytree(TEST_DATA_PATH, workspace) - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=TEST_DATA_PATH, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=TEST_DATA_PATH, + project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND) build_dir = os.path.join(TEST_DATA_PATH, 'out', self.BUILD_DIR_NAME) @@ -370,9 +353,9 @@ class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin, with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'out') os.mkdir(out_path) - config = _create_config(fuzz_seconds=FUZZ_SECONDS, - workspace=tmp_dir, - project_name=EXAMPLE_PROJECT) + config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, + workspace=tmp_dir, + project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.ERROR) diff --git a/infra/test_helpers.py b/infra/cifuzz/test_helpers.py similarity index 55% rename from infra/test_helpers.py rename to infra/cifuzz/test_helpers.py index be0b1b811..3d20bf468 100644 --- a/infra/test_helpers.py +++ b/infra/cifuzz/test_helpers.py @@ -19,6 +19,34 @@ import shutil import tempfile from unittest import mock +import config_utils + + +def _create_config(config_cls, **kwargs): + """Creates a config object from |config_cls| and then sets every attribute + that is a key in |kwargs| to the corresponding value. Asserts that each key in + |kwargs| is an attribute of config.""" + with mock.patch('os.path.basename', return_value=None), mock.patch( + 'config_utils.get_project_src_path', + return_value=None), mock.patch('config_utils._is_dry_run', + return_value=True): + config = config_cls() + + for key, value in kwargs.items(): + assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key + setattr(config, key, value) + return config + + +def create_build_config(**kwargs): + """Wrapper around _create_config for build configs.""" + return _create_config(config_utils.BuildFuzzersConfig, **kwargs) + + +def create_run_config(**kwargs): + """Wrapper around _create_config for run configs.""" + return _create_config(config_utils.RunFuzzersConfig, **kwargs) + def patch_environ(testcase_obj, env=None): """Patch environment.""" diff --git a/infra/pytest.ini b/infra/pytest.ini index d9bb3737e..2a10272e2 100644 --- a/infra/pytest.ini +++ b/infra/pytest.ini @@ -1,2 +1,3 @@ [pytest] -python_files = *_test.py \ No newline at end of file +python_files = *_test.py +log_cli = true \ No newline at end of file diff --git a/infra/retry.py b/infra/retry.py index 1a94180c6..1f6d54b8d 100644 --- a/infra/retry.py +++ b/infra/retry.py @@ -56,9 +56,9 @@ def wrap(retries, """Handle retry.""" if (exception is None or isinstance(exception, exception_type)) and num_try < tries: - logging.log('Retrying on %s failed with %s. Retrying again.', - function_with_type, - sys.exc_info()[1]) + logging.info('Retrying on %s failed with %s. Retrying again.', + function_with_type, + sys.exc_info()[1]) sleep(get_delay(num_try, delay, backoff)) return True