aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjonathanmetzman <31354670+jonathanmetzman@users.noreply.github.com>2021-07-22 12:51:34 -0700
committerGitHub <noreply@github.com>2021-07-22 12:51:34 -0700
commit24eb7e666824435ff0085a64690f625293fb7fae (patch)
tree049a67288037c0c2fd44482623cbf4ea9cef4d7c
parent3d75fc9fb426cb2a96a97c950fe6c08c6214bfc3 (diff)
downloadoss-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__.py2
-rw-r--r--infra/cifuzz/filestore/github_actions/github_actions_test.py138
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."""