Merge pull request #60 from kuba/acme_test

Add acme_test. Sphinx-like doc in acme module.
This commit is contained in:
schoen 2014-11-23 13:02:55 -08:00
commit 0dc4ef1670
2 changed files with 85 additions and 17 deletions

View file

@ -5,9 +5,9 @@ import pkg_resources
import jsonschema
SCHEMATA = {
schema: json.load(open(pkg_resources.resource_filename(
__name__, "schemata/%s.json" % schema))) for schema in [
SCHEMATA = dict([
(schema, json.load(open(pkg_resources.resource_filename(
__name__, "schemata/%s.json" % schema)))) for schema in [
"authorization",
"authorizationRequest",
"certificate",
@ -18,32 +18,42 @@ SCHEMATA = {
"error",
"revocation",
"revocationRequest",
"statusRequest"
"statusRequest",
]
}
])
def acme_object_validate(j):
"""Validate a JSON object against the ACME protocol using JSON Schema.
def acme_object_validate(json_string, schemata=None):
"""Validate a JSON string against the ACME protocol using JSON Schema.
:param json_string: Well-formed input JSON string.
:type json_string: str
:param schemata: Mapping from type name to JSON Schema definition.
Useful for testing.
:type schemata: dict
:returns: None if validation was successful.
:raises: jsonschema.ValidationError if validation was unsuccessful
ValueError if the object cannot even be parsed as valid JSON
Success will return None; failure to validate will raise a
jsonschema.ValidationError exception describing the reason that the
object could not be validated successfully, or a ValueError exception
if the object cannot even be parsed as valid JSON.
"""
j = json.loads(j)
if not isinstance(j, dict):
schemata = SCHEMATA if schemata is None else schemata
json_object = json.loads(json_string)
if not isinstance(json_object, dict):
raise jsonschema.ValidationError("this is not a dictionary object")
if "type" not in j:
if "type" not in json_object:
raise jsonschema.ValidationError("missing type field")
if j["type"] not in SCHEMATA:
raise jsonschema.ValidationError("unknown type %s" % j["type"])
jsonschema.validate(j, SCHEMATA[j["type"]])
if json_object["type"] not in schemata:
raise jsonschema.ValidationError(
"unknown type %s" % json_object["type"])
jsonschema.validate(json_object, schemata[json_object["type"]])
def pretty(json_string):
"""Return a pretty-printed version of any JSON string.
Useful when printing out protocol messages for debugging purposes.
"""
return json.dumps(json.loads(json_string), indent=4)

View file

@ -0,0 +1,58 @@
"""Tests for letsencrypt.client.acme."""
import unittest
import jsonschema
class ACMEObjectValidateTest(unittest.TestCase):
"""Tests for letsencrypt.client.acme.acme_object_validate."""
def setUp(self):
self.schemata = {
'foo': {
'type' : 'object',
'properties' : {
'price' : {'type' : 'number'},
'name' : {'type' : 'string'},
},
},
}
def _call(self, json_string):
from letsencrypt.client.acme import acme_object_validate
return acme_object_validate(json_string, self.schemata)
def _test_fails(self, json_string):
self.assertRaises(jsonschema.ValidationError, self._call, json_string)
def test_non_dictionary_fails(self):
self._test_fails('[]')
def test_dict_without_type_fails(self):
self._test_fails('{}')
def test_unknown_type_fails(self):
self._test_fails('{"type": "bar"}')
def test_valid_returns_none(self):
self.assertTrue(self._call('{"type": "foo"}') is None)
def test_invalid_fails(self):
self._test_fails('{"type": "foo", "price": "asd"}')
class PrettyTest(unittest.TestCase):
"""Tests for letsencrypt.client.acme.pretty."""
def _call(self, json_string):
from letsencrypt.client.acme import pretty
return pretty(json_string)
def test_it(self):
self.assertEqual(
self._call('{"foo": "bar", "foo2": "bar2"}'),
'{\n "foo2": "bar2", \n "foo": "bar"\n}')
if __name__ == '__main__':
unittest.main()