Ejemplo n.º 1
0
class SaratogaAPITests(TestCase):

    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path, "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)


    def test_EmbeddedSaratogaBasic(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/nothing")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_EmbeddedSaratogaWithRegex(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"id": "4"}}
            )

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/example/4")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_EmbeddedSaratogaWithRegex404(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Bad ID :("}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(len(warnings), 1)

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/example/9999")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_customOutputFormatRegistry(self):

        o = OutputRegistry("application/json")
        api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o)
        self.assertIs(o, api.outputRegistry)


    def test_getResource(self):
        """
        Check that Saratoga returns the correct resource.
        """
        self.assertIs(self.api.resource, self.api.getResource())


    def test_basic(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/example").addCallback(rendered)


    def test_basicNothing(self):
        """
        Double check we handle functons that return nothing.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/nothing").addCallback(rendered)


    def test_basicWithEmptyParams(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/example", replaceEmptyWithEmptyDict=True
            ).addCallback(rendered)


    def test_basicRegex(self):
        """
        Basic Saratoga test, testing the regex stuff.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"id": "4"}}
            )

        return self.api.test("/v1/example/4").addCallback(rendered)


    def test_basicRegexFail(self):
        """
        Basic Saratoga test, testing the regex stuff, and handing 404s
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Bad ID :("}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(len(warnings), 1)

        return self.api.test("/v1/example/9999").addCallback(rendered)


    def test_handlingOfExceptions(self):
        """
        Test that throwing a generic exception is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error", "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "OMG LOL WTF")

        return self.api.test("/v1/exception").addCallback(rendered)


    def test_authRequiredWhenDefaultServiceClass(self):
        """
        Test that authentication without an authenticator fails.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error", "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "Authentication required, but there is not an available "
                "authenticator.")

        return self.api.test("/v1/requiresAuth").addCallback(rendered)


    def test_dictResponse(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"hi": "there"}}
            )

        return self.api.test("/v1/dictResponse",
            params={"data": {"hi": "there"}}).addCallback(rendered)

    def test_dictResponsePOSTArgs(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"hi": "there"}}
            )

        return self.api.test("/v1/dictResponse",
                             params={"data": {"hi": "there"}}, useBody=False).addCallback(rendered)


    def test_listResponse(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": ["hi", "there"]}
            )

        return self.api.test("/v1/listResponse",
            params={"data": ["hi", "there"]}).addCallback(rendered)

    def test_listResponsePOSTArgs(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": ["hi", "there"]}
            )

        return self.api.test("/v1/listResponse",
                             params={"data": [["hi", "there"]]}, useBody=False).addCallback(rendered)

    def test_dictResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "[u'hi', u'there'] is not of type 'object'")

        d = self.api.test("/v1/dictResponse",
            params={"data": ["hi", "there"]})
        return d.addCallback(rendered)


    def test_listResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "{u'hi': u'there'} is not of type 'array'")

        d = self.api.test("/v1/listResponse",
            params={"data": {"hi": "there"}})
        return d.addCallback(rendered)


    def test_serviceClass(self):
        """
        Test to make sure it uses the service class you tell it.
        """
        class Foo(object):
            pass

        serviceClass = Foo()
        api = SaratogaAPI(APIImpl, APIDef, serviceClass)
        self.assertEqual(api.serviceClass, serviceClass)


    def test_nonExistingEndpoint(self):
        """
        Test that it handles non-existing endpoints gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Endpoint does not exist."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "Endpoint does not exist.")

        d = self.api.test("/v1/nowhere")
        return d.addCallback(rendered)


    def test_requiredResponseParamsAllowsOptionalParams(self):
        """
        Test that required response params work, and will return an error if
        given extras.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success",
                "data": {"cake": "yes", "muffin": "yes", "pizza": "slice"}}
            )

        d = self.api.test("/v1/responseParams",
            params={"cake": "yes", "muffin": "yes", "pizza": "slice"})
        return d.addCallback(rendered)


    def test_extLoadJSONSchema(self):
        """
        Test that it loads external JSON Schema by loading in something that it
        will fail.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "u'cake' is a "
                "required property, u'muffin' is a required property")

        return self.api.test("/v1/responseParamsExtLoad").addCallback(rendered)


    def test_requiredResponseParamsReturnsErrorIfNotGiven(self):
        """
        Test that required response params work, and will return an error if
        not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "'cake' is a "
                "required property, 'muffin' is a required property")

        return self.api.test("/v1/responseParams").addCallback(rendered)


    def test_requiredParamsReturnsErrorIfNotGiven(self):
        """
        Test that required params work, and will return an error if not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail",
                "data": "'hello' is a required property, 'goodbye' is a "
                    "required property"}
            )

        d = self.api.test("/v1/requestParams")
        return d.addCallback(rendered)


    def test_requiredParamsReturnsErrorIfGivenExtra(self):
        """
        Test that if required params are set, it will disallow unspecified
        params.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail",
                "data": "Additional properties are not allowed (u'unspecified'"
                    " was unexpected)"}
            )

        d = self.api.test("/v1/requestParams", params={
            "hello": "yes", "goodbye": "no", "unspecified": "yes"
            })
        return d.addCallback(rendered)


    def test_requiredParamsAllowsOptionalParams(self):
        """
        Test that if required params are set, it will allow params set as
        optional.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success",
                "data": {"hello": "yes", "goodbye": "no", "the": "beatles"}}
            )

        d = self.api.test("/v1/requestParams", params={
            "hello": "yes", "goodbye": "no", "the": "beatles"
            })
        return d.addCallback(rendered)

    def test_undefinedHTTPMethod(self):
        """
        Test that an undefined HTTP method returns a nice value.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Method not allowed."}
            )

        return self.api.test("/v1/example", method="WAFFLE").addCallback(rendered)


    def test_customHTTPMethods(self):

        APIDef = {
            "metadata": {"versions": [1]},
            "endpoints": [
                {
                    "endpoint": "example",
                    "waffleProcessors": [{"versions": [1]}]
                }
            ]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WAFFLE"])

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": "OK"}
            )

        return self.api.test("/v1/example", method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {"versions": [1]},
            "endpoints": [
                {
                    "endpoint": "example",
                    "waffleProcessors": [{"versions": [1]}]
                }
            ]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": "OK"}
            )

        return self.api.test("/v1/example", method="WAFFlE").addCallback(rendered)
Ejemplo n.º 2
0
class SaratogaAPITestsWithAuthenticator(TestCase):
    def setUp(self):
        self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())

    def test_wrongPasswordBasicAuth(self):
        """
        Test that a wrong password with BASIC auth is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication failed."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:word"))]
                             }).addCallback(rendered)

    def test_malformedAuthHeader(self):
        """
        Test that something that a malformed auth header is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Malformed Authorization header."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization": ["BASIC HITHERE"]
                             }).addCallback(rendered)

    def test_weirdAuthorizationHeader(self):
        """
        Test that weird auth headers are handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Malformed Authorization header."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:pass:word"))]
                             }).addCallback(rendered)

    def test_unsupportedAuthType(self):
        """
        Test that a malformed auth header is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "fail",
                    "data": "Unsupported Authorization type "
                    "'OMGLOLAUTH'"
                })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["OMGLOLAUTH FIODGNDSEGOUER"]
                             }).addCallback(rendered)

    def test_noAuthTypeGiven(self):
        """
        Test that something that Saratoga doesn't support is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication required."
            })

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_correctBasicAuth(self):
        """
        Test that authentication works.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "username": "******"
                }
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:pass"))]
                             }).addCallback(rendered)

    def test_correctHMACAuth(self):
        """
        Test that HMAC authentication works.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "username": "******"
                }
            })

        return self.api.test("/v1/requiresAuth",
                             params={},
                             enableHMAC=("bob", "pass")).addCallback(rendered)

    def test_wrongHMACAuth(self):
        """
        Test that wrong HMACs are rejected.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication failed."
            })

        return self.api.test(
            "/v1/requiresAuth",
            params={
                "hi": "there"
            },
            headers={
                "Authorization": [
                    'Signature signature="dXoOMfIkyAUFrnATzPoR2lpXpW'
                    '9Ei5irJByzfKG3hpc=",algorithm="hmac-sha256",keyId="alice"'
                ]
            }).addCallback(rendered)
Ejemplo n.º 3
0
class SaratogaAPITests(TestCase):
    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path,
             "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)

    def test_customOutputFormatRegistry(self):

        o = OutputRegistry("application/json")
        api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o)
        self.assertIs(o, api.outputRegistry)

    def test_getResource(self):
        """
        Check that Saratoga returns the correct resource.
        """
        self.assertIs(self.api.resource, self.api.getResource())

    def test_basic(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test("/v1/example").addCallback(rendered)

    def test_basic_nothing(self):
        """
        Double check we handle functons that return nothing.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test("/v1/nothing").addCallback(rendered)

    def test_basicWithEmptyParams(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test(
            "/v1/example",
            replaceEmptyWithEmptyDict=True).addCallback(rendered)

    def test_basicRegex(self):
        """
        Basic Saratoga test, testing the regex stuff.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "id": "4"
                }
            })

        return self.api.test("/v1/example/4").addCallback(rendered)

    def test_handlingOfExceptions(self):
        """
        Test that throwing a generic exception is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "OMG LOL WTF")

        return self.api.test("/v1/exception").addCallback(rendered)

    def test_authRequiredWhenDefaultServiceClass(self):
        """
        Test that authentication without an authenticator fails.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(),
                "Authentication required, but there is not an available "
                "authenticator.")

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_dictResponse(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "hi": "there"
                }
            })

        return self.api.test("/v1/dictResponse",
                             params={
                                 "data": {
                                     "hi": "there"
                                 }
                             }).addCallback(rendered)

    def test_dictResponsePOSTArgs(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "hi": "there"
                }
            })

        return self.api.test("/v1/dictResponse",
                             params={
                                 "data": {
                                     "hi": "there"
                                 }
                             },
                             useBody=False).addCallback(rendered)

    def test_listResponse(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": ["hi", "there"]
            })

        return self.api.test("/v1/listResponse",
                             params={
                                 "data": ["hi", "there"]
                             }).addCallback(rendered)

    def test_listResponsePOSTArgs(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": ["hi", "there"]
            })

        return self.api.test("/v1/listResponse",
                             params={
                                 "data": [["hi", "there"]]
                             },
                             useBody=False).addCallback(rendered)

    def test_dictResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "[u'hi', u'there'] is not of type 'object'")

        d = self.api.test("/v1/dictResponse", params={"data": ["hi", "there"]})
        return d.addCallback(rendered)

    def test_listResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "{u'hi': u'there'} is not of type 'array'")

        d = self.api.test("/v1/listResponse", params={"data": {"hi": "there"}})
        return d.addCallback(rendered)

    def test_serviceClass(self):
        """
        Test to make sure it uses the service class you tell it.
        """
        class Foo(object):
            pass

        serviceClass = Foo()
        api = SaratogaAPI(APIImpl, APIDef, serviceClass)
        self.assertEqual(api.serviceClass, serviceClass)

    def test_nonExistingEndpoint(self):
        """
        Test that it handles non-existing endpoints gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Endpoint does not exist."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "Endpoint does not exist.")

        d = self.api.test("/v1/nowhere")
        return d.addCallback(rendered)

    def test_requiredResponseParamsAllowsOptionalParams(self):
        """
        Test that required response params work, and will return an error if
        given extras.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "success",
                    "data": {
                        "cake": "yes",
                        "muffin": "yes",
                        "pizza": "slice"
                    }
                })

        d = self.api.test("/v1/responseParams",
                          params={
                              "cake": "yes",
                              "muffin": "yes",
                              "pizza": "slice"
                          })
        return d.addCallback(rendered)

    def test_extLoadJSONSchema(self):
        """
        Test that it loads external JSON Schema by loading in something that it
        will fail.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(), "u'cake' is a "
                "required property, u'muffin' is a required property")

        return self.api.test("/v1/responseParamsExtLoad").addCallback(rendered)

    def test_requiredResponseParamsReturnsErrorIfNotGiven(self):
        """
        Test that required response params work, and will return an error if
        not given.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(), "'cake' is a "
                "required property, 'muffin' is a required property")

        return self.api.test("/v1/responseParams").addCallback(rendered)

    def test_requiredParamsReturnsErrorIfNotGiven(self):
        """
        Test that required params work, and will return an error if not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status":
                    "fail",
                    "data":
                    "'hello' is a required property, 'goodbye' is a "
                    "required property"
                })

        d = self.api.test("/v1/requestParams")
        return d.addCallback(rendered)

    def test_requiredParamsReturnsErrorIfGivenExtra(self):
        """
        Test that if required params are set, it will disallow unspecified
        params.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status":
                    "fail",
                    "data":
                    "Additional properties are not allowed (u'unspecified'"
                    " was unexpected)"
                })

        d = self.api.test("/v1/requestParams",
                          params={
                              "hello": "yes",
                              "goodbye": "no",
                              "unspecified": "yes"
                          })
        return d.addCallback(rendered)

    def test_requiredParamsAllowsOptionalParams(self):
        """
        Test that if required params are set, it will allow params set as
        optional.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "success",
                    "data": {
                        "hello": "yes",
                        "goodbye": "no",
                        "the": "beatles"
                    }
                })

        d = self.api.test("/v1/requestParams",
                          params={
                              "hello": "yes",
                              "goodbye": "no",
                              "the": "beatles"
                          })
        return d.addCallback(rendered)

    def test_undefinedHTTPMethod(self):
        """
        Test that an undefined HTTP method returns a nice value.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Method not allowed."
            })

        return self.api.test("/v1/example",
                             method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethods(self):

        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "waffleProcessors": [{
                    "versions": [1]
                }]
            }]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WAFFLE"])

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": "OK"
            })

        return self.api.test("/v1/example",
                             method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "waffleProcessors": [{
                    "versions": [1]
                }]
            }]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": "OK"
            })

        return self.api.test("/v1/example",
                             method="WAFFlE").addCallback(rendered)
Ejemplo n.º 4
0
class SaratogaAPITestsWithAuthenticator(TestCase):
    def setUp(self):
        self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())

    def test_wrongPasswordBasicAuth(self):
        """
        Test that a wrong password with BASIC auth is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication failed."})

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:word"))]}
        ).addCallback(rendered)

    def test_malformedAuthHeader(self):
        """
        Test that something that a malformed auth header is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Malformed Authorization header."}
            )

        return self.api.test("/v1/requiresAuth", headers={"Authorization": ["BASIC HITHERE"]}).addCallback(rendered)

    def test_weirdAuthorizationHeader(self):
        """
        Test that weird auth headers are handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Malformed Authorization header."}
            )

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:pass:word"))]}
        ).addCallback(rendered)

    def test_unsupportedAuthType(self):
        """
        Test that a malformed auth header is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Unsupported Authorization type " "'OMGLOLAUTH'"},
            )

        return self.api.test("/v1/requiresAuth", headers={"Authorization": ["OMGLOLAUTH FIODGNDSEGOUER"]}).addCallback(
            rendered
        )

    def test_noAuthTypeGiven(self):
        """
        Test that something that Saratoga doesn't support is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication required."}
            )

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_correctBasicAuth(self):
        """
        Test that authentication works.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "success", "data": {"username": "******"}}
            )

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:pass"))]}
        ).addCallback(rendered)

    def test_correctHMACAuth(self):
        """
        Test that HMAC authentication works.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "success", "data": {"username": "******"}}
            )

        return self.api.test("/v1/requiresAuth", params={}, enableHMAC=("bob", "pass")).addCallback(rendered)

    def test_wrongHMACAuth(self):
        """
        Test that wrong HMACs are rejected.
        """

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication failed."})

        return self.api.test(
            "/v1/requiresAuth",
            params={"hi": "there"},
            headers={
                "Authorization": [
                    'Signature signature="dXoOMfIkyAUFrnATzPoR2lpXpW'
                    '9Ei5irJByzfKG3hpc=",algorithm="hmac-sha256",keyId="alice"'
                ]
            },
        ).addCallback(rendered)