diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-05-06 11:32:25 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-05-06 11:39:05 +0300 |
commit | 4aa5da3a0cd2ffc5c4c8f62d9506b1b9594be0e9 (patch) | |
tree | c789f8780ac20297aa0c1229cb5f44302bb8e452 /contrib/python/itsdangerous/py2/tests/test_itsdangerous | |
parent | 932c96fa924d9afc28d0170c3e63d5e22776613d (diff) | |
download | ydb-4aa5da3a0cd2ffc5c4c8f62d9506b1b9594be0e9.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python/itsdangerous/py2/tests/test_itsdangerous')
8 files changed, 561 insertions, 0 deletions
diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/__init__.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/__init__.py diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_compat.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_compat.py new file mode 100644 index 0000000000..2043fadf5a --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_compat.py @@ -0,0 +1,11 @@ +import pytest + +from itsdangerous._compat import _constant_time_compare + + +@pytest.mark.parametrize( + ("a", "b", "expect"), + ((b"a", b"a", True), (b"a", b"b", False), (b"a", b"aa", False)), +) +def test_python_constant_time_compare(a, b, expect): + assert _constant_time_compare(a, b) == expect diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_encoding.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_encoding.py new file mode 100644 index 0000000000..d60ec173d0 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_encoding.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +import pytest + +from itsdangerous.encoding import base64_decode +from itsdangerous.encoding import base64_encode +from itsdangerous.encoding import bytes_to_int +from itsdangerous.encoding import int_to_bytes +from itsdangerous.encoding import want_bytes +from itsdangerous.exc import BadData + + +@pytest.mark.parametrize("value", (u"mañana", b"tomorrow")) +def test_want_bytes(value): + out = want_bytes(value) + assert isinstance(out, bytes) + + +@pytest.mark.parametrize("value", (u"無限", b"infinite")) +def test_base64(value): + enc = base64_encode(value) + assert isinstance(enc, bytes) + dec = base64_decode(enc) + assert dec == want_bytes(value) + + +def test_base64_bad(): + with pytest.raises(BadData): + base64_decode("12345") + + +@pytest.mark.parametrize( + ("value", "expect"), ((0, b""), (192, b"\xc0"), (18446744073709551615, b"\xff" * 8)) +) +def test_int_bytes(value, expect): + enc = int_to_bytes(value) + assert enc == expect + dec = bytes_to_int(enc) + assert dec == value diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_jws.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_jws.py new file mode 100644 index 0000000000..87529485eb --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_jws.py @@ -0,0 +1,125 @@ +from datetime import timedelta +from functools import partial + +import pytest +from .test_serializer import TestSerializer +from .test_timed import TestTimedSerializer + +from itsdangerous.exc import BadData +from itsdangerous.exc import BadHeader +from itsdangerous.exc import BadPayload +from itsdangerous.exc import BadSignature +from itsdangerous.exc import SignatureExpired +from itsdangerous.jws import JSONWebSignatureSerializer +from itsdangerous.jws import TimedJSONWebSignatureSerializer + + +class TestJWSSerializer(TestSerializer): + @pytest.fixture() + def serializer_factory(self): + return partial(JSONWebSignatureSerializer, secret_key="secret-key") + + test_signer_cls = None + test_signer_kwargs = None + test_fallback_signers = None + test_iter_unsigners = None + + @pytest.mark.parametrize("algorithm_name", ("HS256", "HS384", "HS512", "none")) + def test_algorithm(self, serializer_factory, algorithm_name): + serializer = serializer_factory(algorithm_name=algorithm_name) + assert serializer.loads(serializer.dumps("value")) == "value" + + def test_invalid_algorithm(self, serializer_factory): + with pytest.raises(NotImplementedError) as exc_info: + serializer_factory(algorithm_name="invalid") + + assert "not supported" in str(exc_info.value) + + def test_algorithm_mismatch(self, serializer_factory, serializer): + other = serializer_factory(algorithm_name="HS256") + other.algorithm = serializer.algorithm + signed = other.dumps("value") + + with pytest.raises(BadHeader) as exc_info: + serializer.loads(signed) + + assert "mismatch" in str(exc_info.value) + + @pytest.mark.parametrize( + ("value", "exc_cls", "match"), + ( + ("ab", BadPayload, '"."'), + ("a.b", BadHeader, "base64 decode"), + ("ew.b", BadPayload, "base64 decode"), + ("ew.ab", BadData, "malformed"), + ("W10.ab", BadHeader, "JSON object"), + ), + ) + def test_load_payload_exceptions(self, serializer, value, exc_cls, match): + signer = serializer.make_signer() + signed = signer.sign(value) + + with pytest.raises(exc_cls) as exc_info: + serializer.loads(signed) + + assert match in str(exc_info.value) + + +class TestTimedJWSSerializer(TestJWSSerializer, TestTimedSerializer): + @pytest.fixture() + def serializer_factory(self): + return partial( + TimedJSONWebSignatureSerializer, secret_key="secret-key", expires_in=10 + ) + + def test_default_expires_in(self, serializer_factory): + serializer = serializer_factory(expires_in=None) + assert serializer.expires_in == serializer.DEFAULT_EXPIRES_IN + + test_max_age = None + + def test_exp(self, serializer, value, ts, freeze): + signed = serializer.dumps(value) + freeze.tick() + assert serializer.loads(signed) == value + freeze.tick(timedelta(seconds=10)) + + with pytest.raises(SignatureExpired) as exc_info: + serializer.loads(signed) + + assert exc_info.value.date_signed == ts + assert exc_info.value.payload == value + + test_return_payload = None + + def test_return_header(self, serializer, value, ts): + signed = serializer.dumps(value) + payload, header = serializer.loads(signed, return_header=True) + date_signed = serializer.get_issue_date(header) + assert (payload, date_signed) == (value, ts) + + def test_missing_exp(self, serializer): + header = serializer.make_header(None) + del header["exp"] + signer = serializer.make_signer() + signed = signer.sign(serializer.dump_payload(header, "value")) + + with pytest.raises(BadSignature): + serializer.loads(signed) + + @pytest.mark.parametrize("exp", ("invalid", -1)) + def test_invalid_exp(self, serializer, exp): + header = serializer.make_header(None) + header["exp"] = exp + signer = serializer.make_signer() + signed = signer.sign(serializer.dump_payload(header, "value")) + + with pytest.raises(BadHeader) as exc_info: + serializer.loads(signed) + + assert "IntDate" in str(exc_info.value) + + def test_invalid_iat(self, serializer): + header = serializer.make_header(None) + header["iat"] = "invalid" + assert serializer.get_issue_date(header) is None diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_serializer.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_serializer.py new file mode 100644 index 0000000000..e783c20c00 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_serializer.py @@ -0,0 +1,178 @@ +import hashlib +import pickle +from functools import partial +from io import BytesIO +from io import StringIO + +import pytest + +from itsdangerous import Signer +from itsdangerous.exc import BadPayload +from itsdangerous.exc import BadSignature +from itsdangerous.serializer import Serializer + + +def coerce_str(ref, s): + if not isinstance(s, type(ref)): + return s.encode("utf8") + + return s + + +class TestSerializer(object): + @pytest.fixture(params=(Serializer, partial(Serializer, serializer=pickle))) + def serializer_factory(self, request): + return partial(request.param, secret_key="secret_key") + + @pytest.fixture() + def serializer(self, serializer_factory): + return serializer_factory() + + @pytest.fixture() + def value(self): + return {"id": 42} + + @pytest.mark.parametrize( + "value", (None, True, "str", u"text", [1, 2, 3], {"id": 42}) + ) + def test_serializer(self, serializer, value): + assert serializer.loads(serializer.dumps(value)) == value + + @pytest.mark.parametrize( + "transform", + ( + lambda s: s.upper(), + lambda s: s + coerce_str(s, "a"), + lambda s: coerce_str(s, "a") + s[1:], + lambda s: s.replace(coerce_str(s, "."), coerce_str(s, "")), + ), + ) + def test_changed_value(self, serializer, value, transform): + signed = serializer.dumps(value) + assert serializer.loads(signed) == value + changed = transform(signed) + + with pytest.raises(BadSignature): + serializer.loads(changed) + + def test_bad_signature_exception(self, serializer, value): + bad_signed = serializer.dumps(value)[:-1] + + with pytest.raises(BadSignature) as exc_info: + serializer.loads(bad_signed) + + assert serializer.load_payload(exc_info.value.payload) == value + + def test_bad_payload_exception(self, serializer, value): + original = serializer.dumps(value) + payload = original.rsplit(coerce_str(original, "."), 1)[0] + bad = serializer.make_signer().sign(payload[:-1]) + + with pytest.raises(BadPayload) as exc_info: + serializer.loads(bad) + + assert exc_info.value.original_error is not None + + def test_loads_unsafe(self, serializer, value): + signed = serializer.dumps(value) + assert serializer.loads_unsafe(signed) == (True, value) + + bad_signed = signed[:-1] + assert serializer.loads_unsafe(bad_signed) == (False, value) + + payload = signed.rsplit(coerce_str(signed, "."), 1)[0] + bad_payload = serializer.make_signer().sign(payload[:-1])[:-1] + assert serializer.loads_unsafe(bad_payload) == (False, None) + + class BadUnsign(serializer.signer): + def unsign(self, signed_value, *args, **kwargs): + try: + return super(BadUnsign, self).unsign(signed_value, *args, **kwargs) + except BadSignature as e: + e.payload = None + raise + + serializer.signer = BadUnsign + assert serializer.loads_unsafe(bad_signed) == (False, None) + + def test_file(self, serializer, value): + f = BytesIO() if isinstance(serializer.dumps(value), bytes) else StringIO() + serializer.dump(value, f) + f.seek(0) + assert serializer.load(f) == value + f.seek(0) + assert serializer.load_unsafe(f) == (True, value) + + def test_alt_salt(self, serializer, value): + signed = serializer.dumps(value, salt="other") + + with pytest.raises(BadSignature): + serializer.loads(signed) + + assert serializer.loads(signed, salt="other") == value + + def test_signer_cls(self, serializer_factory, serializer, value): + class Other(serializer.signer): + default_key_derivation = "hmac" + + other = serializer_factory(signer=Other) + assert other.loads(other.dumps(value)) == value + assert other.dumps(value) != serializer.dumps(value) + + def test_signer_kwargs(self, serializer_factory, serializer, value): + other = serializer_factory(signer_kwargs={"key_derivation": "hmac"}) + assert other.loads(other.dumps(value)) == value + assert other.dumps("value") != serializer.dumps("value") + + def test_serializer_kwargs(self, serializer_factory): + serializer = serializer_factory(serializer_kwargs={"skipkeys": True}) + + try: + serializer.serializer.dumps(None, skipkeys=True) + except TypeError: + return + + assert serializer.loads(serializer.dumps({(): 1})) == {} + + def test_fallback_signers(self, serializer_factory, value): + serializer = serializer_factory(signer_kwargs={"digest_method": hashlib.sha256}) + signed = serializer.dumps(value) + + fallback_serializer = serializer_factory( + signer_kwargs={"digest_method": hashlib.sha1}, + fallback_signers=[{"digest_method": hashlib.sha256}], + ) + + assert fallback_serializer.loads(signed) == value + + def test_iter_unsigners(self, serializer, serializer_factory): + class Signer256(serializer.signer): + default_digest_method = hashlib.sha256 + + serializer = serializer_factory( + secret_key="secret_key", + fallback_signers=[ + {"digest_method": hashlib.sha256}, + (Signer, {"digest_method": hashlib.sha256}), + Signer256, + ], + ) + + unsigners = serializer.iter_unsigners() + assert next(unsigners).digest_method == hashlib.sha1 + + for signer in unsigners: + assert signer.digest_method == hashlib.sha256 + + +def test_digests(): + factory = partial(Serializer, secret_key="dev key", salt="dev salt") + default_value = factory(signer_kwargs={}).dumps([42]) + sha1_value = factory(signer_kwargs={"digest_method": hashlib.sha1}).dumps([42]) + sha512_value = factory(signer_kwargs={"digest_method": hashlib.sha512}).dumps([42]) + assert default_value == sha1_value + assert sha1_value == "[42].-9cNi0CxsSB3hZPNCe9a2eEs1ZM" + assert sha512_value == ( + "[42].MKCz_0nXQqv7wKpfHZcRtJRmpT2T5uvs9YQsJEhJimqxc" + "9bCLxG31QzS5uC8OVBI1i6jyOLAFNoKaF5ckO9L5Q" + ) diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_signer.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_signer.py new file mode 100644 index 0000000000..5f7fe8e159 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_signer.py @@ -0,0 +1,99 @@ +import hashlib +from functools import partial + +import pytest + +from itsdangerous.exc import BadSignature +from itsdangerous.signer import HMACAlgorithm +from itsdangerous.signer import NoneAlgorithm +from itsdangerous.signer import Signer +from itsdangerous.signer import SigningAlgorithm + + +class _ReverseAlgorithm(SigningAlgorithm): + def get_signature(self, key, value): + return (key + value)[::-1] + + +class TestSigner(object): + @pytest.fixture() + def signer_factory(self): + return partial(Signer, secret_key="secret-key") + + @pytest.fixture() + def signer(self, signer_factory): + return signer_factory() + + def test_signer(self, signer): + signed = signer.sign("my string") + assert isinstance(signed, bytes) + assert signer.validate(signed) + out = signer.unsign(signed) + assert out == b"my string" + + def test_no_separator(self, signer): + signed = signer.sign("my string") + signed = signed.replace(signer.sep, b"*", 1) + assert not signer.validate(signed) + + with pytest.raises(BadSignature): + signer.unsign(signed) + + def test_broken_signature(self, signer): + signed = signer.sign("b") + bad_signed = signed[:-1] + bad_sig = bad_signed.rsplit(b".", 1)[1] + assert not signer.verify_signature(b"b", bad_sig) + + with pytest.raises(BadSignature) as exc_info: + signer.unsign(bad_signed) + + assert exc_info.value.payload == b"b" + + def test_changed_value(self, signer): + signed = signer.sign("my string") + signed = signed.replace(b"my", b"other", 1) + assert not signer.validate(signed) + + with pytest.raises(BadSignature): + signer.unsign(signed) + + def test_invalid_separator(self, signer_factory): + with pytest.raises(ValueError) as exc_info: + signer_factory(sep="-") + + assert "separator cannot be used" in str(exc_info.value) + + @pytest.mark.parametrize( + "key_derivation", ("concat", "django-concat", "hmac", "none") + ) + def test_key_derivation(self, signer_factory, key_derivation): + signer = signer_factory(key_derivation=key_derivation) + assert signer.unsign(signer.sign("value")) == b"value" + + def test_invalid_key_derivation(self, signer_factory): + signer = signer_factory(key_derivation="invalid") + + with pytest.raises(TypeError): + signer.derive_key() + + def test_digest_method(self, signer_factory): + signer = signer_factory(digest_method=hashlib.md5) + assert signer.unsign(signer.sign("value")) == b"value" + + @pytest.mark.parametrize( + "algorithm", (None, NoneAlgorithm(), HMACAlgorithm(), _ReverseAlgorithm()) + ) + def test_algorithm(self, signer_factory, algorithm): + signer = signer_factory(algorithm=algorithm) + assert signer.unsign(signer.sign("value")) == b"value" + + if algorithm is None: + assert signer.algorithm.digest_method == signer.digest_method + + +def test_abstract_algorithm(): + alg = SigningAlgorithm() + + with pytest.raises(NotImplementedError): + alg.get_signature("a", "b") diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_timed.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_timed.py new file mode 100644 index 0000000000..3783fd4ce4 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_timed.py @@ -0,0 +1,86 @@ +from datetime import datetime +from datetime import timedelta +from functools import partial + +import pytest +from freezegun import freeze_time +from .test_serializer import TestSerializer +from .test_signer import TestSigner + +from itsdangerous import Signer +from itsdangerous.exc import BadTimeSignature +from itsdangerous.exc import SignatureExpired +from itsdangerous.timed import TimedSerializer +from itsdangerous.timed import TimestampSigner + + +class FreezeMixin(object): + @pytest.fixture() + def ts(self): + return datetime(2011, 6, 24, 0, 9, 5) + + @pytest.fixture(autouse=True) + def freeze(self, ts): + with freeze_time(ts) as ft: + yield ft + + +class TestTimestampSigner(FreezeMixin, TestSigner): + @pytest.fixture() + def signer_factory(self): + return partial(TimestampSigner, secret_key="secret-key") + + def test_max_age(self, signer, ts, freeze): + signed = signer.sign("value") + freeze.tick() + assert signer.unsign(signed, max_age=10) == b"value" + freeze.tick(timedelta(seconds=10)) + + with pytest.raises(SignatureExpired) as exc_info: + signer.unsign(signed, max_age=10) + + assert exc_info.value.date_signed == ts + + def test_return_timestamp(self, signer, ts): + signed = signer.sign("value") + assert signer.unsign(signed, return_timestamp=True) == (b"value", ts) + + def test_timestamp_missing(self, signer): + other = Signer("secret-key") + signed = other.sign("value") + + with pytest.raises(BadTimeSignature) as exc_info: + signer.unsign(signed) + + assert "missing" in str(exc_info.value) + + def test_malformed_timestamp(self, signer): + other = Signer("secret-key") + signed = other.sign(b"value.____________") + + with pytest.raises(BadTimeSignature) as exc_info: + signer.unsign(signed) + + assert "Malformed" in str(exc_info.value) + + +class TestTimedSerializer(FreezeMixin, TestSerializer): + @pytest.fixture() + def serializer_factory(self): + return partial(TimedSerializer, secret_key="secret_key") + + def test_max_age(self, serializer, value, ts, freeze): + signed = serializer.dumps(value) + freeze.tick() + assert serializer.loads(signed, max_age=10) == value + freeze.tick(timedelta(seconds=10)) + + with pytest.raises(SignatureExpired) as exc_info: + serializer.loads(signed, max_age=10) + + assert exc_info.value.date_signed == ts + assert serializer.load_payload(exc_info.value.payload) == value + + def test_return_payload(self, serializer, value, ts): + signed = serializer.dumps(value) + assert serializer.loads(signed, return_timestamp=True) == (value, ts) diff --git a/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_url_safe.py b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_url_safe.py new file mode 100644 index 0000000000..76941201e4 --- /dev/null +++ b/contrib/python/itsdangerous/py2/tests/test_itsdangerous/test_url_safe.py @@ -0,0 +1,24 @@ +from functools import partial + +import pytest +from .test_serializer import TestSerializer +from .test_timed import TestTimedSerializer + +from itsdangerous import URLSafeSerializer +from itsdangerous import URLSafeTimedSerializer + + +class TestURLSafeSerializer(TestSerializer): + @pytest.fixture() + def serializer_factory(self): + return partial(URLSafeSerializer, secret_key="secret-key") + + @pytest.fixture(params=({"id": 42}, pytest.param("a" * 1000, id="zlib"))) + def value(self, request): + return request.param + + +class TestURLSafeTimedSerializer(TestURLSafeSerializer, TestTimedSerializer): + @pytest.fixture() + def serializer_factory(self): + return partial(URLSafeTimedSerializer, secret_key="secret-key") |