mirror of
https://github.com/certbot/certbot.git
synced 2026-01-21 19:01:07 +03:00
Merge branch 'master' into boulder
Conflicts: letsencrypt/acme/jose/json_util.py letsencrypt/acme/jose/jwk.py letsencrypt/acme/messages2_test.py
This commit is contained in:
@@ -36,7 +36,6 @@ For squezze you will need to:
|
||||
(``sudo`` is not installed by default) before running the bootstrap
|
||||
script.
|
||||
- Use ``virtualenv --no-site-packages -p python`` instead of ``-p python2``.
|
||||
- Use text mode ``sudo ./venv/bin/letsencrypt --text`` (`#280`_)
|
||||
|
||||
|
||||
.. _`#280`: https://github.com/letsencrypt/lets-encrypt-preview/issues/280
|
||||
|
||||
@@ -13,7 +13,7 @@ from letsencrypt.acme import other
|
||||
|
||||
|
||||
class Challenge(jose.TypedJSONObjectWithFields):
|
||||
# _fields_to_json | pylint: disable=abstract-method
|
||||
# _fields_to_partial_json | pylint: disable=abstract-method
|
||||
"""ACME challenge."""
|
||||
TYPES = {}
|
||||
|
||||
@@ -27,7 +27,7 @@ class DVChallenge(Challenge): # pylint: disable=abstract-method
|
||||
|
||||
|
||||
class ChallengeResponse(jose.TypedJSONObjectWithFields):
|
||||
# _fields_to_json | pylint: disable=abstract-method
|
||||
# _fields_to_partial_json | pylint: disable=abstract-method
|
||||
"""ACME challenge response."""
|
||||
TYPES = {}
|
||||
|
||||
|
||||
@@ -30,13 +30,17 @@ class SimpleHTTPSTest(unittest.TestCase):
|
||||
'token': 'evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+oA',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import SimpleHTTPS
|
||||
self.assertEqual(self.msg, SimpleHTTPS.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import SimpleHTTPS
|
||||
hash(SimpleHTTPS.from_json(self.jmsg))
|
||||
|
||||
|
||||
class SimpleHTTPSResponseTest(unittest.TestCase):
|
||||
|
||||
@@ -52,14 +56,18 @@ class SimpleHTTPSResponseTest(unittest.TestCase):
|
||||
self.assertEqual('https://example.com/.well-known/acme-challenge/'
|
||||
'6tbIMBC5Anhl5bOlWT5ZFA', self.msg.uri('example.com'))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import SimpleHTTPSResponse
|
||||
self.assertEqual(
|
||||
self.msg, SimpleHTTPSResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import SimpleHTTPSResponse
|
||||
hash(SimpleHTTPSResponse.from_json(self.jmsg))
|
||||
|
||||
|
||||
class DVSNITest(unittest.TestCase):
|
||||
|
||||
@@ -79,13 +87,17 @@ class DVSNITest(unittest.TestCase):
|
||||
self.assertEqual('a82d5ff8ef740d12881f6d3c2277ab2e.acme.invalid',
|
||||
self.msg.nonce_domain)
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import DVSNI
|
||||
self.assertEqual(self.msg, DVSNI.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import DVSNI
|
||||
hash(DVSNI.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_invalid_r_length(self):
|
||||
from letsencrypt.acme.challenges import DVSNI
|
||||
self.jmsg['r'] = 'abcd'
|
||||
@@ -124,13 +136,17 @@ class DVSNIResponseTest(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
'{0}.acme.invalid'.format(z), self.msg.z_domain(challenge))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import DVSNIResponse
|
||||
self.assertEqual(self.msg, DVSNIResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import DVSNIResponse
|
||||
hash(DVSNIResponse.from_json(self.jmsg))
|
||||
|
||||
|
||||
class RecoveryContactTest(unittest.TestCase):
|
||||
|
||||
@@ -147,13 +163,17 @@ class RecoveryContactTest(unittest.TestCase):
|
||||
'contact' : 'c********n@example.com',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import RecoveryContact
|
||||
self.assertEqual(self.msg, RecoveryContact.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import RecoveryContact
|
||||
hash(RecoveryContact.from_json(self.jmsg))
|
||||
|
||||
def test_json_without_optionals(self):
|
||||
del self.jmsg['activationURL']
|
||||
del self.jmsg['successURL']
|
||||
@@ -165,7 +185,7 @@ class RecoveryContactTest(unittest.TestCase):
|
||||
self.assertTrue(msg.activation_url is None)
|
||||
self.assertTrue(msg.success_url is None)
|
||||
self.assertTrue(msg.contact is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class RecoveryContactResponseTest(unittest.TestCase):
|
||||
@@ -175,14 +195,18 @@ class RecoveryContactResponseTest(unittest.TestCase):
|
||||
self.msg = RecoveryContactResponse(token='23029d88d9e123e')
|
||||
self.jmsg = {'type': 'recoveryContact', 'token': '23029d88d9e123e'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import RecoveryContactResponse
|
||||
self.assertEqual(
|
||||
self.msg, RecoveryContactResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import RecoveryContactResponse
|
||||
hash(RecoveryContactResponse.from_json(self.jmsg))
|
||||
|
||||
def test_json_without_optionals(self):
|
||||
del self.jmsg['token']
|
||||
|
||||
@@ -190,7 +214,7 @@ class RecoveryContactResponseTest(unittest.TestCase):
|
||||
msg = RecoveryContactResponse.from_json(self.jmsg)
|
||||
|
||||
self.assertTrue(msg.token is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class RecoveryTokenTest(unittest.TestCase):
|
||||
@@ -200,13 +224,17 @@ class RecoveryTokenTest(unittest.TestCase):
|
||||
self.msg = RecoveryToken()
|
||||
self.jmsg = {'type': 'recoveryToken'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import RecoveryToken
|
||||
self.assertEqual(self.msg, RecoveryToken.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import RecoveryToken
|
||||
hash(RecoveryToken.from_json(self.jmsg))
|
||||
|
||||
|
||||
class RecoveryTokenResponseTest(unittest.TestCase):
|
||||
|
||||
@@ -215,14 +243,18 @@ class RecoveryTokenResponseTest(unittest.TestCase):
|
||||
self.msg = RecoveryTokenResponse(token='23029d88d9e123e')
|
||||
self.jmsg = {'type': 'recoveryToken', 'token': '23029d88d9e123e'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import RecoveryTokenResponse
|
||||
self.assertEqual(
|
||||
self.msg, RecoveryTokenResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import RecoveryTokenResponse
|
||||
hash(RecoveryTokenResponse.from_json(self.jmsg))
|
||||
|
||||
def test_json_without_optionals(self):
|
||||
del self.jmsg['token']
|
||||
|
||||
@@ -230,7 +262,7 @@ class RecoveryTokenResponseTest(unittest.TestCase):
|
||||
msg = RecoveryTokenResponse.from_json(self.jmsg)
|
||||
|
||||
self.assertTrue(msg.token is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class ProofOfPossessionHintsTest(unittest.TestCase):
|
||||
@@ -266,16 +298,20 @@ class ProofOfPossessionHintsTest(unittest.TestCase):
|
||||
'authorizedFor': authorized_for,
|
||||
}
|
||||
self.jmsg_from = self.jmsg_to.copy()
|
||||
self.jmsg_from.update({'jwk': jwk.fully_serialize()})
|
||||
self.jmsg_from.update({'jwk': jwk.to_json()})
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossession
|
||||
self.assertEqual(
|
||||
self.msg, ProofOfPossession.Hints.from_json(self.jmsg_from))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossession
|
||||
hash(ProofOfPossession.Hints.from_json(self.jmsg_from))
|
||||
|
||||
def test_json_without_optionals(self):
|
||||
for optional in ['certFingerprints', 'certs', 'subjectKeyIdentifiers',
|
||||
'serialNumbers', 'issuers', 'authorizedFor']:
|
||||
@@ -292,7 +328,7 @@ class ProofOfPossessionHintsTest(unittest.TestCase):
|
||||
self.assertEqual(msg.issuers, ())
|
||||
self.assertEqual(msg.authorized_for, ())
|
||||
|
||||
self.assertEqual(self.jmsg_to, msg.to_json())
|
||||
self.assertEqual(self.jmsg_to, msg.to_partial_json())
|
||||
|
||||
|
||||
class ProofOfPossessionTest(unittest.TestCase):
|
||||
@@ -315,19 +351,23 @@ class ProofOfPossessionTest(unittest.TestCase):
|
||||
}
|
||||
self.jmsg_from = {
|
||||
'type': 'proofOfPossession',
|
||||
'alg': jose.RS256.fully_serialize(),
|
||||
'alg': jose.RS256.to_json(),
|
||||
'nonce': 'eET5udtV7aoX8Xl8gYiZIA',
|
||||
'hints': hints.fully_serialize(),
|
||||
'hints': hints.to_json(),
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossession
|
||||
self.assertEqual(
|
||||
self.msg, ProofOfPossession.from_json(self.jmsg_from))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossession
|
||||
hash(ProofOfPossession.from_json(self.jmsg_from))
|
||||
|
||||
|
||||
class ProofOfPossessionResponseTest(unittest.TestCase):
|
||||
|
||||
@@ -357,20 +397,24 @@ class ProofOfPossessionResponseTest(unittest.TestCase):
|
||||
self.jmsg_from = {
|
||||
'type': 'proofOfPossession',
|
||||
'nonce': 'eET5udtV7aoX8Xl8gYiZIA',
|
||||
'signature': signature.fully_serialize(),
|
||||
'signature': signature.to_json(),
|
||||
}
|
||||
|
||||
def test_verify(self):
|
||||
self.assertTrue(self.msg.verify())
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg_to, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossessionResponse
|
||||
self.assertEqual(
|
||||
self.msg, ProofOfPossessionResponse.from_json(self.jmsg_from))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import ProofOfPossessionResponse
|
||||
hash(ProofOfPossessionResponse.from_json(self.jmsg_from))
|
||||
|
||||
|
||||
class DNSTest(unittest.TestCase):
|
||||
|
||||
@@ -379,13 +423,17 @@ class DNSTest(unittest.TestCase):
|
||||
self.msg = DNS(token='17817c66b60ce2e4012dfad92657527a')
|
||||
self.jmsg = {'type': 'dns', 'token': '17817c66b60ce2e4012dfad92657527a'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import DNS
|
||||
self.assertEqual(self.msg, DNS.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import DNS
|
||||
hash(DNS.from_json(self.jmsg))
|
||||
|
||||
|
||||
class DNSResponseTest(unittest.TestCase):
|
||||
|
||||
@@ -394,13 +442,17 @@ class DNSResponseTest(unittest.TestCase):
|
||||
self.msg = DNSResponse()
|
||||
self.jmsg = {'type': 'dns'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jmsg, self.msg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.challenges import DNSResponse
|
||||
self.assertEqual(self.msg, DNSResponse.from_json(self.jmsg))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.challenges import DNSResponse
|
||||
hash(DNSResponse.from_json(self.jmsg))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -36,8 +36,8 @@ class JSONDeSerializable(object):
|
||||
Turning an arbitrary Python object into Python object that can
|
||||
be encoded into a JSON document. **Full serialization** produces
|
||||
a Python object composed of only basic types as required by the
|
||||
:ref:`conversion table <conversion-table>`.
|
||||
**Partial serialization** (acomplished by :meth:`to_json`)
|
||||
:ref:`conversion table <conversion-table>`. **Partial
|
||||
serialization** (acomplished by :meth:`to_partial_json`)
|
||||
produces a Python object that might also be built from other
|
||||
:class:`JSONDeSerializable` objects.
|
||||
|
||||
@@ -71,15 +71,16 @@ class JSONDeSerializable(object):
|
||||
|
||||
Interestingly, ``default`` is required to perform only partial
|
||||
serialization, as :func:`json.dumps` applies ``default``
|
||||
recursively. This is the idea behind making :meth:`to_json` produce
|
||||
only partial serialization, while providing custom :meth:`json_dumps`
|
||||
that dumps with ``default`` set to :meth:`json_dump_default`.
|
||||
recursively. This is the idea behind making :meth:`to_partial_json`
|
||||
produce only partial serialization, while providing custom
|
||||
:meth:`json_dumps` that dumps with ``default`` set to
|
||||
:meth:`json_dump_default`.
|
||||
|
||||
To make further documentation a bit more concrete, please, consider
|
||||
the following imaginatory implementation example::
|
||||
|
||||
class Foo(JSONDeSerializable):
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return 'foo'
|
||||
|
||||
@classmethod
|
||||
@@ -87,7 +88,7 @@ class JSONDeSerializable(object):
|
||||
return Foo()
|
||||
|
||||
class Bar(JSONDeSerializable):
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return [Foo(), Foo()]
|
||||
|
||||
@classmethod
|
||||
@@ -98,16 +99,16 @@ class JSONDeSerializable(object):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractmethod
|
||||
def to_json(self): # pragma: no cover
|
||||
def to_partial_json(self): # pragma: no cover
|
||||
"""Partially serialize.
|
||||
|
||||
Following the example, **partial serialization** means the following::
|
||||
|
||||
assert isinstance(Bar().to_json()[0], Foo)
|
||||
assert isinstance(Bar().to_json()[1], Foo)
|
||||
assert isinstance(Bar().to_partial_json()[0], Foo)
|
||||
assert isinstance(Bar().to_partial_json()[1], Foo)
|
||||
|
||||
# in particular...
|
||||
assert Bar().to_json() != ['foo', 'foo']
|
||||
assert Bar().to_partial_json() != ['foo', 'foo']
|
||||
|
||||
:raises letsencrypt.acme.jose.errors.SerializationError:
|
||||
in case of any serialization error.
|
||||
@@ -116,13 +117,13 @@ class JSONDeSerializable(object):
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def fully_serialize(self):
|
||||
def to_json(self):
|
||||
"""Fully serialize.
|
||||
|
||||
Again, following the example from before, **full serialization**
|
||||
means the following::
|
||||
|
||||
assert Bar().fully_serialize() == ['foo', 'foo']
|
||||
assert Bar().to_json() == ['foo', 'foo']
|
||||
|
||||
:raises letsencrypt.acme.jose.errors.SerializationError:
|
||||
in case of any serialization error.
|
||||
@@ -131,7 +132,7 @@ class JSONDeSerializable(object):
|
||||
"""
|
||||
def _serialize(obj):
|
||||
if isinstance(obj, JSONDeSerializable):
|
||||
return _serialize(obj.to_json())
|
||||
return _serialize(obj.to_partial_json())
|
||||
if isinstance(obj, basestring): # strings are sequence
|
||||
return obj
|
||||
elif isinstance(obj, list):
|
||||
@@ -163,7 +164,7 @@ class JSONDeSerializable(object):
|
||||
|
||||
"""
|
||||
# TypeError: Can't instantiate abstract class <cls> with
|
||||
# abstract methods from_json, to_json
|
||||
# abstract methods from_json, to_partial_json
|
||||
return cls() # pylint: disable=abstract-class-instantiated
|
||||
|
||||
@classmethod
|
||||
@@ -199,6 +200,6 @@ class JSONDeSerializable(object):
|
||||
|
||||
"""
|
||||
if isinstance(python_object, JSONDeSerializable):
|
||||
return python_object.to_json()
|
||||
return python_object.to_partial_json()
|
||||
else: # this branch is necessary, cannot just "return"
|
||||
raise TypeError(repr(python_object) + ' is not JSON serializable')
|
||||
|
||||
@@ -14,7 +14,7 @@ class JSONDeSerializableTest(unittest.TestCase):
|
||||
def __init__(self, v):
|
||||
self.v = v
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return self.v
|
||||
|
||||
@classmethod
|
||||
@@ -26,7 +26,7 @@ class JSONDeSerializableTest(unittest.TestCase):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return [self.x, self.y]
|
||||
|
||||
@classmethod
|
||||
@@ -39,7 +39,7 @@ class JSONDeSerializableTest(unittest.TestCase):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return {self.x: self.y}
|
||||
|
||||
@classmethod
|
||||
@@ -59,21 +59,21 @@ class JSONDeSerializableTest(unittest.TestCase):
|
||||
self.Sequence = Sequence
|
||||
self.Mapping = Mapping
|
||||
|
||||
def test_fully_serialize_sequence(self):
|
||||
self.assertEqual(self.seq.fully_serialize(), ['foo1', 'foo2'])
|
||||
def test_to_json_sequence(self):
|
||||
self.assertEqual(self.seq.to_json(), ['foo1', 'foo2'])
|
||||
|
||||
def test_fully_serialize_mapping(self):
|
||||
self.assertEqual(self.mapping.fully_serialize(), {'foo1': 'foo2'})
|
||||
def test_to_json_mapping(self):
|
||||
self.assertEqual(self.mapping.to_json(), {'foo1': 'foo2'})
|
||||
|
||||
def test_fully_serialize_other(self):
|
||||
def test_to_json_other(self):
|
||||
mock_value = object()
|
||||
self.assertTrue(self.Basic(mock_value).fully_serialize() is mock_value)
|
||||
self.assertTrue(self.Basic(mock_value).to_json() is mock_value)
|
||||
|
||||
def test_fully_serialize_nested(self):
|
||||
self.assertEqual(self.nested.fully_serialize(), [['foo1']])
|
||||
def test_to_json_nested(self):
|
||||
self.assertEqual(self.nested.to_json(), [['foo1']])
|
||||
|
||||
def test_fully_serialize(self):
|
||||
self.assertEqual(self.tuple.fully_serialize(), (('foo', )))
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.tuple.to_json(), (('foo', )))
|
||||
|
||||
def test_from_json_not_implemented(self):
|
||||
from letsencrypt.acme.jose.interfaces import JSONDeSerializable
|
||||
|
||||
@@ -113,7 +113,7 @@ class Field(object):
|
||||
@classmethod
|
||||
def default_encoder(cls, value):
|
||||
"""Default (passthrough) encoder."""
|
||||
# field.to_json() is no good as encoder has to do partial
|
||||
# field.to_partial_json() is no good as encoder has to do partial
|
||||
# serialization only
|
||||
return value
|
||||
|
||||
@@ -189,7 +189,7 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable):
|
||||
raise errors.DeserializationError('No bar suffix!')
|
||||
return value[:-3]
|
||||
|
||||
assert Foo(bar='baz').to_json() == {'Bar': 'bazbar'}
|
||||
assert Foo(bar='baz').to_partial_json() == {'Bar': 'bazbar'}
|
||||
assert Foo.from_json({'Bar': 'bazbar'}) == Foo(bar='baz')
|
||||
assert (Foo.from_json({'Bar': 'bazbar', 'Empty': '!'})
|
||||
== Foo(bar='baz', empty='!'))
|
||||
@@ -209,7 +209,7 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable):
|
||||
super(JSONObjectWithFields, self).__init__(
|
||||
**(dict(self._defaults(), **kwargs)))
|
||||
|
||||
def fields_to_json(self):
|
||||
def fields_to_partial_json(self):
|
||||
"""Serialize fields to JSON."""
|
||||
jobj = {}
|
||||
for slot, field in self._fields.iteritems():
|
||||
@@ -226,8 +226,8 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable):
|
||||
slot, value, error))
|
||||
return jobj
|
||||
|
||||
def to_json(self):
|
||||
return self.fields_to_json()
|
||||
def to_partial_json(self):
|
||||
return self.fields_to_partial_json()
|
||||
|
||||
@classmethod
|
||||
def _check_required(cls, jobj):
|
||||
@@ -246,7 +246,6 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable):
|
||||
"""Deserialize fields from JSON."""
|
||||
cls._check_required(jobj)
|
||||
fields = {}
|
||||
|
||||
for slot, field in cls._fields.iteritems():
|
||||
if field.json_name not in jobj and field.omitempty:
|
||||
fields[slot] = field.default
|
||||
@@ -377,7 +376,7 @@ class TypedJSONObjectWithFields(JSONObjectWithFields):
|
||||
except KeyError:
|
||||
raise errors.UnrecognizedTypeError(typ, jobj)
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
"""Get JSON serializable object.
|
||||
|
||||
:returns: Serializable JSON object representing ACME typed object.
|
||||
@@ -386,7 +385,7 @@ class TypedJSONObjectWithFields(JSONObjectWithFields):
|
||||
:rtype: dict
|
||||
|
||||
"""
|
||||
jobj = self.fields_to_json()
|
||||
jobj = self.fields_to_partial_json()
|
||||
jobj[self.type_field_name] = self.typ
|
||||
return jobj
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class FieldTest(unittest.TestCase):
|
||||
def test_default_encoder_is_partial(self):
|
||||
class MockField(interfaces.JSONDeSerializable):
|
||||
# pylint: disable=missing-docstring
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return 'foo'
|
||||
@classmethod
|
||||
def from_json(cls, jobj):
|
||||
@@ -113,8 +113,8 @@ class JSONObjectWithFieldsTest(unittest.TestCase):
|
||||
def test_init_defaults(self):
|
||||
self.assertEqual(self.mock, self.MockJSONObjectWithFields(y=2, z=3))
|
||||
|
||||
def test_fields_to_json_omits_empty(self):
|
||||
self.assertEqual(self.mock.fields_to_json(), {'y': 2, 'Z': 3})
|
||||
def test_fields_to_partial_json_omits_empty(self):
|
||||
self.assertEqual(self.mock.fields_to_partial_json(), {'y': 2, 'Z': 3})
|
||||
|
||||
def test_fields_from_json_fills_default_for_empty(self):
|
||||
self.assertEqual(
|
||||
@@ -135,9 +135,10 @@ class JSONObjectWithFieldsTest(unittest.TestCase):
|
||||
errors.DeserializationError,
|
||||
self.MockJSONObjectWithFields.fields_from_json, {'x': 0, 'Z': 0})
|
||||
|
||||
def test_fields_to_json_encoder(self):
|
||||
self.assertEqual(self.MockJSONObjectWithFields(x=1, y=2, z=3).to_json(),
|
||||
{'x': 2, 'y': 2, 'Z': 3})
|
||||
def test_fields_to_partial_json_encoder(self):
|
||||
self.assertEqual(
|
||||
self.MockJSONObjectWithFields(x=1, y=2, z=3).to_partial_json(),
|
||||
{'x': 2, 'y': 2, 'Z': 3})
|
||||
|
||||
def test_fields_from_json_decoder(self):
|
||||
self.assertEqual(
|
||||
@@ -145,10 +146,10 @@ class JSONObjectWithFieldsTest(unittest.TestCase):
|
||||
self.MockJSONObjectWithFields.fields_from_json(
|
||||
{'x': 4, 'y': 2, 'Z': 3}))
|
||||
|
||||
def test_fields_to_json_error_passthrough(self):
|
||||
def test_fields_to_partial_json_error_passthrough(self):
|
||||
self.assertRaises(
|
||||
errors.SerializationError, self.MockJSONObjectWithFields(
|
||||
x=1, y=500, z=3).to_json)
|
||||
x=1, y=500, z=3).to_partial_json)
|
||||
|
||||
def test_fields_from_json_error_passthrough(self):
|
||||
self.assertRaises(
|
||||
@@ -262,14 +263,14 @@ class TypedJSONObjectWithFieldsTest(unittest.TestCase):
|
||||
def fields_from_json(cls, jobj):
|
||||
return {'foo': jobj['foo']}
|
||||
|
||||
def fields_to_json(self):
|
||||
def fields_to_partial_json(self):
|
||||
return {'foo': self.foo}
|
||||
|
||||
self.parent_cls = MockParentTypedJSONObjectWithFields
|
||||
self.msg = MockTypedJSONObjectWithFields(foo='bar')
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), {
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), {
|
||||
'type': 'test',
|
||||
'foo': 'bar',
|
||||
})
|
||||
|
||||
@@ -38,7 +38,7 @@ class JWASignature(JWA):
|
||||
cls.SIGNATURES[signature_cls.name] = signature_cls
|
||||
return signature_cls
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -43,9 +43,9 @@ class JWASignatureTest(unittest.TestCase):
|
||||
self.assertEqual('Sig1', repr(self.Sig1))
|
||||
self.assertEqual('Sig2', repr(self.Sig2))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.Sig1.to_json(), 'Sig1')
|
||||
self.assertEqual(self.Sig2.to_json(), 'Sig2')
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.Sig1.to_partial_json(), 'Sig1')
|
||||
self.assertEqual(self.Sig2.to_partial_json(), 'Sig2')
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.jose.jwa import JWASignature
|
||||
|
||||
@@ -41,7 +41,7 @@ class JWKES(JWK): # pragma: no cover
|
||||
"""
|
||||
typ = 'ES'
|
||||
|
||||
def fields_to_json(self):
|
||||
def fields_to_partial_json(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
@@ -62,7 +62,7 @@ class JWKOct(JWK):
|
||||
typ = 'oct'
|
||||
__slots__ = ('key',)
|
||||
|
||||
def fields_to_json(self):
|
||||
def fields_to_partial_json(self):
|
||||
# TODO: An "alg" member SHOULD also be present to identify the
|
||||
# algorithm intended to be used with the key, unless the
|
||||
# application uses another means or convention to determine
|
||||
@@ -129,9 +129,9 @@ class JWKRSA(JWK):
|
||||
return cls(key=util.HashableRSAKey(
|
||||
Crypto.PublicKey.RSA.construct(
|
||||
(cls._decode_param(jobj['n']),
|
||||
cls._decode_param(jobj['e'])))))
|
||||
cls._decode_param(jobj['e'])))))
|
||||
|
||||
def fields_to_json(self):
|
||||
def fields_to_partial_json(self):
|
||||
return {
|
||||
'n': self._encode_param(self.key.n),
|
||||
'e': self._encode_param(self.key.e),
|
||||
|
||||
@@ -23,13 +23,17 @@ class JWKOctTest(unittest.TestCase):
|
||||
self.jwk = JWKOct(key='foo')
|
||||
self.jobj = {'kty': 'oct', 'k': 'foo'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jwk.to_json(), self.jobj)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jwk.to_partial_json(), self.jobj)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.jose.jwk import JWKOct
|
||||
self.assertEqual(self.jwk, JWKOct.from_json(self.jobj))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.jose.jwk import JWKOct
|
||||
hash(JWKOct.from_json(self.jobj))
|
||||
|
||||
def test_load(self):
|
||||
from letsencrypt.acme.jose.jwk import JWKOct
|
||||
self.assertEqual(self.jwk, JWKOct.load('foo'))
|
||||
@@ -78,9 +82,9 @@ class JWKRSATest(unittest.TestCase):
|
||||
def test_public(self):
|
||||
self.assertEqual(self.jwk256, self.jwk256_private.public())
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jwk256.to_json(), self.jwk256json)
|
||||
self.assertEqual(self.jwk512.to_json(), self.jwk512json)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jwk256.to_partial_json(), self.jwk256json)
|
||||
self.assertEqual(self.jwk512.to_partial_json(), self.jwk512json)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.jose.jwk import JWK
|
||||
@@ -88,6 +92,10 @@ class JWKRSATest(unittest.TestCase):
|
||||
# TODO: fix schemata to allow RSA512
|
||||
#self.assertEqual(self.jwk512, JWK.from_json(self.jwk512json))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.jose.jwk import JWK
|
||||
hash(JWK.from_json(self.jwk256json))
|
||||
|
||||
def test_from_json_non_schema_errors(self):
|
||||
# valid against schema, but still failing
|
||||
from letsencrypt.acme.jose.jwk import JWK
|
||||
|
||||
@@ -46,7 +46,7 @@ class Header(json_util.JSONObjectWithFields):
|
||||
Parameter Names (as defined in section 4.1 of the
|
||||
protocol). If you need Public Header Parameter Names (4.2)
|
||||
or Private Header Parameter Names (4.3), you must subclass
|
||||
and override :meth:`from_json` and :meth:`to_json`
|
||||
and override :meth:`from_json` and :meth:`to_partial_json`
|
||||
appropriately.
|
||||
|
||||
.. warning:: This class does not support any extensions through
|
||||
@@ -223,8 +223,8 @@ class Signature(json_util.JSONObjectWithFields):
|
||||
|
||||
return cls(protected=protected, header=header, signature=signature)
|
||||
|
||||
def fields_to_json(self):
|
||||
fields = super(Signature, self).fields_to_json()
|
||||
def fields_to_partial_json(self):
|
||||
fields = super(Signature, self).fields_to_partial_json()
|
||||
if not fields['header'].not_omitted():
|
||||
del fields['header']
|
||||
return fields
|
||||
@@ -294,12 +294,12 @@ class JWS(json_util.JSONObjectWithFields):
|
||||
signature=json_util.decode_b64jose(signature))
|
||||
return cls(payload=json_util.decode_b64jose(payload), signatures=(sig,))
|
||||
|
||||
def to_json(self, flat=True): # pylint: disable=arguments-differ
|
||||
def to_partial_json(self, flat=True): # pylint: disable=arguments-differ
|
||||
assert self.signatures
|
||||
payload = b64.b64encode(self.payload)
|
||||
|
||||
if flat and len(self.signatures) == 1:
|
||||
ret = self.signatures[0].to_json()
|
||||
ret = self.signatures[0].to_partial_json()
|
||||
ret['payload'] = payload
|
||||
return ret
|
||||
else:
|
||||
|
||||
@@ -72,7 +72,7 @@ class HeaderTest(unittest.TestCase):
|
||||
def test_x5c_decoding(self):
|
||||
from letsencrypt.acme.jose.jws import Header
|
||||
header = Header(x5c=(CERT, CERT))
|
||||
jobj = header.to_json()
|
||||
jobj = header.to_partial_json()
|
||||
cert_b64 = base64.b64encode(CERT.as_der())
|
||||
self.assertEqual(jobj, {'x5c': [cert_b64, cert_b64]})
|
||||
self.assertEqual(header, Header.from_json(jobj))
|
||||
@@ -152,14 +152,13 @@ class JWSTest(unittest.TestCase):
|
||||
self.assertRaises(errors.DeserializationError, JWS.from_compact, '.')
|
||||
|
||||
def test_json_omitempty(self):
|
||||
protected_jobj = self.protected.to_json(flat=True)
|
||||
unprotected_jobj = self.unprotected.to_json(flat=True)
|
||||
protected_jobj = self.protected.to_partial_json(flat=True)
|
||||
unprotected_jobj = self.unprotected.to_partial_json(flat=True)
|
||||
|
||||
self.assertTrue('protected' not in unprotected_jobj)
|
||||
self.assertTrue('header' not in protected_jobj)
|
||||
|
||||
unprotected_jobj['header'] = unprotected_jobj[
|
||||
'header'].fully_serialize()
|
||||
unprotected_jobj['header'] = unprotected_jobj['header'].to_json()
|
||||
|
||||
from letsencrypt.acme.jose.jws import JWS
|
||||
self.assertEqual(JWS.from_json(protected_jobj), self.protected)
|
||||
@@ -173,9 +172,9 @@ class JWSTest(unittest.TestCase):
|
||||
'protected': b64.b64encode(self.mixed.signature.protected),
|
||||
}
|
||||
jobj_from = jobj_to.copy()
|
||||
jobj_from['header'] = jobj_from['header'].fully_serialize()
|
||||
jobj_from['header'] = jobj_from['header'].to_json()
|
||||
|
||||
self.assertEqual(self.mixed.to_json(flat=True), jobj_to)
|
||||
self.assertEqual(self.mixed.to_partial_json(flat=True), jobj_to)
|
||||
from letsencrypt.acme.jose.jws import JWS
|
||||
self.assertEqual(self.mixed, JWS.from_json(jobj_from))
|
||||
|
||||
@@ -185,9 +184,9 @@ class JWSTest(unittest.TestCase):
|
||||
'payload': b64.b64encode('foo'),
|
||||
}
|
||||
jobj_from = jobj_to.copy()
|
||||
jobj_from['signatures'] = [jobj_to['signatures'][0].fully_serialize()]
|
||||
jobj_from['signatures'] = [jobj_to['signatures'][0].to_json()]
|
||||
|
||||
self.assertEqual(self.mixed.to_json(flat=False), jobj_to)
|
||||
self.assertEqual(self.mixed.to_partial_json(flat=False), jobj_to)
|
||||
from letsencrypt.acme.jose.jws import JWS
|
||||
self.assertEqual(self.mixed, JWS.from_json(jobj_from))
|
||||
|
||||
@@ -196,6 +195,10 @@ class JWSTest(unittest.TestCase):
|
||||
self.assertRaises(errors.DeserializationError, JWS.from_json,
|
||||
{'signatures': (), 'signature': 'foo'})
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.jose.jws import JWS
|
||||
hash(JWS.from_json(self.mixed.to_json()))
|
||||
|
||||
|
||||
class CLITest(unittest.TestCase):
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from letsencrypt.acme import util
|
||||
|
||||
|
||||
class Message(jose.TypedJSONObjectWithFields):
|
||||
# _fields_to_json | pylint: disable=abstract-method
|
||||
# _fields_to_partial_json | pylint: disable=abstract-method
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""ACME message."""
|
||||
TYPES = {}
|
||||
|
||||
@@ -57,7 +57,7 @@ class _Constant(jose.JSONDeSerializable):
|
||||
self.POSSIBLE_NAMES[name] = self
|
||||
self.name = name
|
||||
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
@@ -136,8 +136,7 @@ class Registration(ResourceBody):
|
||||
|
||||
# on new-reg key server ignores 'key' and populates it based on
|
||||
# JWS.signature.combined.jwk
|
||||
key = jose.Field('key', omitempty=True,
|
||||
decoder=jose.JWK.from_json, encoder=jose.JWK.to_json)
|
||||
key = jose.Field('key', omitempty=True, decoder=jose.JWK.from_json)
|
||||
contact = jose.Field('contact', omitempty=True, default=())
|
||||
recovery_token = jose.Field('recoveryToken', omitempty=True)
|
||||
agreement = jose.Field('agreement', omitempty=True)
|
||||
@@ -180,9 +179,9 @@ class ChallengeBody(ResourceBody):
|
||||
status = jose.Field('status', decoder=Status.from_json)
|
||||
validated = fields.RFC3339Field('validated', omitempty=True)
|
||||
|
||||
def to_json(self):
|
||||
jobj = super(ChallengeBody, self).to_json()
|
||||
jobj.update(self.chall.to_json())
|
||||
def to_partial_json(self):
|
||||
jobj = super(ChallengeBody, self).to_partial_json()
|
||||
jobj.update(self.chall.to_partial_json())
|
||||
return jobj
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -22,9 +22,9 @@ class ErrorTest(unittest.TestCase):
|
||||
def test_typ_prefix(self):
|
||||
self.assertEqual('malformed', self.error.typ)
|
||||
self.assertEqual(
|
||||
'urn:acme:error:malformed', self.error.to_json()['type'])
|
||||
'urn:acme:error:malformed', self.error.to_partial_json()['type'])
|
||||
self.assertEqual(
|
||||
'malformed', self.error.from_json(self.error.to_json()).typ)
|
||||
'malformed', self.error.from_json(self.error.to_partial_json()).typ)
|
||||
|
||||
def test_typ_decoder_missing_prefix(self):
|
||||
from letsencrypt.acme.messages2 import Error
|
||||
@@ -42,6 +42,10 @@ class ErrorTest(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
'The request message was malformed', self.error.description)
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.messages2 import Error
|
||||
hash(Error.from_json(self.error.to_json()))
|
||||
|
||||
|
||||
class ConstantTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.acme.messages2._Constant."""
|
||||
@@ -55,15 +59,18 @@ class ConstantTest(unittest.TestCase):
|
||||
self.const_a = MockConstant('a')
|
||||
self.const_b = MockConstant('b')
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual('a', self.const_a.to_json())
|
||||
self.assertEqual('b', self.const_b.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual('a', self.const_a.to_partial_json())
|
||||
self.assertEqual('b', self.const_b.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
self.assertEqual(self.const_a, self.MockConstant.from_json('a'))
|
||||
self.assertRaises(
|
||||
jose.DeserializationError, self.MockConstant.from_json, 'c')
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
hash(self.MockConstant.from_json('a'))
|
||||
|
||||
def test_repr(self):
|
||||
self.assertEqual('MockConstant(a)', repr(self.const_a))
|
||||
self.assertEqual('MockConstant(b)', repr(self.const_b))
|
||||
@@ -73,44 +80,39 @@ class RegistrationTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.acme.messages2.Registration."""
|
||||
|
||||
def setUp(self):
|
||||
from letsencrypt.acme.messages2 import Registration
|
||||
|
||||
rsa_key = RSA.importKey(pkg_resources.resource_string(
|
||||
'letsencrypt.client.tests', os.path.join(
|
||||
'testdata', 'rsa256_key.pem')))
|
||||
|
||||
jwk_key = jose.jwk.JWKRSA(key=jose.util.HashableRSAKey(
|
||||
rsa_key.publickey()))
|
||||
|
||||
key = jose.jwk.JWKRSA(key=jose.util.HashableRSAKey(
|
||||
RSA.importKey(pkg_resources.resource_string(
|
||||
'letsencrypt.client.tests', os.path.join(
|
||||
'testdata', 'rsa256_key.pem'))).publickey()))
|
||||
contact = ('mailto:letsencrypt-client@letsencrypt.org',)
|
||||
recovery_token = 'XYZ'
|
||||
agreement = 'https://letsencrypt.org/terms'
|
||||
|
||||
from letsencrypt.acme.messages2 import Registration
|
||||
self.reg = Registration(
|
||||
key=jwk_key, contact=contact,
|
||||
recovery_token=recovery_token, agreement=agreement)
|
||||
key=key, contact=contact, recovery_token=recovery_token,
|
||||
agreement=agreement)
|
||||
|
||||
self.json_jwk_key = {
|
||||
'kty': 'RSA',
|
||||
'e': 'AQAB',
|
||||
'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5'
|
||||
'80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q',
|
||||
}
|
||||
|
||||
self.json_reg = {
|
||||
self.jobj_to = {
|
||||
'contact': contact,
|
||||
'recoveryToken': recovery_token,
|
||||
'agreement': agreement,
|
||||
'key': self.json_jwk_key,
|
||||
'key': key,
|
||||
}
|
||||
self.jobj_from = self.jobj_to.copy()
|
||||
self.jobj_from['key'] = key.to_json()
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.reg.to_json(), self.json_reg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jobj_to, self.reg.to_partial_json())
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages2 import Registration
|
||||
self.assertEqual(self.reg, Registration.from_json(self.jobj_from))
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.messages2 import Registration
|
||||
hash(Registration.from_json(self.jobj_from))
|
||||
|
||||
self.assertEqual(Registration.from_json(self.json_reg), self.reg)
|
||||
|
||||
class ChallengeResourceTest(unittest.TestCase):
|
||||
"""Tests for letsencrypt.acme.messages2.ChallengeResource."""
|
||||
@@ -142,15 +144,16 @@ class ChallengeBodyTest(unittest.TestCase):
|
||||
self.jobj_from = self.jobj_to.copy()
|
||||
self.jobj_from['status'] = 'valid'
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.jobj_to, self.challb.to_json())
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.jobj_to, self.challb.to_partial_json())
|
||||
|
||||
def test_fields_from_json(self):
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages2 import ChallengeBody
|
||||
self.assertEqual(self.challb, ChallengeBody.from_json(self.jobj_from))
|
||||
|
||||
def test_getattr_proxy(self):
|
||||
self.assertEqual('foo', self.challb.token)
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.messages2 import ChallengeBody
|
||||
hash(ChallengeBody.from_json(self.jobj_from))
|
||||
|
||||
|
||||
class AuthorizationTest(unittest.TestCase):
|
||||
@@ -179,8 +182,8 @@ class AuthorizationTest(unittest.TestCase):
|
||||
challenges=self.challbs)
|
||||
|
||||
self.jobj_from = {
|
||||
'identifier': identifier.fully_serialize(),
|
||||
'challenges': [challb.fully_serialize() for challb in self.challbs],
|
||||
'identifier': identifier.to_json(),
|
||||
'challenges': [challb.to_json() for challb in self.challbs],
|
||||
'combinations': combinations,
|
||||
}
|
||||
|
||||
@@ -188,6 +191,10 @@ class AuthorizationTest(unittest.TestCase):
|
||||
from letsencrypt.acme.messages2 import Authorization
|
||||
Authorization.from_json(self.jobj_from)
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.messages2 import Authorization
|
||||
hash(Authorization.from_json(self.jobj_from))
|
||||
|
||||
def test_resolved_combinations(self):
|
||||
self.assertEqual(self.authz.resolved_combinations, (
|
||||
(self.challbs[0], self.challbs[2]),
|
||||
@@ -213,8 +220,12 @@ class RevocationTest(unittest.TestCase):
|
||||
self.assertEqual(self.rev_date, Revocation.from_json(self.jobj_date))
|
||||
|
||||
def test_revoke_encoder(self):
|
||||
self.assertEqual(self.jobj_now, self.rev_now.to_json())
|
||||
self.assertEqual(self.jobj_date, self.rev_date.to_json())
|
||||
self.assertEqual(self.jobj_now, self.rev_now.to_partial_json())
|
||||
self.assertEqual(self.jobj_date, self.rev_date.to_partial_json())
|
||||
|
||||
def test_from_json_hashable(self):
|
||||
from letsencrypt.acme.messages2 import Revocation
|
||||
hash(Revocation.from_json(self.rev_now.to_json()))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -86,7 +86,7 @@ class ChallengeTest(unittest.TestCase):
|
||||
'type': 'challenge',
|
||||
'sessionID': 'aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
|
||||
'nonce': '7Nbyb1lI6xPVI3Hg3aKSqQ',
|
||||
'challenges': [chall.fully_serialize() for chall in challs],
|
||||
'challenges': [chall.to_json() for chall in challs],
|
||||
'combinations': [[0, 2], [1, 2]], # TODO array tuples
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ class ChallengeTest(unittest.TestCase):
|
||||
)
|
||||
))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import Challenge
|
||||
@@ -117,7 +117,7 @@ class ChallengeTest(unittest.TestCase):
|
||||
msg = Challenge.from_json(self.jmsg_from)
|
||||
|
||||
self.assertEqual(msg.combinations, ())
|
||||
self.assertEqual(msg.to_json(), self.jmsg_to)
|
||||
self.assertEqual(msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
|
||||
class ChallengeRequestTest(unittest.TestCase):
|
||||
@@ -131,8 +131,8 @@ class ChallengeRequestTest(unittest.TestCase):
|
||||
'identifier': 'example.com',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import ChallengeRequest
|
||||
@@ -155,11 +155,11 @@ class AuthorizationTest(unittest.TestCase):
|
||||
'jwk': jwk,
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
self.jmsg['jwk'] = self.jmsg['jwk'].to_json()
|
||||
self.jmsg['jwk'] = self.jmsg['jwk'].to_partial_json()
|
||||
|
||||
from letsencrypt.acme.messages import Authorization
|
||||
self.assertEqual(Authorization.from_json(self.jmsg), self.msg)
|
||||
@@ -175,7 +175,7 @@ class AuthorizationTest(unittest.TestCase):
|
||||
self.assertTrue(msg.recovery_token is None)
|
||||
self.assertTrue(msg.identifier is None)
|
||||
self.assertTrue(msg.jwk is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class AuthorizationRequestTest(unittest.TestCase):
|
||||
@@ -216,10 +216,9 @@ class AuthorizationRequestTest(unittest.TestCase):
|
||||
'type': 'authorizationRequest',
|
||||
'sessionID': 'aefoGaavieG9Wihuk2aufai3aeZ5EeW4',
|
||||
'nonce': '7Nbyb1lI6xPVI3Hg3aKSqQ',
|
||||
'responses': [None if response is None
|
||||
else response.fully_serialize()
|
||||
'responses': [None if response is None else response.to_json()
|
||||
for response in self.responses],
|
||||
'signature': signature.fully_serialize(),
|
||||
'signature': signature.to_json(),
|
||||
# TODO: schema validation doesn't recognize tuples as
|
||||
# arrays :(
|
||||
'contact': list(self.contact),
|
||||
@@ -237,8 +236,8 @@ class AuthorizationRequestTest(unittest.TestCase):
|
||||
def test_verify(self):
|
||||
self.assertTrue(self.msg.verify('example.com'))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import AuthorizationRequest
|
||||
@@ -253,7 +252,7 @@ class AuthorizationRequestTest(unittest.TestCase):
|
||||
msg = AuthorizationRequest.from_json(self.jmsg_from)
|
||||
|
||||
self.assertEqual(msg.contact, ())
|
||||
self.assertEqual(self.jmsg_to, msg.to_json())
|
||||
self.assertEqual(self.jmsg_to, msg.to_partial_json())
|
||||
|
||||
|
||||
class CertificateTest(unittest.TestCase):
|
||||
@@ -275,8 +274,8 @@ class CertificateTest(unittest.TestCase):
|
||||
# TODO: schema validation array tuples
|
||||
self.jmsg_from['chain'] = list(self.jmsg_from['chain'])
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import Certificate
|
||||
@@ -293,7 +292,7 @@ class CertificateTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual(msg.chain, ())
|
||||
self.assertTrue(msg.refresh is None)
|
||||
self.assertEqual(self.jmsg_to, msg.to_json())
|
||||
self.assertEqual(self.jmsg_to, msg.to_partial_json())
|
||||
|
||||
|
||||
class CertificateRequestTest(unittest.TestCase):
|
||||
@@ -316,8 +315,7 @@ class CertificateRequestTest(unittest.TestCase):
|
||||
'signature': signature,
|
||||
}
|
||||
self.jmsg_from = self.jmsg_to.copy()
|
||||
self.jmsg_from['signature'] = self.jmsg_from[
|
||||
'signature'].fully_serialize()
|
||||
self.jmsg_from['signature'] = self.jmsg_from['signature'].to_json()
|
||||
|
||||
def test_create(self):
|
||||
from letsencrypt.acme.messages import CertificateRequest
|
||||
@@ -328,8 +326,8 @@ class CertificateRequestTest(unittest.TestCase):
|
||||
def test_verify(self):
|
||||
self.assertTrue(self.msg.verify())
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import CertificateRequest
|
||||
@@ -351,8 +349,8 @@ class DeferTest(unittest.TestCase):
|
||||
'message': 'Warming up the HSM',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import Defer
|
||||
@@ -367,7 +365,7 @@ class DeferTest(unittest.TestCase):
|
||||
|
||||
self.assertTrue(msg.interval is None)
|
||||
self.assertTrue(msg.message is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class ErrorTest(unittest.TestCase):
|
||||
@@ -385,8 +383,8 @@ class ErrorTest(unittest.TestCase):
|
||||
'moreInfo': 'https://ca.example.com/documentation/csr-requirements',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import Error
|
||||
@@ -401,7 +399,7 @@ class ErrorTest(unittest.TestCase):
|
||||
|
||||
self.assertTrue(msg.message is None)
|
||||
self.assertTrue(msg.more_info is None)
|
||||
self.assertEqual(self.jmsg, msg.to_json())
|
||||
self.assertEqual(self.jmsg, msg.to_partial_json())
|
||||
|
||||
|
||||
class RevocationTest(unittest.TestCase):
|
||||
@@ -411,8 +409,8 @@ class RevocationTest(unittest.TestCase):
|
||||
self.msg = Revocation()
|
||||
self.jmsg = {'type': 'revocation'}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import Revocation
|
||||
@@ -441,8 +439,7 @@ class RevocationRequestTest(unittest.TestCase):
|
||||
'signature': signature,
|
||||
}
|
||||
self.jmsg_from = self.jmsg_to.copy()
|
||||
self.jmsg_from['signature'] = self.jmsg_from[
|
||||
'signature'].fully_serialize()
|
||||
self.jmsg_from['signature'] = self.jmsg_from['signature'].to_json()
|
||||
|
||||
def test_create(self):
|
||||
from letsencrypt.acme.messages import RevocationRequest
|
||||
@@ -452,8 +449,8 @@ class RevocationRequestTest(unittest.TestCase):
|
||||
def test_verify(self):
|
||||
self.assertTrue(self.msg.verify())
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import RevocationRequest
|
||||
@@ -470,8 +467,8 @@ class StatusRequestTest(unittest.TestCase):
|
||||
'token': u'O7-s9MNq1siZHlgrMzi9_A',
|
||||
}
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.msg.to_json(), self.jmsg)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.msg.to_partial_json(), self.jmsg)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.messages import StatusRequest
|
||||
|
||||
@@ -42,8 +42,8 @@ class SignatureTest(unittest.TestCase):
|
||||
|
||||
self.jsig_from = {
|
||||
'nonce': b64nonce,
|
||||
'alg': self.alg.to_json(),
|
||||
'jwk': self.jwk.to_json(),
|
||||
'alg': self.alg.to_partial_json(),
|
||||
'jwk': self.jwk.to_partial_json(),
|
||||
'sig': b64sig,
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ class SignatureTest(unittest.TestCase):
|
||||
self.assertEqual(signature.jwk, self.jwk)
|
||||
self.assertTrue(signature.verify(self.msg))
|
||||
|
||||
def test_to_json(self):
|
||||
self.assertEqual(self.signature.to_json(), self.jsig_to)
|
||||
def test_to_partial_json(self):
|
||||
self.assertEqual(self.signature.to_partial_json(), self.jsig_to)
|
||||
|
||||
def test_from_json(self):
|
||||
from letsencrypt.acme.other import Signature
|
||||
@@ -88,7 +88,7 @@ class SignatureTest(unittest.TestCase):
|
||||
|
||||
def test_from_json_non_schema_errors(self):
|
||||
from letsencrypt.acme.other import Signature
|
||||
jwk = self.jwk.to_json()
|
||||
jwk = self.jwk.to_partial_json()
|
||||
self.assertRaises(
|
||||
jose.DeserializationError, Signature.from_json, {
|
||||
'alg': 'RS256', 'sig': 'x', 'nonce': '', 'jwk': jwk})
|
||||
|
||||
@@ -88,7 +88,7 @@ class NetworkTest(unittest.TestCase):
|
||||
# pylint: disable=missing-docstring
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def to_json(self):
|
||||
def to_partial_json(self):
|
||||
return self.value
|
||||
@classmethod
|
||||
def from_json(cls, value):
|
||||
@@ -173,7 +173,7 @@ class NetworkTest(unittest.TestCase):
|
||||
|
||||
def test_register(self):
|
||||
self.response.status_code = httplib.CREATED
|
||||
self.response.json.return_value = self.regr.body.fully_serialize()
|
||||
self.response.json.return_value = self.regr.body.to_json()
|
||||
self.response.headers['Location'] = self.regr.uri
|
||||
self.response.links.update({
|
||||
'next': {'url': self.regr.new_authzr_uri},
|
||||
@@ -186,7 +186,7 @@ class NetworkTest(unittest.TestCase):
|
||||
|
||||
# TODO: split here and separate test
|
||||
reg_wrong_key = self.regr.body.update(key=KEY2.public())
|
||||
self.response.json.return_value = reg_wrong_key.fully_serialize()
|
||||
self.response.json.return_value = reg_wrong_key.to_json()
|
||||
self.assertRaises(
|
||||
errors.UnexpectedUpdate, self.net.register, self.contact)
|
||||
|
||||
@@ -198,20 +198,20 @@ class NetworkTest(unittest.TestCase):
|
||||
|
||||
def test_update_registration(self):
|
||||
self.response.headers['Location'] = self.regr.uri
|
||||
self.response.json.return_value = self.regr.body.fully_serialize()
|
||||
self.response.json.return_value = self.regr.body.to_json()
|
||||
self._mock_post_get()
|
||||
self.assertEqual(self.regr, self.net.update_registration(self.regr))
|
||||
|
||||
# TODO: split here and separate test
|
||||
self.response.json.return_value = self.regr.body.update(
|
||||
contact=()).fully_serialize()
|
||||
contact=()).to_json()
|
||||
self.assertRaises(
|
||||
errors.UnexpectedUpdate, self.net.update_registration, self.regr)
|
||||
|
||||
def test_request_challenges(self):
|
||||
self.response.status_code = httplib.CREATED
|
||||
self.response.headers['Location'] = self.authzr.uri
|
||||
self.response.json.return_value = self.authz.fully_serialize()
|
||||
self.response.json.return_value = self.authz.to_json()
|
||||
self.response.links = {
|
||||
'next': {'url': self.authzr.new_cert_uri},
|
||||
}
|
||||
@@ -222,7 +222,7 @@ class NetworkTest(unittest.TestCase):
|
||||
|
||||
# TODO: split here and separate test
|
||||
authz_wrong_key = self.authz.update(key=KEY2.public())
|
||||
self.response.json.return_value = authz_wrong_key.fully_serialize()
|
||||
self.response.json.return_value = authz_wrong_key.to_json()
|
||||
self.assertRaises(
|
||||
errors.UnexpectedUpdate, self.net.request_challenges,
|
||||
self.identifier, self.regr)
|
||||
@@ -242,7 +242,7 @@ class NetworkTest(unittest.TestCase):
|
||||
|
||||
def test_answer_challenge(self):
|
||||
self.response.links['up'] = {'url': self.challr.authzr_uri}
|
||||
self.response.json.return_value = self.challr.body.fully_serialize()
|
||||
self.response.json.return_value = self.challr.body.to_json()
|
||||
|
||||
chall_response = challenges.DNSResponse()
|
||||
|
||||
@@ -302,7 +302,7 @@ class NetworkTest(unittest.TestCase):
|
||||
self.net.retry_after(response=self.response, default=10))
|
||||
|
||||
def test_poll(self):
|
||||
self.response.json.return_value = self.authzr.body.fully_serialize()
|
||||
self.response.json.return_value = self.authzr.body.to_json()
|
||||
self._mock_post_get()
|
||||
self.assertEqual((self.authzr, self.response),
|
||||
self.net.poll(self.authzr))
|
||||
|
||||
Reference in New Issue
Block a user