|
@@ -1,7 +1,10 @@
|
|
|
+import cv2
|
|
|
import io
|
|
|
+import numpy as np
|
|
|
import os
|
|
|
import uuid
|
|
|
|
|
|
+from PIL import Image
|
|
|
from flask import url_for
|
|
|
from pathlib import Path
|
|
|
from pycs.database.File import File
|
|
@@ -125,3 +128,195 @@ class FileDeletionTests(_BaseFileTests):
|
|
|
self.assertEqual(1, self.project.files.count())
|
|
|
self.post(url, json=dict(remove=True), status_code=400)
|
|
|
self.assertEqual(1, self.project.files.count())
|
|
|
+
|
|
|
+
|
|
|
+class FileGettingTests(_BaseFileTests):
|
|
|
+
|
|
|
+
|
|
|
+ def test_get_file_getting(self):
|
|
|
+
|
|
|
+ file_uuid = str(uuid.uuid1())
|
|
|
+ file, is_new = self.project.add_file(
|
|
|
+ uuid=file_uuid,
|
|
|
+ file_type="image",
|
|
|
+ name=f"name",
|
|
|
+ filename=f"image",
|
|
|
+ extension=".jpg",
|
|
|
+ size=32*1024,
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertTrue(is_new)
|
|
|
+ self.assertEqual(1, self.project.files.count())
|
|
|
+
|
|
|
+ url = url_for("get_file", file_id=file.id)
|
|
|
+
|
|
|
+ # without an actual file, this GET request returns 404
|
|
|
+ self.get(url, status_code=404)
|
|
|
+
|
|
|
+ content = b"some text"
|
|
|
+ with open(file.absolute_path, "wb") as f:
|
|
|
+ f.write(content)
|
|
|
+
|
|
|
+ response = self.get(url)
|
|
|
+
|
|
|
+ self.assertFalse(response.is_json)
|
|
|
+ self.assertEqual(content, response.data)
|
|
|
+
|
|
|
+ def test_get_prev_next_file(self):
|
|
|
+
|
|
|
+ for i in range(1, 6):
|
|
|
+ file_uuid = str(uuid.uuid1())
|
|
|
+ file, is_new = self.project.add_file(
|
|
|
+ uuid=file_uuid,
|
|
|
+ file_type="image",
|
|
|
+ name=f"name_{i}",
|
|
|
+ filename=f"image_{i}",
|
|
|
+ extension=".jpg",
|
|
|
+ size=32*1024,
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertTrue(is_new)
|
|
|
+ with open(file.absolute_path, "wb") as f:
|
|
|
+ f.write(b"some content")
|
|
|
+
|
|
|
+ self.assertEqual(5, self.project.files.count())
|
|
|
+ files = self.project.files.all()
|
|
|
+
|
|
|
+ url = url_for("get_previous_and_next_file", file_id=4542)
|
|
|
+ self.get(url, status_code=404)
|
|
|
+
|
|
|
+ for i, file in enumerate(files):
|
|
|
+ p_file, n_file = None, None
|
|
|
+
|
|
|
+ if i != 0:
|
|
|
+ p_file = files[i-1].serialize()
|
|
|
+
|
|
|
+ if i < len(files)-1:
|
|
|
+ n_file = files[i+1].serialize()
|
|
|
+
|
|
|
+
|
|
|
+ url = url_for("get_previous_and_next_file", file_id=file.id)
|
|
|
+
|
|
|
+ response = self.get(url)
|
|
|
+ self.assertTrue(response.is_json)
|
|
|
+
|
|
|
+ content_should = dict(
|
|
|
+ next=n_file,
|
|
|
+ nextInCollection=n_file,
|
|
|
+ previous=p_file,
|
|
|
+ previousInCollection=p_file,
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertDictEqual(content_should, response.json)
|
|
|
+
|
|
|
+ files[1].delete()
|
|
|
+ file = files[2]
|
|
|
+ p_file, n_file = files[0], files[3]
|
|
|
+ url = url_for("get_previous_and_next_file", file_id=file.id)
|
|
|
+
|
|
|
+ response = self.get(url)
|
|
|
+ self.assertTrue(response.is_json)
|
|
|
+
|
|
|
+ content_should = dict(
|
|
|
+ next=n_file.serialize(),
|
|
|
+ nextInCollection=n_file.serialize(),
|
|
|
+ previous=p_file.serialize(),
|
|
|
+ previousInCollection=p_file.serialize(),
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertDictEqual(content_should, response.json)
|
|
|
+
|
|
|
+ files[3].delete()
|
|
|
+ file = files[2]
|
|
|
+ p_file, n_file = files[0], files[4]
|
|
|
+ url = url_for("get_previous_and_next_file", file_id=file.id)
|
|
|
+
|
|
|
+ response = self.get(url)
|
|
|
+ self.assertTrue(response.is_json)
|
|
|
+
|
|
|
+ content_should = dict(
|
|
|
+ next=n_file.serialize(),
|
|
|
+ nextInCollection=n_file.serialize(),
|
|
|
+ previous=p_file.serialize(),
|
|
|
+ previousInCollection=p_file.serialize(),
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertDictEqual(content_should, response.json)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class FileResizingTests(_BaseFileTests):
|
|
|
+
|
|
|
+ def _add_image(self, shape, file: File):
|
|
|
+ image = np.random.randint(0, 256, shape).astype(np.uint8)
|
|
|
+
|
|
|
+ im = Image.fromarray(image)
|
|
|
+
|
|
|
+ im.save(file.absolute_path)
|
|
|
+ self.assertTrue(os.path.exists(file.absolute_path))
|
|
|
+ return image
|
|
|
+
|
|
|
+ def _compare_images(self, im0, im1, threshold=1e-3):
|
|
|
+ im0, im1 = im0 / 255, im1 / 255
|
|
|
+ mse = np.mean((im0 - im1)**2)
|
|
|
+ self.assertLess(mse, threshold)
|
|
|
+
|
|
|
+ @pаtch_tpool_execute
|
|
|
+ def test_resize_image(self, mocked_execute):
|
|
|
+
|
|
|
+ self.get(url_for("get_resized_file", file_id=4242, resolution=300), status_code=404)
|
|
|
+
|
|
|
+ file_uuid = str(uuid.uuid1())
|
|
|
+ file, is_new = self.project.add_file(
|
|
|
+ uuid=file_uuid,
|
|
|
+ file_type="image",
|
|
|
+ name=f"name",
|
|
|
+ filename=f"image",
|
|
|
+ extension=".png",
|
|
|
+ size=32*1024,
|
|
|
+ )
|
|
|
+
|
|
|
+ self.assertTrue(is_new)
|
|
|
+
|
|
|
+ image = self._add_image((300, 300), file)
|
|
|
+
|
|
|
+ for upscale in [300, 1200, 500, 320]:
|
|
|
+ url = url_for("get_resized_file", file_id=file.id, resolution=upscale)
|
|
|
+ response = self.get(url)
|
|
|
+
|
|
|
+ self.assertFalse(response.is_json)
|
|
|
+
|
|
|
+ returned_im = np.asarray(Image.open(io.BytesIO(response.data)))
|
|
|
+
|
|
|
+ self.assertEqual(image.shape, returned_im.shape)
|
|
|
+ self._compare_images(image, returned_im)
|
|
|
+
|
|
|
+
|
|
|
+ # repeat the last scale two times to get the cached resized image
|
|
|
+ for downscale in [299, 200, 150, 32, 32]:
|
|
|
+ sm_image = np.asarray(Image.fromarray(image).resize((downscale, downscale)))
|
|
|
+
|
|
|
+ url = url_for("get_resized_file", file_id=file.id, resolution=downscale)
|
|
|
+ response = self.get(url)
|
|
|
+
|
|
|
+ self.assertFalse(response.is_json)
|
|
|
+
|
|
|
+ returned_im = np.asarray(Image.open(io.BytesIO(response.data)))
|
|
|
+
|
|
|
+ self.assertEqual(sm_image.shape, returned_im.shape)
|
|
|
+ self._compare_images(sm_image, returned_im)
|
|
|
+
|
|
|
+ del sm_image
|
|
|
+
|
|
|
+
|
|
|
+ save = file.path
|
|
|
+ file.path = "/some/nonexisting/path"
|
|
|
+ file.commit()
|
|
|
+ url = url_for("get_resized_file", file_id=file.id, resolution=upscale)
|
|
|
+ response = self.get(url, status_code=404)
|
|
|
+
|
|
|
+ file.path = save
|
|
|
+ file.commit()
|
|
|
+
|
|
|
+
|
|
|
+
|