Beispiel #1
0
    elif dir_entry["type"] == "rev":
        dir_entry["target_url"] = reverse(
            "api-1-revision",
            url_args={"sha1_git": dir_entry["target"]},
            request=request,
        )

    assert actual_directory == dir_entry


def test_enrich_content_without_hashes():
    assert utils.enrich_content({"id": "123"}) == {"id": "123"}


@given(content())
def test_enrich_content_with_hashes(api_request_factory, content):

    for algo in DEFAULT_ALGORITHMS:

        content_data = dict(content)

        query_string = "%s:%s" % (algo, content_data[algo])

        url = reverse("api-1-content", url_args={"q": query_string})
        request = api_request_factory.get(url)

        enriched_content = utils.enrich_content(content_data,
                                                query_string=query_string,
                                                request=request)
Beispiel #2
0
class ReleaseApiTestCase(WebTestCase, APITestCase):

    @given(release())
    def test_api_release(self, release):

        url = reverse('api-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-person',
                             url_args={'person_id': author_id})
        target_url = reverse('api-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['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'*****@*****.**',
                    '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-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-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-%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['Content-Type'], 'application/json')
            self.assertEqual(rv.data, expected_release)

    @given(unknown_release())
    def test_api_release_not_found(self, unknown_release):

        url = reverse('api-release', url_args={'sha1_git': unknown_release})

        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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-release-uppercase-checksum',
                      url_args={'sha1_git': release.upper()})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)

        redirect_url = reverse('api-release-uppercase-checksum',
                               url_args={'sha1_git': release})

        self.assertEqual(resp['location'], redirect_url)
Beispiel #3
0
class ContentApiTestCase(WebTestCase, APITestCase):
    @given(content())
    def test_api_content_filetype(self, content):

        self.content_add_mimetype(content['sha1'])
        url = reverse('api-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['Content-Type'], 'application/json')
        content_url = reverse('api-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)

    @given(unknown_content())
    def test_api_content_filetype_sha_not_found(self, unknown_content):

        url = reverse('api-content-filetype',
                      url_args={'q': 'sha1:%s' % unknown_content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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']
            })

    @given(content())
    def test_api_content_language(self, content):

        self.content_add_language(content['sha1'])
        url = reverse('api-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['Content-Type'], 'application/json')
        content_url = reverse('api-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)

    @given(unknown_content())
    def test_api_content_language_sha_not_found(self, unknown_content):

        url = reverse('api-content-language',
                      url_args={'q': 'sha1:%s' % unknown_content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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.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-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['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-content'),
                                   ('data_url', 'api-content-raw'),
                                   ('license_url', 'api-content-license'),
                                   ('language_url', 'api-content-language'),
                                   ('filetype_url', 'api-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-content-symbol',
                      url_args={'q': contents_with_ctags['symbol_name']},
                      query_params={'per_page': 2})
        rv = self.client.get(url)

        next_url = reverse('api-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-content-symbol', url_args={'q': 'bar'})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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-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['Content-Type'], 'application/json')
        content_url = reverse('api-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-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['Content-Type'], 'application/json')
        content_url = reverse('api-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)

    @given(unknown_content())
    def test_api_content_license_sha_not_found(self, unknown_content):

        url = reverse('api-content-license',
                      url_args={'q': 'sha1:%s' % unknown_content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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-content', {'q': 'sha1:%s' % content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 200)
        self.assertEqual(rv['Content-Type'], 'application/json')
        expected_data = self.content_get_metadata(content['sha1'])
        for key, view_name in (('data_url', 'api-content-raw'),
                               ('license_url', 'api-content-license'),
                               ('language_url', 'api-content-language'),
                               ('filetype_url', 'api-content-filetype')):
            expected_data[key] = reverse(
                view_name, url_args={'q': 'sha1:%s' % content['sha1']})
        self.assertEqual(rv.data, expected_data)

    @given(unknown_content())
    def test_api_content_not_found_as_json(self, unknown_content):

        url = reverse('api-content',
                      url_args={'q': 'sha1:%s' % unknown_content['sha1']})
        rv = self.client.get(url)
        self.assertEqual(rv.status_code, 404)
        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(unknown_content())
    def test_api_content_not_found_as_yaml(self, unknown_content):

        url = reverse('api-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.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']
            })

    @given(unknown_content())
    def test_api_content_raw_ko_not_found(self, unknown_content):

        url = reverse('api-content-raw',
                      url_args={'q': 'sha1:%s' % unknown_content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 404)
        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-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-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-content-known', url_args={'q': content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 200)
        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-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['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-content-known')
        rv = self.client.post(url,
                              data={'q': content['sha1']},
                              HTTP_ACCEPT='application/yaml')

        self.assertEqual(rv.status_code, 200)
        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
                }
            })

    @given(unknown_content())
    def test_api_check_content_known_not_found(self, unknown_content):

        url = reverse('api-content-known',
                      url_args={'q': unknown_content['sha1']})
        rv = self.client.get(url)

        self.assertEqual(rv.status_code, 200)
        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-content-uppercase-checksum',
                      url_args={'q': content['sha1'].upper()})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)

        redirect_url = reverse('api-content', url_args={'q': content['sha1']})

        self.assertEqual(resp['location'], redirect_url)
Beispiel #4
0
class SwhBrowseIdTest(WebTestCase):

    @given(content())
    def test_content_id_browse(self, content):
        cnt_sha1_git = content['sha1_git']
        swh_id = swh_id_prefix + 'cnt:' + cnt_sha1_git
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        query_string = 'sha1_git:' + cnt_sha1_git
        content_browse_url = reverse('browse-content',
                                     url_args={'query_string': query_string})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], content_browse_url)

    @given(directory())
    def test_directory_id_browse(self, directory):
        swh_id = swh_id_prefix + 'dir:' + directory
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        directory_browse_url = reverse('browse-directory',
                                       url_args={'sha1_git': directory})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], directory_browse_url)

    @given(revision())
    def test_revision_id_browse(self, revision):
        swh_id = swh_id_prefix + 'rev:' + revision
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        revision_browse_url = reverse('browse-revision',
                                      url_args={'sha1_git': revision})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], revision_browse_url)

        query_params = {'origin_type': 'git',
                        'origin': 'https://github.com/user/repo'}

        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id},
                      query_params=query_params)

        revision_browse_url = reverse('browse-revision',
                                      url_args={'sha1_git': revision},
                                      query_params=query_params)

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], revision_browse_url)

    @given(release())
    def test_release_id_browse(self, release):
        swh_id = swh_id_prefix + 'rel:' + release
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        release_browse_url = reverse('browse-release',
                                     url_args={'sha1_git': release})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], release_browse_url)

        query_params = {'origin_type': 'git',
                        'origin': 'https://github.com/user/repo'}

        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id},
                      query_params=query_params)

        release_browse_url = reverse('browse-release',
                                     url_args={'sha1_git': release},
                                     query_params=query_params)

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], release_browse_url)

    @given(snapshot())
    def test_snapshot_id_browse(self, snapshot):
        swh_id = swh_id_prefix + 'snp:' + snapshot
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        snapshot_browse_url = reverse('browse-snapshot',
                                      url_args={'snapshot_id': snapshot})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], snapshot_browse_url)

        query_params = {'origin_type': 'git',
                        'origin': 'https://github.com/user/repo'}

        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id},
                      query_params=query_params)

        release_browse_url = reverse('browse-snapshot',
                                     url_args={'snapshot_id': snapshot},
                                     query_params=query_params)

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], release_browse_url)

    @given(release())
    def test_bad_id_browse(self, release):
        swh_id = swh_id_prefix + 'foo:' + release
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 400)

    @given(content())
    def test_content_id_optional_parts_browse(self, content):
        cnt_sha1_git = content['sha1_git']
        optional_parts = ';lines=4-20;origin=https://github.com/user/repo'
        swh_id = swh_id_prefix + 'cnt:' + cnt_sha1_git + optional_parts
        url = reverse('browse-swh-id',
                      url_args={'swh_id': swh_id})

        query_string = 'sha1_git:' + cnt_sha1_git
        content_browse_url = reverse(
            'browse-content', url_args={'query_string': query_string},
            query_params={'origin': 'https://github.com/user/repo'})
        content_browse_url += '#L4-L20'

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 302)
        self.assertEqual(resp['location'], content_browse_url)
Beispiel #5
0
        input_data.append({"sha1": cnt["sha1"]})
        expected_output.append({"sha1": cnt["sha1"], "found": cnt in contents})

    assert archive.lookup_multiple_hashes(input_data) == expected_output


def test_lookup_hash_does_not_exist():
    unknown_content_ = random_content()

    actual_lookup = archive.lookup_hash("sha1_git:%s" %
                                        unknown_content_["sha1_git"])

    assert actual_lookup == {"found": None, "algo": "sha1_git"}


@given(content())
def test_lookup_hash_exist(archive_data, content):
    actual_lookup = archive.lookup_hash("sha1:%s" % content["sha1"])

    content_metadata = archive_data.content_get(content["sha1"])

    assert {"found": content_metadata, "algo": "sha1"} == actual_lookup


def test_search_hash_does_not_exist():
    unknown_content_ = random_content()

    actual_lookup = archive.search_hash("sha1_git:%s" %
                                        unknown_content_["sha1_git"])

    assert {"found": False} == actual_lookup
Beispiel #6
0
class SwhBrowseContentTest(WebTestCase):
    @given(content())
    def test_content_view_text(self, content):

        sha1_git = content['sha1_git']

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']},
                      query_params={'path': content['path']})

        url_raw = reverse('browse-content-raw',
                          url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        content_display = self._process_content_for_display(content)
        mimetype = content_display['mimetype']

        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        if mimetype.startswith('text/'):
            self.assertContains(
                resp, '<code class="%s">' % content_display['language'])
            self.assertContains(resp, escape(content_display['content_data']))
        self.assertContains(resp, url_raw)

        swh_cnt_id = get_swh_persistent_id('content', sha1_git)
        swh_cnt_id_url = reverse('browse-swh-id',
                                 url_args={'swh_id': swh_cnt_id})
        self.assertContains(resp, swh_cnt_id)
        self.assertContains(resp, swh_cnt_id_url)

    @given(content_text_no_highlight())
    def test_content_view_text_no_highlight(self, content):

        sha1_git = content['sha1_git']

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']})

        url_raw = reverse('browse-content-raw',
                          url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        content_display = self._process_content_for_display(content)

        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        self.assertContains(resp, '<code class="nohighlight">')
        self.assertContains(resp,
                            escape(content_display['content_data']))  # noqa
        self.assertContains(resp, url_raw)

        swh_cnt_id = get_swh_persistent_id('content', sha1_git)
        swh_cnt_id_url = reverse('browse-swh-id',
                                 url_args={'swh_id': swh_cnt_id})

        self.assertContains(resp, swh_cnt_id)
        self.assertContains(resp, swh_cnt_id_url)

    @given(content_text_non_utf8())
    def test_content_view_no_utf8_text(self, content):

        sha1_git = content['sha1_git']

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        content_display = self._process_content_for_display(content)

        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')
        swh_cnt_id = get_swh_persistent_id('content', sha1_git)
        swh_cnt_id_url = reverse('browse-swh-id',
                                 url_args={'swh_id': swh_cnt_id})
        self.assertContains(resp, swh_cnt_id_url)
        self.assertContains(resp, escape(content_display['content_data']))

    @given(content_image_type())
    def test_content_view_image(self, content):

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']})

        url_raw = reverse('browse-content-raw',
                          url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        content_display = self._process_content_for_display(content)
        mimetype = content_display['mimetype']
        content_data = content_display['content_data']

        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        self.assertContains(
            resp, '<img src="data:%s;base64,%s"/>' %
            (mimetype, content_data.decode('utf-8')))
        self.assertContains(resp, url_raw)

    @given(content())
    def test_content_view_with_path(self, content):

        path = content['path']

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']},
                      query_params={'path': path})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        self.assertContains(resp, '<nav class="bread-crumbs')

        content_display = self._process_content_for_display(content)
        mimetype = content_display['mimetype']

        if mimetype.startswith('text/'):
            hljs_language = content['hljs_language']
            self.assertContains(resp, '<code class="%s">' % hljs_language)
            self.assertContains(resp, escape(content_display['content_data']))

        split_path = path.split('/')

        root_dir_sha1 = split_path[0]
        filename = split_path[-1]
        path = path.replace(root_dir_sha1 + '/', '').replace(filename, '')

        path_info = gen_path_info(path)

        root_dir_url = reverse('browse-directory',
                               url_args={'sha1_git': root_dir_sha1})

        self.assertContains(resp,
                            '<li class="swh-path">',
                            count=len(path_info) + 1)

        self.assertContains(
            resp,
            '<a href="' + root_dir_url + '">' + root_dir_sha1[:7] + '</a>')

        for p in path_info:
            dir_url = reverse('browse-directory',
                              url_args={
                                  'sha1_git': root_dir_sha1,
                                  'path': p['path']
                              })
            self.assertContains(
                resp, '<a href="' + dir_url + '">' + p['name'] + '</a>')

        self.assertContains(resp, '<li>' + filename + '</li>')

        url_raw = reverse('browse-content-raw',
                          url_args={'query_string': content['sha1']},
                          query_params={'filename': filename})
        self.assertContains(resp, url_raw)

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']},
                      query_params={'path': filename})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        self.assertNotContains(resp, '<nav class="bread-crumbs')

    @given(content_text())
    def test_content_raw_text(self, content):

        url = reverse('browse-content-raw',
                      url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        content_data = self.content_get(content['sha1'])['data']

        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp['Content-Type'], 'text/plain')
        self.assertEqual(resp['Content-disposition'],
                         'filename=%s_%s' % ('sha1', content['sha1']))
        self.assertEqual(resp.content, content_data)

        filename = content['path'].split('/')[-1]

        url = reverse(
            'browse-content-raw',
            url_args={'query_string': content['sha1']},  # noqa
            query_params={'filename': filename})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp['Content-Type'], 'text/plain')
        self.assertEqual(resp['Content-disposition'], 'filename=%s' % filename)
        self.assertEqual(resp.content, content_data)

    @given(content_text_non_utf8())
    def test_content_raw_no_utf8_text(self, content):

        url = reverse('browse-content-raw',
                      url_args={'query_string': content['sha1']})

        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 200)
        _, encoding = get_mimetype_and_encoding_for_content(resp.content)
        self.assertEqual(encoding, content['encoding'])

    @given(content_image_type())
    def test_content_raw_bin(self, content):

        url = reverse('browse-content-raw',
                      url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        filename = content['path'].split('/')[-1]
        content_data = self.content_get(content['sha1'])['data']

        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp['Content-Type'], 'application/octet-stream')
        self.assertEqual(
            resp['Content-disposition'],
            'attachment; filename=%s_%s' % ('sha1', content['sha1']))
        self.assertEqual(resp.content, content_data)

        url = reverse('browse-content-raw',
                      url_args={'query_string': content['sha1']},
                      query_params={'filename': filename})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp['Content-Type'], 'application/octet-stream')
        self.assertEqual(resp['Content-disposition'],
                         'attachment; filename=%s' % filename)
        self.assertEqual(resp.content, content_data)

    @given(invalid_sha1(), unknown_content())
    def test_content_request_errors(self, invalid_sha1, unknown_content):

        url = reverse('browse-content',
                      url_args={'query_string': invalid_sha1})
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 400)
        self.assertTemplateUsed('error.html')

        url = reverse('browse-content',
                      url_args={'query_string': unknown_content['sha1']})
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 404)
        self.assertTemplateUsed('error.html')

    @patch('swh.web.browse.utils.service')
    @given(content())
    def test_content_bytes_missing(self, mock_service, content):

        content_data = self.content_get_metadata(content['sha1'])
        content_data['data'] = None

        mock_service.lookup_content.return_value = content_data
        mock_service.lookup_content_raw.side_effect = NotFoundExc(
            'Content bytes not available!')

        url = reverse('browse-content',
                      url_args={'query_string': content['sha1']})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 404)
        self.assertTemplateUsed('browse/content.html')

    @patch('swh.web.browse.views.content.request_content')
    def test_content_too_large(self, mock_request_content):
        stub_content_too_large_data = {
            'checksums': {
                'sha1':
                '8624bcdae55baeef00cd11d5dfcfa60f68710a02',
                'sha1_git':
                '94a9ed024d3859793618152ea559a168bbcbb5e2',
                'sha256': ('8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b16'
                           '5a1dcd80c7c545eb65b903'),
                'blake2s256': ('38702b7168c7785bfe748b51b45d9856070ba90'
                               'f9dc6d90f2ea75d4356411ffe')
            },
            'length': 3000000,
            'raw_data': None,
            'mimetype': 'text/plain',
            'encoding': 'us-ascii',
            'language': 'not detected',
            'licenses': 'GPL',
            'error_code': 200,
            'error_message': '',
            'error_description': ''
        }

        content_sha1 = stub_content_too_large_data['checksums']['sha1']

        mock_request_content.return_value = stub_content_too_large_data

        url = reverse('browse-content',
                      url_args={'query_string': content_sha1})

        url_raw = reverse('browse-content-raw',
                          url_args={'query_string': content_sha1})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 200)
        self.assertTemplateUsed('browse/content.html')

        self.assertContains(resp, 'Content is too large to be displayed')
        self.assertContains(resp, url_raw)

    def _process_content_for_display(self, content):
        content_data = self.content_get(content['sha1'])

        mime_type, encoding = get_mimetype_and_encoding_for_content(
            content_data['data'])

        mime_type, content_data = _reencode_content(mime_type, encoding,
                                                    content_data['data'])

        return prepare_content_for_display(content_data, mime_type,
                                           content['path'])

    @given(content())
    def test_content_uppercase(self, content):
        url = reverse('browse-content-uppercase-checksum',
                      url_args={'query_string': content['sha1'].upper()})
        resp = self.client.get(url)
        self.assertEqual(resp.status_code, 302)

        redirect_url = reverse('browse-content',
                               url_args={'query_string': content['sha1']})

        self.assertEqual(resp['location'], redirect_url)
Beispiel #7
0
    rev_data = archive_data.revision_get(revision)
    dir_content = archive_data.directory_ls(rev_data["directory"])
    dir_content = [
        enrich_directory_entry(dir_entry, request=rv.wsgi_request)
        for dir_entry in dir_content
    ]
    assert rv.data == {
        "content": dir_content,
        "path": ".",
        "type": "dir",
        "revision": revision,
    }


@given(content(), new_person(), new_swh_date())
def test_api_revision_directory_ok_returns_content(api_client, archive_data,
                                                   content, person, date):
    content_path = "foo"
    _dir = Directory(entries=(DirectoryEntry(
        name=content_path.encode(),
        type="file",
        target=hash_to_bytes(content["sha1_git"]),
        perms=DentryPerms.content,
    ), ))
    archive_data.directory_add([_dir])

    revision = Revision(
        directory=_dir.id,
        author=person,
        committer=person,
    assert actual_data == {"a": "some-data"}

    mock_ffk.assert_called_once_with(input_data, {"a", "c"})


def test_error_response_handler(mocker, api_client):
    mock_archive = mocker.patch("swh.web.api.views.stat.archive")
    mock_archive.stat_counters.side_effect = Exception("Something went wrong")
    url = reverse("api-1-stat-counters")
    resp = api_client.get(url)
    assert resp.status_code == 500
    assert "traceback" in resp.data
    assert "Traceback" in resp.data["traceback"]


@given(content(), directory(), revision())
def test_api_endpoints_have_cors_headers(client, content, directory, revision):
    url = reverse("api-1-stat-counters")

    resp = check_http_get_response(client,
                                   url,
                                   status_code=200,
                                   http_origin="https://example.org")
    assert ACCESS_CONTROL_ALLOW_ORIGIN in resp

    swhids = [
        gen_swhid(CONTENT, content["sha1_git"]),
        gen_swhid(DIRECTORY, directory),
        gen_swhid(REVISION, revision),
    ]
    url = reverse("api-1-known")
Beispiel #9
0
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-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.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-resolve-swh-pid', url_args={'swh_id': swh_id})

        resp = self.client.get(url)

        self.assertEqual(resp.status_code, 400)

    @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-resolve-swh-pid', url_args={'swh_id': swh_id})

            resp = self.client.get(url)

            self.assertEqual(resp.status_code, 404)
Beispiel #10
0
class ServiceTestCase(WebTestCase):
    @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})

        self.assertEqual(service.lookup_multiple_hashes(input_data),
                         expected_output)

    @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)

        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
            })

        self.assertEqual(service.lookup_multiple_hashes(input_data),
                         expected_output)

    @given(unknown_content())
    def test_lookup_hash_does_not_exist(self, unknown_content):

        actual_lookup = service.lookup_hash('sha1_git:%s' %
                                            unknown_content['sha1_git'])

        self.assertEqual(actual_lookup, {'found': None, 'algo': 'sha1_git'})

    @given(content())
    def test_lookup_hash_exist(self, content):

        actual_lookup = service.lookup_hash('sha1:%s' % content['sha1'])

        content_metadata = self.content_get_metadata(content['sha1'])

        self.assertEqual({
            'found': content_metadata,
            'algo': 'sha1'
        }, actual_lookup)

    @given(unknown_content())
    def test_search_hash_does_not_exist(self, content):

        actual_lookup = service.search_hash('sha1_git:%s' %
                                            content['sha1_git'])

        self.assertEqual({'found': False}, actual_lookup)

    @given(content())
    def test_search_hash_exist(self, content):

        actual_lookup = service.search_hash('sha1:%s' % content['sha1'])

        self.assertEqual({'found': True}, actual_lookup)

    @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):

        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))

        expected_data = list(self.content_get_ctags(content_sha1))
        for ctag in expected_data:
            ctag['id'] = content_sha1

        self.assertEqual(actual_ctags, expected_data)

    @given(unknown_content())
    def test_lookup_content_ctags_no_hash(self, unknown_content):

        actual_ctags = \
            list(service.lookup_content_ctags('sha1:%s' %
                                              unknown_content['sha1']))

        self.assertEqual(actual_ctags, [])

    @given(content())
    def test_lookup_content_filetype(self, content):

        self.content_add_mimetype(content['sha1'])
        actual_filetype = service.lookup_content_filetype(content['sha1'])

        expected_filetype = self.content_get_mimetype(content['sha1'])
        self.assertEqual(actual_filetype, expected_filetype)

    @given(content())
    def test_lookup_content_language(self, content):

        self.content_add_language(content['sha1'])
        actual_language = service.lookup_content_language(content['sha1'])

        expected_language = self.content_get_language(content['sha1'])
        self.assertEqual(actual_language, expected_language)

    @given(contents_with_ctags())
    def test_lookup_expression(self, contents_with_ctags):

        per_page = 10
        expected_ctags = []

        for content_sha1 in contents_with_ctags['sha1s']:
            if len(expected_ctags) == per_page:
                break
            self.content_add_ctags(content_sha1)
            for ctag in self.content_get_ctags(content_sha1):
                if len(expected_ctags) == per_page:
                    break
                if ctag['name'] == contents_with_ctags['symbol_name']:
                    del ctag['id']
                    ctag['sha1'] = content_sha1
                    expected_ctags.append(ctag)

        actual_ctags = \
            list(service.lookup_expression(contents_with_ctags['symbol_name'],
                                           last_sha1=None, per_page=10))

        self.assertEqual(actual_ctags, expected_ctags)

    def test_lookup_expression_no_result(self):

        expected_ctags = []

        actual_ctags = \
            list(service.lookup_expression('barfoo', last_sha1=None,
                                           per_page=10))
        self.assertEqual(actual_ctags, expected_ctags)

    @pytest.mark.skipif(fossology_missing,
                        reason="requires fossology-nomossa installed")
    @given(content())
    def test_lookup_content_license(self, content):

        self.content_add_license(content['sha1'])
        actual_license = service.lookup_content_license(content['sha1'])

        expected_license = self.content_get_license(content['sha1'])
        self.assertEqual(actual_license, expected_license)

    def test_stat_counters(self):
        actual_stats = service.stat_counters()
        self.assertEqual(actual_stats, self.storage.stat_counters())

    @given(new_origin(), visit_dates())
    def test_lookup_origin_visits(self, new_origin, visit_dates):

        origin_id = self.storage.origin_add_one(new_origin)
        for ts in visit_dates:
            self.storage.origin_visit_add(origin_id, ts)

        actual_origin_visits = list(
            service.lookup_origin_visits(origin_id, per_page=100))

        expected_visits = self.origin_visit_get(origin_id)

        self.assertEqual(actual_origin_visits, expected_visits)

    @given(new_origin(), visit_dates())
    def test_lookup_origin_visit(self, new_origin, visit_dates):
        origin_id = self.storage.origin_add_one(new_origin)
        visits = []
        for ts in visit_dates:
            visits.append(self.storage.origin_visit_add(origin_id, ts))

        visit = random.choice(visits)['visit']
        actual_origin_visit = service.lookup_origin_visit(origin_id, visit)

        expected_visit = dict(
            self.storage.origin_visit_get_by(origin_id, visit))
        expected_visit['date'] = expected_visit['date'].isoformat()
        expected_visit['metadata'] = {}

        self.assertEqual(actual_origin_visit, expected_visit)

    @given(new_origin())
    def test_lookup_origin(self, new_origin):
        origin_id = self.storage.origin_add_one(new_origin)

        actual_origin = service.lookup_origin({'id': origin_id})
        expected_origin = self.storage.origin_get({'id': origin_id})
        self.assertEqual(actual_origin, expected_origin)

        actual_origin = service.lookup_origin({
            'type': new_origin['type'],
            'url': new_origin['url']
        })
        expected_origin = self.storage.origin_get({
            'type': new_origin['type'],
            'url': new_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:
            service.lookup_release(invalid_sha1)
        self.assertIn('invalid checksum', cm.exception.args[0].lower())

    @given(sha256())
    def test_lookup_release_ko_id_checksum_too_long(self, sha256):
        with self.assertRaises(BadInputExc) as cm:
            service.lookup_release(sha256)
        self.assertEqual('Only sha1_git is supported.', cm.exception.args[0])

    @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

        with self.assertRaises(BadInputExc) as cm:
            service.lookup_revision_with_context(sha1_git_root, sha1_git)
        self.assertIn('Invalid checksum query string', cm.exception.args[0])

        sha1_git = sha256

        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])

    @given(revision(), unknown_revision())
    def test_lookup_revision_with_context_ko_sha1_git_does_not_exist(
            self, revision, unknown_revision):
        sha1_git_root = revision
        sha1_git = unknown_revision

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_revision_with_context(sha1_git_root, sha1_git)
        self.assertIn('Revision %s not found' % sha1_git, cm.exception.args[0])

    @given(revision(), unknown_revision())
    def test_lookup_revision_with_context_ko_root_sha1_git_does_not_exist(
            self, revision, unknown_revision):
        sha1_git_root = unknown_revision
        sha1_git = revision

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_revision_with_context(sha1_git_root, sha1_git)
        self.assertIn('Revision root %s not found' % sha1_git_root,
                      cm.exception.args[0])

    @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']

        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])

    @given(unknown_revision())
    def test_lookup_directory_with_revision_not_found(self, unknown_revision):

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_directory_with_revision(unknown_revision)
        self.assertIn('Revision %s not found' % unknown_revision,
                      cm.exception.args[0])

    @given(revision())
    def test_lookup_directory_with_revision_ko_path_to_nowhere(self, revision):

        invalid_path = 'path/to/something/unknown'
        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_directory_with_revision(revision, invalid_path)
        exception_text = cm.exception.args[0].lower()
        self.assertIn('directory or file', exception_text)
        self.assertIn(invalid_path, exception_text)
        self.assertIn('revision %s' % revision, exception_text)
        self.assertIn('not found', exception_text)

    @given(revision_with_submodules())
    def test_lookup_directory_with_revision_submodules(
            self, revision_with_submodules):

        rev_sha1_git = revision_with_submodules['rev_sha1_git']
        rev_dir_path = revision_with_submodules['rev_dir_rev_path']

        actual_data = service.lookup_directory_with_revision(
            rev_sha1_git, rev_dir_path)

        revision = self.revision_get(revision_with_submodules['rev_sha1_git'])
        directory = self.directory_ls(revision['directory'])
        rev_entry = next(e for e in directory if e['name'] == rev_dir_path)

        expected_data = {
            'content': self.revision_get(rev_entry['target']),
            'path': rev_dir_path,
            'revision': rev_sha1_git,
            'type': 'rev'
        }

        self.assertEqual(actual_data, expected_data)

    @given(revision())
    def test_lookup_directory_with_revision_without_path(self, revision):

        actual_directory_entries = \
            service.lookup_directory_with_revision(revision)

        revision_data = self.revision_get(revision)
        expected_directory_entries = \
            self.directory_ls(revision_data['directory'])

        self.assertEqual(actual_directory_entries['type'], 'dir')
        self.assertEqual(actual_directory_entries['content'],
                         expected_directory_entries)

    @given(revision())
    def test_lookup_directory_with_revision_with_path(self, revision):

        revision_data = self.revision_get(revision)
        dir_entries = [
            e for e in self.directory_ls(revision_data['directory'])
            if e['type'] in ('file', 'dir')
        ]
        expected_dir_entry = random.choice(dir_entries)

        actual_dir_entry = \
            service.lookup_directory_with_revision(revision,
                                                   expected_dir_entry['name'])

        self.assertEqual(actual_dir_entry['type'], expected_dir_entry['type'])
        self.assertEqual(actual_dir_entry['revision'], revision)
        self.assertEqual(actual_dir_entry['path'], expected_dir_entry['name'])
        if actual_dir_entry['type'] == 'file':
            del actual_dir_entry['content']['checksums']['blake2s256']
            for key in ('checksums', 'status', 'length'):
                self.assertEqual(actual_dir_entry['content'][key],
                                 expected_dir_entry[key])
        else:
            sub_dir_entries = self.directory_ls(expected_dir_entry['target'])
            self.assertEqual(actual_dir_entry['content'], sub_dir_entries)

    @given(revision())
    def test_lookup_directory_with_revision_with_path_to_file_and_data(
            self, revision):

        revision_data = self.revision_get(revision)
        dir_entries = [
            e for e in self.directory_ls(revision_data['directory'])
            if e['type'] == 'file'
        ]
        expected_dir_entry = random.choice(dir_entries)
        expected_data = \
            self.content_get(expected_dir_entry['checksums']['sha1'])

        actual_dir_entry = \
            service.lookup_directory_with_revision(revision,
                                                   expected_dir_entry['name'],
                                                   with_data=True)

        self.assertEqual(actual_dir_entry['type'], expected_dir_entry['type'])
        self.assertEqual(actual_dir_entry['revision'], revision)
        self.assertEqual(actual_dir_entry['path'], expected_dir_entry['name'])
        del actual_dir_entry['content']['checksums']['blake2s256']
        for key in ('checksums', 'status', 'length'):
            self.assertEqual(actual_dir_entry['content'][key],
                             expected_dir_entry[key])
        self.assertEqual(actual_dir_entry['content']['data'],
                         expected_data['data'])

    @given(revision())
    def test_lookup_revision(self, revision):
        actual_revision = service.lookup_revision(revision)
        self.assertEqual(actual_revision, self.revision_get(revision))

    @given(new_revision())
    def test_lookup_revision_invalid_msg(self, new_revision):

        new_revision['message'] = b'elegant fix for bug \xff'
        self.storage.revision_add([new_revision])

        revision = service.lookup_revision(hash_to_hex(new_revision['id']))
        self.assertEqual(revision['message'], None)
        self.assertEqual(revision['message_decoding_failed'], True)

    @given(new_revision())
    def test_lookup_revision_msg_ok(self, new_revision):

        self.storage.revision_add([new_revision])

        revision_message = service.lookup_revision_message(
            hash_to_hex(new_revision['id']))

        self.assertEqual(revision_message,
                         {'message': new_revision['message']})

    @given(new_revision())
    def test_lookup_revision_msg_absent(self, new_revision):

        del new_revision['message']
        self.storage.revision_add([new_revision])

        new_revision_id = hash_to_hex(new_revision['id'])

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_revision_message(new_revision_id)

        self.assertEqual(
            cm.exception.args[0],
            'No message for revision with sha1_git %s.' % new_revision_id)

    @given(unknown_revision())
    def test_lookup_revision_msg_no_rev(self, unknown_revision):

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_revision_message(unknown_revision)

        self.assertEqual(
            cm.exception.args[0],
            'Revision with sha1_git %s not found.' % unknown_revision)

    @given(revisions())
    def test_lookup_revision_multiple(self, revisions):

        actual_revisions = list(service.lookup_revision_multiple(revisions))

        expected_revisions = []
        for rev in revisions:
            expected_revisions.append(self.revision_get(rev))

        self.assertEqual(actual_revisions, expected_revisions)

    @given(unknown_revisions())
    def test_lookup_revision_multiple_none_found(self, unknown_revisions):

        actual_revisions = \
            list(service.lookup_revision_multiple(unknown_revisions))

        self.assertEqual(actual_revisions, [None] * len(unknown_revisions))

    @given(revision())
    def test_lookup_revision_log(self, revision):

        actual_revision_log = \
            list(service.lookup_revision_log(revision, limit=25))
        expected_revision_log = self.revision_log(revision, limit=25)

        self.assertEqual(actual_revision_log, expected_revision_log)

    def _get_origin_branches(self, origin):
        origin_visit = self.origin_visit_get(origin['id'])[-1]
        snapshot = self.snapshot_get(origin_visit['snapshot'])
        branches = {
            k: v
            for (k, v) in snapshot['branches'].items()
            if v['target_type'] == 'revision'
        }
        return branches

    @given(origin())
    def test_lookup_revision_log_by(self, origin):

        branches = self._get_origin_branches(origin)
        branch_name = random.choice(list(branches.keys()))

        actual_log =  \
            list(service.lookup_revision_log_by(origin['id'], branch_name,
                                                None, limit=25))

        expected_log = \
            self.revision_log(branches[branch_name]['target'], limit=25)

        self.assertEqual(actual_log, expected_log)

    @given(origin())
    def test_lookup_revision_log_by_notfound(self, origin):

        with self.assertRaises(NotFoundExc):
            service.lookup_revision_log_by(origin['id'],
                                           'unknown_branch_name',
                                           None,
                                           limit=100)

    @given(unknown_content())
    def test_lookup_content_raw_not_found(self, unknown_content):

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_content_raw('sha1:' + unknown_content['sha1'])

        self.assertIn(
            cm.exception.args[0],
            'Content with %s checksum equals to %s not found!' %
            ('sha1', unknown_content['sha1']))

    @given(content())
    def test_lookup_content_raw(self, content):

        actual_content = service.lookup_content_raw('sha256:%s' %
                                                    content['sha256'])

        expected_content = self.content_get(content['sha1'])

        self.assertEqual(actual_content, expected_content)

    @given(unknown_content())
    def test_lookup_content_not_found(self, unknown_content):

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_content('sha1:%s' % unknown_content['sha1'])

        self.assertIn(
            cm.exception.args[0],
            'Content with %s checksum equals to %s not found!' %
            ('sha1', unknown_content['sha1']))

    @given(content())
    def test_lookup_content_with_sha1(self, content):

        actual_content = service.lookup_content('sha1:%s' % content['sha1'])

        expected_content = self.content_get_metadata(content['sha1'])

        self.assertEqual(actual_content, expected_content)

    @given(content())
    def test_lookup_content_with_sha256(self, content):

        actual_content = service.lookup_content('sha256:%s' %
                                                content['sha256'])

        expected_content = self.content_get_metadata(content['sha1'])

        self.assertEqual(actual_content, expected_content)

    @given(revision())
    def test_lookup_person(self, revision):

        rev_data = self.revision_get(revision)

        actual_person = service.lookup_person(rev_data['author']['id'])

        self.assertEqual(actual_person, rev_data['author'])

    def test_lookup_directory_bad_checksum(self):

        with self.assertRaises(BadInputExc):
            service.lookup_directory('directory_id')

    @given(unknown_directory())
    def test_lookup_directory_not_found(self, unknown_directory):

        with self.assertRaises(NotFoundExc) as cm:
            service.lookup_directory(unknown_directory)

        self.assertIn(
            'Directory with sha1_git %s not found' % unknown_directory,
            cm.exception.args[0])

    @given(directory())
    def test_lookup_directory(self, directory):

        actual_directory_ls = list(service.lookup_directory(directory))

        expected_directory_ls = self.directory_ls(directory)

        self.assertEqual(actual_directory_ls, expected_directory_ls)

    @given(empty_directory())
    def test_lookup_directory_empty(self, empty_directory):

        actual_directory_ls = list(service.lookup_directory(empty_directory))

        self.assertEqual(actual_directory_ls, [])

    @given(origin())
    def test_lookup_revision_by_nothing_found(self, origin):

        with self.assertRaises(NotFoundExc):
            service.lookup_revision_by(origin['id'], 'invalid-branch-name')

    @given(origin())
    def test_lookup_revision_by(self, origin):

        branches = self._get_origin_branches(origin)
        branch_name = random.choice(list(branches.keys()))

        actual_revision =  \
            service.lookup_revision_by(origin['id'], branch_name, None)

        expected_revision = \
            self.revision_get(branches[branch_name]['target'])

        self.assertEqual(actual_revision, expected_revision)

    @given(origin(), revision())
    def test_lookup_revision_with_context_by_ko(self, origin, revision):

        with self.assertRaises(NotFoundExc):
            service.lookup_revision_with_context_by(origin['id'],
                                                    'invalid-branch-name',
                                                    None, revision)

    @given(origin())
    def test_lookup_revision_with_context_by(self, origin):

        branches = self._get_origin_branches(origin)
        branch_name = random.choice(list(branches.keys()))

        root_rev = branches[branch_name]['target']
        root_rev_log = self.revision_log(root_rev)

        children = defaultdict(list)

        for rev in root_rev_log:
            for rev_p in rev['parents']:
                children[rev_p].append(rev['id'])

        rev = root_rev_log[-1]['id']

        actual_root_rev, actual_rev = service.lookup_revision_with_context_by(
            origin['id'], branch_name, None, rev)

        expected_root_rev = self.revision_get(root_rev)
        expected_rev = self.revision_get(rev)
        expected_rev['children'] = children[rev]

        self.assertEqual(actual_root_rev, expected_root_rev)
        self.assertEqual(actual_rev, expected_rev)

    def test_lookup_revision_through_ko_not_implemented(self):

        with self.assertRaises(NotImplementedError):
            service.lookup_revision_through({
                'something-unknown': 10,
            })

    @given(origin())
    def test_lookup_revision_through_with_context_by(self, origin):

        branches = self._get_origin_branches(origin)
        branch_name = random.choice(list(branches.keys()))

        root_rev = branches[branch_name]['target']
        root_rev_log = self.revision_log(root_rev)
        rev = root_rev_log[-1]['id']

        self.assertEqual(
            service.lookup_revision_through({
                'origin_id': origin['id'],
                'branch_name': branch_name,
                'ts': None,
                'sha1_git': rev
            }),
            service.lookup_revision_with_context_by(origin['id'], branch_name,
                                                    None, rev))

    @given(origin())
    def test_lookup_revision_through_with_revision_by(self, origin):

        branches = self._get_origin_branches(origin)
        branch_name = random.choice(list(branches.keys()))

        self.assertEqual(
            service.lookup_revision_through({
                'origin_id': origin['id'],
                'branch_name': branch_name,
                'ts': None,
            }), service.lookup_revision_by(origin['id'], branch_name, None))

    @given(ancestor_revisions())
    def test_lookup_revision_through_with_context(self, ancestor_revisions):

        sha1_git = ancestor_revisions['sha1_git']
        sha1_git_root = ancestor_revisions['sha1_git_root']

        self.assertEqual(
            service.lookup_revision_through({
                'sha1_git_root': sha1_git_root,
                'sha1_git': sha1_git,
            }), service.lookup_revision_with_context(sha1_git_root, sha1_git))

    @given(revision())
    def test_lookup_revision_through_with_revision(self, revision):

        self.assertEqual(
            service.lookup_revision_through({'sha1_git': revision}),
            service.lookup_revision(revision))

    @given(revision())
    def test_lookup_directory_through_revision_ko_not_found(self, revision):

        with self.assertRaises(NotFoundExc):
            service.lookup_directory_through_revision({'sha1_git': revision},
                                                      'some/invalid/path')

    @given(revision())
    def test_lookup_directory_through_revision_ok(self, revision):

        revision_data = self.revision_get(revision)
        dir_entries = [
            e for e in self.directory_ls(revision_data['directory'])
            if e['type'] == 'file'
        ]
        dir_entry = random.choice(dir_entries)

        self.assertEqual(
            service.lookup_directory_through_revision({'sha1_git': revision},
                                                      dir_entry['name']),
            (revision,
             service.lookup_directory_with_revision(revision,
                                                    dir_entry['name'])))

    @given(revision())
    def test_lookup_directory_through_revision_ok_with_data(self, revision):

        revision_data = self.revision_get(revision)
        dir_entries = [
            e for e in self.directory_ls(revision_data['directory'])
            if e['type'] == 'file'
        ]
        dir_entry = random.choice(dir_entries)

        self.assertEqual(
            service.lookup_directory_through_revision({'sha1_git': revision},
                                                      dir_entry['name'],
                                                      with_data=True),
            (revision,
             service.lookup_directory_with_revision(
                 revision, dir_entry['name'], with_data=True)))

    @given(new_origins(20))
    def test_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_idx = expected_origins[-1]['id']
        origin_count = random.randint(1, max_origin_idx - origin_from)

        actual_origins = list(service.lookup_origins(origin_from,
                                                     origin_count))
        expected_origins = list(
            self.storage.origin_get_range(origin_from, origin_count))

        self.assertEqual(actual_origins, expected_origins)