def test_thumbnail_endpoint_authenticated_no_perm(self, client, django_user_model): image = ImageFactoryWithImageFile() url = reverse("retina:image-thumbnail", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_access(self, client, user, expected_status): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:api:image-element-spacing-view", args=[image.pk]) client, _ = client_login(client, user=user) response = client.get(url) assert response.status_code == expected_status
def test_archive_view_returns_correct_error_on_empty_cache( self, client, monkeypatch ): # Clear cache manually cache.clear() # Mock celery task is_called = False def call_task(): nonlocal is_called is_called = True monkeypatch.setattr(cache_archive_data, "delay", call_task) # login client client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") response_data = json.loads(response.content) # check if correct error is sent assert response_data == { "error": [ 1, "Archive data task triggered. Try again in 2 minutes.", ] } assert is_called
def test_thumbnail_endpoint_authenticated_no_perm( self, client, django_user_model ): image = ImageFactoryWithImageFile() url = reverse("retina:image-thumbnail", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_returns_correct_spacing(self, client): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:api:image-element-spacing-view", args=[image.pk]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK r = response.json() assert list(image.get_sitk_image().GetSpacing()) == r
def test_numpy_endpoint_authenticated_status(self, client, django_user_model): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:image-numpy", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK assert response["Content-type"] == "application/octet-stream"
def test_thumbnail_endpoint_authenticated_non_existant( self, client, django_user_model): image = ImageFactoryWithImageFile() url = reverse("retina:image-thumbnail", args=[image.id]) # login client client, _ = client_login(client, user="******") image.delete() # remove model so response must return 404 response = client.get(url) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_archive_view_retina_auth(self, client): # Create data create_datastructures_data() # login client client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") assert response.status_code == status.HTTP_200_OK
def test_thumbnail_endpoint_authenticated_non_existant( self, client, django_user_model ): image = ImageFactoryWithImageFile() url = reverse("retina:image-thumbnail", args=[image.id]) # login client client, _ = client_login(client, user="******") image.delete() # remove model so response must return 404 response = client.get(url) assert response.status_code == status.HTTP_404_NOT_FOUND
def test_numpy_endpoint_authenticated_status( self, client, django_user_model ): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:image-numpy", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK assert response["Content-type"] == "application/octet-stream"
def test_numpy_endpoint_authenticated_images_correspond( self, client, django_user_model): image = ImageFactoryWithImageFile( modality__modality=settings.MODALITY_CF) image.permit_viewing_by_retina_users() url = reverse("retina:image-numpy", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) response_np = np.load(io.BytesIO(response.content)) sitk_image = image.get_sitk_image() nda_image = sitk.GetArrayFromImage(sitk_image) request_image_arr = nda_image.astype(np.int8) assert np.array_equal(response_np, request_image_arr)
def test_caching(self, client): # Clear cache manually cache.clear() # Perform normal request datastructures, _, _, _ = create_datastructures_data() client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") response_data = json.loads(response.content) # Remove archive and perform request again datastructures["archive"].delete() response = client.get(url, HTTP_ACCEPT="application/json") # Check that response is cached so it is not changed assert json.loads(response.content) == response_data
def test_numpy_endpoint_authenticated_images_correspond( self, client, django_user_model ): image = ImageFactoryWithImageFile( modality__modality=settings.MODALITY_CF ) image.permit_viewing_by_retina_users() url = reverse("retina:image-numpy", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) response_np = np.load(io.BytesIO(response.content)) sitk_image = image.get_sitk_image() nda_image = sitk.GetArrayFromImage(sitk_image) request_image_arr = nda_image.astype(np.int8) assert np.array_equal(response_np, request_image_arr)
def test_archive_view_returns_correct_data_from_cache(self, client): # Clear cache manually cache.clear() # Set cached data test_data = {"test": "data", "object": 1} ArchiveDataModel.objects.update_or_create( pk=1, defaults={"value": test_data}, ) # login client client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") response_data = json.loads(response.content) # check if correct data is sent assert response_data == test_data
def test_returns_correct_spacing_changed(self, client): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() element_spacing = (1.5, 0.5) response = create_element_spacing_request( client, image_name=image.name, es=element_spacing ) assert response.status_code == status.HTTP_200_OK r = response.json() assert r["success"] assert element_spacing == image.get_sitk_image().GetSpacing() url = reverse("retina:api:image-element-spacing-view", args=[image.pk]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK r = response.json() assert list(image.get_sitk_image().GetSpacing()) == r
def test_thumbnail_endpoint_authenticated(self, client, django_user_model): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:image-thumbnail", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK assert response["Content-type"] == "image/png" response_np = np.array(PILImage.open(io.BytesIO(response.content)), np.uint8) sitk_image = image.get_sitk_image() depth = sitk_image.GetDepth() nda_image = sitk.GetArrayFromImage(sitk_image) if depth > 0: nda_image = nda_image[depth // 2] expected_np = nda_image.astype(np.uint8) assert np.array_equal(response_np, expected_np)
def test_thumbnail_endpoint_authenticated(self, client, django_user_model): image = ImageFactoryWithImageFile() image.permit_viewing_by_retina_users() url = reverse("retina:image-thumbnail", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_200_OK assert response["Content-type"] == "image/png" response_np = np.array( PILImage.open(io.BytesIO(response.content)), np.uint8 ) sitk_image = image.get_sitk_image() depth = sitk_image.GetDepth() nda_image = sitk.GetArrayFromImage(sitk_image) if depth > 0: nda_image = nda_image[depth // 2] expected_np = nda_image.astype(np.uint8) assert np.array_equal(response_np, expected_np)
def test_numpy_endpoint_normal_non_authenticated(self, client): image = ImageFactoryWithImageFile() url = reverse("retina:image-numpy", args=[image.id]) client, _ = client_login(client, user="******") response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_archive_view_returns_correct_data(self, client): # Clear cache manually (this is not done by pytest-django for some reason...) cache.clear() # Create data datastructures, datastructures_aus, oct_obs_registration, oct_obs_registration_aus = ( create_datastructures_data()) # login client client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") response_data = json.loads(response.content) # check if correct data is sent expected_response_data = { "subfolders": { datastructures["archive"].name: { "subfolders": { datastructures["patient"].name: { "subfolders": { datastructures["study_oct"].name: { "info": "level 5", "images": { datastructures["image_oct"].name: { "images": { "trc_000": "no info", "obs_000": str(datastructures["image_obs"] .id), "mot_comp": "no info", "trc_001": "no info", "oct": str(datastructures["image_oct"] .id), }, "info": { "voxel_size": { "axial": 0, "lateral": 0, "transversal": 0, }, "date": datastructures["study_oct"]. datetime.strftime( "%Y/%m/%d %H:%M:%S"), "registration": { "obs": "Checked separately", "trc": [0, 0, 0, 0], }, }, } }, "name": datastructures["study_oct"].name, "id": str(datastructures["study_oct"].id), "subfolders": {}, }, datastructures["study"].name: { "info": "level 5", "images": { datastructures["image_cf"].name: str(datastructures["image_cf"].id) }, "name": datastructures["study"].name, "id": str(datastructures["study"].id), "subfolders": {}, }, }, "info": "level 4", "name": datastructures["patient"].name, "id": str(datastructures["patient"].id), "images": {}, } }, "info": "level 3", "name": datastructures["archive"].name, "id": str(datastructures["archive"].id), "images": {}, }, datastructures_aus["archive"].name: { "subfolders": { datastructures_aus["patient"].name: { "subfolders": {}, "info": "level 4", "name": datastructures_aus["patient"].name, "id": str(datastructures_aus["patient"].id), "images": { datastructures_aus["image_oct"].name: { "images": { "trc_000": "no info", "obs_000": str(datastructures_aus["image_obs"].id ), "mot_comp": "no info", "trc_001": "no info", "oct": str(datastructures_aus["image_oct"].id ), }, "info": { "voxel_size": { "axial": 0, "lateral": 0, "transversal": 0, }, "date": datastructures_aus["study_oct"]. datetime.strftime("%Y/%m/%d %H:%M:%S"), "registration": { "obs": "Checked separately", "trc": [0, 0, 0, 0], }, }, }, datastructures_aus["image_cf"].name: str(datastructures_aus["image_cf"].id), }, } }, "info": "level 3", "name": datastructures_aus["archive"].name, "id": str(datastructures_aus["archive"].id), "images": {}, }, }, "info": "level 2", "name": "Archives", "id": "none", "images": {}, } # Compare floats separately because of intricacies of floating-point arithmetic in python try: # Get info objects of both archives in response data response_archive_info = (response_data.get("subfolders").get( datastructures["archive"].name).get("subfolders").get( datastructures["patient"].name).get("subfolders").get( datastructures["study_oct"].name).get("images").get( datastructures["image_oct"].name).get("info")) response_archive_australia_info = ( response_data.get("subfolders").get( datastructures_aus["archive"].name).get("subfolders").get( datastructures_aus["patient"].name).get("images").get( datastructures_aus["image_oct"].name).get("info")) floats_to_compare = ( []) # list of (response_float, expected_float, name) tuples for archive, response_info, ds, oor in ( ( "Rotterdam", response_archive_info, datastructures, oct_obs_registration, ), ( "Australia", response_archive_australia_info, datastructures_aus, oct_obs_registration_aus, ), ): # oct obs registration response_obs = response_info.get("registration").get("obs") rv = oor.registration_values floats_to_compare.append(( response_obs[0], rv[0][0], archive + " obs oct registration top left x", )) floats_to_compare.append(( response_obs[1], rv[0][1], archive + " obs oct registration top left y", )) floats_to_compare.append(( response_obs[2], rv[1][0], archive + " obs oct registration bottom right x", )) floats_to_compare.append(( response_obs[3], rv[1][1], archive + " obs oct registration bottom right y", )) # Compare floats for result, expected, name in floats_to_compare: if result != pytest.approx(expected): pytest.fail(name + " does not equal expected value") # Clear voxel and obs registration objects before response object to expected object comparison response_data["subfolders"][datastructures["archive"].name][ "subfolders"][datastructures["patient"].name]["subfolders"][ datastructures["study_oct"].name]["images"][ datastructures["image_oct"].name]["info"][ "registration"]["obs"] = "Checked separately" response_data["subfolders"][datastructures_aus["archive"].name][ "subfolders"][datastructures_aus["patient"].name]["images"][ datastructures_aus["image_oct"]. name]["info"]["registration"]["obs"] = "Checked separately" except (AttributeError, KeyError, TypeError): pytest.fail("Response object structure is not correct") assert response_data == expected_response_data
def test_no_access(self, client, user): image = ImageFactoryWithImageFile() url = reverse("retina:api:image-element-spacing-view", args=[image.pk]) client, _ = client_login(client, user=user) response = client.get(url) assert response.status_code == status.HTTP_403_FORBIDDEN
def test_archive_view_returns_correct_data(self, client): # Clear cache manually (this is not done by pytest-django for some reason...) cache.clear() # Create data datastructures, datastructures_aus, oct_obs_registration, oct_obs_registration_aus = ( create_datastructures_data() ) # login client client, _ = client_login(client, user="******") url = reverse("retina:api:archives-api-view") response = client.get(url, HTTP_ACCEPT="application/json") response_data = json.loads(response.content) # check if correct data is sent expected_response_data = { "subfolders": { datastructures["archive"].name: { "subfolders": { datastructures["patient"].name: { "subfolders": { datastructures["study_oct"].name: { "info": "level 5", "images": { datastructures["image_oct"].name: { "images": { "trc_000": "no info", "obs_000": str( datastructures[ "image_obs" ].id ), "mot_comp": "no info", "trc_001": "no info", "oct": str( datastructures[ "image_oct" ].id ), }, "info": { "voxel_size": { "axial": 0, "lateral": 0, "transversal": 0, }, "date": datastructures[ "study_oct" ].datetime.strftime( "%Y/%m/%d %H:%M:%S" ), "registration": { "obs": "Checked separately", "trc": [0, 0, 0, 0], }, }, } }, "name": datastructures["study_oct"].name, "id": str(datastructures["study_oct"].id), "subfolders": {}, }, datastructures["study"].name: { "info": "level 5", "images": { datastructures["image_cf"].name: str( datastructures["image_cf"].id ) }, "name": datastructures["study"].name, "id": str(datastructures["study"].id), "subfolders": {}, }, }, "info": "level 4", "name": datastructures["patient"].name, "id": str(datastructures["patient"].id), "images": {}, } }, "info": "level 3", "name": datastructures["archive"].name, "id": str(datastructures["archive"].id), "images": {}, }, datastructures_aus["archive"].name: { "subfolders": { datastructures_aus["patient"].name: { "subfolders": {}, "info": "level 4", "name": datastructures_aus["patient"].name, "id": str(datastructures_aus["patient"].id), "images": { datastructures_aus["image_oct"].name: { "images": { "trc_000": "no info", "obs_000": str( datastructures_aus["image_obs"].id ), "mot_comp": "no info", "trc_001": "no info", "oct": str( datastructures_aus["image_oct"].id ), }, "info": { "voxel_size": { "axial": 0, "lateral": 0, "transversal": 0, }, "date": datastructures_aus[ "study_oct" ].datetime.strftime( "%Y/%m/%d %H:%M:%S" ), "registration": { "obs": "Checked separately", "trc": [0, 0, 0, 0], }, }, }, datastructures_aus["image_cf"].name: str( datastructures_aus["image_cf"].id ), }, } }, "info": "level 3", "name": datastructures_aus["archive"].name, "id": str(datastructures_aus["archive"].id), "images": {}, }, }, "info": "level 2", "name": "Archives", "id": "none", "images": {}, } # Compare floats separately because of intricacies of floating-point arithmetic in python try: # Get info objects of both archives in response data response_archive_info = ( response_data.get("subfolders") .get(datastructures["archive"].name) .get("subfolders") .get(datastructures["patient"].name) .get("subfolders") .get(datastructures["study_oct"].name) .get("images") .get(datastructures["image_oct"].name) .get("info") ) response_archive_australia_info = ( response_data.get("subfolders") .get(datastructures_aus["archive"].name) .get("subfolders") .get(datastructures_aus["patient"].name) .get("images") .get(datastructures_aus["image_oct"].name) .get("info") ) floats_to_compare = ( [] ) # list of (response_float, expected_float, name) tuples for archive, response_info, ds, oor in ( ( "Rotterdam", response_archive_info, datastructures, oct_obs_registration, ), ( "Australia", response_archive_australia_info, datastructures_aus, oct_obs_registration_aus, ), ): # oct obs registration response_obs = response_info.get("registration").get("obs") rv = oor.registration_values floats_to_compare.append( ( response_obs[0], rv[0][0], archive + " obs oct registration top left x", ) ) floats_to_compare.append( ( response_obs[1], rv[0][1], archive + " obs oct registration top left y", ) ) floats_to_compare.append( ( response_obs[2], rv[1][0], archive + " obs oct registration bottom right x", ) ) floats_to_compare.append( ( response_obs[3], rv[1][1], archive + " obs oct registration bottom right y", ) ) # Compare floats for result, expected, name in floats_to_compare: if result != pytest.approx(expected): pytest.fail(name + " does not equal expected value") # Clear voxel and obs registration objects before response object to expected object comparison response_data["subfolders"][datastructures["archive"].name][ "subfolders" ][datastructures["patient"].name]["subfolders"][ datastructures["study_oct"].name ][ "images" ][ datastructures["image_oct"].name ][ "info" ][ "registration" ][ "obs" ] = "Checked separately" response_data["subfolders"][datastructures_aus["archive"].name][ "subfolders" ][datastructures_aus["patient"].name]["images"][ datastructures_aus["image_oct"].name ][ "info" ][ "registration" ][ "obs" ] = "Checked separately" except (AttributeError, KeyError, TypeError): pytest.fail("Response object structure is not correct") assert response_data == expected_response_data