Skip to content

Commit 797ec12

Browse files
Merge pull request #624 from adamtheturtle/query-deleted
Query deleted
2 parents a0898ac + 21da69d commit 797ec12

File tree

2 files changed

+191
-2
lines changed

2 files changed

+191
-2
lines changed

src/mock_vws/_mock_web_query_api.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,18 @@ def query(
494494

495495
[image] = parsed['image']
496496
matches: Set[Target] = set([])
497+
gmt = pytz.timezone('GMT')
498+
now = datetime.datetime.now(tz=gmt)
499+
500+
# See https://github.com/adamtheturtle/vws-python/issues/623 for making
501+
# this customizable.
502+
minimum_time_since_delete = datetime.timedelta(seconds=3)
503+
497504
for target in self.mock_web_services_api.targets:
505+
delete_processing = bool(
506+
target.delete_date
507+
and (now - target.delete_date) < minimum_time_since_delete,
508+
)
498509
if target.image.getvalue() == image:
499510
if target.status == TargetStatuses.PROCESSING.value:
500511
# We return an example 500 response.
@@ -513,7 +524,19 @@ def query(
513524
content_type = 'text/html; charset=ISO-8859-1'
514525
context.headers['Content-Type'] = content_type
515526
return Path(match_processing_resp_file).read_text()
516-
if target.active_flag:
527+
if target.active_flag and delete_processing:
528+
# We return an example 500 response.
529+
# Each response given by Vuforia is different.
530+
resources_dir = Path(__file__).parent / 'resources'
531+
filename = 'match_processing_response'
532+
match_processing_resp_file = resources_dir / filename
533+
context.status_code = codes.INTERNAL_SERVER_ERROR
534+
cache_control = 'must-revalidate,no-cache,no-store'
535+
context.headers['Cache-Control'] = cache_control
536+
content_type = 'text/html; charset=ISO-8859-1'
537+
context.headers['Content-Type'] = content_type
538+
return Path(match_processing_resp_file).read_text()
539+
if target.active_flag and not target.delete_date:
517540
matches.add(target)
518541

519542
results: List[Dict[str, Any]] = []

tests/mock_vws/test_query.py

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from mock_vws._constants import TargetStatuses
2121
from tests.mock_vws.utils import (
2222
add_target_to_vws,
23+
delete_target,
2324
get_vws_target,
2425
update_target,
2526
wait_for_target_processed,
@@ -1057,7 +1058,7 @@ def test_invalid(
10571058
@pytest.mark.usefixtures('verify_mock_vuforia')
10581059
class TestActiveFlag:
10591060
"""
1060-
Tests for active targets.
1061+
Tests for active versus inactive targets.
10611062
"""
10621063

10631064
def test_inactive(
@@ -1337,3 +1338,168 @@ def test_updated_target(
13371338
)
13381339
assert_query_success(response=response)
13391340
assert response.json()['results'] == []
1341+
1342+
1343+
@pytest.mark.usefixtures('verify_mock_vuforia')
1344+
class TestDeleted:
1345+
"""
1346+
Tests for matching deleted targets.
1347+
"""
1348+
1349+
def test_deleted(
1350+
self,
1351+
high_quality_image: io.BytesIO,
1352+
vuforia_database_keys: VuforiaDatabaseKeys,
1353+
) -> None:
1354+
"""
1355+
Within approximately 7 seconds of deleting a target, querying for its
1356+
image results in an ``INTERNAL_SERVER_ERROR``.
1357+
"""
1358+
image_content = high_quality_image.getvalue()
1359+
image_data_encoded = base64.b64encode(image_content).decode('ascii')
1360+
add_target_data = {
1361+
'name': 'example_name',
1362+
'width': 1,
1363+
'image': image_data_encoded,
1364+
}
1365+
response = add_target_to_vws(
1366+
vuforia_database_keys=vuforia_database_keys,
1367+
data=add_target_data,
1368+
)
1369+
1370+
target_id = response.json()['target_id']
1371+
1372+
wait_for_target_processed(
1373+
target_id=target_id,
1374+
vuforia_database_keys=vuforia_database_keys,
1375+
)
1376+
1377+
delete_target(
1378+
vuforia_database_keys=vuforia_database_keys,
1379+
target_id=target_id,
1380+
)
1381+
1382+
body = {'image': ('image.jpeg', image_content, 'image/jpeg')}
1383+
1384+
response = query(
1385+
vuforia_database_keys=vuforia_database_keys,
1386+
body=body,
1387+
)
1388+
1389+
# The response text for a 500 response is not consistent.
1390+
# Therefore we only test for consistent features.
1391+
assert 'Error 500 Server Error' in response.text
1392+
assert 'HTTP ERROR 500' in response.text
1393+
assert 'Problem accessing /v1/query' in response.text
1394+
1395+
assert_vwq_failure(
1396+
response=response,
1397+
content_type='text/html; charset=ISO-8859-1',
1398+
status_code=codes.INTERNAL_SERVER_ERROR,
1399+
)
1400+
1401+
def test_deleted_and_wait(
1402+
self,
1403+
high_quality_image: io.BytesIO,
1404+
vuforia_database_keys: VuforiaDatabaseKeys,
1405+
) -> None:
1406+
"""
1407+
After waiting approximately 7 seconds (we wait more to be safer), a
1408+
deleted target is not found when its image is queried for.
1409+
"""
1410+
image_content = high_quality_image.getvalue()
1411+
image_data_encoded = base64.b64encode(image_content).decode('ascii')
1412+
add_target_data = {
1413+
'name': 'example_name',
1414+
'width': 1,
1415+
'image': image_data_encoded,
1416+
}
1417+
response = add_target_to_vws(
1418+
vuforia_database_keys=vuforia_database_keys,
1419+
data=add_target_data,
1420+
)
1421+
1422+
target_id = response.json()['target_id']
1423+
1424+
wait_for_target_processed(
1425+
target_id=target_id,
1426+
vuforia_database_keys=vuforia_database_keys,
1427+
)
1428+
1429+
response = delete_target(
1430+
vuforia_database_keys=vuforia_database_keys,
1431+
target_id=target_id,
1432+
)
1433+
1434+
body = {'image': ('image.jpeg', image_content, 'image/jpeg')}
1435+
1436+
# In practice, we have seen a delay of up to 30 seconds between
1437+
# deleting a target and having no 500 errors.
1438+
#
1439+
# We wait up to 60 seconds to be safe.
1440+
total_waited = 0
1441+
while True:
1442+
response = query(
1443+
vuforia_database_keys=vuforia_database_keys,
1444+
body=body,
1445+
)
1446+
1447+
try:
1448+
assert_query_success(response=response)
1449+
except AssertionError:
1450+
# The response text for a 500 response is not consistent.
1451+
# Therefore we only test for consistent features.
1452+
assert 'Error 500 Server Error' in response.text
1453+
assert 'HTTP ERROR 500' in response.text
1454+
assert 'Problem accessing /v1/query' in response.text
1455+
time.sleep(2)
1456+
total_waited += 2
1457+
else:
1458+
assert response.json()['results'] == []
1459+
break
1460+
1461+
assert total_waited < 60
1462+
1463+
def test_deleted_inactive(
1464+
self,
1465+
high_quality_image: io.BytesIO,
1466+
vuforia_database_keys: VuforiaDatabaseKeys,
1467+
) -> None:
1468+
"""
1469+
No error is returned when querying for an image of recently deleted,
1470+
inactive target.
1471+
"""
1472+
image_content = high_quality_image.getvalue()
1473+
image_data_encoded = base64.b64encode(image_content).decode('ascii')
1474+
add_target_data = {
1475+
'name': 'example_name',
1476+
'width': 1,
1477+
'image': image_data_encoded,
1478+
'active_flag': False,
1479+
}
1480+
response = add_target_to_vws(
1481+
vuforia_database_keys=vuforia_database_keys,
1482+
data=add_target_data,
1483+
)
1484+
1485+
target_id = response.json()['target_id']
1486+
1487+
wait_for_target_processed(
1488+
target_id=target_id,
1489+
vuforia_database_keys=vuforia_database_keys,
1490+
)
1491+
1492+
delete_target(
1493+
vuforia_database_keys=vuforia_database_keys,
1494+
target_id=target_id,
1495+
)
1496+
1497+
body = {'image': ('image.jpeg', image_content, 'image/jpeg')}
1498+
1499+
response = query(
1500+
vuforia_database_keys=vuforia_database_keys,
1501+
body=body,
1502+
)
1503+
1504+
assert_query_success(response=response)
1505+
assert response.json()['results'] == []

0 commit comments

Comments
 (0)