diff --git a/pipeline/fiftyone_pipeline_cloudrequestengine/src/fiftyone_pipeline_cloudrequestengine/constants.py b/pipeline/fiftyone_pipeline_cloudrequestengine/src/fiftyone_pipeline_cloudrequestengine/constants.py index 8014286d..f53bee2a 100644 --- a/pipeline/fiftyone_pipeline_cloudrequestengine/src/fiftyone_pipeline_cloudrequestengine/constants.py +++ b/pipeline/fiftyone_pipeline_cloudrequestengine/src/fiftyone_pipeline_cloudrequestengine/constants.py @@ -71,13 +71,15 @@ class Constants: LICENSE_PARAMETER = "license" VALUES_PARAMETER = "values" - # The cloud service advertises these three among its accepted evidence + # The cloud service reads these names among its accepted evidence # keys, so evidence such as "query.license" would otherwise go into the # request body beside the engine's own credentials, with no way to say # which one the service applied. Evidence whose key strips to one of # them is left out of every request. + LICENCE_SPELLING = "licence" RESERVED_EVIDENCE_SUFFIXES = ( - RESOURCE_PARAMETER, LICENSE_PARAMETER, VALUES_PARAMETER) + RESOURCE_PARAMETER, LICENSE_PARAMETER, LICENCE_SPELLING, + VALUES_PARAMETER) # The path, below the base URL, of the data endpoint that takes no # resource key in its route, used when the engine authenticates on a diff --git a/pipeline/fiftyone_pipeline_cloudrequestengine/tests/test_credentials.py b/pipeline/fiftyone_pipeline_cloudrequestengine/tests/test_credentials.py index 786ae020..09f01bfe 100644 --- a/pipeline/fiftyone_pipeline_cloudrequestengine/tests/test_credentials.py +++ b/pipeline/fiftyone_pipeline_cloudrequestengine/tests/test_credentials.py @@ -307,6 +307,88 @@ def test_reserved_evidence_is_left_out_of_the_body(self): for message in messages: self.assertNotIn("another-key", message) + def send_with_reserved_evidence(self, settings): + """ + Process one flow data holding evidence named resource, license, licence + and values in mixed case under each prefix, with other evidence beside + it, and give back the body of the data request. + """ + + settings["http_client"] = self.mock_http() + engine = CloudRequestEngine(settings) + # The stand-in service lists query.User-Agent alone, so an element + # that accepts every key keeps the other evidence for the engine. + pipeline = PipelineBuilder().add(AcceptEveryKeyElement()) \ + .add(engine).build() + data = pipeline.create_flowdata() + data.evidence.add("query.Resource", "evidence_resource") + data.evidence.add("query.LICENSE", "evidence_license") + data.evidence.add("query.Licence", "evidence_licence") + data.evidence.add("query.Values", "evidence_values") + data.evidence.add("header.resource", "header_resource") + data.evidence.add("cookie.License", "cookie_license") + data.evidence.add("query.other", "query_other") + data.evidence.add("header.other", "header_other") + data.evidence.add("cookie.cookie-only", "cookie_only") + + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + data.process() + + return engine.http_client.requests[-1][2] + + def assert_other_evidence_sent(self, content): + self.assertEqual("query_other", content["other"]) + self.assertEqual("cookie_only", content["cookie-only"]) + for value in content.values(): + self.assertNotIn("evidence_", str(value)) + self.assertNotIn("header_resource", str(value)) + self.assertNotIn("cookie_license", str(value)) + + def test_evidence_never_supplies_resource_or_license(self): + """ + With a Resource Key and a License Key configured, the body carries + those two and none of the evidence named resource, license or + values, in any case and under any prefix. + """ + + content = self.send_with_reserved_evidence({ + "resource_key": RESOURCE_KEY, + "license_key": LICENSE_KEY, + }) + + self.assertEqual(RESOURCE_KEY, content[Constants.RESOURCE_PARAMETER]) + self.assertEqual(LICENSE_KEY, content[Constants.LICENSE_PARAMETER]) + self.assertNotIn(Constants.VALUES_PARAMETER, content) + self.assertEqual( + [], [name for name in content if name.lower() in ( + "resource", "license", "licence", "values") and name not in ( + Constants.RESOURCE_PARAMETER, Constants.LICENSE_PARAMETER)]) + self.assert_other_evidence_sent(content) + + def test_evidence_never_supplies_values(self): + """ + With a License Key and Requested Properties configured, the body + carries the configured list as values and the License Key as + license, and no resource, whatever the evidence holds. + """ + + content = self.send_with_reserved_evidence({ + "license_key": LICENSE_KEY, + "requested_properties": REQUESTED, + }) + + self.assertEqual(LICENSE_KEY, content[Constants.LICENSE_PARAMETER]) + self.assertEqual( + "device.ismobile,device.istablet", + content[Constants.VALUES_PARAMETER]) + self.assertNotIn(Constants.RESOURCE_PARAMETER, content) + self.assertEqual( + [], [name for name in content if name.lower() in ( + "resource", "license", "licence", "values") and name not in ( + Constants.LICENSE_PARAMETER, Constants.VALUES_PARAMETER)]) + self.assert_other_evidence_sent(content) + def test_evidence_no_element_accepts_is_not_sent(self): """ A default pipeline keeps only the evidence one of its elements