test_timed.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from datetime import datetime
  2. from datetime import timedelta
  3. from datetime import timezone
  4. from functools import partial
  5. import pytest
  6. from freezegun import freeze_time
  7. from itsdangerous.exc import BadTimeSignature
  8. from itsdangerous.exc import SignatureExpired
  9. from itsdangerous.signer import Signer
  10. from itsdangerous.timed import TimedSerializer
  11. from itsdangerous.timed import TimestampSigner
  12. from .test_serializer import TestSerializer
  13. from .test_signer import TestSigner
  14. class FreezeMixin:
  15. @pytest.fixture()
  16. def ts(self):
  17. return datetime(2011, 6, 24, 0, 9, 5, tzinfo=timezone.utc)
  18. @pytest.fixture(autouse=True)
  19. def freeze(self, ts):
  20. with freeze_time(ts) as ft:
  21. yield ft
  22. class TestTimestampSigner(FreezeMixin, TestSigner):
  23. @pytest.fixture()
  24. def signer_factory(self):
  25. return partial(TimestampSigner, secret_key="secret-key")
  26. def test_max_age(self, signer, ts, freeze):
  27. signed = signer.sign("value")
  28. freeze.tick()
  29. assert signer.unsign(signed, max_age=10) == b"value"
  30. freeze.tick(timedelta(seconds=10))
  31. with pytest.raises(SignatureExpired) as exc_info:
  32. signer.unsign(signed, max_age=10)
  33. assert exc_info.value.date_signed == ts
  34. def test_return_timestamp(self, signer, ts):
  35. signed = signer.sign("value")
  36. assert signer.unsign(signed, return_timestamp=True) == (b"value", ts)
  37. def test_timestamp_missing(self, signer):
  38. other = Signer("secret-key")
  39. signed = other.sign("value")
  40. with pytest.raises(BadTimeSignature) as exc_info:
  41. signer.unsign(signed)
  42. assert "missing" in str(exc_info.value)
  43. assert exc_info.value.date_signed is None
  44. def test_malformed_timestamp(self, signer):
  45. other = Signer("secret-key")
  46. signed = other.sign(b"value.____________")
  47. with pytest.raises(BadTimeSignature) as exc_info:
  48. signer.unsign(signed)
  49. assert "Malformed" in str(exc_info.value)
  50. assert exc_info.value.date_signed is None
  51. def test_malformed_future_timestamp(self, signer):
  52. signed = b"value.TgPVoaGhoQ.AGBfQ6G6cr07byTRt0zAdPljHOY"
  53. with pytest.raises(BadTimeSignature) as exc_info:
  54. signer.unsign(signed)
  55. assert "Malformed" in str(exc_info.value)
  56. assert exc_info.value.date_signed is None
  57. def test_future_age(self, signer):
  58. signed = signer.sign("value")
  59. with freeze_time("1971-05-31"):
  60. with pytest.raises(SignatureExpired) as exc_info:
  61. signer.unsign(signed, max_age=10)
  62. assert isinstance(exc_info.value.date_signed, datetime)
  63. def test_sig_error_date_signed(self, signer):
  64. signed = signer.sign("my string").replace(b"my", b"other", 1)
  65. with pytest.raises(BadTimeSignature) as exc_info:
  66. signer.unsign(signed)
  67. assert isinstance(exc_info.value.date_signed, datetime)
  68. class TestTimedSerializer(FreezeMixin, TestSerializer):
  69. @pytest.fixture()
  70. def serializer_factory(self):
  71. return partial(TimedSerializer, secret_key="secret_key")
  72. def test_max_age(self, serializer, value, ts, freeze):
  73. signed = serializer.dumps(value)
  74. freeze.tick()
  75. assert serializer.loads(signed, max_age=10) == value
  76. freeze.tick(timedelta(seconds=10))
  77. with pytest.raises(SignatureExpired) as exc_info:
  78. serializer.loads(signed, max_age=10)
  79. assert exc_info.value.date_signed == ts
  80. assert serializer.load_payload(exc_info.value.payload) == value
  81. def test_return_payload(self, serializer, value, ts):
  82. signed = serializer.dumps(value)
  83. assert serializer.loads(signed, return_timestamp=True) == (value, ts)