Spaces:
Running
Running
import io | |
import random | |
import pytest | |
from ..assets import assets_path | |
test_file_path = assets_path / 'test_images' / 'bsn_0.jpg' | |
test_file_2_path = assets_path / 'test_images' / 'bsn_1.jpg' | |
test_file_hashes = ['648351F7CBD472D0CA23EADCCF3B9E619EC9ADDA', 'C5DE90DAC2F75FBDBE48023DF4DE7585A86B2392'] | |
def get_single_img_info(test_client, image_id): | |
query = test_client.get('/search/random') | |
assert query.status_code == 200 | |
assert query.json()['result'][0]['img']['id'] == image_id | |
return query.json()['result'][0]['img'] | |
def test_upload_bad_img_file(test_client): | |
bad_img_file = io.BytesIO(bytearray(random.getrandbits(8) for _ in range(1024 * 1024))) | |
bad_img_file.name = 'bad_image.jpg' | |
resp = test_client.post('/admin/upload', | |
files={'image_file': bad_img_file}, | |
params={'local': True}) | |
assert resp.status_code == 422 | |
def test_upload_unsupported_types(test_client): | |
bad_img_file = io.BytesIO(bytearray(random.getrandbits(8) for _ in range(1024 * 1024))) | |
bad_img_file.name = 'bad_image.tga' | |
resp = test_client.post('/admin/upload', | |
files={'image_file': ('bad_img.tga', bad_img_file, 'image/tga')}, | |
params={'local': True}) | |
assert resp.status_code == 415 | |
async def test_upload_duplicate(test_client, ensure_local_dir_empty, wait_for_background_task): | |
def upload(file): | |
return test_client.post('/admin/upload', | |
files={'image_file': file}, | |
params={'local': True}) | |
def validate(hashes): | |
return test_client.post('/admin/duplication_validate', | |
json={'hashes': hashes}) | |
with open(test_file_path, 'rb') as f: | |
# Validate 1# | |
val_resp = validate(test_file_hashes) | |
assert val_resp.status_code == 200 | |
assert val_resp.json()['exists'] == [False, False] | |
assert val_resp.json()['entity_ids'] == [None, None] | |
# Upload | |
resp = upload(f) | |
assert resp.status_code == 200 | |
image_id = resp.json()['image_id'] | |
for i in range(0, 2): | |
# Re-upload | |
resp = upload(f) | |
assert resp.status_code == 409, i | |
# Query by ID | |
query = test_client.get(f'/images/id/{image_id}') | |
assert query.status_code == 200 | |
assert query.json()['img_status'] == 'mapped' if i == 1 else 'in_queue' | |
# Validate | |
val_resp = validate(test_file_hashes) | |
assert val_resp.status_code == 200, i | |
assert val_resp.json()['exists'] == [True, False], i | |
assert val_resp.json()['entity_ids'] == [str(image_id), None], i | |
# Wait for the image to be indexed | |
if i == 0: | |
await wait_for_background_task(1) | |
# cleanup | |
resp = test_client.delete(f'/admin/delete/{image_id}') | |
assert resp.status_code == 200 | |
TEST_FAKE_URL = 'fake-url' | |
TEST_FAKE_THUMBNAIL_URL = 'fake-thumbnail-url' | |
TEST_UPLOAD_THUMBNAILS_PARAMS = [ | |
(True, {'local': True}, True, 'local'), | |
(True, {'local': True, 'local_thumbnail': 'never'}, True, 'none'), | |
(False, {'local': True, 'local_thumbnail': 'always'}, True, 'local'), | |
(False, {'local': True}, True, 'none'), | |
(False, {'local': False, 'url': TEST_FAKE_URL, 'thumbnail_url': TEST_FAKE_THUMBNAIL_URL}, False, 'fake'), | |
(False, {'local': False, 'url': TEST_FAKE_URL, 'local_thumbnail': 'always'}, False, 'local'), | |
(False, {'local': False, 'url': TEST_FAKE_URL}, False, 'none'), | |
] | |
async def test_upload_thumbnails(test_client, ensure_local_dir_empty, wait_for_background_task, # Fixtures | |
add_trailing_bytes, params, expect_local_url, expect_thumbnail_mode): # Parameters | |
with open(test_file_path, 'rb') as f: | |
# append 500KB to the image, to make it large enough to generate a thumbnail | |
if add_trailing_bytes: | |
img_bytes = f.read() | |
img_bytes += bytearray(random.getrandbits(8) for _ in range(1024 * 500)) | |
f_patched = io.BytesIO(img_bytes) | |
f_patched.name = 'bsn_0.jpg' | |
else: | |
f_patched = f | |
resp = test_client.post('/admin/upload', | |
files={'image_file': f_patched}, | |
params=params) | |
assert resp.status_code == 200 | |
image_id = resp.json()['image_id'] | |
await wait_for_background_task(1) | |
query = get_single_img_info(test_client, image_id) | |
if expect_local_url: | |
assert query['url'].startswith(f'/static/{image_id}.') | |
img_request = test_client.get(query['url']) | |
assert img_request.status_code == 200 | |
else: | |
assert query['url'] == TEST_FAKE_URL | |
match expect_thumbnail_mode: | |
case 'local': | |
assert query['thumbnail_url'] == f'/static/thumbnails/{image_id}.webp' | |
thumbnail_request = test_client.get(query['thumbnail_url']) | |
assert thumbnail_request.status_code == 200 | |
# IDK why starlette doesn't return the correct content type, but it works on the browser anyway | |
# assert thumbnail_request.headers['Content-Type'] == 'image/webp' | |
case 'fake': | |
assert query['thumbnail_url'] == TEST_FAKE_THUMBNAIL_URL | |
case 'none': | |
assert query['thumbnail_url'] is None | |
# cleanup | |
resp = test_client.delete(f'/admin/delete/{image_id}') | |
assert resp.status_code == 200 | |
TEST_FAKE_URL_NEW = 'fake-url-new' | |
TEST_FAKE_THUMBNAIL_URL_NEW = 'fake-thumbnail-url-new' | |
TEST_UPDATE_OPT_PARAMS = [ | |
({'url': TEST_FAKE_URL}, {'url': TEST_FAKE_URL_NEW, 'thumbnail_url': TEST_FAKE_THUMBNAIL_URL_NEW}, | |
{'url': TEST_FAKE_URL_NEW, 'thumbnail_url': TEST_FAKE_THUMBNAIL_URL_NEW}, 200), | |
({'local_thumbnail': 'always', 'url': TEST_FAKE_URL}, {'url': TEST_FAKE_URL_NEW}, {'url': TEST_FAKE_URL_NEW}, 200), | |
({'local': True}, {'categories': ['1'], 'starred': True}, {'categories': ['1'], 'starred': True}, 200), | |
({'local': True}, {'url': TEST_FAKE_URL_NEW}, {}, 422), | |
({'local': True}, {'thumbnail_url': TEST_FAKE_THUMBNAIL_URL_NEW}, {}, 422), | |
({'local_thumbnail': 'always', 'url': TEST_FAKE_URL}, {'thumbnail_url': TEST_FAKE_THUMBNAIL_URL_NEW}, {}, 422), | |
({'local': True}, {}, {}, 422), | |
] | |
async def test_update_opt(test_client, ensure_local_dir_empty, wait_for_background_task, # Fixtures | |
initial_param, update_param, expected_param, resp_code): # Parameters | |
with open(test_file_path, 'rb') as f: | |
resp = test_client.post('/admin/upload', | |
files={'image_file': f}, | |
params=initial_param) | |
assert resp.status_code == 200 | |
image_id = resp.json()['image_id'] | |
await wait_for_background_task(1) | |
old_info = get_single_img_info(test_client, image_id) | |
resp = test_client.put(f'/admin/update_opt/{image_id}', json=update_param) | |
assert resp.status_code == resp_code | |
new_info = get_single_img_info(test_client, image_id) | |
# Ensure expected keys are updated | |
for key, value in expected_param.items(): | |
assert new_info[key] == value | |
del new_info[key] | |
# Ensure that the other keys are kept untouched | |
for key, value in new_info.items(): | |
assert old_info[key] == value | |
# cleanup | |
resp = test_client.delete(f'/admin/delete/{image_id}') | |
assert resp.status_code == 200 | |
async def test_delete(test_client, ensure_local_dir_empty, wait_for_background_task): | |
with open(test_file_path, 'rb') as f: | |
resp = test_client.post('/admin/upload', | |
files={'image_file': f}, | |
params={'local': True}) | |
assert resp.status_code == 200 | |
image_id = resp.json()['image_id'] | |
await wait_for_background_task(1) | |
img_query = test_client.get(f'/static/{image_id}.jpeg') | |
assert img_query.status_code == 200 | |
resp = test_client.delete(f'/admin/delete/{image_id}') | |
assert resp.status_code == 200 | |
img_query = test_client.get(f'/static/{image_id}.jpeg') | |
assert img_query.status_code == 404 | |
query = test_client.get('/search/random') | |
assert query.status_code == 200 | |
assert not query.json()['result'] | |
resp = test_client.delete(f'/admin/delete/{image_id}') | |
assert resp.status_code == 404 | |