def test_bad_target_request( self, high_quality_image: io.BytesIO, vws_client: VWS, ) -> None: """ The ``request_usage`` count does not increase with each request to the target API, even if it is a bad request. """ report = vws_client.get_database_summary_report() original_request_usage = report.request_usage with pytest.raises(Fail) as exc: vws_client.add_target( name='example', width=-1, image=high_quality_image, active_flag=True, application_metadata=None, ) assert exc.value.response.status_code == HTTPStatus.BAD_REQUEST report = vws_client.get_database_summary_report() new_request_usage = report.request_usage assert new_request_usage == original_request_usage
def test_query_request( self, cloud_reco_client: CloudRecoService, high_quality_image: io.BytesIO, vws_client: VWS, ) -> None: """ The ``*_recos`` counts seem to be delayed by a significant amount of time. We therefore test that they exist, are integers and do not change between quick requests. """ target_id = vws_client.add_target( name=uuid.uuid4().hex, width=1, image=high_quality_image, active_flag=True, application_metadata=None, ) vws_client.wait_for_target_processed(target_id=target_id) report_before = vws_client.get_database_summary_report() cloud_reco_client.query(image=high_quality_image) report_after = vws_client.get_database_summary_report() assert report_before.total_recos == report_after.total_recos assert (report_before.current_month_recos == report_after.current_month_recos) assert (report_before.previous_month_recos == report_after.previous_month_recos)
def test_inactive_project( self, inactive_vws_client: VWS, ) -> None: """ The project's active state does not affect the database summary. """ inactive_vws_client.get_database_summary_report()
def test_target_request( self, vws_client: VWS, ) -> None: """ The ``request_usage`` count does not increase with each request to the target API. """ report = vws_client.get_database_summary_report() original_request_usage = report.request_usage report = vws_client.get_database_summary_report() new_request_usage = report.request_usage assert new_request_usage == original_request_usage
def test_query_request( self, cloud_reco_client: CloudRecoService, high_quality_image: io.BytesIO, vws_client: VWS, ) -> None: """ The ``request_usage`` count does not increase with each query. """ report = vws_client.get_database_summary_report() original_request_usage = report.request_usage cloud_reco_client.query(image=high_quality_image) report = vws_client.get_database_summary_report() new_request_usage = report.request_usage # The request usage goes up for the database summary request, not the # query. assert new_request_usage == original_request_usage
def test_custom_seconds_between_requests( self, high_quality_image: io.BytesIO, ) -> None: """ It is possible to customize the time waited between polling requests. """ runner = CliRunner() with MockVWS(processing_time_seconds=0.5) as mock: mock_database = VuforiaDatabase() mock.add_database(database=mock_database) vws_client = VWS( server_access_key=mock_database.server_access_key, server_secret_key=mock_database.server_secret_key, ) target_id = vws_client.add_target( name='x', width=1, image=high_quality_image, active_flag=True, application_metadata=None, ) commands = [ 'wait-for-target-processed', '--target-id', target_id, '--seconds-between-requests', '0.3', '--server-access-key', mock_database.server_access_key, '--server-secret-key', mock_database.server_secret_key, ] result = runner.invoke(vws_group, commands, catch_exceptions=False) assert result.exit_code == 0 assert result.stdout == '' report = vws_client.get_database_summary_report() expected_requests = ( # Add target request 1 + # Database summary request 1 + # Initial request 1 + # Request after 0.3 seconds - not processed # This assumes that there is less than 0.2 seconds taken # between the start of the target processing and the start of # waiting for the target to be processed. 1 + # Request after 0.6 seconds - processed 1) # At the time of writing there is a bug which prevents request # usage from being tracked so we cannot track this. expected_requests = 0 assert report.request_usage == expected_requests
def test_quotas(self, vws_client: VWS) -> None: """ Quotas are included in the database summary. These match the quotas given for a free license. """ report = vws_client.get_database_summary_report() assert report.target_quota == 1000 assert report.request_quota == 100000 assert report.reco_threshold == 1000
def test_custom_seconds_between_requests( self, high_quality_image: io.BytesIO, ) -> None: """ It is possible to customize the time waited between polling requests. """ with MockVWS(processing_time_seconds=0.5) as mock: database = VuforiaDatabase() mock.add_database(database=database) vws_client = VWS( server_access_key=database.server_access_key, server_secret_key=database.server_secret_key, ) target_id = vws_client.add_target( name='x', width=1, image=high_quality_image, active_flag=True, application_metadata=None, ) vws_client.wait_for_target_processed( target_id=target_id, seconds_between_requests=0.3, ) report = vws_client.get_database_summary_report() expected_requests = ( # Add target request 1 + # Database summary request 1 + # Initial request 1 + # Request after 0.3 seconds - not processed # This assumes that there is less than 0.2 seconds taken # between the start of the target processing and the start of # waiting for the target to be processed. 1 + # Request after 0.6 seconds - processed 1 ) # At the time of writing there is a bug which prevents request # usage from being tracked so we cannot track this. expected_requests = 0 assert report.request_usage == expected_requests
def test_success( self, vuforia_database: VuforiaDatabase, vws_client: VWS, ) -> None: """ It is possible to get a success response. """ report = vws_client.get_database_summary_report() assert report.name == vuforia_database.database_name _wait_for_image_numbers( vws_client=vws_client, active_images=0, inactive_images=0, failed_images=0, processing_images=0, )
def get_database_summary_report( server_access_key: str, server_secret_key: str, base_vws_url: str, ) -> None: """ Get a database summary report. \b See https://library.vuforia.com/articles/Solution/How-To-Use-the-Vuforia-Web-Services-API.html#How-To-Get-a-Database-Summary-Report. """ vws_client = VWS( server_access_key=server_access_key, server_secret_key=server_secret_key, base_vws_url=base_vws_url, ) report = vws_client.get_database_summary_report() yaml_report = yaml.dump(dataclasses.asdict(report)) click.echo(yaml_report)
def test_get_target(self, vws_client: VWS) -> None: """ Details of a database are returned by ``get_database_summary_report``. """ report = vws_client.get_database_summary_report() expected_report = DatabaseSummaryReport( active_images=0, current_month_recos=0, failed_images=0, inactive_images=0, name=report.name, previous_month_recos=0, processing_images=0, reco_threshold=1000, request_quota=100000, request_usage=0, target_quota=1000, total_recos=0, ) assert report == expected_report
def _wait_for_image_numbers( vws_client: VWS, active_images: int, inactive_images: int, failed_images: int, processing_images: int, ) -> None: """ Wait up to 500 seconds (arbitrary, though we saw timeouts with 300 seconds) for the number of images in various categories to match the expected number. This is necessary because the database summary endpoint lags behind the real data. This is susceptible to false positives because if, for example, we expect no images, and the endpoint adds images with a delay, we will not know. Args: vws_client: The client to use to connect to Vuforia. active_images: The expected number of active images. inactive_images: The expected number of inactive images. failed_images: The expected number of failed images. processing_images: The expected number of processing images. Raises: Exception: The numbers of images in various categories do not match within the time limit. """ requirements = { 'active_images': active_images, 'inactive_images': inactive_images, 'failed_images': failed_images, 'processing_images': processing_images, } maximum_wait_seconds = 500 start_time = time.monotonic() # If we wait for all requirements to match at the same time, # we will often not reach that. # We therefore wait for each requirement to match at least once. # We wait 0.2 seconds rather than less than that to decrease the number # of calls made to the API, to decrease the likelihood of hitting the # request quota. sleep_seconds = 0.2 for key, value in requirements.items(): while True: seconds_waited = time.monotonic() - start_time if seconds_waited > maximum_wait_seconds: # pragma: no cover raise Exception('Timed out waiting.') report = vws_client.get_database_summary_report() relevant_images_in_summary = getattr(report, key) if value != relevant_images_in_summary: # pragma: no cover message = (f'Expected {value} `{key}`s. ' f'Found {relevant_images_in_summary} `{key}`s.') LOGGER.debug(message) time.sleep(sleep_seconds) # This makes the entire test invalid. # However, we have found that without this Vuforia is flaky. # We have waited over 10 minutes for the summary to change and # that is not sustainable in a test suite. break