diff --git a/swh/web/tests/common/test_service.py b/swh/web/tests/common/test_service.py --- a/swh/web/tests/common/test_service.py +++ b/swh/web/tests/common/test_service.py @@ -4,14 +4,26 @@ # See top-level LICENSE file for more information import datetime +import itertools +import pytest +import random -from unittest.mock import MagicMock, patch, call +from hypothesis import given +from unittest.mock import MagicMock, patch from swh.model.hashutil import hash_to_bytes, hash_to_hex from swh.web.common import service from swh.web.common.exc import BadInputExc, NotFoundExc -from swh.web.tests.testcase import WebTestCase +from swh.web.tests.strategies import ( + content, contents, unknown_content, unknown_contents, + contents_with_ctags, origin, visit_dates, directory, + release, revision, unknown_revision, ancestor_revisions, + non_ancestor_revisions, invalid_sha1, sha256 +) +from swh.web.tests.testcase import ( + WebTestCase, ctags_json_missing +) class ServiceTestCase(WebTestCase): @@ -114,244 +126,102 @@ 'visit': 1 } - @patch('swh.web.common.service.storage') - def test_lookup_multiple_hashes_ball_missing(self, mock_storage): - # given - mock_storage.content_missing_per_sha1 = MagicMock(return_value=[]) + @given(contents()) + def test_lookup_multiple_hashes_all_present(self, contents): + input_data = [] + expected_output = [] + for cnt in contents: + input_data.append({'sha1': cnt['sha1']}) + expected_output.append({'sha1': cnt['sha1'], + 'found': True}) - # when - actual_lookup = service.lookup_multiple_hashes( - [{'filename': 'a', - 'sha1': '456caf10e9535160d90e874b45aa426de762f19f'}, - {'filename': 'b', - 'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865'}]) + self.assertEqual(service.lookup_multiple_hashes(input_data), + expected_output) - # then - self.assertEqual(actual_lookup, [ - {'filename': 'a', - 'sha1': '456caf10e9535160d90e874b45aa426de762f19f', - 'found': True}, - {'filename': 'b', - 'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865', - 'found': True} - ]) + @given(contents(), unknown_contents()) + def test_lookup_multiple_hashes_some_missing(self, contents, + unknown_contents): + input_contents = list(itertools.chain(contents, unknown_contents)) + random.shuffle(input_contents) - @patch('swh.web.common.service.storage') - def test_lookup_multiple_hashes_some_missing(self, mock_storage): - # given - mock_storage.content_missing_per_sha1 = MagicMock(return_value=[ - hash_to_bytes('456caf10e9535160d90e874b45aa426de762f19f') - ]) + input_data = [] + expected_output = [] + for cnt in input_contents: + input_data.append({'sha1': cnt['sha1']}) + expected_output.append({'sha1': cnt['sha1'], + 'found': cnt in contents}) - # when - actual_lookup = service.lookup_multiple_hashes( - [{'filename': 'a', - 'sha1': '456caf10e9535160d90e874b45aa426de762f19f'}, - {'filename': 'b', - 'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865'}]) + self.assertEqual(service.lookup_multiple_hashes(input_data), + expected_output) - # then - self.assertEqual(actual_lookup, [ - {'filename': 'a', - 'sha1': '456caf10e9535160d90e874b45aa426de762f19f', - 'found': False}, - {'filename': 'b', - 'sha1': '745bab676c8f3cec8016e0c39ea61cf57e518865', - 'found': True} - ]) + @given(unknown_content()) + def test_lookup_hash_does_not_exist(self, unknown_content): - @patch('swh.web.common.service.storage') - def test_lookup_hash_does_not_exist(self, mock_storage): - # given - mock_storage.content_find = MagicMock(return_value=None) + actual_lookup = service.lookup_hash('sha1_git:%s' % + unknown_content['sha1_git']) - # when - actual_lookup = service.lookup_hash( - 'sha1_git:123caf10e9535160d90e874b45aa426de762f19f') + self.assertEqual(actual_lookup, {'found': None, + 'algo': 'sha1_git'}) - # then - self.assertEqual({'found': None, - 'algo': 'sha1_git'}, actual_lookup) + @given(content()) + def test_lookup_hash_exist(self, content): - # check the function has been called with parameters - mock_storage.content_find.assert_called_with( - {'sha1_git': - hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')}) + actual_lookup = service.lookup_hash('sha1:%s' % content['sha1']) - @patch('swh.web.common.service.storage') - def test_lookup_hash_exist(self, mock_storage): - # given - stub_content = { - 'sha1': hash_to_bytes( - '456caf10e9535160d90e874b45aa426de762f19f') - } - mock_storage.content_find = MagicMock(return_value=stub_content) + content_metadata = self.content_get_metadata(content['sha1']) - # when - actual_lookup = service.lookup_hash( - 'sha1:456caf10e9535160d90e874b45aa426de762f19f') - - # then - self.assertEqual({ - 'found': { - 'checksums': { - 'sha1': '456caf10e9535160d90e874b45aa426de762f19f' - } - }, - 'algo': 'sha1' - }, actual_lookup) - - mock_storage.content_find.assert_called_with( - {'sha1': - hash_to_bytes('456caf10e9535160d90e874b45aa426de762f19f')} - ) + self.assertEqual({'found': content_metadata, + 'algo': 'sha1'}, actual_lookup) - @patch('swh.web.common.service.storage') - def test_search_hash_does_not_exist(self, mock_storage): - # given - mock_storage.content_find = MagicMock(return_value=None) + @given(unknown_content()) + def test_search_hash_does_not_exist(self, content): - # when - actual_lookup = service.search_hash( - 'sha1_git:123caf10e9535160d90e874b45aa426de762f19f') + actual_lookup = service.search_hash('sha1_git:%s' % + content['sha1_git']) - # then self.assertEqual({'found': False}, actual_lookup) - # check the function has been called with parameters - mock_storage.content_find.assert_called_with( - {'sha1_git': - hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')}) - - @patch('swh.web.common.service.storage') - def test_search_hash_exist(self, mock_storage): - # given - stub_content = { - 'sha1': hash_to_bytes( - '456caf10e9535160d90e874b45aa426de762f19f') - } - mock_storage.content_find = MagicMock(return_value=stub_content) + @given(content()) + def test_search_hash_exist(self, content): - # when - actual_lookup = service.search_hash( - 'sha1:456caf10e9535160d90e874b45aa426de762f19f') + actual_lookup = service.search_hash('sha1:%s' % content['sha1']) - # then self.assertEqual({'found': True}, actual_lookup) - mock_storage.content_find.assert_called_with( - {'sha1': - hash_to_bytes('456caf10e9535160d90e874b45aa426de762f19f')}, - ) + @pytest.mark.skipif(ctags_json_missing, + reason="requires ctags with json output support") + @given(contents_with_ctags()) + def test_lookup_content_ctags(self, contents_with_ctags): - @patch('swh.web.common.service.idx_storage') - def test_lookup_content_ctags(self, mock_idx_storage): - # given - mock_idx_storage.content_ctags_get = MagicMock( - return_value=[{ - 'id': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f'), - 'line': 100, - 'name': 'hello', - 'kind': 'function', - 'tool_name': 'ctags', - 'tool_version': 'some-version', - }]) - expected_ctags = [{ - 'id': '123caf10e9535160d90e874b45aa426de762f19f', - 'line': 100, - 'name': 'hello', - 'kind': 'function', - 'tool_name': 'ctags', - 'tool_version': 'some-version', - }] + content_sha1 = random.choice(contents_with_ctags['sha1s']) + self.content_add_ctags(content_sha1) + actual_ctags = \ + list(service.lookup_content_ctags('sha1:%s' % content_sha1)) - # when - actual_ctags = list(service.lookup_content_ctags( - 'sha1:123caf10e9535160d90e874b45aa426de762f19f')) + expected_data = list(self.content_get_ctags(content_sha1)) + for ctag in expected_data: + ctag['id'] = content_sha1 - # then - self.assertEqual(actual_ctags, expected_ctags) + self.assertEqual(actual_ctags, expected_data) - mock_idx_storage.content_ctags_get.assert_called_with( - [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - - @patch('swh.web.common.service.idx_storage') - def test_lookup_content_ctags_no_hash(self, mock_idx_storage): - # given - mock_idx_storage.content_ctags_get = MagicMock(return_value=[]) + @given(unknown_content()) + def test_lookup_content_ctags_no_hash(self, unknown_content): - # when - actual_ctags = list(service.lookup_content_ctags( - 'sha1:123caf10e9535160d90e874b45aa426de762f19f')) + actual_ctags = \ + list(service.lookup_content_ctags('sha1:%s' % + unknown_content['sha1'])) - # then self.assertEqual(actual_ctags, []) - @patch('swh.web.common.service.idx_storage') - def test_lookup_content_filetype(self, mock_idx_storage): - # given - mock_idx_storage.content_mimetype_get = MagicMock( - return_value=[{ - 'id': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f'), - 'mimetype': 'text/x-c++', - 'encoding': 'us-ascii', - }]) - expected_filetype = { - 'id': '123caf10e9535160d90e874b45aa426de762f19f', - 'mimetype': 'text/x-c++', - 'encoding': 'us-ascii', - } - - # when - actual_filetype = service.lookup_content_filetype( - 'sha1:123caf10e9535160d90e874b45aa426de762f19f') - - # then - self.assertEqual(actual_filetype, expected_filetype) - - mock_idx_storage.content_mimetype_get.assert_called_with( - [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - - @patch('swh.web.common.service.idx_storage') - @patch('swh.web.common.service.storage') - def test_lookup_content_filetype_2(self, mock_storage, mock_idx_storage): - # given - mock_storage.content_find = MagicMock( - return_value={ - 'sha1': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f') - } - ) - mock_idx_storage.content_mimetype_get = MagicMock( - return_value=[{ - 'id': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f'), - 'mimetype': 'text/x-python', - 'encoding': 'us-ascii', - }] - ) - expected_filetype = { - 'id': '123caf10e9535160d90e874b45aa426de762f19f', - 'mimetype': 'text/x-python', - 'encoding': 'us-ascii', - } + @given(content()) + def test_lookup_content_filetype(self, content): - # when - actual_filetype = service.lookup_content_filetype( - 'sha1_git:456caf10e9535160d90e874b45aa426de762f19f') + self.content_add_mimetype(content['sha1']) + actual_filetype = service.lookup_content_filetype(content['sha1']) - # then + expected_filetype = self.content_get_mimetype(content['sha1']) self.assertEqual(actual_filetype, expected_filetype) - mock_storage.content_find( - 'sha1_git', hash_to_bytes( - '456caf10e9535160d90e874b45aa426de762f19f') - ) - mock_idx_storage.content_mimetype_get.assert_called_with( - [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - @patch('swh.web.common.service.idx_storage') def test_lookup_content_language(self, mock_idx_storage): # given @@ -377,42 +247,6 @@ [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) @patch('swh.web.common.service.idx_storage') - @patch('swh.web.common.service.storage') - def test_lookup_content_language_2(self, mock_storage, mock_idx_storage): - # given - mock_storage.content_find = MagicMock( - return_value={ - 'sha1': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f') - } - ) - mock_idx_storage.content_language_get = MagicMock( - return_value=[{ - 'id': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f'), - 'lang': 'haskell', - }] - ) - expected_language = { - 'id': '123caf10e9535160d90e874b45aa426de762f19f', - 'lang': 'haskell', - } - - # when - actual_language = service.lookup_content_language( - 'sha1_git:456caf10e9535160d90e874b45aa426de762f19f') - - # then - self.assertEqual(actual_language, expected_language) - - mock_storage.content_find( - 'sha1_git', hash_to_bytes( - '456caf10e9535160d90e874b45aa426de762f19f') - ) - mock_idx_storage.content_language_get.assert_called_with( - [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - - @patch('swh.web.common.service.idx_storage') def test_lookup_expression(self, mock_idx_storage): # given mock_idx_storage.content_ctags_search = MagicMock( @@ -487,470 +321,161 @@ mock_idx_storage.content_fossology_license_get.assert_called_with( [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - @patch('swh.web.common.service.idx_storage') - @patch('swh.web.common.service.storage') - def test_lookup_content_license_2(self, mock_storage, mock_idx_storage): - # given - mock_storage.content_find = MagicMock( - return_value={ - 'sha1': hash_to_bytes( - '123caf10e9535160d90e874b45aa426de762f19f') - } - ) - mock_idx_storage.content_fossology_license_get = MagicMock( - return_value=[{ - hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f'): [{ - 'licenses': ['BSD-2-Clause'], - 'tool': {} - }] - - }] - ) - expected_license = { - 'id': '123caf10e9535160d90e874b45aa426de762f19f', - 'facts': [{ - 'licenses': ['BSD-2-Clause'], - 'tool': {} - }] - } - - # when - actual_license = service.lookup_content_license( - 'sha1_git:456caf10e9535160d90e874b45aa426de762f19f') - - # then - self.assertEqual(actual_license, expected_license) - - mock_storage.content_find( - 'sha1_git', hash_to_bytes( - '456caf10e9535160d90e874b45aa426de762f19f') - ) - mock_idx_storage.content_fossology_license_get.assert_called_with( - [hash_to_bytes('123caf10e9535160d90e874b45aa426de762f19f')]) - - @patch('swh.web.common.service.storage') - def test_stat_counters(self, mock_storage): - # given - input_stats = { - "content": 1770830, - "directory": 211683, - "directory_entry_dir": 209167, - "directory_entry_file": 1807094, - "directory_entry_rev": 0, - "origin": 1096, - "person": 0, - "release": 8584, - "revision": 7792, - "revision_history": 0, - "skipped_content": 0 - } - mock_storage.stat_counters = MagicMock(return_value=input_stats) - - # when + def test_stat_counters(self): actual_stats = service.stat_counters() + self.assertEqual(actual_stats, self.storage.stat_counters()) - # then - expected_stats = input_stats - self.assertEqual(actual_stats, expected_stats) + @given(origin(), visit_dates()) + def test_lookup_origin_visits(self, origin, visit_dates): - mock_storage.stat_counters.assert_called_with() + origin_id = self.storage.origin_add_one(origin) + for ts in visit_dates: + self.storage.origin_visit_add(origin_id, ts) - @patch('swh.web.common.service._lookup_origin_visits') - def test_lookup_origin_visits(self, mock_lookup_visits): - # given - date_origin_visit2 = datetime.datetime( - 2013, 7, 1, 20, 0, 0, - tzinfo=datetime.timezone.utc) + actual_origin_visits = list(service.lookup_origin_visits(origin_id)) - date_origin_visit3 = datetime.datetime( - 2015, 1, 1, 21, 0, 0, - tzinfo=datetime.timezone.utc) - stub_result = [self.origin_visit1, { - 'date': date_origin_visit2, - 'origin': 1, - 'visit': 2, - 'target': hash_to_bytes( - '65a55bbdf3629f916219feb3dcc7393ded1bc8db'), - 'branch': b'master', - 'target_type': 'release', - 'metadata': None, - }, { - 'date': date_origin_visit3, - 'origin': 1, - 'visit': 3 - }] - mock_lookup_visits.return_value = stub_result + expected_visits = list(self.storage.origin_visit_get(origin_id)) + for visit in expected_visits: + visit['date'] = visit['date'].isoformat() + visit['metadata'] = {} - # when - expected_origin_visits = [{ - 'date': self.origin_visit1['date'].isoformat(), - 'origin': self.origin_visit1['origin'], - 'visit': self.origin_visit1['visit'] - }, { - 'date': date_origin_visit2.isoformat(), - 'origin': 1, - 'visit': 2, - 'target': '65a55bbdf3629f916219feb3dcc7393ded1bc8db', - 'branch': 'master', - 'target_type': 'release', - 'metadata': {}, - }, { - 'date': date_origin_visit3.isoformat(), - 'origin': 1, - 'visit': 3 - }] + self.assertEqual(actual_origin_visits, expected_visits) - actual_origin_visits = service.lookup_origin_visits(6) + @given(origin(), visit_dates()) + def test_lookup_origin_visit(self, origin, visit_dates): + origin_id = self.storage.origin_add_one(origin) + visits = [] + for ts in visit_dates: + visits.append(self.storage.origin_visit_add(origin_id, ts)) - # then - self.assertEqual(list(actual_origin_visits), expected_origin_visits) + visit = random.choice(visits)['visit'] + actual_origin_visit = service.lookup_origin_visit(origin_id, visit) - mock_lookup_visits.assert_called_once_with( - 6, last_visit=None, limit=10) + expected_visit = dict(self.storage.origin_visit_get_by(origin_id, + visit)) + expected_visit['date'] = expected_visit['date'].isoformat() + expected_visit['metadata'] = {} - @patch('swh.web.common.service.storage') - def test_lookup_origin_visit(self, mock_storage): - # given - stub_result = self.origin_visit1 - mock_storage.origin_visit_get_by.return_value = stub_result + self.assertEqual(actual_origin_visit, expected_visit) - expected_origin_visit = { - 'date': self.origin_visit1['date'].isoformat(), - 'origin': self.origin_visit1['origin'], - 'visit': self.origin_visit1['visit'] - } + @given(origin()) + def test_lookup_origin(self, origin): + origin_id = self.storage.origin_add_one(origin) - # when - actual_origin_visit = service.lookup_origin_visit(1, 1) - - # then - self.assertEqual(actual_origin_visit, expected_origin_visit) - - mock_storage.origin_visit_get_by.assert_called_once_with(1, 1) - - @patch('swh.web.common.service.storage') - def test_lookup_origin(self, mock_storage): - # given - mock_storage.origin_get = MagicMock(return_value={ - 'id': 'origin-id', - 'url': 'ftp://some/url/to/origin', - 'type': 'ftp'}) - - # when - actual_origin = service.lookup_origin({'id': 'origin-id'}) - - # then - self.assertEqual(actual_origin, {'id': 'origin-id', - 'url': 'ftp://some/url/to/origin', - 'type': 'ftp'}) + actual_origin = service.lookup_origin({'id': origin_id}) + expected_origin = self.storage.origin_get({'id': origin_id}) + self.assertEqual(actual_origin, expected_origin) - mock_storage.origin_get.assert_called_with({'id': 'origin-id'}) - - @patch('swh.web.common.service.storage') - def test_lookup_release_ko_id_checksum_not_a_sha1(self, mock_storage): - # given - mock_storage.release_get = MagicMock() + actual_origin = service.lookup_origin({'type': origin['type'], + 'url': origin['url']}) + expected_origin = self.storage.origin_get({'type': origin['type'], + 'url': origin['url']}) + self.assertEqual(actual_origin, expected_origin) + @given(invalid_sha1()) + def test_lookup_release_ko_id_checksum_not_a_sha1(self, invalid_sha1): with self.assertRaises(BadInputExc) as cm: - # when - service.lookup_release('not-a-sha1') + service.lookup_release(invalid_sha1) self.assertIn('invalid checksum', cm.exception.args[0].lower()) - mock_storage.release_get.called = False - - @patch('swh.web.common.service.storage') - def test_lookup_release_ko_id_checksum_too_long(self, mock_storage): - # given - mock_storage.release_get = MagicMock() - - # when + @given(sha256()) + def test_lookup_release_ko_id_checksum_too_long(self, sha256): with self.assertRaises(BadInputExc) as cm: - service.lookup_release( - '13c1d34d138ec13b5ebad226dc2528dc7506c956e4646f62d4daf5' - '1aea892abe') + service.lookup_release(sha256) self.assertEqual('Only sha1_git is supported.', cm.exception.args[0]) - mock_storage.release_get.called = False - - @patch('swh.web.common.service.storage') - def test_lookup_directory_with_path_not_found(self, mock_storage): - # given - mock_storage.lookup_directory_with_path = MagicMock(return_value=None) - - sha1_git = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' - - # when - actual_directory = mock_storage.lookup_directory_with_path( - sha1_git, 'some/path/here') - - self.assertIsNone(actual_directory) - - @patch('swh.web.common.service.storage') - def test_lookup_directory_with_path_found(self, mock_storage): - # given - sha1_git = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' - entry = {'id': 'dir-id', - 'type': 'dir', - 'name': 'some/path/foo'} - - mock_storage.lookup_directory_with_path = MagicMock(return_value=entry) - - # when - actual_directory = mock_storage.lookup_directory_with_path( - sha1_git, 'some/path/here') - - self.assertEqual(entry, actual_directory) - - @patch('swh.web.common.service.storage') - def test_lookup_release(self, mock_storage): - # given - mock_storage.release_get = MagicMock(return_value=[{ - 'id': hash_to_bytes('65a55bbdf3629f916219feb3dcc7393ded1bc8db'), - 'target': None, - 'date': { - 'timestamp': datetime.datetime( - 2015, 1, 1, 22, 0, 0, - tzinfo=datetime.timezone.utc).timestamp(), - 'offset': 0, - 'negative_utc': True, - }, - 'name': b'v0.0.1', - 'message': b'synthetic release', - 'synthetic': True, - }]) - - # when - actual_release = service.lookup_release( - '65a55bbdf3629f916219feb3dcc7393ded1bc8db') - - # then - self.assertEqual(actual_release, { - 'id': '65a55bbdf3629f916219feb3dcc7393ded1bc8db', - 'target': None, - 'date': '2015-01-01T22:00:00-00:00', - 'name': 'v0.0.1', - 'message': 'synthetic release', - 'synthetic': True, - }) - - mock_storage.release_get.assert_called_with( - [hash_to_bytes('65a55bbdf3629f916219feb3dcc7393ded1bc8db')]) - - def test_lookup_revision_with_context_ko_not_a_sha1_1(self): - # given - sha1_git = '13c1d34d138ec13b5ebad226dc2528dc7506c956e4646f62d4' \ - 'daf51aea892abe' - sha1_git_root = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' + @given(directory()) + def test_lookup_directory_with_path_not_found(self, directory): + path = 'some/invalid/path/here' + with self.assertRaises(NotFoundExc) as cm: + service.lookup_directory_with_path(directory, path) + self.assertEqual('Directory entry with path %s from %s ' + 'not found' % (path, directory), + cm.exception.args[0]) + + @given(directory()) + def test_lookup_directory_with_path_found(self, directory): + directory_content = self.directory_ls(directory) + directory_entry = random.choice(directory_content) + path = directory_entry['name'] + actual_result = service.lookup_directory_with_path(directory, path) + self.assertEqual(actual_result, directory_entry) + + @given(release()) + def test_lookup_release(self, release): + actual_release = service.lookup_release(release) + + self.assertEqual(actual_release, + self.release_get(release)) + + @given(revision(), invalid_sha1(), sha256()) + def test_lookup_revision_with_context_ko_not_a_sha1(self, revision, + invalid_sha1, + sha256): + sha1_git_root = revision + sha1_git = invalid_sha1 - # when with self.assertRaises(BadInputExc) as cm: service.lookup_revision_with_context(sha1_git_root, sha1_git) - self.assertIn('Only sha1_git is supported', cm.exception.args[0]) + self.assertIn('Invalid checksum query string', cm.exception.args[0]) - def test_lookup_revision_with_context_ko_not_a_sha1_2(self): - # given - sha1_git_root = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' - sha1_git = '13c1d34d138ec13b5ebad226dc2528dc7506c956e4646f6' \ - '2d4daf51aea892abe' + sha1_git = sha256 - # when with self.assertRaises(BadInputExc) as cm: service.lookup_revision_with_context(sha1_git_root, sha1_git) self.assertIn('Only sha1_git is supported', cm.exception.args[0]) - @patch('swh.web.common.service.storage') + @given(revision(), unknown_revision()) def test_lookup_revision_with_context_ko_sha1_git_does_not_exist( - self, - mock_storage): - # given - sha1_git_root = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' - sha1_git = '777777bdf3629f916219feb3dcc7393ded1bc8db' - - sha1_git_bin = hash_to_bytes(sha1_git) - - mock_storage.revision_get.return_value = None + self, revision, unknown_revision): + sha1_git_root = revision + sha1_git = unknown_revision - # when with self.assertRaises(NotFoundExc) as cm: service.lookup_revision_with_context(sha1_git_root, sha1_git) - self.assertIn('Revision 777777bdf3629f916219feb3dcc7393ded1bc8db' - ' not found', cm.exception.args[0]) - - mock_storage.revision_get.assert_called_once_with( - [sha1_git_bin]) + self.assertIn('Revision %s not found' % sha1_git, cm.exception.args[0]) - @patch('swh.web.common.service.storage') + @given(revision(), unknown_revision()) def test_lookup_revision_with_context_ko_root_sha1_git_does_not_exist( - self, - mock_storage): - # given - sha1_git_root = '65a55bbdf3629f916219feb3dcc7393ded1bc8db' - sha1_git = '777777bdf3629f916219feb3dcc7393ded1bc8db' - - sha1_git_root_bin = hash_to_bytes(sha1_git_root) - sha1_git_bin = hash_to_bytes(sha1_git) + self, revision, unknown_revision): + sha1_git_root = unknown_revision + sha1_git = revision - mock_storage.revision_get.side_effect = ['foo', None] - - # when with self.assertRaises(NotFoundExc) as cm: service.lookup_revision_with_context(sha1_git_root, sha1_git) - self.assertIn('Revision root 65a55bbdf3629f916219feb3dcc7393ded1bc8db' - ' not found', cm.exception.args[0]) - - mock_storage.revision_get.assert_has_calls([call([sha1_git_bin]), - call([sha1_git_root_bin])]) - - @patch('swh.web.common.service.storage') - @patch('swh.web.common.service.query') - def test_lookup_revision_with_context(self, mock_query, mock_storage): - # given - sha1_git_root = '666' - sha1_git = '883' - - sha1_git_root_bin = b'666' - sha1_git_bin = b'883' - - sha1_git_root_dict = { - 'id': sha1_git_root_bin, - 'parents': [b'999'], - } - sha1_git_dict = { - 'id': sha1_git_bin, - 'parents': [], - 'directory': b'278', - } - - stub_revisions = [ - sha1_git_root_dict, - { - 'id': b'999', - 'parents': [b'777', b'883', b'888'], - }, - { - 'id': b'777', - 'parents': [b'883'], - }, - sha1_git_dict, - { - 'id': b'888', - 'parents': [b'889'], - }, - { - 'id': b'889', - 'parents': [], - }, - ] - - # inputs ok - mock_query.parse_hash_with_algorithms_or_throws.side_effect = [ - ('sha1', sha1_git_bin), - ('sha1', sha1_git_root_bin) - ] - - # lookup revision first 883, then 666 (both exists) - mock_storage.revision_get.return_value = [ - sha1_git_dict, - sha1_git_root_dict - ] - - mock_storage.revision_log = MagicMock( - return_value=stub_revisions) - - # when - - actual_revision = service.lookup_revision_with_context( - sha1_git_root, - sha1_git) - - # then - self.assertEqual(actual_revision, { - 'id': hash_to_hex(sha1_git_bin), - 'parents': [], - 'children': [hash_to_hex(b'999'), hash_to_hex(b'777')], - 'directory': hash_to_hex(b'278'), - 'merge': False - }) - - mock_query.parse_hash_with_algorithms_or_throws.assert_has_calls( - [call(sha1_git, ['sha1'], 'Only sha1_git is supported.'), - call(sha1_git_root, ['sha1'], 'Only sha1_git is supported.')]) - - mock_storage.revision_log.assert_called_with( - [sha1_git_root_bin], 100) - - @patch('swh.web.common.service.storage') - @patch('swh.web.common.service.query') - def test_lookup_revision_with_context_retrieved_as_dict( - self, mock_query, mock_storage): - # given - sha1_git = '883' - - sha1_git_root_bin = b'666' - sha1_git_bin = b'883' - - sha1_git_root_dict = { - 'id': sha1_git_root_bin, - 'parents': [b'999'], - } - - sha1_git_dict = { - 'id': sha1_git_bin, - 'parents': [], - 'directory': b'278', - } - - stub_revisions = [ - sha1_git_root_dict, - { - 'id': b'999', - 'parents': [b'777', b'883', b'888'], - }, - { - 'id': b'777', - 'parents': [b'883'], - }, - sha1_git_dict, - { - 'id': b'888', - 'parents': [b'889'], - }, - { - 'id': b'889', - 'parents': [], - }, - ] - - # inputs ok - mock_query.parse_hash_with_algorithms_or_throws.return_value = ( - 'sha1', sha1_git_bin) - - # lookup only on sha1 - mock_storage.revision_get.return_value = [sha1_git_dict] - - mock_storage.revision_log.return_value = stub_revisions - - # when - actual_revision = service.lookup_revision_with_context( - {'id': sha1_git_root_bin}, - sha1_git) - - # then - self.assertEqual(actual_revision, { - 'id': hash_to_hex(sha1_git_bin), - 'parents': [], - 'children': [hash_to_hex(b'999'), hash_to_hex(b'777')], - 'directory': hash_to_hex(b'278'), - 'merge': False - }) - - mock_query.parse_hash_with_algorithms_or_throws.assert_called_once_with( # noqa - sha1_git, ['sha1'], 'Only sha1_git is supported.') + self.assertIn('Revision root %s not found' % sha1_git_root, + cm.exception.args[0]) - mock_storage.revision_get.assert_called_once_with([sha1_git_bin]) + @given(ancestor_revisions()) + def test_lookup_revision_with_context(self, ancestor_revisions): + sha1_git = ancestor_revisions['sha1_git'] + root_sha1_git = ancestor_revisions['sha1_git_root'] + for sha1_git_root in (root_sha1_git, + {'id': hash_to_bytes(root_sha1_git)}): + actual_revision = \ + service.lookup_revision_with_context(sha1_git_root, + sha1_git) + + children = [] + for rev in self.revision_log(root_sha1_git): + for p_rev in rev['parents']: + p_rev_hex = hash_to_hex(p_rev) + if p_rev_hex == sha1_git: + children.append(rev['id']) + + expected_revision = self.revision_get(sha1_git) + expected_revision['children'] = children + self.assertEqual(actual_revision, expected_revision) + + @given(non_ancestor_revisions()) + def test_lookup_revision_with_context_ko(self, non_ancestor_revisions): + sha1_git = non_ancestor_revisions['sha1_git'] + root_sha1_git = non_ancestor_revisions['sha1_git_root'] - mock_storage.revision_log.assert_called_with( - [sha1_git_root_bin], 100) + with self.assertRaises(NotFoundExc) as cm: + service.lookup_revision_with_context(root_sha1_git, sha1_git) + self.assertIn('Revision %s is not an ancestor of %s' % + (sha1_git, root_sha1_git), cm.exception.args[0]) @patch('swh.web.common.service.storage') @patch('swh.web.common.service.query') @@ -1241,21 +766,10 @@ mock_storage.content_find.assert_called_once_with({'sha1_git': b'789'}) mock_storage.content_get.assert_called_once_with([b'content-sha1']) - @patch('swh.web.common.service.storage') - def test_lookup_revision(self, mock_storage): - # given - mock_storage.revision_get = MagicMock( - return_value=[self.SAMPLE_REVISION_RAW]) - - # when - actual_revision = service.lookup_revision( - self.SHA1_SAMPLE) - - # then - self.assertEqual(actual_revision, self.SAMPLE_REVISION) - - mock_storage.revision_get.assert_called_with( - [self.SHA1_SAMPLE_BIN]) + @given(revision()) + def test_lookup_revision(self, revision): + actual_revision = service.lookup_revision(revision) + self.assertEqual(actual_revision, self.revision_get(revision)) @patch('swh.web.common.service.storage') def test_lookup_revision_invalid_msg(self, mock_storage):