• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 Google LLC
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Test the functionality of the RepoManager class."""
15
16import contextlib
17import os
18import tempfile
19import unittest
20from unittest import mock
21
22import repo_manager
23import utils
24
25# pylint: disable=protected-access
26
27OSS_FUZZ_REPO_URL = 'https://github.com/google/oss-fuzz'
28
29
30@contextlib.contextmanager
31def get_oss_fuzz_repo():
32  """Clones a temporary copy of the OSS-Fuzz repo. Returns the path to the
33  repo."""
34  repo_name = 'oss-fuzz'
35  with tempfile.TemporaryDirectory() as tmp_dir:
36    repo_manager._clone(OSS_FUZZ_REPO_URL, tmp_dir, repo_name)
37    yield os.path.join(tmp_dir, repo_name)
38
39
40class CloneTest(unittest.TestCase):
41  """Tests the _clone function."""
42
43  @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
44                   'INTEGRATION_TESTS=1 not set')
45  def test_clone_valid_repo_integration(self):
46    """Integration test that tests the correct location of the git repo."""
47    with get_oss_fuzz_repo() as oss_fuzz_repo:
48      git_path = os.path.join(oss_fuzz_repo, '.git')
49      self.assertTrue(os.path.isdir(git_path))
50
51  def test_clone_invalid_repo(self):
52    """Tests that cloning an invalid repo will fail."""
53    with tempfile.TemporaryDirectory() as tmp_dir:
54      with self.assertRaises(RuntimeError):
55        repo_manager._clone('https://github.com/oss-fuzz-not-real.git', tmp_dir,
56                            'oss-fuzz')
57
58
59@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
60                 'INTEGRATION_TESTS=1 not set')
61class RepoManagerCheckoutTest(unittest.TestCase):
62  """Tests the checkout functionality of RepoManager."""
63
64  def test_checkout_valid_commit(self):
65    """Tests that the git checkout command works."""
66    with get_oss_fuzz_repo() as oss_fuzz_repo:
67      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
68      commit_to_test = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b'
69      repo_man.checkout_commit(commit_to_test)
70      self.assertEqual(commit_to_test, repo_man.get_current_commit())
71
72  def test_checkout_invalid_commit(self):
73    """Tests that the git checkout invalid commit fails."""
74    with get_oss_fuzz_repo() as oss_fuzz_repo:
75      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
76      with self.assertRaises(ValueError):
77        repo_man.checkout_commit(' ')
78      with self.assertRaises(ValueError):
79        repo_man.checkout_commit('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
80      with self.assertRaises(ValueError):
81        repo_man.checkout_commit('not-a-valid-commit')
82
83
84@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
85                 'INTEGRATION_TESTS=1 not set')
86class RepoManagerGetCommitListTest(unittest.TestCase):
87  """Tests the get_commit_list method of RepoManager."""
88
89  def test_get_valid_commit_list(self):
90    """Tests an accurate commit list can be retrieved from the repo manager."""
91    with get_oss_fuzz_repo() as oss_fuzz_repo:
92      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
93      old_commit = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b'
94      new_commit = 'fa662173bfeb3ba08d2e84cefc363be11e6c8463'
95      commit_list = [
96          'fa662173bfeb3ba08d2e84cefc363be11e6c8463',
97          '17035317a44fa89d22fe6846d868d4bf57def78b',
98          '97dee00a3c4ce95071c3e061592f5fd577dea886',
99          '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b'
100      ]
101      result_list = repo_man.get_commit_list(new_commit, old_commit)
102      self.assertListEqual(commit_list, result_list)
103
104  def test_get_invalid_commit_list(self):
105    """Tests that the proper errors are thrown when invalid commits are
106    passed to get_commit_list."""
107    with get_oss_fuzz_repo() as oss_fuzz_repo:
108      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
109      old_commit = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b'
110      new_commit = 'fa662173bfeb3ba08d2e84cefc363be11e6c8463'
111      with self.assertRaises(ValueError):
112        repo_man.get_commit_list('fakecommit', new_commit)
113      with self.assertRaises(ValueError):
114        repo_man.get_commit_list(new_commit, 'fakecommit')
115      with self.assertRaises(RuntimeError):
116        repo_man.get_commit_list(old_commit, new_commit)  # pylint: disable=arguments-out-of-order
117
118
119@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
120                 'INTEGRATION_TESTS=1 not set')
121class GitDiffTest(unittest.TestCase):
122  """Tests get_git_diff."""
123
124  def test_diff_exists(self):
125    """Tests that a real diff is returned when a valid repo manager exists."""
126    with get_oss_fuzz_repo() as oss_fuzz_repo:
127      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
128      with mock.patch.object(utils,
129                             'execute',
130                             return_value=('test.py\ndiff.py', None, 0)):
131        diff = repo_man.get_git_diff()
132        self.assertCountEqual(diff, ['test.py', 'diff.py'])
133
134  def test_diff_empty(self):
135    """Tests that None is returned when there is no difference between repos."""
136    with get_oss_fuzz_repo() as oss_fuzz_repo:
137      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
138      with mock.patch.object(utils, 'execute', return_value=('', None, 0)):
139        diff = repo_man.get_git_diff()
140        self.assertIsNone(diff)
141
142  def test_error_on_command(self):
143    """Tests that None is returned when the command errors out."""
144    with get_oss_fuzz_repo() as oss_fuzz_repo:
145      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
146      with mock.patch.object(utils,
147                             'execute',
148                             return_value=('', 'Test error.', 1)):
149        diff = repo_man.get_git_diff()
150        self.assertIsNone(diff)
151
152  def test_diff_no_change(self):
153    """Tests that None is returned when there is no difference between repos."""
154    with get_oss_fuzz_repo() as oss_fuzz_repo:
155      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
156      diff = repo_man.get_git_diff()
157      self.assertIsNone(diff)
158
159
160@unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
161                 'INTEGRATION_TESTS=1 not set')
162class CheckoutPrIntegrationTest(unittest.TestCase):
163  """Does Integration tests on the checkout_pr method of RepoManager."""
164
165  def test_pull_request_exists(self):
166    """Tests that a diff is returned when a valid PR is checked out."""
167    with get_oss_fuzz_repo() as oss_fuzz_repo:
168      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
169      repo_man.checkout_pr('refs/pull/3415/merge')
170      diff = repo_man.get_git_diff()
171      self.assertCountEqual(diff, ['README.md'])
172
173  def test_checkout_invalid_pull_request(self):
174    """Tests that the git checkout invalid pull request fails."""
175    with get_oss_fuzz_repo() as oss_fuzz_repo:
176      repo_man = repo_manager.RepoManager(oss_fuzz_repo)
177      with self.assertRaises(RuntimeError):
178        repo_man.checkout_pr(' ')
179      with self.assertRaises(RuntimeError):
180        repo_man.checkout_pr('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
181      with self.assertRaises(RuntimeError):
182        repo_man.checkout_pr('not/a/valid/pr')
183
184
185if __name__ == '__main__':
186  unittest.main()
187