Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions tests/mock_vws/content_length/test_incorrect.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
import pytest

from mock_vws._constants import ResultCodes
from tests.mock_vws.fixtures.vuforia_backends import VuforiaBackend
from tests.mock_vws.utils import Endpoint
from tests.mock_vws.utils.assertions import (
assert_valid_date_header,
assert_vwq_failure,
assert_vws_failure,
)
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities
from tests.mock_vws.utils.too_many_requests import handle_server_errors


Expand Down Expand Up @@ -85,12 +85,14 @@ def test_not_integer(endpoint: Endpoint, base_vwq_url: str) -> None:

def test_too_large(
endpoint: Endpoint,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
base_vwq_url: str,
) -> None:
"""An error is given if the given content length is too large."""
if verify_mock_vuforia is VuforiaBackend.REAL:
pytest.skip(reason="Real Vuforia takes too long to respond")
if not backend_capabilities.fast_oversized_content_length_response:
pytest.skip(
reason="This backend responds slowly to oversized Content-Length."
)

if not bool(endpoint.headers.get("Content-Type")):
pytest.skip(reason="No Content-Type header for this request")
Expand Down
16 changes: 16 additions & 0 deletions tests/mock_vws/fixtures/vuforia_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
VuMarkCloudDatabase,
get_model_target_credentials,
)
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities
from tests.mock_vws.utils.cloud_databases import AddCloudDatabase
from tests.mock_vws.utils.model_target_retries import (
retrying_transient_real_backend_failures,
Expand Down Expand Up @@ -883,3 +884,18 @@ def fixture_signed_model_target_credentials(
return _model_target_credentials_for_backend(
backend=verify_model_target_mock_vuforia,
)


@pytest.fixture(name="backend_capabilities")
def fixture_backend_capabilities(
*,
verify_mock_vuforia: VuforiaBackend,
) -> BackendCapabilities:
"""The behavior supported by the running VWS and query backend."""
is_mock = verify_mock_vuforia != VuforiaBackend.REAL
return BackendCapabilities(
deterministic_target_order=is_mock,
deterministic_query_order=is_mock,
fast_oversized_content_length_response=is_mock,
rolling_rate_limit_window=is_mock,
)
10 changes: 6 additions & 4 deletions tests/mock_vws/get_duplicates/test_duplicates.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from vws import VWS
from vws.reports import TargetStatuses

from tests.mock_vws.fixtures.vuforia_backends import VuforiaBackend
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities


def test_duplicates(
Expand Down Expand Up @@ -136,7 +136,7 @@ def test_status(

def test_order_is_upload_date_then_target_id(
*,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
high_quality_image: io.BytesIO,
vws_client: VWS,
) -> None:
Expand All @@ -145,8 +145,10 @@ def test_order_is_upload_date_then_target_id(
The real Vuforia Web Services do not document an order, so we do
not verify this against them.
"""
if verify_mock_vuforia == VuforiaBackend.REAL:
pytest.skip(reason="The real Vuforia does not document an order.")
if not backend_capabilities.deterministic_target_order:
pytest.skip(
reason="This backend does not guarantee target upload-date order."
)

target_ids = [
vws_client.add_target(
Expand Down
14 changes: 7 additions & 7 deletions tests/mock_vws/query/test_result_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@
from vws import VWS

from mock_vws.database import CloudDatabase
from tests.mock_vws.fixtures.vuforia_backends import VuforiaBackend
from tests.mock_vws.query.helpers import (
query,
)
from tests.mock_vws.utils.assertions import (
assert_query_success,
)
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities


def test_order_is_upload_date_then_target_id(
*,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
high_quality_image: io.BytesIO,
vws_client: VWS,
vuforia_database: CloudDatabase,
Expand All @@ -33,9 +33,9 @@ def test_order_is_upload_date_then_target_id(
matcher, so we do not verify this against the real Vuforia Web
Services.
"""
if verify_mock_vuforia == VuforiaBackend.REAL:
if not backend_capabilities.deterministic_query_order:
pytest.skip(
reason="The real Query API uses Vuforia's match scores.",
reason="This backend does not guarantee query upload-date order.",
)

target_ids = [
Expand Down Expand Up @@ -72,7 +72,7 @@ def test_order_is_upload_date_then_target_id(

def test_max_num_results_keeps_the_first_results(
*,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
high_quality_image: io.BytesIO,
vws_client: VWS,
vuforia_database: CloudDatabase,
Expand All @@ -84,9 +84,9 @@ def test_max_num_results_keeps_the_first_results(
Which matches survive the truncation therefore does not vary
between runs.
"""
if verify_mock_vuforia == VuforiaBackend.REAL:
if not backend_capabilities.deterministic_query_order:
pytest.skip(
reason="The real Query API uses Vuforia's match scores.",
reason="This backend does not guarantee query upload-date order.",
)

target_ids = [
Expand Down
8 changes: 3 additions & 5 deletions tests/mock_vws/target_list/test_rate_limit.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
from mock_vws._constants import ResultCodes
from mock_vws.database import CloudDatabase
from mock_vws.request_rate_limits import DOCUMENTED_REQUEST_RATE_LIMITS
from tests.mock_vws.fixtures.vuforia_backends import (
VuforiaBackend,
)
from tests.mock_vws.utils import Endpoint
from tests.mock_vws.utils.assertions import assert_vws_too_many_requests
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities


def test_two_requests_per_minute(
*,
base_vws_url: str,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
rate_limited_database: CloudDatabase,
) -> None:
"""A third ``GET /targets`` request within a minute is rate
Expand Down Expand Up @@ -66,7 +64,7 @@ def test_two_requests_per_minute(
assert len(responses) <= limit.max_requests + 2

status_codes = [response.status_code for response in responses]
if verify_mock_vuforia != VuforiaBackend.REAL:
if backend_capabilities.rolling_rate_limit_window:
assert status_codes == [
*[HTTPStatus.OK] * limit.max_requests,
HTTPStatus.TOO_MANY_REQUESTS,
Expand Down
12 changes: 6 additions & 6 deletions tests/mock_vws/target_list/test_target_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
import pytest
from vws import VWS

from tests.mock_vws.fixtures.vuforia_backends import (
VuforiaBackend,
)
from tests.mock_vws.utils.backend_capabilities import BackendCapabilities


def test_includes_targets(
Expand All @@ -32,7 +30,7 @@ def test_deleted(

def test_order_is_upload_date_then_target_id(
*,
verify_mock_vuforia: VuforiaBackend,
backend_capabilities: BackendCapabilities,
high_quality_image: io.BytesIO,
vws_client: VWS,
) -> None:
Expand All @@ -41,8 +39,10 @@ def test_order_is_upload_date_then_target_id(
The real Vuforia Web Services do not document an order, so we do
not verify this against them.
"""
if verify_mock_vuforia == VuforiaBackend.REAL:
pytest.skip(reason="The real Vuforia does not document an order.")
if not backend_capabilities.deterministic_target_order:
pytest.skip(
reason="This backend does not guarantee target upload-date order."
)

target_ids = [
vws_client.add_target(
Expand Down
29 changes: 29 additions & 0 deletions tests/mock_vws/utils/backend_capabilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Behavior declared by an adapter for the shared API tests."""

from dataclasses import dataclass

from beartype import beartype


@beartype
@dataclass(frozen=True, kw_only=True)
class BackendCapabilities:
"""The behavior and checks supported by the running service.

``deterministic_target_order`` covers upload-date ordering for target
lists and duplicate lists. ``deterministic_query_order`` covers that
ordering for matches to identical images.

``fast_oversized_content_length_response`` enables requests whose
declared body length exceeds their actual length. Services which wait
too long for the missing bytes cannot run that check.

``rolling_rate_limit_window`` enables the exact request-sequence
assertion for a fresh database. Services with a fixed clock window
still run the common rate-limit assertions.
"""

deterministic_target_order: bool
deterministic_query_order: bool
fast_oversized_content_length_response: bool
rolling_rate_limit_window: bool
Loading