diff options
author | Leo Neat <leosneat@gmail.com> | 2020-01-31 15:31:18 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-31 15:31:18 -0800 |
commit | 1a87da68c870ce09ab6ffac30589da12e7ff6a8d (patch) | |
tree | 1c3431bff2ead5c227919db2b4464ec07bac06dd | |
parent | c2fa07a0956bcfebf2b70b5df13f5ed4c4d7c7e5 (diff) | |
download | oss-fuzz-1a87da68c870ce09ab6ffac30589da12e7ff6a8d.tar.gz |
[cifuzz] - commit and pull request hook functionality (#3310)
-rw-r--r-- | infra/cifuzz/actions/entrypoint.py | 25 | ||||
-rw-r--r-- | infra/cifuzz/cifuzz.py | 59 | ||||
-rw-r--r-- | infra/cifuzz/cifuzz_test.py | 144 | ||||
-rw-r--r-- | infra/repo_manager.py | 94 | ||||
-rw-r--r-- | infra/repo_manager_test.py | 49 |
5 files changed, 211 insertions, 160 deletions
diff --git a/infra/cifuzz/actions/entrypoint.py b/infra/cifuzz/actions/entrypoint.py index 5b07c81fb..e6802074c 100644 --- a/infra/cifuzz/actions/entrypoint.py +++ b/infra/cifuzz/actions/entrypoint.py @@ -37,6 +37,8 @@ def main(): FUZZ_TIME: The length of time in seconds that fuzzers are to be run. GITHUB_REPOSITORY: The name of the Github repo that called this script. GITHUB_SHA: The commit SHA that triggered this script. + GITHUB_REF: The pull request reference that triggered this script. + GITHUB_EVENT_NAME: The name of the hook event that triggered this script. Returns: 0 on success or 1 on Failure. @@ -44,28 +46,31 @@ def main(): oss_fuzz_project_name = os.environ.get('PROJECT_NAME') fuzz_seconds = int(os.environ.get('FUZZ_SECONDS', 360)) github_repo_name = os.path.basename(os.environ.get('GITHUB_REPOSITORY')) + pr_ref = os.environ.get('GITHUB_REF') commit_sha = os.environ.get('GITHUB_SHA') + event = os.environ.get('GITHUB_EVENT_NAME') # Get the shared volume directory and create required directorys. workspace = os.environ.get('GITHUB_WORKSPACE') if not workspace: logging.error('This script needs to be run in the Github action context.') return 1 - git_workspace = os.path.join(workspace, 'storage') - os.makedirs(git_workspace, exist_ok=True) - out_dir = os.path.join(workspace, 'out') - os.makedirs(out_dir, exist_ok=True) - # Build the specified project's fuzzers from the current repo state. - if not cifuzz.build_fuzzers(oss_fuzz_project_name, github_repo_name, - commit_sha, git_workspace, out_dir): - logging.error('Error building fuzzers for project %s.', - oss_fuzz_project_name) + if event == 'push' and not cifuzz.build_fuzzers( + oss_fuzz_project_name, github_repo_name, workspace, + commit_sha=commit_sha): + logging.error('Error building fuzzers for project %s with commit %s.', + oss_fuzz_project_name, commit_sha) + return 1 + if event == 'pull_request' and not cifuzz.build_fuzzers( + oss_fuzz_project_name, github_repo_name, workspace, pr_ref=pr_ref): + logging.error('Error building fuzzers for project %s with pull request %s.', + oss_fuzz_project_name, pr_ref) return 1 # Run the specified project's fuzzers from the build. run_status, bug_found = cifuzz.run_fuzzers(oss_fuzz_project_name, - fuzz_seconds, out_dir) + fuzz_seconds, workspace) if not run_status: logging.error('Error occured while running fuzzers for project %s.', oss_fuzz_project_name) diff --git a/infra/cifuzz/cifuzz.py b/infra/cifuzz/cifuzz.py index 81c99c82a..ce7586e5e 100644 --- a/infra/cifuzz/cifuzz.py +++ b/infra/cifuzz/cifuzz.py @@ -38,27 +38,36 @@ logging.basicConfig( level=logging.DEBUG) -def build_fuzzers(project_name, project_repo_name, commit_sha, git_workspace, - out_dir): +def build_fuzzers(project_name, + project_repo_name, + workspace, + pr_ref=None, + commit_sha=None): """Builds all of the fuzzers for a specific OSS-Fuzz project. Args: project_name: The name of the OSS-Fuzz project being built. project_repo_name: The name of the projects repo. - commit_sha: The commit SHA to be checked out and fuzzed. - git_workspace: The location in the shared volume to store git repos. - out_dir: The location in the shared volume to store output artifacts. + workspace: The location in a shared volume to store a git repo and build + artifacts. + pr_ref: The pull request reference to be built. + commit_sha: The commit sha for the project to be built at. Returns: True if build succeeded or False on failure. """ - if not os.path.exists(git_workspace): - logging.error('Invalid git workspace: %s.', format(git_workspace)) - return False - if not os.path.exists(out_dir): - logging.error('Invalid out directory %s.', format(out_dir)) + # Validate inputs. + assert pr_ref or commit_sha + if not os.path.exists(workspace): + logging.error('Invalid workspace: %s.', workspace) return False + git_workspace = os.path.join(workspace, 'storage') + os.makedirs(git_workspace, exist_ok=True) + out_dir = os.path.join(workspace, 'out') + os.makedirs(out_dir, exist_ok=True) + + # Detect repo information. inferred_url, oss_fuzz_repo_path = build_specified_commit.detect_main_repo( project_name, repo_name=project_repo_name) if not inferred_url or not oss_fuzz_repo_path: @@ -72,12 +81,18 @@ def build_fuzzers(project_name, project_repo_name, commit_sha, git_workspace, git_workspace, repo_name=oss_fuzz_repo_name) try: - build_repo_manager.checkout_commit(commit_sha) - except repo_manager.RepoManagerError: - logging.error('Specified commit does not exist.') - # NOTE: Remove return statement for testing. + if pr_ref: + build_repo_manager.checkout_pr(pr_ref) + else: + build_repo_manager.checkout_commit(commit_sha) + except RuntimeError: + logging.error('Can not check out requested state.') + return False + except ValueError: + logging.error('Invalid commit SHA requested %s.', commit_sha) return False + # Build Fuzzers using docker run. command = [ '--cap-add', 'SYS_PTRACE', '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'SANITIZER=address', '-e', 'ARCHITECTURE=x86_64' @@ -103,41 +118,43 @@ def build_fuzzers(project_name, project_repo_name, commit_sha, git_workspace, '-c', ]) command.append(bash_command) - if helper.docker_run(command): logging.error('Building fuzzers failed.') return False return True -def run_fuzzers(project_name, fuzz_seconds, out_dir): +def run_fuzzers(project_name, fuzz_seconds, workspace): """Runs all fuzzers for a specific OSS-Fuzz project. Args: project_name: The name of the OSS-Fuzz project being built. fuzz_seconds: The total time allotted for fuzzing. - out_dir: The location in the shared volume to store output artifacts. + workspace: The location in a shared volume to store a git repo and build + artifacts. Returns: (True if run was successful, True if bug was found). """ - if not out_dir or not os.path.exists(out_dir): - logging.error('Unreachable out_dir argument %s.', format(out_dir)) + # Validate inputs. + if not os.path.exists(workspace): + logging.error('Invalid workspace: %s.', workspace) return False, False - + out_dir = os.path.join(workspace, 'out') if not fuzz_seconds or fuzz_seconds < 1: logging.error('Fuzz_seconds argument must be greater than 1, but was: %s.', format(fuzz_seconds)) return False, False + # Get fuzzer information. fuzzer_paths = utils.get_fuzz_targets(out_dir) if not fuzzer_paths: logging.error('No fuzzers were found in out directory: %s.', format(out_dir)) return False, False - fuzz_seconds_per_target = fuzz_seconds // len(fuzzer_paths) + # Run fuzzers for alotted time. for fuzzer_path in fuzzer_paths: target = fuzz_target.FuzzTarget(project_name, fuzzer_path, fuzz_seconds_per_target, out_dir) diff --git a/infra/cifuzz/cifuzz_test.py b/infra/cifuzz/cifuzz_test.py index 90c93a2da..7c17b6f84 100644 --- a/infra/cifuzz/cifuzz_test.py +++ b/infra/cifuzz/cifuzz_test.py @@ -33,78 +33,80 @@ EXAMPLE_PROJECT = 'example' class BuildFuzzersIntegrationTest(unittest.TestCase): """Test build_fuzzers function in the utils module.""" - def test_valid(self): + def test_valid_commit(self): """Test building fuzzers with valid inputs.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'out') - workspace_path = os.path.join(tmp_dir, 'workspace') os.mkdir(out_path) - os.mkdir(workspace_path) self.assertTrue( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'oss-fuzz', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - workspace_path, out_path)) + cifuzz.build_fuzzers( + EXAMPLE_PROJECT, + 'oss-fuzz', + tmp_dir, + commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')) self.assertTrue(os.path.exists(os.path.join(out_path, 'do_stuff_fuzzer'))) + def test_valid_pull_request(self): + """Test building fuzzers with valid pull request.""" + with tempfile.TemporaryDirectory() as tmp_dir: + out_path = os.path.join(tmp_dir, 'out') + os.mkdir(out_path) + self.assertTrue( + cifuzz.build_fuzzers(EXAMPLE_PROJECT, + 'oss-fuzz', + tmp_dir, + pr_ref='refs/pull/3310/merge')) + self.assertTrue(os.path.exists(os.path.join(out_path, 'do_stuff_fuzzer'))) -def test_invalid_project_name(self): - """Test building fuzzers with invalid project name.""" - with tempfile.TemporaryDirectory() as tmp_dir: - out_path = os.path.join(tmp_dir, 'out') - workspace_path = os.path.join(tmp_dir, 'workspace') - os.mkdir(out_path) - os.mkdir(workspace_path) - self.assertFalse( - cifuzz.build_fuzzers('not_a_valid_project', 'oss-fuzz', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - workspace_path, out_path)) - - -def test_invalid_repo_name(self): - """Test building fuzzers with invalid repo name.""" - with tempfile.TemporaryDirectory() as tmp_dir: - out_path = os.path.join(tmp_dir, 'out') - workspace_path = os.path.join(tmp_dir, 'workspace') - os.mkdir(out_path) - os.mkdir(workspace_path) - self.assertFalse( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'not-real-repo', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - workspace_path, out_path)) - - -def test_invalid_commit_sha(self): - """Test building fuzzers with invalid commit SHA.""" - with tempfile.TemporaryDirectory() as tmp_dir: - out_path = os.path.join(tmp_dir, 'out') - workspace_path = os.path.join(tmp_dir, 'workspace') - os.mkdir(out_path) - os.mkdir(workspace_path) - self.assertFalse( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'oss-fuzz', '', workspace_path, - out_path)) - - -def test_invalid_workspace(self): - """Test building fuzzers with invalid workspace.""" - with tempfile.TemporaryDirectory() as tmp_dir: - out_path = os.path.join(tmp_dir, 'out') - os.mkdir(out_path) - self.assertFalse( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'oss-fuzz', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - 'not/a/dir', out_path)) - - -def test_invalid_out(self): - """Test building fuzzers with invalid out directory.""" - with tempfile.TemporaryDirectory() as tmp_dir: - workspace_path = os.path.join(tmp_dir, 'workspace') - os.mkdir(workspace_path) + def test_invalid_pull_request(self): + """Test building fuzzers with invalid pull request.""" + with tempfile.TemporaryDirectory() as tmp_dir: + out_path = os.path.join(tmp_dir, 'out') + os.mkdir(out_path) + self.assertFalse( + cifuzz.build_fuzzers(EXAMPLE_PROJECT, + 'oss-fuzz', + tmp_dir, + pr_ref='ref-1/merge')) + + def test_invalid_project_name(self): + """Test building fuzzers with invalid project name.""" + with tempfile.TemporaryDirectory() as tmp_dir: + self.assertFalse( + cifuzz.build_fuzzers( + 'not_a_valid_project', + 'oss-fuzz', + tmp_dir, + commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')) + + def test_invalid_repo_name(self): + """Test building fuzzers with invalid repo name.""" + with tempfile.TemporaryDirectory() as tmp_dir: + self.assertFalse( + cifuzz.build_fuzzers( + EXAMPLE_PROJECT, + 'not-real-repo', + tmp_dir, + commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')) + + def test_invalid_commit_sha(self): + """Test building fuzzers with invalid commit SHA.""" + with tempfile.TemporaryDirectory() as tmp_dir: + with self.assertRaises(AssertionError): + cifuzz.build_fuzzers(EXAMPLE_PROJECT, + 'oss-fuzz', + tmp_dir, + commit_sha='') + + def test_invalid_workspace(self): + """Test building fuzzers with invalid workspace.""" self.assertFalse( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'oss-fuzz', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - workspace_path, 'not/a/dir')) + cifuzz.build_fuzzers( + EXAMPLE_PROJECT, + 'oss-fuzz', + 'not/a/dir', + commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523', + )) class RunFuzzersIntegrationTest(unittest.TestCase): @@ -114,15 +116,15 @@ class RunFuzzersIntegrationTest(unittest.TestCase): """Test run_fuzzers with a valid build.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'out') - workspace_path = os.path.join(tmp_dir, 'workspace') os.mkdir(out_path) - os.mkdir(workspace_path) self.assertTrue( - cifuzz.build_fuzzers(EXAMPLE_PROJECT, 'oss-fuzz', - '0b95fe1039ed7c38fea1f97078316bfc1030c523', - workspace_path, out_path)) + cifuzz.build_fuzzers( + EXAMPLE_PROJECT, + 'oss-fuzz', + tmp_dir, + commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')) self.assertTrue(os.path.exists(os.path.join(out_path, 'do_stuff_fuzzer'))) - run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 5, out_path) + run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 5, tmp_dir) self.assertTrue(run_success) self.assertTrue(bug_found) @@ -131,7 +133,7 @@ class RunFuzzersIntegrationTest(unittest.TestCase): with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'out') os.mkdir(out_path) - run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 5, out_path) + run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 5, tmp_dir) self.assertFalse(run_success) self.assertFalse(bug_found) @@ -140,7 +142,7 @@ class RunFuzzersIntegrationTest(unittest.TestCase): with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'out') os.mkdir(out_path) - run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 0, out_path) + run_success, bug_found = cifuzz.run_fuzzers(EXAMPLE_PROJECT, 0, tmp_dir) self.assertFalse(run_success) self.assertFalse(bug_found) diff --git a/infra/repo_manager.py b/infra/repo_manager.py index bb3fe2371..cf98ab944 100644 --- a/infra/repo_manager.py +++ b/infra/repo_manager.py @@ -27,27 +27,23 @@ import shutil import utils -class RepoManagerError(Exception): - """Class to describe the exceptions in RepoManager.""" - - class RepoManager: """Class to manage git repos from python. Attributes: - repo_url: The location of the git repo - base_dir: The location of where the repo clone is stored locally - repo_name: The name of the github project - repo_dir: The location of the main repo + repo_url: The location of the git repo. + base_dir: The location of where the repo clone is stored locally. + repo_name: The name of the GitHub project. + repo_dir: The location of the main repo. """ def __init__(self, repo_url, base_dir, repo_name=None): """Constructs a repo manager class. Args: - repo_url: The github url needed to clone - base_dir: The full filepath where the git repo is located - repo_name: The name of the directory the repo is cloned to + repo_url: The github url needed to clone. + base_dir: The full file-path where the git repo is located. + repo_name: The name of the directory the repo is cloned to. """ self.repo_url = repo_url self.base_dir = base_dir @@ -62,7 +58,7 @@ class RepoManager: """Creates a clone of the repo in the specified directory. Raises: - RepoManagerError if the repo was not able to be cloned + ValueError: when the repo is not able to be cloned. """ if not os.path.exists(self.base_dir): os.makedirs(self.base_dir) @@ -70,13 +66,13 @@ class RepoManager: out, err = utils.execute(['git', 'clone', self.repo_url, self.repo_name], location=self.base_dir) if not self._is_git_repo(): - raise RepoManagerError('%s is not a git repo' % self.repo_url) + raise ValueError('%s is not a git repo' % self.repo_url) def _is_git_repo(self): """Test if the current repo dir is a git repo or not. Returns: - True if the current repo_dir is a valid git repo + True if the current repo_dir is a valid git repo. """ git_path = os.path.join(self.repo_dir, '.git') return os.path.isdir(git_path) @@ -85,19 +81,13 @@ class RepoManager: """Checks to see if a commit exists in the project repo. Args: - commit: The commit SHA you are checking + commit: The commit SHA you are checking. Returns: - True if the commit exits in the project - - Raises: - ValueException: an empty string was passed in as a commit + True if the commit exits in the project. """ - - # Handle the exception case, if empty string is passed execute will - # raise a ValueError if not commit.rstrip(): - raise RepoManagerError('An empty string is not a valid commit SHA') + return False _, err_code = utils.execute(['git', 'cat-file', '-e', commit], self.repo_dir) @@ -107,7 +97,7 @@ class RepoManager: """Gets the current commit SHA of the repo. Returns: - The current active commit SHA + The current active commit SHA. """ out, _ = utils.execute(['git', 'rev-parse', 'HEAD'], self.repo_dir, @@ -118,20 +108,21 @@ class RepoManager: """Gets the list of commits(inclusive) between the old and new commits. Args: - old_commit: The oldest commit to be in the list - new_commit: The newest commit to be in the list + old_commit: The oldest commit to be in the list. + new_commit: The newest commit to be in the list. Returns: - The list of commit SHAs from newest to oldest + The list of commit SHAs from newest to oldest. Raises: - RepoManagerError when commits dont exist + ValueError: When either the old or new commit does not exist. + RuntimeError: When there is an error getting the commit list. """ if not self.commit_exists(old_commit): - raise RepoManagerError('The old commit %s does not exist' % old_commit) + raise ValueError('The old commit %s does not exist' % old_commit) if not self.commit_exists(new_commit): - raise RepoManagerError('The new commit %s does not exist' % new_commit) + raise ValueError('The new commit %s does not exist' % new_commit) if old_commit == new_commit: return [old_commit] out, err_code = utils.execute( @@ -139,37 +130,54 @@ class RepoManager: commits = out.split('\n') commits = [commit for commit in commits if commit] if err_code or not commits: - raise RepoManagerError('Error getting commit list between %s and %s ' % - (old_commit, new_commit)) + raise RuntimeError('Error getting commit list between %s and %s ' % + (old_commit, new_commit)) # Make sure result is inclusive commits.append(old_commit) return commits + def fetch_unshallow(self): + """Gets the current git repository history.""" + git_path = os.path.join(self.repo_dir, '.git', 'shallow') + if os.path.exists(git_path): + utils.execute(['git', 'fetch', '--unshallow'], + self.repo_dir, + check_result=True) + + def checkout_pr(self, pr_ref): + """Checks out a remote pull request. + + Args: + pr_ref: The pull request reference to be checked out. + """ + self.fetch_unshallow() + utils.execute(['git', 'fetch', 'origin', pr_ref], + self.repo_dir, + check_result=True) + utils.execute(['git', 'checkout', '-f', 'FETCH_HEAD'], + self.repo_dir, + check_result=True) + def checkout_commit(self, commit): """Checks out a specific commit from the repo. Args: - commit: The commit SHA to be checked out + commit: The commit SHA to be checked out. Raises: - RepoManagerError when checkout is not successful + RuntimeError: when checkout is not successful. + ValueError: when commit does not exist. """ + self.fetch_unshallow() if not self.commit_exists(commit): - raise RepoManagerError('Commit %s does not exist in current branch' % - commit) - - git_path = os.path.join(self.repo_dir, '.git', 'shallow') - if os.path.exists(git_path): - utils.execute(['git', 'fetch', '--unshallow'], - self.repo_dir, - check_result=True) + raise ValueError('Commit %s does not exist in current branch' % commit) utils.execute(['git', 'checkout', '-f', commit], self.repo_dir, check_result=True) utils.execute(['git', 'clean', '-fxd'], self.repo_dir, check_result=True) if self.get_current_commit() != commit: - raise RepoManagerError('Error checking out commit %s' % commit) + raise RuntimeError('Error checking out commit %s' % commit) def remove_repo(self): """Attempts to remove the git repo. """ diff --git a/infra/repo_manager_test.py b/infra/repo_manager_test.py index d4fa2695c..f489b2da1 100644 --- a/infra/repo_manager_test.py +++ b/infra/repo_manager_test.py @@ -11,12 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing perepo_managerissions and # limitations under the License. -"""Test the functionality of the RepoManager class -The will consist of the following functional tests - 1. Cloning of directory in desired location - 2. Checking out a specific commit - 3. Can get a list of commits between two SHAs -""" +"""Test the functionality of the RepoManager class.""" import os import unittest @@ -46,11 +41,11 @@ class RepoManagerCloneUnitTests(unittest.TestCase): def test_clone_invalid_repo(self): """Test that constructing RepoManager with an invalid repo will fail.""" with tempfile.TemporaryDirectory() as tmp_dir: - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): repo_manager.RepoManager(' ', tmp_dir) - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): repo_manager.RepoManager('not_a_valid_repo', tmp_dir) - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): repo_manager.RepoManager('https://github.com/oss-fuzz-not-real.git', tmp_dir) @@ -70,12 +65,12 @@ class RepoManagerCheckoutUnitTests(unittest.TestCase): """Tests that the git checkout invalid commit fails.""" with tempfile.TemporaryDirectory() as tmp_dir: test_repo_manager = repo_manager.RepoManager(OSS_FUZZ_REPO, tmp_dir) - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): test_repo_manager.checkout_commit(' ') - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): test_repo_manager.checkout_commit( 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): test_repo_manager.checkout_commit('not-a-valid-commit') @@ -105,14 +100,38 @@ class RepoManagerGetCommitListUnitTests(unittest.TestCase): old_commit = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b' new_commit = 'fa662173bfeb3ba08d2e84cefc363be11e6c8463' test_repo_manager = repo_manager.RepoManager(OSS_FUZZ_REPO, tmp_dir) - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): test_repo_manager.get_commit_list('fakecommit', new_commit) - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(ValueError): test_repo_manager.get_commit_list(new_commit, 'fakecommit') - with self.assertRaises(repo_manager.RepoManagerError): + with self.assertRaises(RuntimeError): # pylint: disable=arguments-out-of-order test_repo_manager.get_commit_list(new_commit, old_commit) +class RepoManagerCheckoutPullRequestUnitTests(unittest.TestCase): + """Class to test the functionality of checkout_pr of the RepoManager class.""" + + def test_checkout_valid_pull_request(self): + """Tests that the git checkout pull request works.""" + with tempfile.TemporaryDirectory() as tmp_dir: + test_repo_manager = repo_manager.RepoManager(OSS_FUZZ_REPO, tmp_dir) + test_repo_manager.checkout_pr('refs/pull/3310/merge') + self.assertEqual(test_repo_manager.get_current_commit(), + 'ff00c1685ccf32f729cf6c834e641223ce6262e4') + + def test_checkout_invalid_pull_request(self): + """Tests that the git checkout invalid pull request fails.""" + with tempfile.TemporaryDirectory() as tmp_dir: + test_repo_manager = repo_manager.RepoManager(OSS_FUZZ_REPO, tmp_dir) + with self.assertRaises(RuntimeError): + test_repo_manager.checkout_pr(' ') + with self.assertRaises(RuntimeError): + test_repo_manager.checkout_pr( + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') + with self.assertRaises(RuntimeError): + test_repo_manager.checkout_pr('not/a/valid/pr') + + if __name__ == '__main__': unittest.main() |