def test_handle_release_upload_exists_in_db_and_not_on_disk(file_content): filehash = hashlib.sha256(file_content).hexdigest() stream = io.BytesIO(file_content) existing = ReleaseFileFactory( name="file1.txt", path="foo/file1.txt", filehash=filehash, uploaded_at=None, ) # check out test setup is correct assert existing.filehash == filehash # upload same files releases.handle_file_upload( existing.release, existing.release.backend, existing.created_by, stream, "file1.txt", ) existing.refresh_from_db() assert existing.uploaded_at assert existing.absolute_path().exists()
def test_releasefile_format(): rfile = ReleaseFileFactory() rfile.size = 3.2 * 1024 * 1024 # 3.2Mb rfile.save() assert f"{rfile:b}" == "3,355,443.2b" assert f"{rfile:Kb}" == "3,276.8Kb" assert f"{rfile:Mb}" == "3.2Mb" assert f"{rfile}".startswith("ReleaseFile object")
def test_reviewapi_success(api_rf): release = ReleaseFactory() ReleaseFileFactory(release=release, name="test1", filehash="test1") ReleaseFileFactory(release=release, name="test2", filehash="test2") data = { "files": [ { "name": "test1", "url": "url", "size": 7, "sha256": "test1", "date": timezone.now(), "metadata": {}, "review": { "status": "APPROVED", "comments": {"test": "foo"}, }, }, { "name": "test2", "url": "url", "size": 7, "sha256": "test2", "date": timezone.now(), "metadata": {}, "review": { "status": "REJECTED", "comments": {"test": "bar"}, }, }, ], "metadata": {}, "review": {"foo": "bar"}, } request = api_rf.post("/", data=data, format="json") request.user = UserFactory(roles=[OutputChecker]) response = ReviewAPI.as_view()(request, release_id=release.pk) assert response.status_code == 200, response.data release.refresh_from_db() assert release.review == {"foo": "bar"} review1, review2 = ReleaseFileReview.objects.filter( release_file__release=release ).order_by("release_file__name") assert review1.status == "APPROVED" assert review1.comments == {"test": "foo"} assert review2.status == "REJECTED" assert review2.comments == {"test": "bar"}
def test_releasefile_get_latest_url(): rfile = ReleaseFileFactory(name="file1.txt") url = rfile.get_latest_url() assert url == reverse( "workspace-latest-outputs-detail", kwargs={ "org_slug": rfile.release.workspace.project.org.slug, "project_slug": rfile.release.workspace.project.slug, "workspace_slug": rfile.release.workspace.name, "path": f"{rfile.release.backend.slug}/{rfile.name}", }, )
def test_releasefile_get_delete_url(): rfile = ReleaseFileFactory() url = rfile.get_delete_url() assert url == reverse( "release-file-delete", kwargs={ "org_slug": rfile.release.workspace.project.org.slug, "project_slug": rfile.release.workspace.project.slug, "workspace_slug": rfile.release.workspace.name, "pk": rfile.release.id, "release_file_id": rfile.pk, }, )
def test_releasefile_get_absolute_url(): rfile = ReleaseFileFactory(name="file1.txt") url = rfile.get_absolute_url() assert url == reverse( "release-detail", kwargs={ "org_slug": rfile.release.workspace.project.org.slug, "project_slug": rfile.release.workspace.project.slug, "workspace_slug": rfile.release.workspace.name, "pk": rfile.release.id, "path": rfile.name, }, )
def test_release_with_a_missing_file(download_file_mock, repository, rf): """ If a local ReleaseFile had a missing file we must set local as False, redirect to the PyPI, requeue the download_file task. """ release_file = ReleaseFileFactory(release__package__repository=repository) os.remove(release_file.distribution.path) url_kwargs = { 'repo': repository.slug, 'name': release_file.release.package.name, 'pk': release_file.pk, 'filename': release_file.filename } request = rf.get(reverse('packages:download', kwargs=url_kwargs)) response = views.DownloadReleaseFile.as_view()(request, **url_kwargs) # The request is redirected to PyPI assert response.status_code == 302 assert response.url == release_file.url # The download file task must the queued assert download_file_mock.delay.call_count == 1 assert download_file_mock.delay.call_args[1] == {'pk': release_file.pk}
def test_releasefile_get_api_url_with_is_published(): rfile = ReleaseFileFactory() # mirror the SnapshotAPI view setting this value on the ReleaseFile object. setattr(rfile, "is_published", True) url = rfile.get_api_url() assert url == reverse( "published-file", kwargs={ "org_slug": rfile.workspace.project.org.slug, "project_slug": rfile.workspace.project.slug, "workspace_slug": rfile.workspace.name, "file_id": rfile.id, }, )
def test_releasefileapi_with_anonymous_user(api_rf): rfile = ReleaseFileFactory() request = api_rf.get("/") response = ReleaseFileAPI.as_view()(request, file_id=rfile.id) assert response.status_code == 403
def test_releasefileapi_without_permission(api_rf): rfile = ReleaseFileFactory() request = api_rf.get("/") request.user = UserFactory() # logged in, but no permission response = ReleaseFileAPI.as_view()(request, file_id=rfile.id) assert response.status_code == 403
def test_build_outputs_zip_with_missing_files(build_release_with_files): release = build_release_with_files(["test1", "test3", "test5"]) # create a couple of deleted files user = UserFactory() ReleaseFileFactory(release=release, name="test2", deleted_at=timezone.now(), deleted_by=user) ReleaseFileFactory(release=release, name="test4", deleted_at=timezone.now(), deleted_by=user) release.requested_files.append([{"name": "test2"}, {"name": "test4"}]) files = release.files.order_by("name") zf = releases.build_outputs_zip(files, lambda u: u) with zipfile.ZipFile(zf, "r") as zip_obj: assert zip_obj.testzip() is None assert zip_obj.namelist() == [ "test1", "test2", "test3", "test4", "test5" ] # check ReleaseFile on-disk contents matches their zipped contents for name in ["test1", "test3", "test5"]: with open(files.get(name=name).absolute_path(), "rb") as f: original_contents = f.read() with zip_obj.open(name) as f: zipped_contents = f.read() assert zipped_contents == original_contents for name in ["test2", "test4"]: with zip_obj.open(name) as f: zipped_contents = f.read().decode() rfile = files.get(name=name) assert rfile.get_absolute_url() in zipped_contents, zipped_contents assert "This file was redacted by" in zipped_contents, zipped_contents
def test_create_release_reupload(): rfile = ReleaseFileFactory(name="file1.txt", filehash="hash") files = {"file1.txt": "hash"} with pytest.raises(releases.ReleaseFileAlreadyExists): releases.create_release( rfile.release.workspace, rfile.release.backend, rfile.release.created_by, files, )
def test_reviewapi_unknown_filename_or_content(api_rf): release = ReleaseFactory() ReleaseFileFactory(release=release, name="test1", filehash="test1") ReleaseFileFactory(release=release, name="test2", filehash="test2") data = { "files": [ { "name": "unknown", "url": "url", "size": 7, "sha256": "test1", "date": timezone.now(), "metadata": {}, "review": { "status": "APPROVED", "comments": {"test": "foo"}, }, }, { "name": "test2", "url": "url", "size": 7, "sha256": "unknown", "date": timezone.now(), "metadata": {}, "review": { "status": "REJECTED", "comments": {"test": "bar"}, }, }, ], "metadata": {}, "review": {}, } request = api_rf.post("/", data=data, format="json") request.user = UserFactory(roles=[OutputChecker]) response = ReviewAPI.as_view()(request, release_id=release.pk) assert response.status_code == 400, response.data
def test_upload_should_not_overwrite_pypi_package(app, repository, admin_user): ReleaseFileFactory( release__package__repository=repository, release__package__name='localshop') headers = { 'Content-type': tostr('multipart/form-data; boundary=--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'), 'Authorization': basic_auth_header('admin', 'password'), } response = app.post( '/repo/%s/' % repository.slug, REGISTER_POST, headers=headers, status=400) assert response.unicode_body == 'localshop is a pypi package!'
def test_wrong_package_name_case(app, admin_user, repository, pypi_stub): repository.upstream_pypi_url = pypi_stub.url repository.save() ReleaseFileFactory( release__package__repository=repository, release__package__name='minibar') response = app.get( reverse('packages:simple_detail', kwargs={ 'slug': 'Minibar', 'repo': 'default' })) assert response.status_code == 302 assert response.url == 'http://testserver/repo/default/minibar/'
def test_releasefileapi_with_deleted_file(api_rf): rfile = ReleaseFileFactory(deleted_at=timezone.now(), deleted_by=UserFactory()) user = UserFactory() ProjectMembershipFactory( user=user, project=rfile.release.workspace.project, roles=[ProjectCollaborator], ) request = api_rf.get("/") request.user = user response = ReleaseFileAPI.as_view()(request, file_id=rfile.id) assert response.status_code == 404, response.data
def test_download_file_incorrect_md5_sum(requests_mock): file_data = six.b('My cool package') release_file = ReleaseFileFactory(distribution=None, md5_digest='arcoiro') requests_mock.return_value = mock.Mock(**{ 'headers': { 'content-length': len(file_data), 'content-type': 'application/octet-stream', }, 'content': file_data, }) tasks.download_file.run(release_file.pk) release_file = models.ReleaseFile.objects.get(pk=release_file.pk) assert not release_file.distribution
def test_workspace_files_one_release(build_release): backend = BackendFactory(slug="backend") names = ["test1", "test2", "test3"] release = build_release(names, backend=backend) for name in names: ReleaseFileFactory( release=release, workspace=release.workspace, name=name, ) output = releases.workspace_files(release.workspace) assert output == { "backend/test1": release.files.get(name="test1"), "backend/test2": release.files.get(name="test2"), "backend/test3": release.files.get(name="test3"), }
def test_handle_release_upload_exists_with_incorrect_filehash(file_content): stream = io.BytesIO(file_content) existing = ReleaseFileFactory( name="file1.txt", path="foo/file1.txt", filehash="hash", uploaded_at=None, ) with pytest.raises(Exception, match="^Contents of uploaded"): releases.handle_file_upload( existing.release, existing.release.backend, existing.created_by, stream, "file1.txt", )
def test_releaseworkspaceapi_post_release_already_exists(api_rf): user = UserFactory(roles=[OutputChecker]) release = ReleaseFactory() rfile = ReleaseFileFactory( release=release, created_by=user, name="file.txt", filehash="hash", ) BackendMembershipFactory(backend=release.backend, user=user) ProjectMembershipFactory(project=release.workspace.project, user=user) data = { "files": [ { "name": rfile.name, "url": "url", "size": 7, "sha256": rfile.filehash, "date": timezone.now(), "metadata": {}, "review": None, } ], "metadata": {}, "review": {}, } request = api_rf.post( "/", data=data, format="json", HTTP_AUTHORIZATION=release.backend.auth_token, HTTP_OS_USER=user.username, ) response = ReleaseWorkspaceAPI.as_view()( request, workspace_name=release.workspace.name ) assert response.status_code == 400 assert "file.txt" in response.data["detail"] assert "already been uploaded" in response.data["detail"]
def test_create_release_new_style_reupload(): rfile = ReleaseFileFactory(name="file1.txt", filehash="hash") files = [{ "name": "file1.txt", "path": "path/to/file1.txt", "url": "", "size": 4, "sha256": "hash", "mtime": "2022-08-17T13:37Z", "metadata": {}, }] with pytest.raises(releases.ReleaseFileAlreadyExists): releases.create_release( rfile.release.workspace, rfile.release.backend, rfile.release.created_by, files, )
def test_download_pypi_release(download_file_mock, repository, rf): release_file = ReleaseFileFactory(release__package__repository=repository, distribution=None) url_kwargs = { 'repo': repository.slug, 'name': release_file.release.package.name, 'pk': release_file.pk, 'filename': release_file.filename } request = rf.get(reverse('packages:download', kwargs=url_kwargs)) response = views.DownloadReleaseFile.as_view()(request, **url_kwargs) # The request is redirected to PyPI assert response.status_code == 302 assert response.url == release_file.url # The download file task must the queued assert download_file_mock.delay.call_count == 1 assert download_file_mock.delay.call_args[1] == {'pk': release_file.pk}
def test_upload_should_not_overwrite_pypi_package( django_app, repository, admin_user, upload_post_data ): ReleaseFileFactory( release__package__repository=repository, release__package__name='localshop') key = admin_user.access_keys.create(comment='For testing') headers = { 'Content-type': upload_post_data.content_type, 'Authorization': basic_auth_header(key.access_key, key.secret_key) } response = django_app.post( '/repo/%s/' % repository.slug, params=upload_post_data.to_string(), headers=headers, status=400) assert response.unicode_body == 'localshop is a pypi package!'
def test_success(app, admin_user, repository, pypi_stub): repository.upstream_pypi_url = pypi_stub.url repository.save() release_file = ReleaseFileFactory(release__package__repository=repository) response = app.get( reverse('packages:simple_detail', kwargs={ 'slug': release_file.release.package.name, 'repo': release_file.release.package.repository.slug })) assert response.status_code == 200 assert 'Links for test-package' in response.unicode_body a_elms = response.html.select('a') assert len(a_elms) == 1 assert a_elms[0]['href'] == ( '/repo/default/download/test-package/1/test-1.0.0-sdist.zip' + '#md5=62ecd3ee980023db87945470aa2b347b') assert a_elms[0]['rel'][0] == 'package'
def test_download_file_missing_content_length(requests_mock, settings, tmpdir): settings.MEDIA_ROOT = tmpdir file_data = six.b('My cool package') release_file = ReleaseFileFactory(distribution=None, md5_digest=md5(file_data).hexdigest()) requests_mock.return_value = mock.Mock(**{ 'headers': { 'content-type': 'application/octet-stream', }, 'content': file_data, }) tasks.download_file.run(release_file.pk) release_file = models.ReleaseFile.objects.get(pk=release_file.pk) assert release_file.distribution.read() == file_data assert release_file.distribution.size == len(file_data) assert release_file.distribution.name == ( 'default/2.7/t/test-package/test-1.0.0-sdist.zip')
def test_download_local_release(rf, isolated, repository, settings): settings.LOCALSHOP_ISOLATED = isolated release_file = ReleaseFileFactory(release__package__repository=repository) url_kwargs = { 'repo': repository.slug, 'name': release_file.release.package.name, 'pk': release_file.pk, 'filename': release_file.filename } request = rf.get(reverse('packages:download', kwargs=url_kwargs)) response = views.DownloadReleaseFile.as_view()(request, **url_kwargs) # Localshop must return the release file assert response.status_code == 200 assert response.content == six.b('the file data') assert response.get('Content-Length') == '13' assert response.get( 'Content-Disposition') == 'attachment; filename=test-1.0.0-sdist.zip'
def test_download_file_with_proxy_enabled(requests_mock, settings): settings.LOCALSHOP_HTTP_PROXY = { "http": "http://10.10.1.10:3128/", } file_data = six.b('My cool package') release_file = ReleaseFileFactory(distribution=None, md5_digest=md5(file_data).hexdigest()) requests_mock.return_value = mock.Mock(**{ 'headers': { 'content-length': len(file_data), 'content-type': 'application/octet-stream', }, 'content': file_data, }) tasks.download_file.run(release_file.pk) requests_mock.assert_called_once_with( 'http://www.example.org/download/test-1.0.0-sdist.zip', proxies=settings.LOCALSHOP_HTTP_PROXY, stream=True)
def test_releasefileapi_with_no_file_on_disk(api_rf, build_release): release = build_release(["file1.txt"]) rfile = ReleaseFileFactory( release=release, workspace=release.workspace, name="file1.txt", uploaded_at=None, ) user = UserFactory() ProjectMembershipFactory( user=user, project=release.workspace.project, roles=[ProjectCollaborator], ) request = api_rf.get("/") request.user = user response = ReleaseFileAPI.as_view()(request, file_id=rfile.id) assert response.status_code == 404, response.data
def test_download_pypi_release_when_isolated_is_on(requests_mock, rf, repository, settings): file_data = six.b('Hello from PyPI') md5_digest = md5(file_data).hexdigest() settings.LOCALSHOP_ISOLATED = True release_file = ReleaseFileFactory(release__package__repository=repository, distribution=None, md5_digest=md5_digest) url_kwargs = { 'repo': repository.slug, 'name': release_file.release.package.name, 'pk': release_file.pk, 'filename': release_file.filename } requests_mock.return_value = Mock( **{ 'headers': { 'content-length': len(file_data), 'content-type': 'application/octet-stream', }, 'content': file_data, }) request = rf.get(reverse('packages:download', kwargs=url_kwargs)) response = views.DownloadReleaseFile.as_view()(request, **url_kwargs) assert response.status_code == 200 assert response.content == file_data requests_mock.assert_called_with( u'http://www.example.org/download/test-1.0.0-sdist.zip', proxies=None, stream=True)
def test_releasefile_constraints_missing_deleted_at_or_deleted_by(): with pytest.raises(IntegrityError): ReleaseFileFactory(deleted_at=None, deleted_by=UserFactory()) with pytest.raises(IntegrityError): ReleaseFileFactory(deleted_at=timezone.now(), deleted_by=None)