diff options
author | jonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com> | 2021-07-22 12:51:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-22 12:51:34 -0700 |
commit | 24eb7e666824435ff0085a64690f625293fb7fae (patch) | |
tree | 049a67288037c0c2fd44482623cbf4ea9cef4d7c | |
parent | 3d75fc9fb426cb2a96a97c950fe6c08c6214bfc3 (diff) | |
download | oss-fuzz-24eb7e666824435ff0085a64690f625293fb7fae.tar.gz |
[NFC][cifuzz] Add tests for github actions. (#6094)
To avoid issues like #6087 before they land.
-rw-r--r-- | infra/cifuzz/filestore/github_actions/__init__.py | 2 | ||||
-rw-r--r-- | infra/cifuzz/filestore/github_actions/github_actions_test.py | 138 |
2 files changed, 129 insertions, 11 deletions
diff --git a/infra/cifuzz/filestore/github_actions/__init__.py b/infra/cifuzz/filestore/github_actions/__init__.py index dc7119fd1..c9d04e4ab 100644 --- a/infra/cifuzz/filestore/github_actions/__init__.py +++ b/infra/cifuzz/filestore/github_actions/__init__.py @@ -53,6 +53,8 @@ class GithubActionsFilestore(filestore.BaseFilestore): self.github_api_http_headers = github_api.get_http_auth_headers(config) def _get_artifact_name(self, name): + """Returns |name| prefixed with |self.ARITFACT_PREFIX| if it isn't already + prefixed. Otherwise returns |name|.""" if name.startswith(self.ARTIFACT_PREFIX): return name return f'{self.ARTIFACT_PREFIX}{name}' diff --git a/infra/cifuzz/filestore/github_actions/github_actions_test.py b/infra/cifuzz/filestore/github_actions/github_actions_test.py index a975c03d8..f9ff69ad2 100644 --- a/infra/cifuzz/filestore/github_actions/github_actions_test.py +++ b/infra/cifuzz/filestore/github_actions/github_actions_test.py @@ -13,12 +13,15 @@ # limitations under the License. """Tests for github_actions.""" import os +import shutil import sys import tarfile import tempfile import unittest from unittest import mock +from pyfakefs import fake_filesystem_unittest + # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.dirname( @@ -31,12 +34,19 @@ import test_helpers # pylint: disable=protected-access,no-self-use -class GithubActionsFilestoreTest(unittest.TestCase): +class GithubActionsFilestoreTest(fake_filesystem_unittest.TestCase): """Tests for GithubActionsFilestore.""" def setUp(self): test_helpers.patch_environ(self) self.github_token = 'example githubtoken' + self.owner = 'exampleowner' + self.repo = 'examplerepo' + os.environ['GITHUB_REPOSITORY'] = f'{self.owner}/{self.repo}' + self.config = test_helpers.create_run_config(github_token=self.github_token) + self.artifact_name = 'corpus' + self.corpus_dir = '/corpus-dir' + self.testcase = os.path.join(self.corpus_dir, 'testcase') def _get_expected_http_headers(self): return { @@ -47,13 +57,9 @@ class GithubActionsFilestoreTest(unittest.TestCase): @mock.patch('filestore.github_actions.github_api.list_artifacts') def test_list_artifacts(self, mocked_list_artifacts): """Tests that _list_artifacts works as intended.""" - owner = 'exampleowner' - repo = 'examplerepo' - os.environ['GITHUB_REPOSITORY'] = f'{owner}/{repo}' - config = test_helpers.create_run_config(github_token=self.github_token) - filestore = github_actions.GithubActionsFilestore(config) + filestore = github_actions.GithubActionsFilestore(self.config) filestore._list_artifacts() - mocked_list_artifacts.assert_called_with(owner, repo, + mocked_list_artifacts.assert_called_with(self.owner, self.repo, self._get_expected_http_headers()) @mock.patch('logging.warning') @@ -64,8 +70,7 @@ class GithubActionsFilestoreTest(unittest.TestCase): def test_download_latest_build_no_artifact(self, _, __, mocked_warning): """Tests that download_latest_build returns None and doesn't exception when find_artifact can't find an artifact.""" - config = test_helpers.create_run_config(github_token=self.github_token) - filestore = github_actions.GithubActionsFilestore(config) + filestore = github_actions.GithubActionsFilestore(self.config) name = 'build-name' build_dir = 'build-dir' self.assertIsNone(filestore.download_latest_build(name, build_dir)) @@ -80,14 +85,125 @@ class GithubActionsFilestoreTest(unittest.TestCase): def test_download_corpus_no_artifact(self, _, __, mocked_warning): """Tests that download_corpus_build returns None and doesn't exception when find_artifact can't find an artifact.""" - config = test_helpers.create_run_config(github_token=self.github_token) - filestore = github_actions.GithubActionsFilestore(config) + filestore = github_actions.GithubActionsFilestore(self.config) name = 'corpus-name' dst_dir = 'corpus-dir' self.assertFalse(filestore.download_corpus(name, dst_dir)) mocked_warning.assert_called_with('Could not download artifact: %s.', 'cifuzz-' + name) + @mock.patch('filestore.github_actions.tar_directory') + @mock.patch('third_party.github_actions_toolkit.artifact.artifact_client' + '.upload_artifact') + def test_upload_directory(self, mocked_upload_artifact, mocked_tar_directory): + """Tests that upload_directory invokes tar_directory and + artifact_client.upload_artifact properly.""" + self._create_corpus_dir() + filestore = github_actions.GithubActionsFilestore(self.config) + filestore.upload_directory(self.artifact_name, self.corpus_dir) + + # Don't assert what second argument will be since it's a temporary + # directory. + self.assertEqual(mocked_tar_directory.call_args_list[0][0][0], + self.corpus_dir) + + # Don't assert what second and third arguments will be since they are + # temporary directories. + expected_artifact_name = 'cifuzz-' + self.artifact_name + self.assertEqual(mocked_upload_artifact.call_args_list[0][0][0], + expected_artifact_name) + + # Assert artifacts list contains one tarfile. + artifacts_list = mocked_upload_artifact.call_args_list[0][0][1] + self.assertEqual(len(artifacts_list), 1) + self.assertEqual(os.path.basename(artifacts_list[0]), + expected_artifact_name + '.tar') + + def _create_corpus_dir(self): + """Sets up pyfakefs and creates a corpus directory containing + self.testcase.""" + self.setUpPyfakefs() + self.fs.create_file(self.testcase, contents='hi') + + @mock.patch('filestore.github_actions.GithubActionsFilestore._find_artifact') + @mock.patch('http_utils.download_and_unpack_zip') + def test_download_artifact(self, mocked_download_and_unpack_zip, + mocked_find_artifact): + """Tests that _download_artifact works as intended.""" + artifact_download_url = 'http://example.com/download' + artifact_listing = { + 'expired': False, + 'name': self.artifact_name, + 'archive_download_url': artifact_download_url + } + mocked_find_artifact.return_value = artifact_listing + + self._create_corpus_dir() + with tempfile.TemporaryDirectory() as temp_dir: + # Create a tarball. + archive_path = os.path.join(temp_dir, f'cifuzz-{self.artifact_name}.tar') + github_actions.tar_directory(self.corpus_dir, archive_path) + + artifact_download_dst_dir = os.path.join(temp_dir, 'dst') + os.mkdir(artifact_download_dst_dir) + + def mock_download_and_unpack_zip(url, download_artifact_temp_dir, + headers): + self.assertEqual(url, artifact_download_url) + self.assertEqual(headers, self._get_expected_http_headers()) + shutil.copy( + archive_path, + os.path.join(download_artifact_temp_dir, + os.path.basename(archive_path))) + return True + + mocked_download_and_unpack_zip.side_effect = mock_download_and_unpack_zip + filestore = github_actions.GithubActionsFilestore(self.config) + self.assertTrue( + filestore._download_artifact(self.artifact_name, + artifact_download_dst_dir)) + mocked_find_artifact.assert_called_with(f'cifuzz-{self.artifact_name}') + self.assertTrue( + os.path.exists( + os.path.join(artifact_download_dst_dir, + os.path.basename(self.testcase)))) + + @mock.patch('filestore.github_actions.github_api.list_artifacts') + def test_find_artifact(self, mocked_list_artifacts): + """Tests that _find_artifact works as intended.""" + artifact_listing_1 = { + 'expired': False, + 'name': 'other', + 'archive_download_url': 'http://download1' + } + artifact_listing_2 = { + 'expired': False, + 'name': self.artifact_name, + 'archive_download_url': 'http://download2' + } + artifact_listing_3 = { + 'expired': True, + 'name': self.artifact_name, + 'archive_download_url': 'http://download3' + } + artifact_listing_4 = { + 'expired': False, + 'name': self.artifact_name, + 'archive_download_url': 'http://download4' + } + artifacts = [ + artifact_listing_1, artifact_listing_2, artifact_listing_3, + artifact_listing_4 + ] + mocked_list_artifacts.return_value = artifacts + filestore = github_actions.GithubActionsFilestore(self.config) + # Test that find_artifact will return the most recent unexpired artifact + # with the correct name. + self.assertEqual(filestore._find_artifact(self.artifact_name), + artifact_listing_2) + mocked_list_artifacts.assert_called_with(self.owner, self.repo, + self._get_expected_http_headers()) + class TarDirectoryTest(unittest.TestCase): """Tests for tar_directory.""" |