diff --git a/swh/web/tests/api/test_apidoc.py b/swh/web/tests/api/test_apidoc.py index 7ba43c28..c9080036 100644 --- a/swh/web/tests/api/test_apidoc.py +++ b/swh/web/tests/api/test_apidoc.py @@ -1,279 +1,279 @@ # Copyright (C) 2015-2018 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from rest_framework.test import APITestCase from rest_framework.response import Response from swh.web.api.apidoc import api_doc, _parse_httpdomain_doc from swh.web.api.apiurls import api_route from swh.web.tests.testcase import WebTestCase # flake8: noqa httpdomain_doc = """ .. http:get:: /api/1/revision/(sha1_git)/ Get information about a revision in the archive. Revisions are identified by **sha1** checksums, compatible with Git commit identifiers. See :func:`swh.model.identifiers.revision_identifier` in our data model module for details about how they are computed. :param string sha1_git: hexadecimal representation of the revision **sha1_git** identifier :reqheader Accept: the requested response content type, either ``application/json`` (default) or ``application/yaml`` :resheader Content-Type: this depends on :http:header:`Accept` header of request :>json object author: information about the author of the revision :>json string author_url: link to :http:get:`/api/1/person/(person_id)/` to get information about the author of the revision :>json object committer: information about the committer of the revision :>json string committer_url: link to :http:get:`/api/1/person/(person_id)/` to get information about the committer of the revision :>json string committer_date: ISO representation of the commit date (in UTC) :>json string date: ISO representation of the revision date (in UTC) :>json string directory: the unique identifier that revision points to :>json string directory_url: link to :http:get:`/api/1/directory/(sha1_git)/[(path)/]` to get information about the directory associated to the revision :>json string id: the revision unique identifier :>json boolean merge: whether or not the revision corresponds to a merge commit :>json string message: the message associated to the revision :>json array parents: the parents of the revision, i.e. the previous revisions that head directly to it, each entry of that array contains an unique parent revision identifier but also a link to :http:get:`/api/1/revision/(sha1_git)/` to get more information about it :>json string type: the type of the revision **Allowed HTTP Methods:** :http:method:`get`, :http:method:`head`, :http:method:`options` :statuscode 200: no error :statuscode 400: an invalid **sha1_git** value has been provided :statuscode 404: requested revision can not be found in the archive **Request:** .. parsed-literal:: $ curl -i :swh_web_api:`revision/aafb16d69fd30ff58afdd69036a26047f3aebdc6/` """ class APIDocTestCase(WebTestCase, APITestCase): def test_apidoc_nodoc_failure(self): with self.assertRaises(Exception): @api_doc('/my/nodoc/url/') def apidoc_nodoc_tester(request, arga=0, argb=0): return Response(arga + argb) @staticmethod @api_route(r'/some/(?P[0-9]+)/(?P[0-9]+)/', 'some-doc-route') @api_doc('/some/doc/route/') def apidoc_route(request, myarg, myotherarg, akw=0): """ Sample doc """ return {'result': int(myarg) + int(myotherarg) + akw} def test_apidoc_route_doc(self): # when rv = self.client.get('/api/1/some/doc/route/') # then - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertTemplateUsed('api/apidoc.html') def test_apidoc_route_fn(self): # when rv = self.client.get('/api/1/some/1/1/') # then - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) @staticmethod @api_route(r'/some/full/(?P[0-9]+)/(?P[0-9]+)/', 'some-complete-doc-route') @api_doc('/some/complete/doc/route/') def apidoc_full_stack(request, myarg, myotherarg, akw=0): """ Sample doc """ return {'result': int(myarg) + int(myotherarg) + akw} def test_apidoc_full_stack_doc(self): # when rv = self.client.get('/api/1/some/complete/doc/route/') # then - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertTemplateUsed('api/apidoc.html') def test_apidoc_full_stack_fn(self): # when rv = self.client.get('/api/1/some/full/1/1/') # then - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) def test_api_doc_parse_httpdomain(self): doc_data = { 'description': '', 'urls': [], 'args': [], 'params': [], 'resheaders': [], 'reqheaders': [], 'return_type': '', 'returns': [], 'status_codes': [], 'examples': [] } _parse_httpdomain_doc(httpdomain_doc, doc_data) expected_urls = [{ 'rule': '/api/1/revision/ **\\(sha1_git\\)** /', 'methods': ['GET', 'HEAD', 'OPTIONS'] }] self.assertIn('urls', doc_data) self.assertEqual(doc_data['urls'], expected_urls) expected_description = 'Get information about a revision in the archive. \ Revisions are identified by **sha1** checksums, compatible with Git commit \ identifiers. See **swh.model.identifiers.revision_identifier** in our data \ model module for details about how they are computed.' self.assertIn('description', doc_data) self.assertEqual(doc_data['description'], expected_description) expected_args = [{ 'name': 'sha1_git', 'type': 'string', 'doc': 'hexadecimal representation of the revision **sha1_git** identifier' }] self.assertIn('args', doc_data) self.assertEqual(doc_data['args'], expected_args) expected_params = [] self.assertIn('params', doc_data) self.assertEqual(doc_data['params'], expected_params) expected_reqheaders = [{ 'doc': 'the requested response content type, either ``application/json`` or ``application/yaml``', 'name': 'Accept' }] self.assertIn('reqheaders', doc_data) self.assertEqual(doc_data['reqheaders'], expected_reqheaders) expected_resheaders = [{ 'doc': 'this depends on **Accept** header of request', 'name': 'Content-Type' }] self.assertIn('resheaders', doc_data) self.assertEqual(doc_data['resheaders'], expected_resheaders) expected_statuscodes = [ { 'code': '200', 'doc': 'no error' }, { 'code': '400', 'doc': 'an invalid **sha1_git** value has been provided' }, { 'code': '404', 'doc': 'requested revision can not be found in the archive' } ] self.assertIn('status_codes', doc_data) self.assertEqual(doc_data['status_codes'], expected_statuscodes) expected_return_type = 'object' self.assertIn('return_type', doc_data) self.assertEqual(doc_data['return_type'], expected_return_type) expected_returns = [ { 'name': 'author', 'type': 'object', 'doc': 'information about the author of the revision' }, { 'name': 'author_url', 'type': 'string', 'doc': 'link to ``_ to get information about the author of the revision' }, { 'name': 'committer', 'type': 'object', 'doc': 'information about the committer of the revision' }, { 'name': 'committer_url', 'type': 'string', 'doc': 'link to ``_ to get information about the committer of the revision' }, { 'name': 'committer_date', 'type': 'string', 'doc': 'ISO representation of the commit date (in UTC)' }, { 'name': 'date', 'type': 'string', 'doc': 'ISO representation of the revision date (in UTC)' }, { 'name': 'directory', 'type': 'string', 'doc': 'the unique identifier that revision points to' }, { 'name': 'directory_url', 'type': 'string', 'doc': 'link to ``_ to get information about the directory associated to the revision' }, { 'name': 'id', 'type': 'string', 'doc': 'the revision unique identifier' }, { 'name': 'merge', 'type': 'boolean', 'doc': 'whether or not the revision corresponds to a merge commit' }, { 'name': 'message', 'type': 'string', 'doc': 'the message associated to the revision' }, { 'name': 'parents', 'type': 'array', 'doc': 'the parents of the revision, i.e. the previous revisions that head directly to it, each entry of that array contains an unique parent revision identifier but also a link to ``_ to get more information about it' }, { 'name': 'type', 'type': 'string', 'doc': 'the type of the revision' } ] self.assertIn('returns', doc_data) self.assertEqual(doc_data['returns'], expected_returns) expected_examples = ['/api/1/revision/aafb16d69fd30ff58afdd69036a26047f3aebdc6/'] self.assertIn('examples', doc_data) self.assertEqual(doc_data['examples'], expected_examples) diff --git a/swh/web/tests/api/test_apiresponse.py b/swh/web/tests/api/test_apiresponse.py index 21d295f9..74702de8 100644 --- a/swh/web/tests/api/test_apiresponse.py +++ b/swh/web/tests/api/test_apiresponse.py @@ -1,169 +1,169 @@ # Copyright (C) 2015-2018 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import json from rest_framework.test import APIRequestFactory from unittest.mock import patch from swh.web.api.apiresponse import ( compute_link_header, transform, make_api_response, filter_by_fields ) from swh.web.tests.testcase import WebTestCase api_request_factory = APIRequestFactory() class SWHComputeLinkHeaderTest(WebTestCase): def test_compute_link_header(self): rv = { 'headers': {'link-next': 'foo', 'link-prev': 'bar'}, 'results': [1, 2, 3] } options = {} # when headers = compute_link_header( rv, options) self.assertEqual(headers, { 'Link': '; rel="next",; rel="previous"', }) def test_compute_link_header_nothing_changed(self): rv = {} options = {} # when headers = compute_link_header( rv, options) self.assertEqual(headers, {}) def test_compute_link_header_nothing_changed_2(self): rv = {'headers': {}} options = {} # when headers = compute_link_header( rv, options) self.assertEqual(headers, {}) class SWHTransformProcessorTest(WebTestCase): def test_transform_only_return_results_1(self): rv = {'results': {'some-key': 'some-value'}} self.assertEqual(transform(rv), {'some-key': 'some-value'}) def test_transform_only_return_results_2(self): rv = {'headers': {'something': 'do changes'}, 'results': {'some-key': 'some-value'}} self.assertEqual(transform(rv), {'some-key': 'some-value'}) def test_transform_do_remove_headers(self): rv = {'headers': {'something': 'do changes'}, 'some-key': 'some-value'} self.assertEqual(transform(rv), {'some-key': 'some-value'}) def test_transform_do_nothing(self): rv = {'some-key': 'some-value'} self.assertEqual(transform(rv), {'some-key': 'some-value'}) class RendererTestCase(WebTestCase): @patch('swh.web.api.apiresponse.json') @patch('swh.web.api.apiresponse.filter_by_fields') @patch('swh.web.api.apiresponse.shorten_path') def test_swh_multi_response_mimetype(self, mock_shorten_path, mock_filter, mock_json): # given data = { 'data': [12, 34], 'id': 'adc83b19e793491b1c6ea0fd8b46cd9f32e592fc' } mock_filter.return_value = data mock_shorten_path.return_value = 'my_short_path' accepted_response_formats = {'html': 'text/html', 'yaml': 'application/yaml', 'json': 'application/json'} for format in accepted_response_formats: request = api_request_factory.get('/api/test/path/') mime_type = accepted_response_formats[format] setattr(request, 'accepted_media_type', mime_type) if mime_type == 'text/html': expected_data = { 'response_data': json.dumps(data), 'request': { 'path': request.path, 'method': request.method, 'absolute_uri': request.build_absolute_uri() }, 'headers_data': {}, 'heading': 'my_short_path', 'status_code': 200 } mock_json.dumps.return_value = json.dumps(data) else: expected_data = data # when rv = make_api_response(request, data) # then mock_filter.assert_called_with(request, data) self.assertEqual(rv.data, expected_data) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) if mime_type == 'text/html': self.assertEqual(rv.template_name, 'api/apidoc.html') def test_swh_filter_renderer_do_nothing(self): # given input_data = {'a': 'some-data'} request = api_request_factory.get('/api/test/path/', data={}) setattr(request, 'query_params', request.GET) # when actual_data = filter_by_fields(request, input_data) # then self.assertEqual(actual_data, input_data) @patch('swh.web.api.apiresponse.utils.filter_field_keys') def test_swh_filter_renderer_do_filter(self, mock_ffk): # given mock_ffk.return_value = {'a': 'some-data'} request = api_request_factory.get('/api/test/path/', data={'fields': 'a,c'}) setattr(request, 'query_params', request.GET) input_data = {'a': 'some-data', 'b': 'some-other-data'} # when actual_data = filter_by_fields(request, input_data) # then self.assertEqual(actual_data, {'a': 'some-data'}) mock_ffk.assert_called_once_with(input_data, {'a', 'c'}) diff --git a/swh/web/tests/api/views/test_content.py b/swh/web/tests/api/views/test_content.py index 6aff75f9..5f372109 100644 --- a/swh/web/tests/api/views/test_content.py +++ b/swh/web/tests/api/views/test_content.py @@ -1,391 +1,391 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import pytest from hypothesis import given from rest_framework.test import APITestCase from swh.web.common.utils import reverse from swh.web.tests.data import random_content from swh.web.tests.strategies import ( content, contents_with_ctags ) from swh.web.tests.testcase import ( WebTestCase, ctags_json_missing, fossology_missing ) class ContentApiTestCase(WebTestCase, APITestCase): @given(content()) def test_api_content_filetype(self, content): self.content_add_mimetype(content['sha1']) url = reverse('api-1-content-filetype', url_args={'q': 'sha1_git:%s' % content['sha1_git']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') content_url = reverse('api-1-content', url_args={'q': 'sha1:%s' % content['sha1']}) expected_data = self.content_get_mimetype(content['sha1']) expected_data['content_url'] = content_url self.assertEqual(rv.data, expected_data) def test_api_content_filetype_sha_not_found(self): unknown_content_ = random_content() url = reverse('api-1-content-filetype', url_args={'q': 'sha1:%s' % unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'No filetype information found for content ' 'sha1:%s.' % unknown_content_['sha1'] }) @pytest.mark.xfail # Language indexer is disabled @given(content()) def test_api_content_language(self, content): self.content_add_language(content['sha1']) url = reverse('api-1-content-language', url_args={'q': 'sha1_git:%s' % content['sha1_git']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') content_url = reverse('api-1-content', url_args={'q': 'sha1:%s' % content['sha1']}) expected_data = self.content_get_language(content['sha1']) expected_data['content_url'] = content_url self.assertEqual(rv.data, expected_data) def test_api_content_language_sha_not_found(self): unknown_content_ = random_content() url = reverse('api-1-content-language', url_args={'q': 'sha1:%s' % unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'No language information found for content ' 'sha1:%s.' % unknown_content_['sha1'] }) @pytest.mark.xfail # Language indexer is disabled @pytest.mark.skipif(ctags_json_missing, reason="requires ctags with json output support") @given(contents_with_ctags()) def test_api_content_symbol(self, contents_with_ctags): expected_data = {} for content_sha1 in contents_with_ctags['sha1s']: self.content_add_ctags(content_sha1) for ctag in self.content_get_ctags(content_sha1): if ctag['name'] == contents_with_ctags['symbol_name']: expected_data[content_sha1] = ctag break url = reverse('api-1-content-symbol', url_args={'q': contents_with_ctags['symbol_name']}, query_params={'per_page': 100}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') for entry in rv.data: content_sha1 = entry['sha1'] expected_entry = expected_data[content_sha1] for key, view_name in (('content_url', 'api-1-content'), ('data_url', 'api-1-content-raw'), ('license_url', 'api-1-content-license'), ('language_url', 'api-1-content-language'), ('filetype_url', 'api-1-content-filetype')): expected_entry[key] = reverse(view_name, url_args={'q': 'sha1:%s' % content_sha1}) expected_entry['sha1'] = content_sha1 del expected_entry['id'] self.assertEqual(entry, expected_entry) self.assertFalse('Link' in rv) url = reverse('api-1-content-symbol', url_args={'q': contents_with_ctags['symbol_name']}, query_params={'per_page': 2}) rv = self.client.get(url) next_url = reverse('api-1-content-symbol', url_args={'q': contents_with_ctags['symbol_name']}, query_params={'last_sha1': rv.data[1]['sha1'], 'per_page': 2}) self.assertEqual(rv['Link'], '<%s>; rel="next"' % next_url) def test_api_content_symbol_not_found(self): url = reverse('api-1-content-symbol', url_args={'q': 'bar'}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'No indexed raw content match expression \'bar\'.' }) self.assertFalse('Link' in rv) @pytest.mark.skipif(ctags_json_missing, reason="requires ctags with json output support") @given(content()) def test_api_content_ctags(self, content): self.content_add_ctags(content['sha1']) url = reverse('api-1-content-ctags', url_args={'q': 'sha1_git:%s' % content['sha1_git']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') content_url = reverse('api-1-content', url_args={'q': 'sha1:%s' % content['sha1']}) expected_data = list(self.content_get_ctags(content['sha1'])) for e in expected_data: e['content_url'] = content_url self.assertEqual(rv.data, expected_data) @pytest.mark.skipif(fossology_missing, reason="requires fossology-nomossa installed") @given(content()) def test_api_content_license(self, content): self.content_add_license(content['sha1']) url = reverse('api-1-content-license', url_args={'q': 'sha1_git:%s' % content['sha1_git']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') content_url = reverse('api-1-content', url_args={'q': 'sha1:%s' % content['sha1']}) expected_data = self.content_get_license(content['sha1']) expected_data['content_url'] = content_url self.assertEqual(rv.data, expected_data) def test_api_content_license_sha_not_found(self): unknown_content_ = random_content() url = reverse('api-1-content-license', url_args={'q': 'sha1:%s' % unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'No license information found for content ' 'sha1:%s.' % unknown_content_['sha1'] }) @given(content()) def test_api_content_metadata(self, content): url = reverse('api-1-content', {'q': 'sha1:%s' % content['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = self.content_get_metadata(content['sha1']) for key, view_name in (('data_url', 'api-1-content-raw'), ('license_url', 'api-1-content-license'), ('language_url', 'api-1-content-language'), ('filetype_url', 'api-1-content-filetype')): expected_data[key] = reverse(view_name, url_args={'q': 'sha1:%s' % content['sha1']}) self.assertEqual(rv.data, expected_data) def test_api_content_not_found_as_json(self): unknown_content_ = random_content() url = reverse('api-1-content', url_args={'q': 'sha1:%s' % unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Content with sha1 checksum equals to %s not found!' % unknown_content_['sha1'] }) def test_api_content_not_found_as_yaml(self): unknown_content_ = random_content() url = reverse('api-1-content', url_args={'q': 'sha256:%s' % unknown_content_['sha256']}) rv = self.client.get(url, HTTP_ACCEPT='application/yaml') - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertTrue('application/yaml' in rv['Content-Type']) self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Content with sha256 checksum equals to %s not found!' % unknown_content_['sha256'] }) def test_api_content_raw_ko_not_found(self): unknown_content_ = random_content() url = reverse('api-1-content-raw', url_args={'q': 'sha1:%s' % unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Content with sha1 checksum equals to %s not found!' % unknown_content_['sha1'] }) @given(content()) def test_api_content_raw_text(self, content): url = reverse('api-1-content-raw', url_args={'q': 'sha1:%s' % content['sha1']}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200) self.assertEqual(rv['Content-Type'], 'application/octet-stream') self.assertEqual( rv['Content-disposition'], 'attachment; filename=content_sha1_%s_raw' % content['sha1']) self.assertEqual( rv['Content-Type'], 'application/octet-stream') expected_data = self.content_get(content['sha1']) self.assertEqual(rv.content, expected_data['data']) @given(content()) def test_api_content_raw_text_with_filename(self, content): url = reverse('api-1-content-raw', url_args={'q': 'sha1:%s' % content['sha1']}, query_params={'filename': 'filename.txt'}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200) self.assertEqual(rv['Content-Type'], 'application/octet-stream') self.assertEqual( rv['Content-disposition'], 'attachment; filename=filename.txt') self.assertEqual( rv['Content-Type'], 'application/octet-stream') expected_data = self.content_get(content['sha1']) self.assertEqual(rv.content, expected_data['data']) @given(content()) def test_api_check_content_known(self, content): url = reverse('api-1-content-known', url_args={'q': content['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'search_res': [ { 'found': True, 'sha1': content['sha1'] } ], 'search_stats': {'nbfiles': 1, 'pct': 100.0} }) @given(content()) def test_api_check_content_known_as_yaml(self, content): url = reverse('api-1-content-known', url_args={'q': content['sha1']}) rv = self.client.get(url, HTTP_ACCEPT='application/yaml') - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/yaml') self.assertEqual(rv.data, { 'search_res': [ { 'found': True, 'sha1': content['sha1'] } ], 'search_stats': {'nbfiles': 1, 'pct': 100.0} }) @given(content()) def test_api_check_content_known_post_as_yaml(self, content): url = reverse('api-1-content-known') rv = self.client.post( url, data={ 'q': content['sha1'] }, HTTP_ACCEPT='application/yaml' ) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertTrue('application/yaml' in rv['Content-Type']) self.assertEqual(rv.data, { 'search_res': [ { 'found': True, 'sha1': content['sha1'] } ], 'search_stats': {'nbfiles': 1, 'pct': 100.0} }) def test_api_check_content_known_not_found(self): unknown_content_ = random_content() url = reverse('api-1-content-known', url_args={'q': unknown_content_['sha1']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'search_res': [ { 'found': False, 'sha1': unknown_content_['sha1'] } ], 'search_stats': {'nbfiles': 1, 'pct': 0.0} }) @given(content()) def test_api_content_uppercase(self, content): url = reverse('api-1-content-uppercase-checksum', url_args={'q': content['sha1'].upper()}) resp = self.client.get(url) self.assertEqual(resp.status_code, 302) redirect_url = reverse('api-1-content', url_args={'q': content['sha1']}) self.assertEqual(resp['location'], redirect_url) diff --git a/swh/web/tests/api/views/test_directory.py b/swh/web/tests/api/views/test_directory.py index 621280fd..8bc57df4 100644 --- a/swh/web/tests/api/views/test_directory.py +++ b/swh/web/tests/api/views/test_directory.py @@ -1,106 +1,106 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import random from hypothesis import given from rest_framework.test import APITestCase from swh.web.common.utils import reverse from swh.web.tests.data import random_sha1 from swh.web.tests.strategies import directory from swh.web.tests.testcase import WebTestCase class DirectoryApiTestCase(WebTestCase, APITestCase): @given(directory()) def test_api_directory(self, directory): url = reverse('api-1-directory', url_args={'sha1_git': directory}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = list(map(self._enrich_dir_data, self.directory_ls(directory))) self.assertEqual(rv.data, expected_data) def test_api_directory_not_found(self): unknown_directory_ = random_sha1() url = reverse('api-1-directory', url_args={'sha1_git': unknown_directory_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Directory with sha1_git %s not found' % unknown_directory_}) @given(directory()) def test_api_directory_with_path_found(self, directory): directory_content = self.directory_ls(directory) path = random.choice(directory_content) url = reverse('api-1-directory', url_args={'sha1_git': directory, 'path': path['name']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, self._enrich_dir_data(path)) @given(directory()) def test_api_directory_with_path_not_found(self, directory): path = 'some/path/to/nonexistent/dir/' url = reverse('api-1-directory', url_args={'sha1_git': directory, 'path': path}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': ('Directory entry with path %s from %s not found' % (path, directory))}) @given(directory()) def test_api_directory_uppercase(self, directory): url = reverse('api-1-directory-uppercase-checksum', url_args={'sha1_git': directory.upper()}) resp = self.client.get(url) self.assertEqual(resp.status_code, 302) redirect_url = reverse('api-1-directory', url_args={'sha1_git': directory}) self.assertEqual(resp['location'], redirect_url) @classmethod def _enrich_dir_data(cls, dir_data): if dir_data['type'] == 'file': dir_data['target_url'] = \ reverse('api-1-content', url_args={'q': 'sha1_git:%s' % dir_data['target']}) elif dir_data['type'] == 'dir': dir_data['target_url'] = \ reverse('api-1-directory', url_args={'sha1_git': dir_data['target']}) elif dir_data['type'] == 'rev': dir_data['target_url'] = \ reverse('api-1-revision', url_args={'sha1_git': dir_data['target']}) return dir_data diff --git a/swh/web/tests/api/views/test_identifiers.py b/swh/web/tests/api/views/test_identifiers.py index 5dbe36f7..d6f5059c 100644 --- a/swh/web/tests/api/views/test_identifiers.py +++ b/swh/web/tests/api/views/test_identifiers.py @@ -1,91 +1,91 @@ # Copyright (C) 2018-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from hypothesis import given from rest_framework.test import APITestCase from swh.model.identifiers import ( CONTENT, DIRECTORY, RELEASE, REVISION, SNAPSHOT ) from swh.web.common.utils import reverse from swh.web.tests.strategies import ( content, directory, origin, release, revision, snapshot, unknown_content, unknown_directory, unknown_release, unknown_revision, unknown_snapshot ) from swh.web.tests.testcase import WebTestCase class SwhIdsApiTestCase(WebTestCase, APITestCase): @given(origin(), content(), directory(), release(), revision(), snapshot()) def test_swh_id_resolve_success(self, origin, content, directory, release, revision, snapshot): for obj_type_short, obj_type, obj_id in ( ('cnt', CONTENT, content['sha1_git']), ('dir', DIRECTORY, directory), ('rel', RELEASE, release), ('rev', REVISION, revision), ('snp', SNAPSHOT, snapshot)): swh_id = 'swh:1:%s:%s;origin=%s' % (obj_type_short, obj_id, origin['url']) url = reverse('api-1-resolve-swh-pid', url_args={'swh_id': swh_id}) resp = self.client.get(url) if obj_type == CONTENT: url_args = {'query_string': 'sha1_git:%s' % obj_id} elif obj_type == SNAPSHOT: url_args = {'snapshot_id': obj_id} else: url_args = {'sha1_git': obj_id} browse_rev_url = reverse('browse-%s' % obj_type, url_args=url_args, query_params={'origin': origin['url']}) expected_result = { 'browse_url': browse_rev_url, 'metadata': {'origin': origin['url']}, 'namespace': 'swh', 'object_id': obj_id, 'object_type': obj_type, 'scheme_version': 1 } - self.assertEqual(resp.status_code, 200) + self.assertEqual(resp.status_code, 200, resp.data) self.assertEqual(resp.data, expected_result) def test_swh_id_resolve_invalid(self): rev_id_invalid = '96db9023b8_foo_50d6c108e9a3' swh_id = 'swh:1:rev:%s' % rev_id_invalid url = reverse('api-1-resolve-swh-pid', url_args={'swh_id': swh_id}) resp = self.client.get(url) - self.assertEqual(resp.status_code, 400) + self.assertEqual(resp.status_code, 400, resp.data) @given(unknown_content(), unknown_directory(), unknown_release(), unknown_revision(), unknown_snapshot()) def test_swh_id_resolve_not_found(self, unknown_content, unknown_directory, unknown_release, unknown_revision, unknown_snapshot): for obj_type_short, obj_id in (('cnt', unknown_content['sha1_git']), ('dir', unknown_directory), ('rel', unknown_release), ('rev', unknown_revision), ('snp', unknown_snapshot)): swh_id = 'swh:1:%s:%s' % (obj_type_short, obj_id) url = reverse('api-1-resolve-swh-pid', url_args={'swh_id': swh_id}) resp = self.client.get(url) - self.assertEqual(resp.status_code, 404) + self.assertEqual(resp.status_code, 404, resp.data) diff --git a/swh/web/tests/api/views/test_origin.py b/swh/web/tests/api/views/test_origin.py index 3bdcdc5d..8e2a61f2 100644 --- a/swh/web/tests/api/views/test_origin.py +++ b/swh/web/tests/api/views/test_origin.py @@ -1,408 +1,408 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import random from hypothesis import given from rest_framework.test import APITestCase from unittest.mock import patch from swh.storage.exc import StorageDBError, StorageAPIError from swh.web.common.utils import reverse from swh.web.common.origin_visits import get_origin_visits from swh.web.tests.strategies import ( origin, new_origin, new_origins, visit_dates, new_snapshots ) from swh.web.tests.testcase import WebTestCase class OriginApiTestCase(WebTestCase, APITestCase): @patch('swh.web.api.views.origin.get_origin_visits') def test_api_lookup_origin_visits_raise_error( self, mock_get_origin_visits, ): err_msg = 'voluntary error to check the bad request middleware.' mock_get_origin_visits.side_effect = ValueError(err_msg) url = reverse('api-1-origin-visits', url_args={'origin_id': 2}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 400) + self.assertEqual(rv.status_code, 400, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'ValueError', 'reason': err_msg}) @patch('swh.web.api.views.origin.get_origin_visits') def test_api_lookup_origin_visits_raise_swh_storage_error_db( self, mock_get_origin_visits): err_msg = 'Storage exploded! Will be back online shortly!' mock_get_origin_visits.side_effect = StorageDBError(err_msg) url = reverse('api-1-origin-visits', url_args={'origin_id': 2}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 503) + self.assertEqual(rv.status_code, 503, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'StorageDBError', 'reason': 'An unexpected error occurred in the backend: %s' % err_msg}) @patch('swh.web.api.views.origin.get_origin_visits') def test_api_lookup_origin_visits_raise_swh_storage_error_api( self, mock_get_origin_visits): err_msg = 'Storage API dropped dead! Will resurrect asap!' mock_get_origin_visits.side_effect = StorageAPIError(err_msg) url = reverse('api-1-origin-visits', url_args={'origin_id': 2}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 503) + self.assertEqual(rv.status_code, 503, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'StorageAPIError', 'reason': 'An unexpected error occurred in the api backend: %s' % err_msg }) @given(new_origin(), visit_dates(3), new_snapshots(3)) def test_api_lookup_origin_visits(self, new_origin, visit_dates, new_snapshots): origin_id = self.storage.origin_add_one(new_origin) new_origin['id'] = origin_id for i, visit_date in enumerate(visit_dates): origin_visit = self.storage.origin_visit_add(origin_id, visit_date) self.storage.snapshot_add(origin_id, origin_visit['visit'], new_snapshots[i]) all_visits = list(reversed(get_origin_visits(new_origin))) for last_visit, expected_visits in ( (None, all_visits[:2]), (all_visits[1]['visit'], all_visits[2:4])): url = reverse('api-1-origin-visits', url_args={'origin_id': origin_id}, query_params={'per_page': 2, 'last_visit': last_visit}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') for expected_visit in expected_visits: origin_visit_url = reverse( 'api-1-origin-visit', url_args={'origin_id': origin_id, 'visit_id': expected_visit['visit']}) snapshot_url = reverse( 'api-1-snapshot', url_args={'snapshot_id': expected_visit['snapshot']}) expected_visit['origin_visit_url'] = origin_visit_url expected_visit['snapshot_url'] = snapshot_url self.assertEqual(rv.data, expected_visits) @given(new_origin(), visit_dates(3), new_snapshots(3)) def test_api_lookup_origin_visit(self, new_origin, visit_dates, new_snapshots): origin_id = self.storage.origin_add_one(new_origin) new_origin['id'] = origin_id for i, visit_date in enumerate(visit_dates): origin_visit = self.storage.origin_visit_add(origin_id, visit_date) visit_id = origin_visit['visit'] self.storage.snapshot_add(origin_id, origin_visit['visit'], new_snapshots[i]) url = reverse('api-1-origin-visit', url_args={'origin_id': origin_id, 'visit_id': visit_id}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') expected_visit = self.origin_visit_get_by(origin_id, visit_id) origin_url = reverse('api-1-origin', url_args={'origin_id': origin_id}) snapshot_url = reverse( 'api-1-snapshot', url_args={'snapshot_id': expected_visit['snapshot']}) expected_visit['origin_url'] = origin_url expected_visit['snapshot_url'] = snapshot_url self.assertEqual(rv.data, expected_visit) @given(origin()) def test_api_lookup_origin_visit_not_found(self, origin): all_visits = list(reversed(get_origin_visits(origin))) max_visit_id = max([v['visit'] for v in all_visits]) url = reverse('api-1-origin-visit', url_args={'origin_id': origin['id'], 'visit_id': max_visit_id + 1}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Origin with id %s or its visit with id %s not found!' % (origin['id'], max_visit_id+1) }) @given(origin()) def test_api_origin_by_id(self, origin): url = reverse('api-1-origin', url_args={'origin_id': origin['id']}) rv = self.client.get(url) expected_origin = self.origin_get(origin) origin_visits_url = reverse('api-1-origin-visits', url_args={'origin_id': origin['id']}) expected_origin['origin_visits_url'] = origin_visits_url - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_origin) @given(origin()) def test_api_origin_by_type_url(self, origin): url = reverse('api-1-origin', url_args={'origin_type': origin['type'], 'origin_url': origin['url']}) rv = self.client.get(url) expected_origin = self.origin_get(origin) origin_visits_url = reverse('api-1-origin-visits', url_args={'origin_id': origin['id']}) expected_origin['origin_visits_url'] = origin_visits_url - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_origin) @given(new_origin()) def test_api_origin_not_found(self, new_origin): url = reverse('api-1-origin', url_args={'origin_type': new_origin['type'], 'origin_url': new_origin['url']}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Origin with type %s and url %s not found!' % (new_origin['type'], new_origin['url']) }) @given(origin()) def test_api_origin_metadata_search(self, origin): with patch('swh.web.common.service.idx_storage') as mock_idx_storage: mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .side_effect = lambda conjunction, limit: [{ 'from_revision': ( b'p&\xb7\xc1\xa2\xafVR\x1e\x95\x1c\x01\xed ' b'\xf2U\xfa\x05B8'), 'metadata': {'author': 'Jane Doe'}, 'id': origin['id'], 'tool': { 'configuration': { 'context': ['NpmMapping', 'CodemetaMapping'], 'type': 'local' }, 'id': 3, 'name': 'swh-metadata-detector', 'version': '0.0.1' } }] url = reverse('api-1-origin-metadata-search', query_params={'fulltext': 'Jane Doe'}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200, rv.content) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = [{ 'id': origin['id'], 'type': origin['type'], 'url': origin['url'], 'metadata': { 'metadata': {'author': 'Jane Doe'}, 'from_revision': ( '7026b7c1a2af56521e951c01ed20f255fa054238'), 'tool': { 'configuration': { 'context': ['NpmMapping', 'CodemetaMapping'], 'type': 'local' }, 'id': 3, 'name': 'swh-metadata-detector', 'version': '0.0.1', } } }] self.assertEqual(rv.data, expected_data) mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .assert_called_with(conjunction=['Jane Doe'], limit=70) @given(origin()) def test_api_origin_metadata_search_limit(self, origin): with patch('swh.web.common.service.idx_storage') as mock_idx_storage: mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .side_effect = lambda conjunction, limit: [{ 'from_revision': ( b'p&\xb7\xc1\xa2\xafVR\x1e\x95\x1c\x01\xed ' b'\xf2U\xfa\x05B8'), 'metadata': {'author': 'Jane Doe'}, 'id': origin['id'], 'tool': { 'configuration': { 'context': ['NpmMapping', 'CodemetaMapping'], 'type': 'local' }, 'id': 3, 'name': 'swh-metadata-detector', 'version': '0.0.1' } }] url = reverse('api-1-origin-metadata-search', query_params={'fulltext': 'Jane Doe'}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200, rv.content) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(len(rv.data), 1) mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .assert_called_with(conjunction=['Jane Doe'], limit=70) url = reverse('api-1-origin-metadata-search', query_params={'fulltext': 'Jane Doe', 'limit': 10}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200, rv.content) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(len(rv.data), 1) mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .assert_called_with(conjunction=['Jane Doe'], limit=10) url = reverse('api-1-origin-metadata-search', query_params={'fulltext': 'Jane Doe', 'limit': 987}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200, rv.content) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(len(rv.data), 1) mock_idx_storage.origin_intrinsic_metadata_search_fulltext \ .assert_called_with(conjunction=['Jane Doe'], limit=100) @given(origin()) def test_api_origin_intrinsic_metadata(self, origin): with patch('swh.web.common.service.idx_storage') as mock_idx_storage: mock_idx_storage.origin_intrinsic_metadata_get \ .side_effect = lambda origin_ids: [{ 'from_revision': ( b'p&\xb7\xc1\xa2\xafVR\x1e\x95\x1c\x01\xed ' b'\xf2U\xfa\x05B8'), 'metadata': {'author': 'Jane Doe'}, 'id': origin['id'], 'tool': { 'configuration': { 'context': ['NpmMapping', 'CodemetaMapping'], 'type': 'local' }, 'id': 3, 'name': 'swh-metadata-detector', 'version': '0.0.1' } }] url = reverse('api-origin-intrinsic-metadata', url_args={'origin_type': origin['type'], 'origin_url': origin['url']}) rv = self.client.get(url) mock_idx_storage.origin_intrinsic_metadata_get \ .assert_called_once_with([origin['id']]) self.assertEqual(rv.status_code, 200, rv.content) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = {'author': 'Jane Doe'} self.assertEqual(rv.data, expected_data) @patch('swh.web.common.service.idx_storage') def test_api_origin_metadata_search_invalid(self, mock_idx_storage): url = reverse('api-1-origin-metadata-search') rv = self.client.get(url) self.assertEqual(rv.status_code, 400, rv.content) mock_idx_storage.assert_not_called() @given(new_origins(10)) def test_api_lookup_origins(self, new_origins): nb_origins = len(new_origins) expected_origins = self.storage.origin_add(new_origins) origin_from_idx = random.randint(1, nb_origins-1) - 1 origin_from = expected_origins[origin_from_idx]['id'] max_origin_id = expected_origins[-1]['id'] origin_count = random.randint(1, max_origin_id - origin_from) url = reverse('api-1-origins', query_params={'origin_from': origin_from, 'origin_count': origin_count}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) start = origin_from_idx end = origin_from_idx + origin_count expected_origins = expected_origins[start:end] for expected_origin in expected_origins: expected_origin['origin_visits_url'] = reverse( 'api-1-origin-visits', url_args={'origin_id': expected_origin['id']}) self.assertEqual(rv.data, expected_origins) next_origin_id = expected_origins[-1]['id']+1 if self.storage.origin_get({'id': next_origin_id}): self.assertIn('Link', rv) next_url = reverse('api-1-origins', query_params={'origin_from': next_origin_id, 'origin_count': origin_count}) self.assertIn(next_url, rv['Link']) diff --git a/swh/web/tests/api/views/test_person.py b/swh/web/tests/api/views/test_person.py index e00c36ed..6b98f066 100644 --- a/swh/web/tests/api/views/test_person.py +++ b/swh/web/tests/api/views/test_person.py @@ -1,42 +1,42 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import random from hypothesis import given from rest_framework.test import APITestCase from swh.web.common.utils import reverse from swh.web.tests.strategies import person from swh.web.tests.testcase import WebTestCase class PersonApiTestCase(WebTestCase, APITestCase): @given(person()) def test_api_person(self, person): url = reverse('api-1-person', url_args={'person_id': person}) rv = self.client.get(url) expected_person = self.person_get(person) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_person) def test_api_person_not_found(self): unknown_person_ = random.randint(1000, 10000000) url = reverse('api-1-person', url_args={'person_id': unknown_person_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Person with id %s not found' % unknown_person_}) diff --git a/swh/web/tests/api/views/test_release.py b/swh/web/tests/api/views/test_release.py index 7aca0417..3233e849 100644 --- a/swh/web/tests/api/views/test_release.py +++ b/swh/web/tests/api/views/test_release.py @@ -1,125 +1,125 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from datetime import datetime from hypothesis import given from rest_framework.test import APITestCase from swh.model.hashutil import hash_to_bytes from swh.web.common.utils import reverse from swh.web.tests.data import random_sha1 from swh.web.tests.strategies import ( release, sha1, content, directory ) from swh.web.tests.testcase import WebTestCase class ReleaseApiTestCase(WebTestCase, APITestCase): @given(release()) def test_api_release(self, release): url = reverse('api-1-release', url_args={'sha1_git': release}) rv = self.client.get(url) expected_release = self.release_get(release) author_id = expected_release['author']['id'] target_revision = expected_release['target'] author_url = reverse('api-1-person', url_args={'person_id': author_id}) target_url = reverse('api-1-revision', url_args={'sha1_git': target_revision}) expected_release['author_url'] = author_url expected_release['target_url'] = target_url - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_release) @given(sha1(), sha1(), sha1(), content(), directory(), release()) def test_api_release_target_type_not_a_revision(self, new_rel1, new_rel2, new_rel3, content, directory, release): for new_rel_id, target_type, target in ( (new_rel1, 'content', content), (new_rel2, 'directory', directory), (new_rel3, 'release', release)): if target_type == 'content': target = target['sha1_git'] sample_release = { 'author': { 'email': b'author@company.org', 'fullname': b'author ', 'name': b'author' }, 'date': { 'timestamp': int(datetime.now().timestamp()), 'offset': 0, 'negative_utc': False, }, 'id': hash_to_bytes(new_rel_id), 'message': b'sample release message', 'name': b'sample release', 'synthetic': False, 'target': hash_to_bytes(target), 'target_type': target_type } self.storage.release_add([sample_release]) url = reverse('api-1-release', url_args={'sha1_git': new_rel_id}) rv = self.client.get(url) expected_release = self.release_get(new_rel_id) author_id = expected_release['author']['id'] author_url = reverse('api-1-person', url_args={'person_id': author_id}) if target_type == 'content': url_args = {'q': 'sha1_git:%s' % target} else: url_args = {'sha1_git': target} target_url = reverse('api-1-%s' % target_type, url_args=url_args) expected_release['author_url'] = author_url expected_release['target_url'] = target_url - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_release) def test_api_release_not_found(self): unknown_release_ = random_sha1() url = reverse('api-1-release', url_args={'sha1_git': unknown_release_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Release with sha1_git %s not found.' % unknown_release_ }) @given(release()) def test_api_release_uppercase(self, release): url = reverse('api-1-release-uppercase-checksum', url_args={'sha1_git': release.upper()}) resp = self.client.get(url) self.assertEqual(resp.status_code, 302) redirect_url = reverse('api-1-release-uppercase-checksum', url_args={'sha1_git': release}) self.assertEqual(resp['location'], redirect_url) diff --git a/swh/web/tests/api/views/test_revision.py b/swh/web/tests/api/views/test_revision.py index 457d61be..fb45b282 100644 --- a/swh/web/tests/api/views/test_revision.py +++ b/swh/web/tests/api/views/test_revision.py @@ -1,539 +1,539 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import random from hypothesis import given from rest_framework.test import APITestCase from unittest.mock import patch from swh.model.hashutil import hash_to_hex from swh.web.common.exc import NotFoundExc from swh.web.common.utils import reverse, parse_timestamp from swh.web.tests.data import random_sha1 from swh.web.tests.strategies import ( revision, new_revision, origin, origin_with_multiple_visits ) from swh.web.tests.testcase import WebTestCase class RevisionApiTestCase(WebTestCase, APITestCase): @given(revision()) def test_api_revision(self, revision): url = reverse('api-1-revision', url_args={'sha1_git': revision}) rv = self.client.get(url) expected_revision = self.revision_get(revision) self._enrich_revision(expected_revision) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_revision) def test_api_revision_not_found(self): unknown_revision_ = random_sha1() url = reverse('api-1-revision', url_args={'sha1_git': unknown_revision_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Revision with sha1_git %s not found.' % unknown_revision_}) @given(revision()) def test_api_revision_raw_ok(self, revision): url = reverse('api-1-revision-raw-message', url_args={'sha1_git': revision}) rv = self.client.get(url) expected_message = self.revision_get(revision)['message'] self.assertEqual(rv.status_code, 200) self.assertEqual(rv['Content-Type'], 'application/octet-stream') self.assertEqual(rv.content, expected_message.encode()) @given(new_revision()) def test_api_revision_raw_ok_no_msg(self, new_revision): del new_revision['message'] self.storage.revision_add([new_revision]) new_revision_id = hash_to_hex(new_revision['id']) url = reverse('api-1-revision-raw-message', url_args={'sha1_git': new_revision_id}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'No message for revision with sha1_git %s.' % new_revision_id}) def test_api_revision_raw_ko_no_rev(self): unknown_revision_ = random_sha1() url = reverse('api-1-revision-raw-message', url_args={'sha1_git': unknown_revision_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Revision with sha1_git %s not found.' % unknown_revision_}) def test_api_revision_with_origin_not_found(self): unknown_origin_id_ = random.randint(1000, 1000000) url = reverse('api-1-revision-origin', url_args={'origin_id': unknown_origin_id_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Origin with id %s not found!' % unknown_origin_id_}) @given(origin()) def test_api_revision_with_origin(self, origin): url = reverse('api-1-revision-origin', url_args={'origin_id': origin['id']}) rv = self.client.get(url) snapshot = self.snapshot_get_latest(origin['id']) expected_revision = self.revision_get( snapshot['branches']['HEAD']['target']) self._enrich_revision(expected_revision) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_revision) @given(origin()) def test_api_revision_with_origin_and_branch_name(self, origin): snapshot = self.snapshot_get_latest(origin['id']) branch_name = random.choice( list(b for b in snapshot['branches'].keys() if snapshot['branches'][b]['target_type'] == 'revision')) url = reverse('api-1-revision-origin', url_args={'origin_id': origin['id'], 'branch_name': branch_name}) rv = self.client.get(url) expected_revision = self.revision_get( snapshot['branches'][branch_name]['target']) self._enrich_revision(expected_revision) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_revision) @given(origin_with_multiple_visits()) def test_api_revision_with_origin_and_branch_name_and_ts(self, origin): visit = random.choice(self.origin_visit_get(origin['id'])) snapshot = self.snapshot_get(visit['snapshot']) branch_name = random.choice( list(b for b in snapshot['branches'].keys() if snapshot['branches'][b]['target_type'] == 'revision')) url = reverse('api-1-revision-origin', url_args={'origin_id': origin['id'], 'branch_name': branch_name, 'ts': visit['date']}) rv = self.client.get(url) expected_revision = self.revision_get( snapshot['branches'][branch_name]['target']) self._enrich_revision(expected_revision) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_revision) @given(origin_with_multiple_visits()) def test_api_revision_with_origin_and_branch_name_and_ts_escapes(self, origin): visit = random.choice(self.origin_visit_get(origin['id'])) snapshot = self.snapshot_get(visit['snapshot']) branch_name = random.choice( list(b for b in snapshot['branches'].keys() if snapshot['branches'][b]['target_type'] == 'revision')) date = parse_timestamp(visit['date']) formatted_date = date.strftime('Today is %B %d, %Y at %X') url = reverse('api-1-revision-origin', url_args={'origin_id': origin['id'], 'branch_name': branch_name, 'ts': formatted_date}) rv = self.client.get(url) expected_revision = self.revision_get( snapshot['branches'][branch_name]['target']) self._enrich_revision(expected_revision) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_revision) def test_api_directory_through_revision_origin_ko(self): unknown_origin_id_ = random.randint(1000, 1000000) url = reverse('api-1-revision-origin-directory', url_args={'origin_id': unknown_origin_id_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Origin with id %s not found!' % unknown_origin_id_ }) @given(origin()) def test_api_directory_through_revision_origin(self, origin): url = reverse('api-1-revision-origin-directory', url_args={'origin_id': origin['id']}) rv = self.client.get(url) snapshot = self.snapshot_get_latest(origin['id']) revision_id = snapshot['branches']['HEAD']['target'] revision = self.revision_get(revision_id) directory = self.directory_ls(revision['directory']) for entry in directory: if entry['type'] == 'dir': entry['target_url'] = reverse( 'api-1-directory', url_args={'sha1_git': entry['target']} ) entry['dir_url'] = reverse( 'api-1-revision-origin-directory', url_args={'origin_id': origin['id'], 'path': entry['name']}) elif entry['type'] == 'file': entry['target_url'] = reverse( 'api-1-content', url_args={'q': 'sha1_git:%s' % entry['target']} ) entry['file_url'] = reverse( 'api-1-revision-origin-directory', url_args={'origin_id': origin['id'], 'path': entry['name']}) elif entry['type'] == 'rev': entry['target_url'] = reverse( 'api-1-revision', url_args={'sha1_git': entry['target']} ) entry['rev_url'] = reverse( 'api-1-revision-origin-directory', url_args={'origin_id': origin['id'], 'path': entry['name']}) expected_result = { 'content': directory, 'path': '.', 'revision': revision_id, 'type': 'dir' } - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_result) @given(revision()) def test_api_revision_log(self, revision): per_page = 10 url = reverse('api-1-revision-log', url_args={'sha1_git': revision}, query_params={'per_page': per_page}) rv = self.client.get(url) expected_log = self.revision_log(revision, limit=per_page+1) expected_log = list(map(self._enrich_revision, expected_log)) has_next = len(expected_log) > per_page - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_log[:-1] if has_next else expected_log) if has_next: self.assertIn('Link', rv) next_log_url = reverse( 'api-1-revision-log', url_args={'sha1_git': expected_log[-1]['id']}, query_params={'per_page': per_page}) self.assertIn(next_log_url, rv['Link']) def test_api_revision_log_not_found(self): unknown_revision_ = random_sha1() url = reverse('api-1-revision-log', url_args={'sha1_git': unknown_revision_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Revision with sha1_git %s not found.' % unknown_revision_}) self.assertFalse(rv.has_header('Link')) @given(revision()) def test_api_revision_log_context(self, revision): revisions = self.revision_log(revision, limit=4) prev_rev = revisions[0]['id'] rev = revisions[-1]['id'] per_page = 10 url = reverse('api-1-revision-log', url_args={'sha1_git': rev, 'prev_sha1s': prev_rev}, query_params={'per_page': per_page}) rv = self.client.get(url) expected_log = self.revision_log(rev, limit=per_page) prev_revision = self.revision_get(prev_rev) expected_log.insert(0, prev_revision) expected_log = list(map(self._enrich_revision, expected_log)) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_log) @given(origin()) def test_api_revision_log_by(self, origin): per_page = 10 url = reverse('api-1-revision-origin-log', url_args={'origin_id': origin['id']}, query_params={'per_page': per_page}) rv = self.client.get(url) snapshot = self.snapshot_get_latest(origin['id']) expected_log = self.revision_log( snapshot['branches']['HEAD']['target'], limit=per_page+1) expected_log = list(map(self._enrich_revision, expected_log)) has_next = len(expected_log) > per_page - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_log[:-1] if has_next else expected_log) if has_next: self.assertIn('Link', rv) next_log_url = reverse( 'api-1-revision-origin-log', url_args={'origin_id': origin['id'], 'branch_name': 'HEAD'}, query_params={'per_page': per_page, 'sha1_git': expected_log[-1]['id']}) self.assertIn(next_log_url, rv['Link']) @given(origin()) def test_api_revision_log_by_ko(self, origin): invalid_branch_name = 'foobar' url = reverse('api-1-revision-origin-log', url_args={'origin_id': origin['id'], 'branch_name': invalid_branch_name}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertFalse(rv.has_header('Link')) self.assertEqual( rv.data, {'exception': 'NotFoundExc', 'reason': 'Revision for origin %s and branch %s not found.' % (origin['id'], invalid_branch_name)}) @patch('swh.web.api.views.revision._revision_directory_by') def test_api_revision_directory_ko_not_found(self, mock_rev_dir): # given mock_rev_dir.side_effect = NotFoundExc('Not found') # then rv = self.client.get('/api/1/revision/999/directory/some/path/to/dir/') - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'NotFoundExc', 'reason': 'Not found'}) mock_rev_dir.assert_called_once_with( {'sha1_git': '999'}, 'some/path/to/dir', '/api/1/revision/999/directory/some/path/to/dir/', with_data=False) @patch('swh.web.api.views.revision._revision_directory_by') def test_api_revision_directory_ok_returns_dir_entries(self, mock_rev_dir): stub_dir = { 'type': 'dir', 'revision': '999', 'content': [ { 'sha1_git': '789', 'type': 'file', 'target': '101', 'target_url': '/api/1/content/sha1_git:101/', 'name': 'somefile', 'file_url': '/api/1/revision/999/directory/some/path/' 'somefile/' }, { 'sha1_git': '123', 'type': 'dir', 'target': '456', 'target_url': '/api/1/directory/456/', 'name': 'to-subdir', 'dir_url': '/api/1/revision/999/directory/some/path/' 'to-subdir/', }] } # given mock_rev_dir.return_value = stub_dir # then rv = self.client.get('/api/1/revision/999/directory/some/path/') - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, stub_dir) mock_rev_dir.assert_called_once_with( {'sha1_git': '999'}, 'some/path', '/api/1/revision/999/directory/some/path/', with_data=False) @patch('swh.web.api.views.revision._revision_directory_by') def test_api_revision_directory_ok_returns_content(self, mock_rev_dir): stub_content = { 'type': 'file', 'revision': '999', 'content': { 'sha1_git': '789', 'sha1': '101', 'data_url': '/api/1/content/101/raw/', } } # given mock_rev_dir.return_value = stub_content # then url = '/api/1/revision/666/directory/some/other/path/' rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, stub_content) mock_rev_dir.assert_called_once_with( {'sha1_git': '666'}, 'some/other/path', url, with_data=False) def _enrich_revision(self, revision): author_url = reverse( 'api-1-person', url_args={'person_id': revision['author']['id']}) committer_url = reverse( 'api-1-person', url_args={'person_id': revision['committer']['id']}) directory_url = reverse( 'api-1-directory', url_args={'sha1_git': revision['directory']}) history_url = reverse('api-1-revision-log', url_args={'sha1_git': revision['id']}) parents_id_url = [] for p in revision['parents']: parents_id_url.append({ 'id': p, 'url': reverse('api-1-revision', url_args={'sha1_git': p}) }) revision_url = reverse('api-1-revision', url_args={'sha1_git': revision['id']}) revision['author_url'] = author_url revision['committer_url'] = committer_url revision['directory_url'] = directory_url revision['history_url'] = history_url revision['url'] = revision_url revision['parents'] = parents_id_url return revision @given(revision()) def test_api_revision_uppercase(self, revision): url = reverse('api-1-revision-uppercase-checksum', url_args={'sha1_git': revision.upper()}) resp = self.client.get(url) self.assertEqual(resp.status_code, 302) redirect_url = reverse('api-1-revision', url_args={'sha1_git': revision}) self.assertEqual(resp['location'], redirect_url) diff --git a/swh/web/tests/api/views/test_snapshot.py b/swh/web/tests/api/views/test_snapshot.py index c2330352..a1fb0b3a 100644 --- a/swh/web/tests/api/views/test_snapshot.py +++ b/swh/web/tests/api/views/test_snapshot.py @@ -1,190 +1,190 @@ # Copyright (C) 2018-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import random from hypothesis import given from rest_framework.test import APITestCase from swh.model.hashutil import hash_to_hex from swh.web.common.utils import reverse from swh.web.tests.data import random_sha1 from swh.web.tests.strategies import ( snapshot, new_snapshot ) from swh.web.tests.testcase import WebTestCase class SnapshotApiTestCase(WebTestCase, APITestCase): @given(snapshot()) def test_api_snapshot(self, snapshot): url = reverse('api-1-snapshot', url_args={'snapshot_id': snapshot}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = self.snapshot_get(snapshot) expected_data = self._enrich_snapshot(expected_data) self.assertEqual(rv.data, expected_data) @given(snapshot()) def test_api_snapshot_paginated(self, snapshot): branches_offset = 0 branches_count = 2 snapshot_branches = [] for k, v in sorted(self.snapshot_get(snapshot)['branches'].items()): snapshot_branches.append({ 'name': k, 'target_type': v['target_type'], 'target': v['target'] }) whole_snapshot = {'id': snapshot, 'branches': {}, 'next_branch': None} while branches_offset < len(snapshot_branches): branches_from = snapshot_branches[branches_offset]['name'] url = reverse('api-1-snapshot', url_args={'snapshot_id': snapshot}, query_params={'branches_from': branches_from, 'branches_count': branches_count}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') expected_data = self.snapshot_get_branches(snapshot, branches_from, branches_count) expected_data = self._enrich_snapshot(expected_data) branches_offset += branches_count if branches_offset < len(snapshot_branches): next_branch = snapshot_branches[branches_offset]['name'] expected_data['next_branch'] = next_branch else: expected_data['next_branch'] = None self.assertEqual(rv.data, expected_data) whole_snapshot['branches'].update(expected_data['branches']) if branches_offset < len(snapshot_branches): next_url = reverse( 'api-1-snapshot', url_args={'snapshot_id': snapshot}, query_params={'branches_from': next_branch, 'branches_count': branches_count}) self.assertEqual(rv['Link'], '<%s>; rel="next"' % next_url) else: self.assertFalse(rv.has_header('Link')) url = reverse('api-1-snapshot', url_args={'snapshot_id': snapshot}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, whole_snapshot) @given(snapshot()) def test_api_snapshot_filtered(self, snapshot): snapshot_branches = [] for k, v in sorted(self.snapshot_get(snapshot)['branches'].items()): snapshot_branches.append({ 'name': k, 'target_type': v['target_type'], 'target': v['target'] }) target_type = random.choice(snapshot_branches)['target_type'] url = reverse('api-1-snapshot', url_args={'snapshot_id': snapshot}, query_params={'target_types': target_type}) rv = self.client.get(url) expected_data = self.snapshot_get_branches( snapshot, target_types=target_type) expected_data = self._enrich_snapshot(expected_data) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, expected_data) def test_api_snapshot_errors(self): unknown_snapshot_ = random_sha1() url = reverse('api-1-snapshot', url_args={'snapshot_id': '63ce369'}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 400) + self.assertEqual(rv.status_code, 400, rv.data) url = reverse('api-1-snapshot', url_args={'snapshot_id': unknown_snapshot_}) rv = self.client.get(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) def _enrich_snapshot(self, snapshot): def _get_branch_url(target_type, target): url = None if target_type == 'revision': url = reverse('api-1-revision', url_args={'sha1_git': target}) if target_type == 'release': url = reverse('api-1-release', url_args={'sha1_git': target}) return url for branch in snapshot['branches'].keys(): target = snapshot['branches'][branch]['target'] target_type = snapshot['branches'][branch]['target_type'] snapshot['branches'][branch]['target_url'] = \ _get_branch_url(target_type, target) for branch in snapshot['branches'].keys(): target = snapshot['branches'][branch]['target'] target_type = snapshot['branches'][branch]['target_type'] if target_type == 'alias': if target in snapshot['branches']: snapshot['branches'][branch]['target_url'] = \ snapshot['branches'][target]['target_url'] else: snp = self.snapshot_get_branches(snapshot['id'], branches_from=target, branches_count=1) alias_target = snp['branches'][target]['target'] alias_target_type = snp['branches'][target]['target_type'] snapshot['branches'][branch]['target_url'] = \ _get_branch_url(alias_target_type, alias_target) return snapshot @given(snapshot()) def test_api_snapshot_uppercase(self, snapshot): url = reverse('api-1-snapshot-uppercase-checksum', url_args={'snapshot_id': snapshot.upper()}) resp = self.client.get(url) self.assertEqual(resp.status_code, 302) redirect_url = reverse('api-1-snapshot-uppercase-checksum', url_args={'snapshot_id': snapshot}) self.assertEqual(resp['location'], redirect_url) @given(new_snapshot(min_size=4)) def test_api_snapshot_null_branch(self, new_snapshot): snp_dict = new_snapshot.to_dict() snp_id = hash_to_hex(snp_dict['id']) for branch in snp_dict['branches'].keys(): snp_dict['branches'][branch] = None break self.storage.snapshot_add([snp_dict]) url = reverse('api-1-snapshot', url_args={'snapshot_id': snp_id}) rv = self.client.get(url) self.assertEqual(rv.status_code, 200, rv.data) diff --git a/swh/web/tests/api/views/test_stat.py b/swh/web/tests/api/views/test_stat.py index 3124dad1..1e8ba052 100644 --- a/swh/web/tests/api/views/test_stat.py +++ b/swh/web/tests/api/views/test_stat.py @@ -1,75 +1,75 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from rest_framework.test import APITestCase from unittest.mock import patch from swh.storage.exc import StorageDBError, StorageAPIError from swh.web.common.utils import reverse from swh.web.tests.testcase import WebTestCase class StatApiTestCase(WebTestCase, APITestCase): @patch('swh.web.api.views.stat.service') def test_api_1_stat_counters_raise_error(self, mock_service): mock_service.stat_counters.side_effect = ValueError( 'voluntary error to check the bad request middleware.') url = reverse('api-1-stat-counters') rv = self.client.get(url) - self.assertEqual(rv.status_code, 400) + self.assertEqual(rv.status_code, 400, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'ValueError', 'reason': 'voluntary error to check the bad request middleware.'}) @patch('swh.web.api.views.stat.service') def test_api_1_stat_counters_raise_from_db(self, mock_service): mock_service.stat_counters.side_effect = StorageDBError( 'Storage exploded! Will be back online shortly!') url = reverse('api-1-stat-counters') rv = self.client.get(url) - self.assertEqual(rv.status_code, 503) + self.assertEqual(rv.status_code, 503, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'StorageDBError', 'reason': 'An unexpected error occurred in the backend: ' 'Storage exploded! Will be back online shortly!'}) @patch('swh.web.api.views.stat.service') def test_api_1_stat_counters_raise_from_api(self, mock_service): mock_service.stat_counters.side_effect = StorageAPIError( 'Storage API dropped dead! Will resurrect from its ashes asap!' ) url = reverse('api-1-stat-counters') rv = self.client.get(url) - self.assertEqual(rv.status_code, 503) + self.assertEqual(rv.status_code, 503, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { 'exception': 'StorageAPIError', 'reason': 'An unexpected error occurred in the api backend: ' 'Storage API dropped dead! Will resurrect from its ashes asap!' }) def test_api_1_stat_counters(self): url = reverse('api-1-stat-counters') rv = self.client.get(url) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, self.storage.stat_counters()) diff --git a/swh/web/tests/api/views/test_vault.py b/swh/web/tests/api/views/test_vault.py index a856a157..0548f408 100644 --- a/swh/web/tests/api/views/test_vault.py +++ b/swh/web/tests/api/views/test_vault.py @@ -1,122 +1,122 @@ # Copyright (C) 2017-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information from rest_framework.test import APITestCase from unittest.mock import patch from swh.model import hashutil from swh.web.tests.testcase import WebTestCase TEST_OBJ_ID = 'd4905454cc154b492bd6afed48694ae3c579345e' OBJECT_TYPES = {'directory': ('directory', None), 'revision_gitfast': ('revision', 'gitfast')} class VaultApiTestCase(WebTestCase, APITestCase): @patch('swh.web.api.views.vault.service') def test_api_vault_cook(self, mock_service): stub_cook = { 'fetch_url': ('http://127.0.0.1:5004/api/1/vault/directory/{}/raw/' .format(TEST_OBJ_ID)), 'obj_id': TEST_OBJ_ID, 'obj_type': 'test_type', 'progress_message': None, 'status': 'done', 'task_uuid': 'de75c902-5ee5-4739-996e-448376a93eff', } stub_fetch = b'content' mock_service.vault_cook.return_value = stub_cook mock_service.vault_fetch.return_value = stub_fetch for obj_type, (obj_type_name, obj_type_format) in OBJECT_TYPES.items(): url = '/api/1/vault/{}/{}/'.format(obj_type_name, TEST_OBJ_ID) if obj_type_format: url += '{}/'.format(obj_type_format) rv = self.client.post(url, {'email': 'test@test.mail'}) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, stub_cook) mock_service.vault_cook.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID), 'test@test.mail') rv = self.client.get(url + 'raw/') self.assertEqual(rv.status_code, 200) self.assertEqual(rv['Content-Type'], 'application/gzip') self.assertEqual(rv.content, stub_fetch) mock_service.vault_fetch.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID)) @patch('swh.web.api.views.vault.service') def test_api_vault_cook_uppercase_hash(self, mock_service): stub_cook = { 'fetch_url': ('http://127.0.0.1:5004/api/1/vault/directory/{}/raw/' .format(TEST_OBJ_ID.upper())), 'obj_id': TEST_OBJ_ID.upper(), 'obj_type': 'test_type', 'progress_message': None, 'status': 'done', 'task_uuid': 'de75c902-5ee5-4739-996e-448376a93eff', } stub_fetch = b'content' mock_service.vault_cook.return_value = stub_cook mock_service.vault_fetch.return_value = stub_fetch for obj_type, (obj_type_name, obj_type_format) in OBJECT_TYPES.items(): url = '/api/1/vault/{}/{}/'.format(obj_type_name, TEST_OBJ_ID) if obj_type_format: url += '{}/'.format(obj_type_format) rv = self.client.post(url, {'email': 'test@test.mail'}) - self.assertEqual(rv.status_code, 200) + self.assertEqual(rv.status_code, 200, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, stub_cook) mock_service.vault_cook.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID), 'test@test.mail') rv = self.client.get(url + 'raw/') self.assertEqual(rv.status_code, 200) self.assertEqual(rv['Content-Type'], 'application/gzip') self.assertEqual(rv.content, stub_fetch) mock_service.vault_fetch.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID)) @patch('swh.web.api.views.vault.service') def test_api_vault_cook_notfound(self, mock_service): mock_service.vault_cook.return_value = None mock_service.vault_fetch.return_value = None for obj_type, (obj_type_name, obj_type_format) in OBJECT_TYPES.items(): url = '/api/1/vault/{}/{}/'.format(obj_type_name, TEST_OBJ_ID) if obj_type_format: url += '{}/'.format(obj_type_format) rv = self.client.post(url) - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data['exception'], 'NotFoundExc') mock_service.vault_cook.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID), None) rv = self.client.get(url + 'raw/') - self.assertEqual(rv.status_code, 404) + self.assertEqual(rv.status_code, 404, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data['exception'], 'NotFoundExc') mock_service.vault_fetch.assert_called_with( obj_type, hashutil.hash_to_bytes(TEST_OBJ_ID))