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)
def run(host="localhost", user="******", password="******", database="opendkim", bindAddress='', bindPort=8000): "This program runs a web server to retrieve reputation data from the opendkim database" outputRegistry = OutputRegistry('application/reputon+json') outputRegistry.register('application/reputon+json', jsonDateFormatter) outputRegistry.register('text/html', jsonDateFormatter) api = SaratogaAPI(DKIM, DKIM_APIDef, serviceClass=Database(user=user, password=password, host=host, database=database), outputRegistry=outputRegistry) api.run(port=bindPort)
def makeService(options): # pragma: no cover """ Make a service. @param options: The option parameters. @return: A service. """ fp = getModule(__name__).filePath.parent().child("api.json") sc = api_impl.TwinodeServiceClass(options['dbname']) api = SaratogaAPI(api_impl.TwinodeAPI, json.load(fp.open()), serviceClass=sc) site = server.Site(api.getResource()) return strports.service(options['port'], site)
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)
def test_missingImplementationInVersion(self): class APIImpl(object): class v1(object): def example_GET(self, request, params): """""" class v2(object): """""" APIDef = { "metadata": { "versions": [1, 2] }, "endpoints": [{ "endpoint": "example", "getProcessors": [{ "versions": [1, 2] }] }] } try: SaratogaAPI(APIImpl, APIDef) except Exception, e: self.assertEqual( e.message, "Implementation is missing the GET processor in the v2 example " "endpoint")
def test_missingMetadata(self): APIDef = {"endpoints": []} try: SaratogaAPI(APIImpl, APIDef) except Exception, e: self.assertEqual(e.message, "Definition requires a metadata section.")
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_missingVersionClass(self): APIDef = { "metadata": { "versions": [1, 2] }, "endpoints": [{ "endpoint": "example", "getProcessors": [{ "versions": [1, 2] }] }] } try: SaratogaAPI(APIImpl, APIDef) except Exception, e: self.assertEqual(e.message, "Implementation is missing version 2")
def test_undeclaredVersion(self): APIDef = { "metadata": { "versions": [1] }, "endpoints": [{ "endpoint": "example", "getProcessors": [{ "versions": [1, 2] }] }] } try: SaratogaAPI(APIImpl, APIDef) except Exception, e: self.assertEqual( e.message, "Version mismatch - 2 in example is not a declared version")
from saratoga.api import SaratogaAPI import json class ExampleAPI(object): class v1(object): def example_GET(self, request, params): raise Exception("oh no!") SaratogaAPI(ExampleAPI, json.load(open("simple.json"))).run()
import json from saratoga.api import SaratogaAPI class PlanetAPI(object): class v1(object): def yearlength_GET(self, request, params): planetName = params["params"]["name"].lower() if planetName == "earth": return {"seconds": 31536000} elif planetName == "pluto": return {"seconds": 7816176000} APIDescription = json.load(open("planets.json")) myAPI = SaratogaAPI(PlanetAPI, APIDescription) myAPI.run(port=8094)
def test_customOutputFormatRegistry(self): o = OutputRegistry("application/json") api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o) self.assertIs(o, api.outputRegistry)
def setUp(self): self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())
def setUp(self): fp = getModule(__name__).filePath copy(fp.parent().child("jsonschemaext.json").path, "jsonschemaext.json") self.api = SaratogaAPI(APIImpl, APIDef)
from saratoga.api import SaratogaAPI import json class ServiceClassExample(object): stuff = "foo" class ExampleAPI(object): class v1(object): def example_GET(self, request, params): return self.stuff api = SaratogaAPI(ExampleAPI, json.load(open("simple.json")), serviceClass=ServiceClassExample()) api.run()
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)
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)
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)
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)