eventsourcing 9.3.2__py3-none-any.whl → 9.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of eventsourcing might be problematic. Click here for more details.

Files changed (129) hide show
  1. eventsourcing/postgres.py +2 -1
  2. eventsourcing/system.py +3 -1
  3. {eventsourcing-9.3.2.dist-info → eventsourcing-9.3.4.dist-info}/METADATA +3 -8
  4. eventsourcing-9.3.4.dist-info/RECORD +24 -0
  5. eventsourcing/examples/__init__.py +0 -0
  6. eventsourcing/examples/aggregate1/__init__.py +0 -0
  7. eventsourcing/examples/aggregate1/application.py +0 -27
  8. eventsourcing/examples/aggregate1/domainmodel.py +0 -16
  9. eventsourcing/examples/aggregate1/test_application.py +0 -37
  10. eventsourcing/examples/aggregate2/__init__.py +0 -0
  11. eventsourcing/examples/aggregate2/application.py +0 -27
  12. eventsourcing/examples/aggregate2/domainmodel.py +0 -22
  13. eventsourcing/examples/aggregate2/test_application.py +0 -37
  14. eventsourcing/examples/aggregate3/__init__.py +0 -0
  15. eventsourcing/examples/aggregate3/application.py +0 -27
  16. eventsourcing/examples/aggregate3/domainmodel.py +0 -38
  17. eventsourcing/examples/aggregate3/test_application.py +0 -37
  18. eventsourcing/examples/aggregate4/__init__.py +0 -0
  19. eventsourcing/examples/aggregate4/application.py +0 -27
  20. eventsourcing/examples/aggregate4/domainmodel.py +0 -114
  21. eventsourcing/examples/aggregate4/test_application.py +0 -38
  22. eventsourcing/examples/aggregate5/__init__.py +0 -0
  23. eventsourcing/examples/aggregate5/application.py +0 -27
  24. eventsourcing/examples/aggregate5/domainmodel.py +0 -131
  25. eventsourcing/examples/aggregate5/test_application.py +0 -38
  26. eventsourcing/examples/aggregate6/__init__.py +0 -0
  27. eventsourcing/examples/aggregate6/application.py +0 -30
  28. eventsourcing/examples/aggregate6/domainmodel.py +0 -123
  29. eventsourcing/examples/aggregate6/test_application.py +0 -38
  30. eventsourcing/examples/aggregate6a/__init__.py +0 -0
  31. eventsourcing/examples/aggregate6a/application.py +0 -40
  32. eventsourcing/examples/aggregate6a/domainmodel.py +0 -149
  33. eventsourcing/examples/aggregate6a/test_application.py +0 -45
  34. eventsourcing/examples/aggregate7/__init__.py +0 -0
  35. eventsourcing/examples/aggregate7/application.py +0 -48
  36. eventsourcing/examples/aggregate7/domainmodel.py +0 -144
  37. eventsourcing/examples/aggregate7/persistence.py +0 -57
  38. eventsourcing/examples/aggregate7/test_application.py +0 -38
  39. eventsourcing/examples/aggregate7/test_compression_and_encryption.py +0 -45
  40. eventsourcing/examples/aggregate7/test_snapshotting_intervals.py +0 -67
  41. eventsourcing/examples/aggregate7a/__init__.py +0 -0
  42. eventsourcing/examples/aggregate7a/application.py +0 -56
  43. eventsourcing/examples/aggregate7a/domainmodel.py +0 -170
  44. eventsourcing/examples/aggregate7a/test_application.py +0 -46
  45. eventsourcing/examples/aggregate7a/test_compression_and_encryption.py +0 -45
  46. eventsourcing/examples/aggregate8/__init__.py +0 -0
  47. eventsourcing/examples/aggregate8/application.py +0 -47
  48. eventsourcing/examples/aggregate8/domainmodel.py +0 -65
  49. eventsourcing/examples/aggregate8/persistence.py +0 -57
  50. eventsourcing/examples/aggregate8/test_application.py +0 -37
  51. eventsourcing/examples/aggregate8/test_compression_and_encryption.py +0 -44
  52. eventsourcing/examples/aggregate8/test_snapshotting_intervals.py +0 -38
  53. eventsourcing/examples/bankaccounts/__init__.py +0 -0
  54. eventsourcing/examples/bankaccounts/application.py +0 -70
  55. eventsourcing/examples/bankaccounts/domainmodel.py +0 -56
  56. eventsourcing/examples/bankaccounts/test.py +0 -173
  57. eventsourcing/examples/cargoshipping/__init__.py +0 -0
  58. eventsourcing/examples/cargoshipping/application.py +0 -126
  59. eventsourcing/examples/cargoshipping/domainmodel.py +0 -330
  60. eventsourcing/examples/cargoshipping/interface.py +0 -143
  61. eventsourcing/examples/cargoshipping/test.py +0 -231
  62. eventsourcing/examples/contentmanagement/__init__.py +0 -0
  63. eventsourcing/examples/contentmanagement/application.py +0 -118
  64. eventsourcing/examples/contentmanagement/domainmodel.py +0 -69
  65. eventsourcing/examples/contentmanagement/test.py +0 -180
  66. eventsourcing/examples/contentmanagement/utils.py +0 -26
  67. eventsourcing/examples/contentmanagementsystem/__init__.py +0 -0
  68. eventsourcing/examples/contentmanagementsystem/application.py +0 -54
  69. eventsourcing/examples/contentmanagementsystem/postgres.py +0 -17
  70. eventsourcing/examples/contentmanagementsystem/sqlite.py +0 -17
  71. eventsourcing/examples/contentmanagementsystem/system.py +0 -14
  72. eventsourcing/examples/contentmanagementsystem/test_system.py +0 -180
  73. eventsourcing/examples/searchablecontent/__init__.py +0 -0
  74. eventsourcing/examples/searchablecontent/application.py +0 -45
  75. eventsourcing/examples/searchablecontent/persistence.py +0 -23
  76. eventsourcing/examples/searchablecontent/postgres.py +0 -118
  77. eventsourcing/examples/searchablecontent/sqlite.py +0 -136
  78. eventsourcing/examples/searchablecontent/test_application.py +0 -110
  79. eventsourcing/examples/searchablecontent/test_recorder.py +0 -68
  80. eventsourcing/examples/searchabletimestamps/__init__.py +0 -0
  81. eventsourcing/examples/searchabletimestamps/application.py +0 -32
  82. eventsourcing/examples/searchabletimestamps/persistence.py +0 -20
  83. eventsourcing/examples/searchabletimestamps/postgres.py +0 -110
  84. eventsourcing/examples/searchabletimestamps/sqlite.py +0 -99
  85. eventsourcing/examples/searchabletimestamps/test_searchabletimestamps.py +0 -94
  86. eventsourcing/examples/test_invoice.py +0 -176
  87. eventsourcing/examples/test_parking_lot.py +0 -206
  88. eventsourcing/tests/application_tests/__init__.py +0 -0
  89. eventsourcing/tests/application_tests/test_application_with_automatic_snapshotting.py +0 -55
  90. eventsourcing/tests/application_tests/test_application_with_popo.py +0 -22
  91. eventsourcing/tests/application_tests/test_application_with_postgres.py +0 -75
  92. eventsourcing/tests/application_tests/test_application_with_sqlite.py +0 -72
  93. eventsourcing/tests/application_tests/test_cache.py +0 -134
  94. eventsourcing/tests/application_tests/test_event_sourced_log.py +0 -162
  95. eventsourcing/tests/application_tests/test_notificationlog.py +0 -232
  96. eventsourcing/tests/application_tests/test_notificationlogreader.py +0 -126
  97. eventsourcing/tests/application_tests/test_processapplication.py +0 -110
  98. eventsourcing/tests/application_tests/test_processingpolicy.py +0 -109
  99. eventsourcing/tests/application_tests/test_repository.py +0 -504
  100. eventsourcing/tests/application_tests/test_snapshotting.py +0 -68
  101. eventsourcing/tests/application_tests/test_upcasting.py +0 -459
  102. eventsourcing/tests/docs_tests/__init__.py +0 -0
  103. eventsourcing/tests/docs_tests/test_docs.py +0 -293
  104. eventsourcing/tests/domain_tests/__init__.py +0 -0
  105. eventsourcing/tests/domain_tests/test_aggregate.py +0 -1200
  106. eventsourcing/tests/domain_tests/test_aggregate_decorators.py +0 -1604
  107. eventsourcing/tests/domain_tests/test_domainevent.py +0 -80
  108. eventsourcing/tests/interface_tests/__init__.py +0 -0
  109. eventsourcing/tests/interface_tests/test_remotenotificationlog.py +0 -258
  110. eventsourcing/tests/persistence_tests/__init__.py +0 -0
  111. eventsourcing/tests/persistence_tests/test_aes.py +0 -93
  112. eventsourcing/tests/persistence_tests/test_connection_pool.py +0 -722
  113. eventsourcing/tests/persistence_tests/test_eventstore.py +0 -72
  114. eventsourcing/tests/persistence_tests/test_infrastructure_factory.py +0 -21
  115. eventsourcing/tests/persistence_tests/test_mapper.py +0 -113
  116. eventsourcing/tests/persistence_tests/test_noninterleaving_notification_ids.py +0 -69
  117. eventsourcing/tests/persistence_tests/test_popo.py +0 -124
  118. eventsourcing/tests/persistence_tests/test_postgres.py +0 -1119
  119. eventsourcing/tests/persistence_tests/test_sqlite.py +0 -348
  120. eventsourcing/tests/persistence_tests/test_transcoder.py +0 -44
  121. eventsourcing/tests/system_tests/__init__.py +0 -0
  122. eventsourcing/tests/system_tests/test_runner.py +0 -935
  123. eventsourcing/tests/system_tests/test_system.py +0 -284
  124. eventsourcing/tests/utils_tests/__init__.py +0 -0
  125. eventsourcing/tests/utils_tests/test_utils.py +0 -226
  126. eventsourcing-9.3.2.dist-info/RECORD +0 -145
  127. {eventsourcing-9.3.2.dist-info → eventsourcing-9.3.4.dist-info}/AUTHORS +0 -0
  128. {eventsourcing-9.3.2.dist-info → eventsourcing-9.3.4.dist-info}/LICENSE +0 -0
  129. {eventsourcing-9.3.2.dist-info → eventsourcing-9.3.4.dist-info}/WHEEL +0 -0
@@ -1,80 +0,0 @@
1
- from dataclasses import _DataclassParams
2
- from datetime import datetime, timezone
3
- from time import sleep
4
- from unittest.case import TestCase
5
- from uuid import UUID, uuid4
6
-
7
- from eventsourcing.domain import DomainEvent, MetaDomainEvent
8
-
9
-
10
- class TestMetaDomainEvent(TestCase):
11
- def test_class_instance_defined_as_frozen_dataclass(self):
12
- class A(metaclass=MetaDomainEvent):
13
- pass
14
-
15
- self.assertIsInstance(A, type)
16
- self.assertTrue("__dataclass_params__" in A.__dict__)
17
- self.assertIsInstance(A.__dataclass_params__, _DataclassParams)
18
- self.assertTrue(A.__dataclass_params__.frozen)
19
-
20
-
21
- class TestDomainEvent(TestCase):
22
- def test_domain_event_class_is_a_meta_domain_event(self):
23
- self.assertIsInstance(DomainEvent, MetaDomainEvent)
24
-
25
- def test_create_timestamp(self):
26
- before = datetime.now(tz=timezone.utc)
27
- sleep(1e-5)
28
- timestamp = DomainEvent.create_timestamp()
29
- sleep(1e-5)
30
- after = datetime.now(tz=timezone.utc)
31
- self.assertGreater(timestamp, before)
32
- self.assertGreater(after, timestamp)
33
-
34
- def test_domain_event_instance(self):
35
- originator_id = uuid4()
36
- originator_version = 101
37
- timestamp = DomainEvent.create_timestamp()
38
- a = DomainEvent(
39
- originator_id=originator_id,
40
- originator_version=originator_version,
41
- timestamp=timestamp,
42
- )
43
- self.assertEqual(a.originator_id, originator_id)
44
- self.assertEqual(a.originator_version, originator_version)
45
- self.assertEqual(a.timestamp, timestamp)
46
-
47
- def test_examples(self):
48
- # Define an 'account opened' domain event.
49
- class AccountOpened(DomainEvent):
50
- full_name: str
51
-
52
- # Create an 'account opened' event.
53
- event3 = AccountOpened(
54
- originator_id=uuid4(),
55
- originator_version=0,
56
- timestamp=AccountOpened.create_timestamp(),
57
- full_name="Alice",
58
- )
59
-
60
- self.assertEqual(event3.full_name, "Alice")
61
- assert isinstance(event3.originator_id, UUID)
62
- self.assertEqual(event3.originator_version, 0)
63
-
64
- # Define a 'full name updated' domain event.
65
- class FullNameUpdated(DomainEvent):
66
- full_name: str
67
- timestamp: datetime
68
-
69
- # Create a 'full name updated' domain event.
70
- event4 = FullNameUpdated(
71
- originator_id=event3.originator_id,
72
- originator_version=1,
73
- timestamp=FullNameUpdated.create_timestamp(),
74
- full_name="Bob",
75
- )
76
-
77
- # Check the attribute values of the domain event.
78
- self.assertEqual(event4.full_name, "Bob")
79
- assert isinstance(event4.originator_id, UUID)
80
- self.assertEqual(event4.originator_version, 1)
File without changes
@@ -1,258 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import threading
5
- from abc import abstractmethod
6
- from http.client import HTTPConnection
7
- from http.server import BaseHTTPRequestHandler, HTTPServer
8
- from threading import Event, Thread
9
- from typing import Callable, ClassVar, List, Sequence
10
- from unittest.case import TestCase
11
- from uuid import UUID
12
-
13
- from eventsourcing.interface import (
14
- NotificationLogInterface,
15
- NotificationLogJSONClient,
16
- NotificationLogJSONService,
17
- )
18
- from eventsourcing.tests.application import BankAccounts
19
-
20
-
21
- class TestRemoteNotificationLog(TestCase):
22
- def test_directly(self):
23
- client = BankAccountsJSONClient(BankAccountsJSONService(BankAccounts()))
24
- account_id1 = client.open_account("Alice", "alice@example.com")
25
- account_id2 = client.open_account("Bob", "bob@example.com")
26
-
27
- # Get the "first" section of log.
28
- section = client.log["1,10"]
29
- self.assertEqual(len(section.items), 2)
30
- self.assertEqual(section.items[0].originator_id, account_id1)
31
- self.assertEqual(section.items[1].originator_id, account_id2)
32
-
33
- # Get notifications start 1, limit 10.
34
- notifications = client.log.select(start=1, limit=10)
35
- self.assertEqual(len(notifications), 2)
36
- self.assertEqual(notifications[0].originator_id, account_id1)
37
- self.assertEqual(notifications[1].originator_id, account_id2)
38
-
39
- def test_with_http(self):
40
- server_address = ("127.0.0.1", 8080)
41
-
42
- server = HTTPApplicationServer(
43
- address=server_address,
44
- handler=BankAccountsHTTPHandler,
45
- )
46
- server.start()
47
- if not server.is_running.wait(timeout=5):
48
- server.stop()
49
- self.fail("Unable to start HTTPApplicationServer")
50
-
51
- try:
52
- client = BankAccountsJSONClient(
53
- BankAccountsHTTPClient(server_address=server_address)
54
- )
55
-
56
- account_id1 = client.open_account("Alice", "alice@example.com")
57
- account_id2 = client.open_account("Bob", "bob@example.com")
58
-
59
- # Get the "first" section of log.
60
- section = client.log["1,10"]
61
- self.assertEqual(len(section.items), 2)
62
- self.assertEqual(section.items[0].originator_id, account_id1)
63
- self.assertEqual(section.items[1].originator_id, account_id2)
64
-
65
- # Get notifications start 1, limit 10.
66
- notifications = client.log.select(1, 10)
67
- self.assertEqual(len(notifications), 2)
68
- self.assertEqual(notifications[0].originator_id, account_id1)
69
- self.assertEqual(notifications[1].originator_id, account_id2)
70
- finally:
71
- server.stop()
72
-
73
- def test_with_http_and_threads(self):
74
- server_address = ("127.0.0.1", 8081)
75
-
76
- server = HTTPApplicationServer(
77
- address=server_address,
78
- handler=BankAccountsHTTPHandler,
79
- )
80
- server.start()
81
- if not server.is_running.wait(timeout=5):
82
- server.stop()
83
- self.fail("Unable to start HTTPApplicationServer")
84
-
85
- try:
86
- self.has_errors = False
87
-
88
- def open_account():
89
- client = BankAccountsJSONClient(
90
- BankAccountsHTTPClient(server_address=server_address)
91
- )
92
- try:
93
- for _ in range(30):
94
- client.open_account("Alice", "alice@example.com")
95
- # print(threading.get_ident(), account_id1)
96
- except Exception as e:
97
- print(threading.get_ident(), "error:", e)
98
- self.has_errors = True
99
- raise
100
-
101
- thread1 = Thread(target=open_account)
102
- thread1.start()
103
- thread2 = Thread(target=open_account)
104
- thread2.start()
105
-
106
- thread1.join()
107
- thread2.join()
108
-
109
- self.assertFalse(self.has_errors)
110
-
111
- # Check the notification log.
112
- client = BankAccountsJSONClient(
113
- BankAccountsHTTPClient(server_address=server_address)
114
- )
115
- self.assertEqual(len(client.log["1,10"].items), 10)
116
- self.assertEqual(len(client.log["11,20"].items), 10)
117
- self.assertEqual(len(client.log["21,30"].items), 10)
118
- self.assertEqual(len(client.log["31,40"].items), 10)
119
- self.assertEqual(len(client.log["41,50"].items), 10)
120
- self.assertEqual(len(client.log["51,60"].items), 10)
121
- self.assertEqual(len(client.log["61,70"].items), 0)
122
-
123
- self.assertEqual(len(client.log.select(start=1, limit=10)), 10)
124
- self.assertEqual(len(client.log.select(start=11, limit=10)), 10)
125
- self.assertEqual(len(client.log.select(start=21, limit=10)), 10)
126
- self.assertEqual(len(client.log.select(start=31, limit=10)), 10)
127
- self.assertEqual(len(client.log.select(start=41, limit=10)), 10)
128
- self.assertEqual(len(client.log.select(start=51, limit=10)), 10)
129
- self.assertEqual(len(client.log.select(start=61, limit=10)), 0)
130
-
131
- finally:
132
- server.stop()
133
-
134
-
135
- class BankAccountsInterface(NotificationLogInterface):
136
- @abstractmethod
137
- def open_account(self, body: str) -> str:
138
- pass
139
-
140
-
141
- class BankAccountsJSONService(
142
- BankAccountsInterface,
143
- NotificationLogJSONService[BankAccounts],
144
- ):
145
- def open_account(self, request: str) -> str:
146
- kwargs = json.loads(request)
147
- account_id = self.app.open_account(**kwargs)
148
- return json.dumps({"account_id": account_id.hex})
149
-
150
-
151
- class BankAccountsJSONClient:
152
- def __init__(self, interface: BankAccountsInterface):
153
- self.interface = interface
154
- self.log = NotificationLogJSONClient(interface)
155
-
156
- def open_account(self, full_name, email_address) -> UUID:
157
- body = json.dumps(
158
- {
159
- "full_name": full_name,
160
- "email_address": email_address,
161
- }
162
- )
163
- body = self.interface.open_account(body)
164
- return UUID(json.loads(body)["account_id"])
165
-
166
-
167
- class HTTPApplicationServer(Thread):
168
- prepare: ClassVar[List[Callable]] = []
169
-
170
- def __init__(self, address, handler):
171
- super().__init__(daemon=True)
172
- self.server = HTTPServer(
173
- server_address=address,
174
- RequestHandlerClass=handler,
175
- )
176
- self.is_running = Event()
177
-
178
- def run(self):
179
- [f() for f in self.prepare]
180
- self.is_running.set()
181
- self.server.serve_forever()
182
-
183
- def stop(self):
184
- self.server.shutdown()
185
- self.join()
186
-
187
- @classmethod
188
- def before_first_request(cls, f):
189
- HTTPApplicationServer.prepare.append(f)
190
- return f
191
-
192
-
193
- class BankAccountsHTTPHandler(BaseHTTPRequestHandler):
194
- def do_PUT(self): # noqa: N802
195
- if self.path.startswith("/accounts/"):
196
- length = int(self.headers["Content-Length"])
197
- request_msg = self.rfile.read(length).decode("utf8")
198
- body = bank_accounts_service.open_account(request_msg)
199
- status = 201
200
- else:
201
- body = "Not found: " + self.path
202
- status = 404
203
- self.send(body, status)
204
-
205
- def do_GET(self): # noqa: N802
206
- if self.path.startswith("/notifications/"):
207
- section_id = self.path.split("/")[-1]
208
- body = bank_accounts_service.get_log_section(section_id)
209
- status = 200
210
- elif self.path.startswith("/notifications"):
211
- args = self.path.split("?")[-1].split("&")
212
- args = [p.split("=") for p in args]
213
- args = {p[0]: p[1] for p in args}
214
- start = int(args["start"])
215
- limit = int(args["limit"])
216
-
217
- body = bank_accounts_service.get_notifications(start=start, limit=limit)
218
- status = 200
219
- else:
220
- body = "Not found: " + self.path
221
- status = 404
222
- self.send(body, status)
223
-
224
- def send(self, body: str, status: int):
225
- self.send_response(status)
226
- self.send_header("Content-type", "text/html")
227
- self.end_headers()
228
- self.wfile.write(body.encode("utf8"))
229
-
230
-
231
- class BankAccountsHTTPClient(BankAccountsInterface):
232
- def __init__(self, server_address):
233
- self.connection = HTTPConnection(*server_address)
234
-
235
- def get_log_section(self, section_id: str) -> str:
236
- return self._request("GET", f"/notifications/{section_id}")
237
-
238
- def get_notifications(
239
- self, start: int, limit: int, topics: Sequence[str] = ()
240
- ) -> str:
241
- return self._request("GET", f"/notifications?start={start}&limit={limit}")
242
-
243
- def open_account(self, body: str) -> str:
244
- return self._request("PUT", "/accounts/", body.encode("utf8"))
245
-
246
- def _request(self, method, url, body=None):
247
- self.connection.request(method, url, body)
248
- response = self.connection.getresponse()
249
- return response.read().decode()
250
-
251
-
252
- bank_accounts_service: BankAccountsInterface
253
-
254
-
255
- @HTTPApplicationServer.before_first_request
256
- def init_bank_accounts() -> None:
257
- global bank_accounts_service # noqa: PLW0603
258
- bank_accounts_service = BankAccountsJSONService(BankAccounts())
File without changes
@@ -1,93 +0,0 @@
1
- from base64 import b64encode
2
- from unittest.case import TestCase
3
-
4
- from eventsourcing.cipher import AESCipher
5
- from eventsourcing.utils import Environment
6
-
7
-
8
- class TestAESCipher(TestCase):
9
- def test_createkey(self):
10
- environment = Environment()
11
-
12
- # Valid key lengths.
13
- key = AESCipher.create_key(16)
14
- environment["CIPHER_KEY"] = key
15
- AESCipher(environment)
16
-
17
- key = AESCipher.create_key(24)
18
- environment["CIPHER_KEY"] = key
19
- AESCipher(environment)
20
-
21
- key = AESCipher.create_key(32)
22
- environment["CIPHER_KEY"] = key
23
- AESCipher(environment)
24
-
25
- # Non-valid key lengths (on generate key).
26
- with self.assertRaises(ValueError):
27
- AESCipher.create_key(12)
28
-
29
- with self.assertRaises(ValueError):
30
- AESCipher.create_key(20)
31
-
32
- with self.assertRaises(ValueError):
33
- AESCipher.create_key(28)
34
-
35
- with self.assertRaises(ValueError):
36
- AESCipher.create_key(36)
37
-
38
- # Non-valid key lengths (on construction).
39
- def create_key(num_bytes):
40
- return b64encode(AESCipher.random_bytes(num_bytes)).decode("utf8")
41
-
42
- key = create_key(12)
43
- environment["CIPHER_KEY"] = key
44
- with self.assertRaises(ValueError):
45
- AESCipher(environment)
46
-
47
- key = create_key(20)
48
- environment["CIPHER_KEY"] = key
49
- with self.assertRaises(ValueError):
50
- AESCipher(environment)
51
-
52
- key = create_key(28)
53
- environment["CIPHER_KEY"] = key
54
- with self.assertRaises(ValueError):
55
- AESCipher(environment)
56
-
57
- key = create_key(36)
58
- environment["CIPHER_KEY"] = key
59
- with self.assertRaises(ValueError):
60
- AESCipher(environment)
61
-
62
- def test_encrypt_and_decrypt(self):
63
- environment = Environment()
64
-
65
- key = AESCipher.create_key(16)
66
- environment["CIPHER_KEY"] = key
67
-
68
- # Check plain text can be encrypted and recovered.
69
- plain_text = b"some text"
70
- cipher = AESCipher(environment)
71
- cipher_text = cipher.encrypt(plain_text)
72
- cipher = AESCipher(environment)
73
- recovered_text = cipher.decrypt(cipher_text)
74
- self.assertEqual(recovered_text, plain_text)
75
-
76
- # Check raises on invalid nonce.
77
- with self.assertRaises(ValueError):
78
- cipher.decrypt(cipher_text[:10])
79
-
80
- # Check raises on invalid tag.
81
- with self.assertRaises(ValueError):
82
- cipher.decrypt(cipher_text[:20])
83
-
84
- # Check raises on invalid data.
85
- with self.assertRaises(ValueError):
86
- cipher.decrypt(cipher_text[:30])
87
-
88
- # Check raises on invalid key.
89
- key = AESCipher.create_key(16)
90
- environment["CIPHER_KEY"] = key
91
- cipher = AESCipher(environment)
92
- with self.assertRaises(ValueError):
93
- cipher.decrypt(cipher_text)