Esempio n. 1
0
    def test_credential_refresh_failure(self):
        """Verify that a useful error message results when the Odilo bearer
        token cannot be refreshed, since this is the most likely point
        of failure on a new setup.
        """
        self.api.access_token_response = MockRequestsResponse(
            200, {"Content-Type": "text/html"},
            "Hi, this is the website, not the API.")
        credential = self.api.credential_object(lambda x: x)
        with pytest.raises(BadResponseException) as excinfo:
            self.api.refresh_creds(credential)
        assert "Bad response from " in str(excinfo.value)
        assert (
            "may not be the right base URL. Response document was: 'Hi, this is the website, not the API.'"
            in str(excinfo.value))

        # Also test a 400 response code.
        self.api.access_token_response = MockRequestsResponse(
            400,
            {"Content-Type": "application/json"},
            json.dumps(dict(errors=[dict(description="Oops")])),
        )
        with pytest.raises(BadResponseException) as excinfo:
            self.api.refresh_creds(credential)
        assert "Bad response from" in str(excinfo.value)
        assert "Oops" in str(excinfo.value)

        # If there's a 400 response but no error information,
        # the generic error message is used.
        self.api.access_token_response = MockRequestsResponse(
            400, {"Content-Type": "application/json"}, json.dumps(dict()))
        with pytest.raises(BadResponseException) as excinfo:
            self.api.refresh_creds(credential)
        assert "Bad response from" in str(excinfo.value)
        assert "may not be the right base URL." in str(excinfo.value)
Esempio n. 2
0
    def test_process_debuggable_response(self):
        """Test a method that gives more detailed information when a
        problem happens.
        """
        m = HTTP.process_debuggable_response
        success = MockRequestsResponse(200, content="Success!")
        assert success == m("url", success)

        success = MockRequestsResponse(302, content="Success!")
        assert success == m("url", success)

        # An error is turned into a detailed ProblemDetail
        error = MockRequestsResponse(500, content="Error!")
        problem = m("url", error)
        assert isinstance(problem, ProblemDetail)
        assert INTEGRATION_ERROR.uri == problem.uri
        assert "500 response from integration server: 'Error!'" == problem.detail

        content, status_code, headers = INVALID_INPUT.response
        error = MockRequestsResponse(status_code, headers, content)
        problem = m("url", error)
        assert isinstance(problem, ProblemDetail)
        assert INTEGRATION_ERROR.uri == problem.uri
        assert (
            "Remote service returned a problem detail document: %r" % content
            == problem.detail
        )
        assert content == problem.debug_message
        # You can force a response to be treated as successful by
        # passing in its response code as allowed_response_codes.
        assert error == m("url", error, allowed_response_codes=[400])
        assert error == m("url", error, allowed_response_codes=["400"])
        assert error == m("url", error, allowed_response_codes=["4xx"])
Esempio n. 3
0
    def test__send_registration_request(self):
        class Mock(object):
            def __init__(self, response):
                self.response = response

            def do_post(self, url, payload, **kwargs):
                self.called_with = (url, payload, kwargs)
                return self.response

        # If everything goes well, the return value of do_post is
        # passed through.
        mock = Mock(MockRequestsResponse(200, content="all good"))
        url = "url"
        payload = "payload"
        headers = "headers"
        m = Registration._send_registration_request
        result = m(url, headers, payload, mock.do_post)
        assert mock.response == result
        called_with = mock.called_with
        assert called_with == (
            url,
            payload,
            dict(
                headers=headers,
                timeout=60,
                allowed_response_codes=["2xx", "3xx", "400", "401"],
            ),
        )

        # Most error handling is expected to be handled by do_post
        # raising an exception, but certain responses get special
        # treatment:

        # The remote sends a 401 response with a problem detail.
        mock = Mock(
            MockRequestsResponse(
                401,
                {"Content-Type": PROBLEM_DETAIL_JSON_MEDIA_TYPE},
                content=json.dumps(dict(detail="this is a problem detail")),
            ))
        result = m(url, headers, payload, mock.do_post)
        assert isinstance(result, ProblemDetail)
        assert REMOTE_INTEGRATION_FAILED.uri == result.uri
        assert 'Remote service returned: "this is a problem detail"' == result.detail

        # The remote sends some other kind of 401 response.
        mock = Mock(
            MockRequestsResponse(401, {"Content-Type": "text/html"},
                                 content="log in why don't you"))
        result = m(url, headers, payload, mock.do_post)
        assert isinstance(result, ProblemDetail)
        assert REMOTE_INTEGRATION_FAILED.uri == result.uri
        assert 'Remote service returned: "log in why don\'t you"' == result.detail
Esempio n. 4
0
    def test_helper_constructor(self):
        response = MockRequestsResponse(102, content="nonsense")
        exc = BadResponseException.from_response(
            "http://url/", "Terrible response, just terrible", response
        )

        # Turn the exception into a problem detail document, and it's full
        # of useful information.
        doc, status_code, headers = exc.as_problem_detail_document(debug=True).response
        doc = json.loads(doc)

        assert "Bad response" == doc["title"]
        assert (
            "The server made a request to http://url/, and got an unexpected or invalid response."
            == doc["detail"]
        )
        assert (
            "Bad response from http://url/: Terrible response, just terrible\n\nStatus code: 102\nContent: nonsense"
            == doc["debug_message"]
        )

        # Unless debug is turned off, in which case none of that
        # information is present.
        doc, status_code, headers = exc.as_problem_detail_document(debug=False).response
        assert "debug_message" not in json.loads(doc)
 def _send_registration_request(self, register_url, payload,
                                do_post):
     self._send_registration_request_called_with = (register_url,
                                                    payload,
                                                    do_post)
     return MockRequestsResponse(200,
                                 content=json.dumps("you did it!"))
Esempio n. 6
0
    def test_import_feed_response(self):
        """Verify that import_feed_response instantiates the
        OPDS_IMPORTER_CLASS subclass and calls import_from_feed
        on it.
        """
        class MockOPDSImporter(OPDSImporter):
            def import_from_feed(self, text):
                """Return information that's useful for verifying
                that the OPDSImporter was instantiated with the
                right values.
                """
                return (text, self.collection, self.identifier_mapping,
                        self.data_source_name)

        class MockProvider(MockOPDSImportCoverageProvider):
            OPDS_IMPORTER_CLASS = MockOPDSImporter

        provider = MockProvider(self._default_collection)
        provider.lookup_client = MockSimplifiedOPDSLookup(self._url)

        response = MockRequestsResponse(
            200, {'content-type': OPDSFeed.ACQUISITION_FEED_TYPE}, "some data")
        id_mapping = object()
        (text, collection, mapping,
         data_source_name) = provider.import_feed_response(
             response, id_mapping)
        eq_("some data", text)
        eq_(provider.collection, collection)
        eq_(id_mapping, mapping)
        eq_(provider.data_source.name, data_source_name)
Esempio n. 7
0
 def _request(self, *args, **kwargs):
     self.called_with.append((args, kwargs))
     if self.timeout:
         self.timeout = False
         raise RequestTimedOut("url", "timeout")
     else:
         return MockRequestsResponse(200, content="content")
Esempio n. 8
0
 def _request(self, *args, **kwargs):
     self.called_with.append((args, kwargs))
     return MockRequestsResponse(
         200,
         content="<html><title>oh no</title><body>%s</body>" %
         (EnkiAPI.ERROR_INDICATOR),
     )
Esempio n. 9
0
    def test_bad_status_code_helper(object):
        response = MockRequestsResponse(500, content="Internal Server Error!")
        exc = BadResponseException.bad_status_code("http://url/", response)
        doc, status_code, headers = exc.as_problem_detail_document(debug=True).response
        doc = json.loads(doc)

        assert doc["debug_message"].startswith(
            "Bad response from http://url/: Got status code 500 from external server, cannot continue."
        )
    def test_badresponseexception_on_non_opds_feed(self):

        response = MockRequestsResponse(200, {"content-type": "text/plain"},
                                        "Some data")

        provider = self._provider()
        assert_raises_regexp(BadResponseException,
                             "Wrong media type: text/plain",
                             provider.import_feed_response, response, None)
Esempio n. 11
0
 def test_401_during_refresh_raises_error(self):
     """If we fail to refresh the OAuth bearer token, an exception is
     raised.
     """
     self.api.access_token_response = MockRequestsResponse(401, {}, "")
     with pytest.raises(BadResponseException) as excinfo:
         self.api.refresh_creds(None)
     assert "Got status code 401" in str(excinfo.value)
     assert "can only continue on: 200." in str(excinfo.value)
    def test_process_feed(self):
        data = sample_data("metadata_reaper_response.opds", "opds")
        response = MockRequestsResponse(
            200, {'content-type': OPDSFeed.ACQUISITION_FEED_TYPE}, data)

        # A successful response gives us OPDSMessage objects.
        values = list(self.reaper.process_feed_response(response, {}))
        for x in values:
            assert isinstance(x, OPDSMessage)

        eq_([
            'Successfully removed', 'Not in collection catalog',
            "I've never heard of this work."
        ], [x.message for x in values])

        # We get an error if the 'server' sends data with the wrong media
        # type.
        response = MockRequestsResponse(200, {"content-type": "text/plain"},
                                        data)
        assert_raises(BadResponseException, self.reaper.process_feed_response,
                      response, {})
Esempio n. 13
0
        def fake_200_response(*args, **kwargs):
            # The HTTP method and URL are passed in the order
            # requests.request would expect.
            assert ("GET", "http://url/") == args

            # Keyword arguments to _request_with_timeout are passed in
            # as-is.
            assert "value" == kwargs["kwarg"]

            # A default timeout is added.
            assert 20 == kwargs["timeout"]
            return MockRequestsResponse(200, content="Success!")
Esempio n. 14
0
    def test_badresponseexception_on_non_opds_feed(self):
        """If the lookup protocol sends something that's not an OPDS
        feed, refuse to go any further.
        """
        provider = self._provider()
        provider.lookup_client = MockSimplifiedOPDSLookup(self._url)

        response = MockRequestsResponse(200, {"content-type": "text/plain"},
                                        "Some data")
        provider.lookup_client.queue_response(response)
        assert_raises_regexp(BadResponseException,
                             "Wrong media type: text/plain",
                             provider.import_feed_response, response, None)
 def mock_ask_registry(self, service_area_object, db):
     places = {"US": ["Chicago"], "CA": ["Victoria, BC"]}
     service_area_info = json.loads(
         urllib.parse.unquote(service_area_object))
     nation = list(service_area_info.keys())[0]
     city_or_county = list(service_area_info.values())[0]
     if city_or_county == "ERROR":
         test.responses.append(MockRequestsResponse(502))
     elif city_or_county in places[nation]:
         self.called_with.append(service_area_info)
         test.responses.append(
             MockRequestsResponse(200,
                                  content=json.dumps(
                                      dict(unknown=None,
                                           ambiguous=None))))
     else:
         self.called_with.append(service_area_info)
         test.responses.append(
             MockRequestsResponse(
                 200,
                 content=json.dumps(
                     dict(unknown=[city_or_county]))))
     return original_ask_registry(service_area_object, db, get)
Esempio n. 16
0
    def test_process_feed_response(self):
        data = sample_data("metadata_reaper_response.opds", "opds")
        response = MockRequestsResponse(
            200, {'content-type': OPDSFeed.ACQUISITION_FEED_TYPE}, data)

        # A successful response gives us OPDSMessage objects.
        values = list(self.provider.process_feed_response(response, {}))
        for x in values:
            assert isinstance(x, OPDSMessage)

        eq_([
            'Successfully removed', 'Not in collection catalog',
            "I've never heard of this work."
        ], [x.message for x in values])
Esempio n. 17
0
 def updates(self, timestamp):
     self.last_timestamp = timestamp
     return MockRequestsResponse(
         200, {"content-type": OPDSFeed.ACQUISITION_FEED_TYPE})
Esempio n. 18
0
 def do_get(*args, **kwargs):
     return MockRequestsResponse(200, content=auth_response)
Esempio n. 19
0
 def extract(document, type=Registration.OPDS_2_TYPE):
     response = MockRequestsResponse(200, {"Content-Type": type},
                                     document)
     return Registration._extract_catalog_information(response)
    def test_ask_registry(self, monkeypatch):
        validator = GeographicValidator()

        registry_1 = "https://registry_1_url"
        registry_2 = "https://registry_2_url"
        registry_3 = "https://registry_3_url"
        registries = self._registries([registry_1, registry_2, registry_3],
                                      monkeypatch)

        true_response = MockRequestsResponse(200, content="{}")
        unknown_response = MockRequestsResponse(200,
                                                content='{"unknown": "place"}')
        ambiguous_response = MockRequestsResponse(
            200, content='{"ambiguous": "place"}')
        problem_response = MockRequestsResponse(404)

        # Registry 1 knows about the place
        self.responses.append(true_response)
        response_1 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        assert response_1 == True
        assert len(self.requests) == 1
        request_1 = self.requests.pop()
        assert (
            request_1[0] ==
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 says the place is unknown, but Registry 2 finds it.
        self.responses.append(true_response)
        self.responses.append(unknown_response)
        response_2 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        assert response_2 == True
        assert len(self.requests) == 2
        request_2 = self.requests.pop()
        assert (
            request_2[0] ==
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        assert (
            request_1[0] ==
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry_1 says the place is ambiguous and Registry_2 says it's unknown, but Registry_3 finds it.
        self.responses.append(true_response)
        self.responses.append(unknown_response)
        self.responses.append(ambiguous_response)
        response_3 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        assert response_3 == True
        assert len(self.requests) == 3
        request_3 = self.requests.pop()
        assert (
            request_3[0] ==
            'https://registry_3_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_2 = self.requests.pop()
        assert (
            request_2[0] ==
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        assert (
            request_1[0] ==
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 returns a problem detail, but Registry 2 finds the place
        self.responses.append(true_response)
        self.responses.append(problem_response)
        response_4 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        assert response_4 == True
        assert len(self.requests) == 2
        request_2 = self.requests.pop()
        assert (
            request_2[0] ==
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        assert (
            request_1[0] ==
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 returns a problem detail and the other two registries can't find the place
        self.responses.append(unknown_response)
        self.responses.append(ambiguous_response)
        self.responses.append(problem_response)
        response_5 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        assert response_5.status_code == 502
        assert (response_5.detail ==
                "Unable to contact the registry at https://registry_1_url.")
        assert len(self.requests) == 3
        request_3 = self.requests.pop()
        assert (
            request_3[0] ==
            'https://registry_3_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_2 = self.requests.pop()
        assert (
            request_2[0] ==
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        assert (
            request_1[0] ==
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')
    def test_ask_registry(self):
        validator = GeographicValidator()

        registry_1 = self._registry("https://registry_1_url")
        registry_2 = self._registry("https://registry_2_url")
        registry_3 = self._registry("https://registry_3_url")

        true_response = MockRequestsResponse(200, content="{}")
        unknown_response = MockRequestsResponse(200,
                                                content='{"unknown": "place"}')
        ambiguous_response = MockRequestsResponse(
            200, content='{"ambiguous": "place"}')
        problem_response = MockRequestsResponse(404)

        # Registry 1 knows about the place
        self.responses.append(true_response)
        response_1 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        eq_(response_1, True)
        eq_(len(self.requests), 1)
        request_1 = self.requests.pop()
        eq_(request_1[0],
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 says the place is unknown, but Registry 2 finds it.
        self.responses.append(true_response)
        self.responses.append(unknown_response)
        response_2 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        eq_(response_2, True)
        eq_(len(self.requests), 2)
        request_2 = self.requests.pop()
        eq_(request_2[0],
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        eq_(request_1[0],
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry_1 says the place is ambiguous and Registry_2 says it's unknown, but Registry_3 finds it.
        self.responses.append(true_response)
        self.responses.append(unknown_response)
        self.responses.append(ambiguous_response)
        response_3 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        eq_(response_3, True)
        eq_(len(self.requests), 3)
        request_3 = self.requests.pop()
        eq_(request_3[0],
            'https://registry_3_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_2 = self.requests.pop()
        eq_(request_2[0],
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        eq_(request_1[0],
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 returns a problem detail, but Registry 2 finds the place
        self.responses.append(true_response)
        self.responses.append(problem_response)
        response_4 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        eq_(response_4, True)
        eq_(len(self.requests), 2)
        request_2 = self.requests.pop()
        eq_(request_2[0],
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        eq_(request_1[0],
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')

        # Registry 1 returns a problem detail and the other two registries can't find the place
        self.responses.append(unknown_response)
        self.responses.append(ambiguous_response)
        self.responses.append(problem_response)
        response_5 = validator.ask_registry(json.dumps({"CA": "Victoria, BC"}),
                                            self._db, self.do_request)
        eq_(response_5.status_code, 502)
        eq_(response_5.detail,
            "Unable to contact the registry at https://registry_1_url.")
        eq_(len(self.requests), 3)
        request_3 = self.requests.pop()
        eq_(request_3[0],
            'https://registry_3_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_2 = self.requests.pop()
        eq_(request_2[0],
            'https://registry_2_url/coverage?coverage={"CA": "Victoria, BC"}')
        request_1 = self.requests.pop()
        eq_(request_1[0],
            'https://registry_1_url/coverage?coverage={"CA": "Victoria, BC"}')
Esempio n. 22
0
 def response(self, *args, **kwargs):
     self.requests.append((args, kwargs))
     return MockRequestsResponse(200, content="Success!")
Esempio n. 23
0
 def mock_access_token_response(self, credential, expires_in=-1):
     token = dict(token=credential, expiresIn=expires_in)
     return MockRequestsResponse(200, {}, json.dumps(token))
Esempio n. 24
0
 def fake_200_response(*args, **kwargs):
     return MockRequestsResponse(200, content="Hurray")
Esempio n. 25
0
 def fake_401_response(*args, **kwargs):
     return MockRequestsResponse(401, content="Weird")
Esempio n. 26
0
 def fake_500_response(*args, **kwargs):
     return MockRequestsResponse(500, content="Failure!")
Esempio n. 27
0
 def _get(self, _url):
     self.urls.append(_url)
     return MockRequestsResponse(
         200, {"content-type": OPDSFeed.ACQUISITION_FEED_TYPE})
Esempio n. 28
0
 def queue_response(self, status_code, headers={}, content=None):
     from core.testing import MockRequestsResponse
     self.responses.insert(
         0, MockRequestsResponse(status_code, headers, content))
 def queue_response(self, status_code, headers={}, content=None):
     self.responses.insert(
         0, MockRequestsResponse(status_code, headers, content)
     )
Esempio n. 30
0
 def mock_request(*args, **kwargs):
     response = MockRequestsResponse(200, "Success!")
     return response