klongpy 0.6.9__py3-none-any.whl → 0.7.1__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.
- klongpy/__init__.py +17 -1
- klongpy/adverbs.py +84 -82
- klongpy/autograd.py +299 -0
- klongpy/backend.py +38 -103
- klongpy/backends/__init__.py +26 -0
- klongpy/backends/base.py +469 -0
- klongpy/backends/numpy_backend.py +123 -0
- klongpy/backends/registry.py +76 -0
- klongpy/backends/torch_backend.py +1047 -0
- klongpy-0.6.9.data/scripts/kgpy → klongpy/cli.py +110 -90
- klongpy/core.py +113 -974
- klongpy/db/sys_fn_db.py +7 -6
- klongpy/db/sys_fn_kvs.py +2 -4
- klongpy/dyads.py +332 -160
- klongpy/interpreter.py +60 -15
- klongpy/monads.py +121 -75
- klongpy/parser.py +328 -0
- klongpy/repl.py +23 -5
- klongpy/sys_fn.py +170 -21
- klongpy/sys_fn_autograd.py +290 -0
- klongpy/sys_fn_ipc.py +22 -15
- klongpy/sys_fn_timer.py +13 -3
- klongpy/types.py +503 -0
- klongpy/web/sys_fn_web.py +14 -4
- klongpy/writer.py +122 -0
- klongpy/ws/sys_fn_ws.py +5 -8
- klongpy-0.7.1.dist-info/METADATA +544 -0
- klongpy-0.7.1.dist-info/RECORD +52 -0
- {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/WHEEL +1 -1
- klongpy-0.7.1.dist-info/entry_points.txt +2 -0
- {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/top_level.txt +0 -1
- klongpy-0.6.9.dist-info/METADATA +0 -448
- klongpy-0.6.9.dist-info/RECORD +0 -77
- tests/__init__.py +0 -6
- tests/gen_join_over.py +0 -119
- tests/gen_py_suite.py +0 -77
- tests/gen_test_fn.py +0 -259
- tests/perf_async.py +0 -25
- tests/perf_avg.py +0 -18
- tests/perf_duckdb.py +0 -32
- tests/perf_gen.py +0 -38
- tests/perf_ipc_overhead.py +0 -34
- tests/perf_join.py +0 -53
- tests/perf_load.py +0 -17
- tests/perf_prog.py +0 -18
- tests/perf_serdes.py +0 -52
- tests/perf_sys_fn_db.py +0 -263
- tests/perf_vector.py +0 -40
- tests/test_accel.py +0 -227
- tests/test_df_cache.py +0 -85
- tests/test_eval_monad_list.py +0 -34
- tests/test_examples.py +0 -64
- tests/test_extra_suite.py +0 -382
- tests/test_file_cache.py +0 -185
- tests/test_interop.py +0 -180
- tests/test_kg_asarray.py +0 -94
- tests/test_kgtests.py +0 -65
- tests/test_known_bugs.py +0 -206
- tests/test_prog.py +0 -107
- tests/test_reshape_strings.py +0 -33
- tests/test_suite.py +0 -1480
- tests/test_suite_file.py +0 -153
- tests/test_sys_fn.py +0 -420
- tests/test_sys_fn_db.py +0 -88
- tests/test_sys_fn_ipc.py +0 -587
- tests/test_sys_fn_timer.py +0 -133
- tests/test_sys_fn_web.py +0 -50
- tests/test_util.py +0 -233
- tests/utils.py +0 -126
- {klongpy-0.6.9.dist-info → klongpy-0.7.1.dist-info}/licenses/LICENSE +0 -0
tests/test_sys_fn_ipc.py
DELETED
|
@@ -1,587 +0,0 @@
|
|
|
1
|
-
import asyncio
|
|
2
|
-
import threading
|
|
3
|
-
import unittest
|
|
4
|
-
from unittest.mock import AsyncMock, MagicMock, patch
|
|
5
|
-
|
|
6
|
-
from utils import LoopsBase
|
|
7
|
-
|
|
8
|
-
from klongpy import KlongInterpreter
|
|
9
|
-
from klongpy.sys_fn_ipc import *
|
|
10
|
-
from klongpy.utils import CallbackEvent
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def run_coroutine_threadsafe(coro, loop):
|
|
14
|
-
future = asyncio.run_coroutine_threadsafe(coro, loop)
|
|
15
|
-
return future.result()
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class TestEncodeDecode(unittest.TestCase):
|
|
19
|
-
def test_encode_decode(self):
|
|
20
|
-
msg_id = uuid.uuid4()
|
|
21
|
-
msg = {'key': 'value'}
|
|
22
|
-
encoded_message = encode_message(msg_id, msg)
|
|
23
|
-
decoded_msglen = decode_message_len(encoded_message[16:20])
|
|
24
|
-
decoded_msg_id, decoded_message = decode_message(encoded_message[:16], encoded_message[20:])
|
|
25
|
-
|
|
26
|
-
self.assertEqual(decoded_msglen, len(pickle.dumps(msg)))
|
|
27
|
-
self.assertEqual(decoded_msg_id, msg_id)
|
|
28
|
-
self.assertEqual(decoded_message, msg)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class TestStreamSendRecv(unittest.IsolatedAsyncioTestCase):
|
|
32
|
-
async def test_stream_send_recv(self):
|
|
33
|
-
msg_id = uuid.uuid4()
|
|
34
|
-
msg = {'key': 'value'}
|
|
35
|
-
|
|
36
|
-
# Mock writer
|
|
37
|
-
writer = AsyncMock()
|
|
38
|
-
writer.write = MagicMock()
|
|
39
|
-
writer.close = MagicMock()
|
|
40
|
-
|
|
41
|
-
# Mock reader
|
|
42
|
-
reader = AsyncMock()
|
|
43
|
-
reader.readexactly = AsyncMock(side_effect=[
|
|
44
|
-
msg_id.bytes, # raw_msg_id
|
|
45
|
-
struct.pack("!I", len(pickle.dumps(msg))), # raw_msglen
|
|
46
|
-
pickle.dumps(msg) # data
|
|
47
|
-
])
|
|
48
|
-
|
|
49
|
-
# Simulate sending the message
|
|
50
|
-
await stream_send_msg(writer, msg_id, msg)
|
|
51
|
-
writer.write.assert_called_once()
|
|
52
|
-
writer.drain.assert_awaited_once()
|
|
53
|
-
|
|
54
|
-
# Simulate receiving the message
|
|
55
|
-
received_msg_id, received_message = await stream_recv_msg(reader)
|
|
56
|
-
|
|
57
|
-
self.assertEqual(received_msg_id, msg_id)
|
|
58
|
-
self.assertEqual(received_message, msg)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class TestAsync(LoopsBase, unittest.TestCase):
|
|
62
|
-
|
|
63
|
-
def test_async_fn(self):
|
|
64
|
-
klong = KlongInterpreter()
|
|
65
|
-
|
|
66
|
-
klong['.system'] = {'ioloop': self.ioloop, 'klongloop': self.klongloop}
|
|
67
|
-
|
|
68
|
-
async def _test():
|
|
69
|
-
klong("fn::{x+1}")
|
|
70
|
-
klong("result::0")
|
|
71
|
-
klong("cb::{result::x}")
|
|
72
|
-
klong("afn::.async(fn;cb)")
|
|
73
|
-
r = klong("afn(2)")
|
|
74
|
-
self.assertEqual(r,1)
|
|
75
|
-
|
|
76
|
-
async def _test_result():
|
|
77
|
-
r = klong("result")
|
|
78
|
-
self.assertEqual(r,3)
|
|
79
|
-
|
|
80
|
-
run_coroutine_threadsafe(_test(), self.klongloop)
|
|
81
|
-
run_coroutine_threadsafe(_test_result(), self.klongloop)
|
|
82
|
-
|
|
83
|
-
def test_async_python_lambda_fn(self):
|
|
84
|
-
klong = KlongInterpreter()
|
|
85
|
-
klong['.system'] = {'ioloop': self.ioloop, 'klongloop': self.klongloop}
|
|
86
|
-
|
|
87
|
-
async def _test():
|
|
88
|
-
klong["fn"] = lambda x: x+1
|
|
89
|
-
klong("result::0")
|
|
90
|
-
klong("cb::{result::x}")
|
|
91
|
-
klong("afn::.async(fn;cb)")
|
|
92
|
-
r = klong("afn(2)")
|
|
93
|
-
self.assertEqual(r,1)
|
|
94
|
-
|
|
95
|
-
async def _test_result():
|
|
96
|
-
r = klong("result")
|
|
97
|
-
self.assertEqual(r,3)
|
|
98
|
-
|
|
99
|
-
run_coroutine_threadsafe(_test(), self.klongloop)
|
|
100
|
-
run_coroutine_threadsafe(_test_result(), self.klongloop)
|
|
101
|
-
|
|
102
|
-
def test_async_python_remote_fn(self):
|
|
103
|
-
klong = KlongInterpreter()
|
|
104
|
-
klong['.system'] = {'ioloop': self.ioloop, 'klongloop': self.klongloop}
|
|
105
|
-
|
|
106
|
-
# create a fake remote network client that mimics the remote execution of lambda x: x+1
|
|
107
|
-
nc = NetworkClient(self.ioloop, self.klongloop, klong, None)
|
|
108
|
-
nc.call = MagicMock(return_value=3)
|
|
109
|
-
|
|
110
|
-
async def _test():
|
|
111
|
-
klong["fn"] = nc
|
|
112
|
-
klong("result::0")
|
|
113
|
-
klong("cb::{result::x}")
|
|
114
|
-
klong("afn::.async(fn;cb)")
|
|
115
|
-
r = klong("afn(2)")
|
|
116
|
-
self.assertEqual(r,1)
|
|
117
|
-
|
|
118
|
-
async def _test_result():
|
|
119
|
-
r = klong("result")
|
|
120
|
-
self.assertEqual(r,3)
|
|
121
|
-
|
|
122
|
-
run_coroutine_threadsafe(_test(), self.klongloop)
|
|
123
|
-
run_coroutine_threadsafe(_test_result(), self.klongloop)
|
|
124
|
-
|
|
125
|
-
# ensure that the nc was called with the correct arguments
|
|
126
|
-
nc.call.assert_called_once_with(2)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
class TestConnectionProvider(unittest.TestCase):
|
|
131
|
-
|
|
132
|
-
def test_connection_provider_raises_exception(self):
|
|
133
|
-
conn = ConnectionProvider()
|
|
134
|
-
with self.assertRaises(KlongIPCCreateConnectionException):
|
|
135
|
-
asyncio.run(conn.connect())
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
class TestHostPortConnectionProvider(LoopsBase, unittest.TestCase):
|
|
139
|
-
|
|
140
|
-
@patch('klongpy.sys_fn_ipc.asyncio.open_connection')
|
|
141
|
-
def test_successful_connection(self, mock_open_connection):
|
|
142
|
-
mock_reader = MagicMock()
|
|
143
|
-
mock_writer = MagicMock()
|
|
144
|
-
mock_open_connection.return_value = mock_reader, mock_writer
|
|
145
|
-
|
|
146
|
-
provider = HostPortConnectionProvider("localhost", 8080)
|
|
147
|
-
reader, writer = run_coroutine_threadsafe(provider.connect(), self.ioloop)
|
|
148
|
-
|
|
149
|
-
self.assertEqual(reader, mock_reader)
|
|
150
|
-
self.assertEqual(writer, mock_writer)
|
|
151
|
-
|
|
152
|
-
@patch('klongpy.sys_fn_ipc.asyncio.open_connection', new_callable=AsyncMock)
|
|
153
|
-
def test_retry_logic(self, mock_open_connection):
|
|
154
|
-
mock_open_connection.side_effect = [OSError(), OSError(), (MagicMock(), MagicMock())] # Fail twice, then succeed
|
|
155
|
-
|
|
156
|
-
provider = HostPortConnectionProvider("localhost", 8080, max_retries=5, retry_delay=0)
|
|
157
|
-
run_coroutine_threadsafe(provider.connect(), self.ioloop)
|
|
158
|
-
|
|
159
|
-
self.assertEqual(mock_open_connection.call_count, 3)
|
|
160
|
-
self.assertIsNotNone(provider.reader)
|
|
161
|
-
self.assertIsNotNone(provider.writer)
|
|
162
|
-
|
|
163
|
-
def test_is_open(self):
|
|
164
|
-
provider = HostPortConnectionProvider("localhost", 8080)
|
|
165
|
-
self.assertFalse(provider.is_open())
|
|
166
|
-
|
|
167
|
-
provider.writer = MagicMock()
|
|
168
|
-
provider.writer.is_closing.return_value = False
|
|
169
|
-
self.assertTrue(provider.is_open())
|
|
170
|
-
|
|
171
|
-
provider.writer.is_closing.return_value = True
|
|
172
|
-
self.assertFalse(provider.is_open())
|
|
173
|
-
|
|
174
|
-
def test_close(self):
|
|
175
|
-
provider = HostPortConnectionProvider("localhost", 8080)
|
|
176
|
-
reader = MagicMock()
|
|
177
|
-
writer = MagicMock()
|
|
178
|
-
provider.reader = reader
|
|
179
|
-
provider.writer = writer
|
|
180
|
-
provider._thread_ident = self.ioloop_thread.ident
|
|
181
|
-
provider.writer.wait_closed = AsyncMock()
|
|
182
|
-
provider.writer.is_closing.return_value = False
|
|
183
|
-
|
|
184
|
-
self.assertTrue(provider.is_open())
|
|
185
|
-
|
|
186
|
-
# Run the close method in the ioloop thread without waiting for its completion
|
|
187
|
-
run_coroutine_threadsafe(provider.close(), self.ioloop)
|
|
188
|
-
|
|
189
|
-
self.assertIsNone(provider.reader)
|
|
190
|
-
self.assertIsNone(provider.writer)
|
|
191
|
-
writer.close.assert_called_once()
|
|
192
|
-
writer.wait_closed.assert_called_once()
|
|
193
|
-
|
|
194
|
-
self.assertFalse(provider.is_open())
|
|
195
|
-
|
|
196
|
-
def test_str(self):
|
|
197
|
-
host = "localhost"
|
|
198
|
-
port = 1234
|
|
199
|
-
conn = HostPortConnectionProvider(host, port)
|
|
200
|
-
self.assertEqual(str(conn), f"remote[{host}:{port}]")
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
class TestReaderWriterConnectionProvider(unittest.TestCase):
|
|
204
|
-
|
|
205
|
-
def test_readerwriter_connection_provider_at_eof(self):
|
|
206
|
-
mock_reader = MagicMock(at_eof=MagicMock(return_value=True))
|
|
207
|
-
mock_writer = MagicMock()
|
|
208
|
-
conn = ReaderWriterConnectionProvider(mock_reader, mock_writer, "localhost", 1234)
|
|
209
|
-
with self.assertRaises(KlongIPCCreateConnectionException):
|
|
210
|
-
asyncio.run(conn.connect())
|
|
211
|
-
|
|
212
|
-
def test_readerwriter_connection_provider_successful_connection(self):
|
|
213
|
-
mock_reader = MagicMock()
|
|
214
|
-
mock_writer = MagicMock(is_closing=MagicMock(return_value=False))
|
|
215
|
-
conn = ReaderWriterConnectionProvider(mock_reader, mock_writer, "localhost", 1234)
|
|
216
|
-
reader, writer = asyncio.run(conn.connect())
|
|
217
|
-
self.assertEqual(reader, mock_reader)
|
|
218
|
-
self.assertEqual(writer, mock_writer)
|
|
219
|
-
|
|
220
|
-
def test_str(self):
|
|
221
|
-
host = "localhost"
|
|
222
|
-
port = 1234
|
|
223
|
-
conn = ReaderWriterConnectionProvider(None, None, host, port)
|
|
224
|
-
self.assertEqual(str(conn), f"remote[{host}:{port}]")
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
class TestNetworkClient(LoopsBase, unittest.TestCase):
|
|
228
|
-
|
|
229
|
-
def test_initialization(self):
|
|
230
|
-
klong = KlongInterpreter()
|
|
231
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234)
|
|
232
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider)
|
|
233
|
-
self.assertEqual(client.ioloop, self.ioloop)
|
|
234
|
-
self.assertEqual(client.klongloop, self.klongloop)
|
|
235
|
-
self.assertEqual(client.klong, klong)
|
|
236
|
-
self.assertEqual(client.conn_provider, conn_provider)
|
|
237
|
-
self.assertEqual(client.reader, None)
|
|
238
|
-
self.assertEqual(client.writer, None)
|
|
239
|
-
self.assertEqual(client.pending_responses, {})
|
|
240
|
-
self.assertEqual(client.running, False)
|
|
241
|
-
|
|
242
|
-
def test_initialization_with_callbacks(self):
|
|
243
|
-
klong = KlongInterpreter()
|
|
244
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234)
|
|
245
|
-
on_connect = lambda x: x
|
|
246
|
-
on_error = lambda x: x
|
|
247
|
-
on_close = lambda x: x
|
|
248
|
-
|
|
249
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider, on_connect=on_connect, on_error=on_error, on_close=on_close)
|
|
250
|
-
self.assertEqual(client.ioloop, self.ioloop)
|
|
251
|
-
self.assertEqual(client.klongloop, self.klongloop)
|
|
252
|
-
self.assertEqual(client.klong, klong)
|
|
253
|
-
self.assertEqual(client.conn_provider, conn_provider)
|
|
254
|
-
self.assertEqual(client.reader, None)
|
|
255
|
-
self.assertEqual(client.writer, None)
|
|
256
|
-
self.assertEqual(client.pending_responses, {})
|
|
257
|
-
self.assertEqual(client.running, False)
|
|
258
|
-
self.assertEqual(client.on_connect, on_connect)
|
|
259
|
-
self.assertEqual(client.on_error, on_error)
|
|
260
|
-
self.assertEqual(client.on_close, on_close)
|
|
261
|
-
|
|
262
|
-
def test_str(self):
|
|
263
|
-
klong = KlongInterpreter()
|
|
264
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234)
|
|
265
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider)
|
|
266
|
-
self.assertEqual(str(client), f"{str(conn_provider)}:fn")
|
|
267
|
-
|
|
268
|
-
def test_connect(self):
|
|
269
|
-
klong = KlongInterpreter()
|
|
270
|
-
reader = AsyncMock()
|
|
271
|
-
writer = AsyncMock()
|
|
272
|
-
writer.write = MagicMock()
|
|
273
|
-
writer.close = MagicMock()
|
|
274
|
-
writer.is_closing = MagicMock(return_value=False)
|
|
275
|
-
|
|
276
|
-
async def _test_on_connect(client):
|
|
277
|
-
self.assertEqual(threading.current_thread().ident, self.ioloop_thread.ident)
|
|
278
|
-
self.assertEqual(client.reader, reader)
|
|
279
|
-
self.assertEqual(client.writer, writer)
|
|
280
|
-
client.running = False
|
|
281
|
-
|
|
282
|
-
conn_provider = ReaderWriterConnectionProvider(reader, writer, "localhost", 1234)
|
|
283
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider, on_connect=_test_on_connect)
|
|
284
|
-
client.run_client()
|
|
285
|
-
|
|
286
|
-
# after client.running is set to False, the _run method will exit
|
|
287
|
-
# block until the _run method has finished
|
|
288
|
-
client._run_exit_event.wait()
|
|
289
|
-
|
|
290
|
-
self.assertFalse(client.running)
|
|
291
|
-
self.assertEqual(client.reader, None)
|
|
292
|
-
self.assertEqual(client.writer, None)
|
|
293
|
-
|
|
294
|
-
@patch("klongpy.sys_fn_ipc.uuid.uuid4", new_callable=MagicMock)
|
|
295
|
-
@patch("klongpy.sys_fn_ipc.stream_send_msg")
|
|
296
|
-
@patch("klongpy.sys_fn_ipc.stream_recv_msg")
|
|
297
|
-
def test_close(self, mock_stream_recv_msg, mock_stream_send_msg: MagicMock, mock_uuid):
|
|
298
|
-
klong = MagicMock()
|
|
299
|
-
|
|
300
|
-
reader = AsyncMock()
|
|
301
|
-
writer = AsyncMock()
|
|
302
|
-
writer.write = MagicMock()
|
|
303
|
-
writer.close = MagicMock()
|
|
304
|
-
writer.is_closing = MagicMock(return_value=False)
|
|
305
|
-
|
|
306
|
-
msg_id = uuid.uuid4()
|
|
307
|
-
# msg = KGRemoteCloseConnection()
|
|
308
|
-
msg = "hello"
|
|
309
|
-
|
|
310
|
-
mock_uuid.return_value = msg_id
|
|
311
|
-
mock_stream_recv_msg.return_value = (msg_id, msg)
|
|
312
|
-
|
|
313
|
-
async def _test_on_connect(client):
|
|
314
|
-
self.assertEqual(threading.current_thread().ident, self.ioloop_thread.ident)
|
|
315
|
-
self.assertEqual(client.reader, reader)
|
|
316
|
-
self.assertEqual(client.writer, writer)
|
|
317
|
-
|
|
318
|
-
conn_provider = ReaderWriterConnectionProvider(reader, writer, "localhost", 1234)
|
|
319
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider, on_connect=_test_on_connect)
|
|
320
|
-
client.run_client()
|
|
321
|
-
|
|
322
|
-
client.close()
|
|
323
|
-
|
|
324
|
-
# mock_stream_send_msg.assert_called_with(writer, msg_id, msg)
|
|
325
|
-
|
|
326
|
-
self.assertFalse(client.running)
|
|
327
|
-
self.assertEqual(client.reader, None)
|
|
328
|
-
self.assertEqual(client.writer, None)
|
|
329
|
-
|
|
330
|
-
@patch("klongpy.sys_fn_ipc.stream_recv_msg")
|
|
331
|
-
def test_on_error(self, mock_stream_recv_msg):
|
|
332
|
-
klong = MagicMock()
|
|
333
|
-
klong._context = MagicMock()
|
|
334
|
-
|
|
335
|
-
# reader = AsyncMock()
|
|
336
|
-
writer = AsyncMock()
|
|
337
|
-
writer.write = MagicMock()
|
|
338
|
-
writer.close = MagicMock()
|
|
339
|
-
writer.is_closing = MagicMock(return_value=False)
|
|
340
|
-
|
|
341
|
-
# mock_stream_recv_msg.return_value = (uuid.uuid4(), "test_message")
|
|
342
|
-
|
|
343
|
-
# async def _test_on_connect(client):
|
|
344
|
-
# raise KlongIPCCreateConnectionException()
|
|
345
|
-
|
|
346
|
-
on_error_called = False
|
|
347
|
-
async def _test_on_error(client, e):
|
|
348
|
-
nonlocal on_error_called
|
|
349
|
-
on_error_called = True
|
|
350
|
-
client.running = False
|
|
351
|
-
|
|
352
|
-
# conn_provider = ReaderWriterConnectionProvider(reader, writer, "localhost", 1234)
|
|
353
|
-
conn_provider = MagicMock()
|
|
354
|
-
conn_provider.connect.side_effect = KlongIPCCreateConnectionException()
|
|
355
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider, on_error=_test_on_error)
|
|
356
|
-
client.run_client()
|
|
357
|
-
|
|
358
|
-
# after client.running is set to False, the _run method will exit
|
|
359
|
-
# block until the _run method has finished
|
|
360
|
-
client._run_exit_event.wait()
|
|
361
|
-
|
|
362
|
-
self.assertTrue(on_error_called)
|
|
363
|
-
self.assertFalse(client.running)
|
|
364
|
-
self.assertEqual(client.reader, None)
|
|
365
|
-
self.assertEqual(client.writer, None)
|
|
366
|
-
|
|
367
|
-
def test_on_close(self):
|
|
368
|
-
reader = AsyncMock()
|
|
369
|
-
writer = AsyncMock()
|
|
370
|
-
writer.close = MagicMock()
|
|
371
|
-
writer.write = MagicMock()
|
|
372
|
-
writer.is_closing = MagicMock(return_value=False)
|
|
373
|
-
|
|
374
|
-
async def _test_on_connect(client):
|
|
375
|
-
client.running = False
|
|
376
|
-
|
|
377
|
-
on_close_called = False
|
|
378
|
-
async def _test_on_close(client):
|
|
379
|
-
nonlocal on_close_called
|
|
380
|
-
on_close_called = True
|
|
381
|
-
|
|
382
|
-
conn_provider = ReaderWriterConnectionProvider(reader, writer, "localhost", 1234)
|
|
383
|
-
client = NetworkClient(self.ioloop, self.klongloop, "klong", conn_provider, on_connect=_test_on_connect, on_close=_test_on_close)
|
|
384
|
-
client.run_client()
|
|
385
|
-
|
|
386
|
-
# after client.running is set to False, the _run method will exit
|
|
387
|
-
# block until the _run method has finished
|
|
388
|
-
client._run_exit_event.wait()
|
|
389
|
-
|
|
390
|
-
self.assertTrue(on_close_called)
|
|
391
|
-
self.assertFalse(client.running)
|
|
392
|
-
self.assertEqual(client.reader, None)
|
|
393
|
-
self.assertEqual(client.writer, None)
|
|
394
|
-
|
|
395
|
-
@patch("klongpy.sys_fn_ipc.asyncio.open_connection", new_callable=AsyncMock)
|
|
396
|
-
def test_max_retries(self, mock_open_connection):
|
|
397
|
-
mock_open_connection.side_effect = ConnectionResetError() # Simulate a connection error
|
|
398
|
-
|
|
399
|
-
called_after_connect = False
|
|
400
|
-
error_event = threading.Event()
|
|
401
|
-
|
|
402
|
-
async def _test_on_connect(*args, **kwargs):
|
|
403
|
-
nonlocal called_after_connect
|
|
404
|
-
called_after_connect = True
|
|
405
|
-
|
|
406
|
-
async def _test_on_error(client, e):
|
|
407
|
-
nonlocal error_event
|
|
408
|
-
error_event.set()
|
|
409
|
-
client.running = False
|
|
410
|
-
|
|
411
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234, max_retries=3, retry_delay=0)
|
|
412
|
-
client = NetworkClient(self.ioloop, self.klongloop, "klong", conn_provider, on_connect=_test_on_connect, on_error=_test_on_error)
|
|
413
|
-
client.run_client()
|
|
414
|
-
|
|
415
|
-
client._run_exit_event.wait()
|
|
416
|
-
error_event.wait()
|
|
417
|
-
|
|
418
|
-
self.assertFalse(called_after_connect) # after_connect should never be called
|
|
419
|
-
self.assertEqual(client.reader, None)
|
|
420
|
-
self.assertEqual(client.writer, None)
|
|
421
|
-
self.assertEqual(mock_open_connection.call_count, 3) # Check if the retries were called 3 times
|
|
422
|
-
|
|
423
|
-
@patch("klongpy.sys_fn_ipc.asyncio.open_connection", new_callable=AsyncMock)
|
|
424
|
-
def test_connect_after_failure(self, mock_open_connection):
|
|
425
|
-
mock_open_connection.side_effect = [OSError(), OSError(), (MagicMock(), MagicMock())]
|
|
426
|
-
|
|
427
|
-
called_after_error = False
|
|
428
|
-
called_after_connect = False
|
|
429
|
-
|
|
430
|
-
async def _test_on_connect(client, **kwargs):
|
|
431
|
-
nonlocal called_after_connect
|
|
432
|
-
called_after_connect = True
|
|
433
|
-
client.running = False
|
|
434
|
-
|
|
435
|
-
async def _test_on_error(client, e):
|
|
436
|
-
nonlocal called_after_error
|
|
437
|
-
called_after_error = True
|
|
438
|
-
|
|
439
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234, max_retries=3, retry_delay=0)
|
|
440
|
-
client = NetworkClient(self.ioloop, self.klongloop, "klong", conn_provider, on_connect=_test_on_connect, on_error=_test_on_error)
|
|
441
|
-
client.run_client()
|
|
442
|
-
|
|
443
|
-
client._run_exit_event.wait()
|
|
444
|
-
|
|
445
|
-
self.assertTrue(called_after_connect)
|
|
446
|
-
self.assertFalse(called_after_error)
|
|
447
|
-
self.assertEqual(client.reader, None)
|
|
448
|
-
self.assertEqual(client.writer, None)
|
|
449
|
-
self.assertEqual(mock_open_connection.call_count, 3)
|
|
450
|
-
|
|
451
|
-
@patch("klongpy.sys_fn_ipc.stream_send_msg")
|
|
452
|
-
@patch("klongpy.sys_fn_ipc.stream_recv_msg")
|
|
453
|
-
def test_listen_pending_response(self, mock_stream_recv_msg, mock_stream_send_msg):
|
|
454
|
-
klong = MagicMock()
|
|
455
|
-
|
|
456
|
-
# Define the message and response
|
|
457
|
-
msg_id = uuid.uuid4()
|
|
458
|
-
msg = "test_message"
|
|
459
|
-
|
|
460
|
-
mock_stream_recv_msg.return_value = (msg_id, msg)
|
|
461
|
-
|
|
462
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, None)
|
|
463
|
-
future = self.ioloop.create_future()
|
|
464
|
-
client.pending_responses[msg_id] = future
|
|
465
|
-
|
|
466
|
-
run_coroutine_threadsafe(client._listen(), self.ioloop)
|
|
467
|
-
|
|
468
|
-
self.assertEqual(future.result(), msg)
|
|
469
|
-
|
|
470
|
-
@patch("klongpy.sys_fn_ipc.stream_send_msg")
|
|
471
|
-
@patch("klongpy.sys_fn_ipc.stream_recv_msg")
|
|
472
|
-
def test_listen_klong_request(self, mock_stream_recv_msg, mock_stream_send_msg):
|
|
473
|
-
# Define the message and response
|
|
474
|
-
msg_id = uuid.uuid4()
|
|
475
|
-
msg = "test_message"
|
|
476
|
-
|
|
477
|
-
klong = MagicMock()
|
|
478
|
-
klong.return_value = msg
|
|
479
|
-
|
|
480
|
-
mock_stream_recv_msg.return_value = (msg_id, msg)
|
|
481
|
-
|
|
482
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, None)
|
|
483
|
-
|
|
484
|
-
run_coroutine_threadsafe(client._listen(), self.ioloop)
|
|
485
|
-
|
|
486
|
-
klong.assert_called_once_with(msg)
|
|
487
|
-
mock_stream_send_msg.assert_called_once_with(client.writer, msg_id, msg)
|
|
488
|
-
|
|
489
|
-
@patch.object(HostPortConnectionProvider, "connect", new_callable=AsyncMock)
|
|
490
|
-
def test_call_disconnected(self, mock_connect):
|
|
491
|
-
|
|
492
|
-
# Mock the connect method to raise a KlongConnectionException
|
|
493
|
-
mock_connect.side_effect = KlongIPCCreateConnectionException("Unable to connect")
|
|
494
|
-
|
|
495
|
-
# Create a mock Klong object
|
|
496
|
-
klong = MagicMock()
|
|
497
|
-
|
|
498
|
-
conn_provider = HostPortConnectionProvider("localhost", 1234)
|
|
499
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider)
|
|
500
|
-
|
|
501
|
-
with self.assertRaises(KlongException) as context:
|
|
502
|
-
client.call("some_message")
|
|
503
|
-
|
|
504
|
-
self.assertTrue("connection not established" in str(context.exception))
|
|
505
|
-
client.close()
|
|
506
|
-
|
|
507
|
-
@patch("klongpy.sys_fn_ipc.uuid.uuid4", new_callable=MagicMock)
|
|
508
|
-
@patch("klongpy.sys_fn_ipc.stream_send_msg")
|
|
509
|
-
@patch("klongpy.sys_fn_ipc.stream_recv_msg")
|
|
510
|
-
def test_call(self, mock_stream_recv_msg, mock_stream_send_msg, mock_uuid):
|
|
511
|
-
|
|
512
|
-
klong = MagicMock()
|
|
513
|
-
|
|
514
|
-
writer = AsyncMock()
|
|
515
|
-
writer.is_closing = MagicMock(return_value=False)
|
|
516
|
-
writer.close = MagicMock()
|
|
517
|
-
reader = AsyncMock()
|
|
518
|
-
|
|
519
|
-
msg_id = uuid.uuid4()
|
|
520
|
-
msg = "test_message"
|
|
521
|
-
|
|
522
|
-
mock_uuid.return_value = msg_id
|
|
523
|
-
mock_stream_recv_msg.return_value = (msg_id, msg)
|
|
524
|
-
|
|
525
|
-
conn_provider = ReaderWriterConnectionProvider(reader, writer, "localhost", 1234)
|
|
526
|
-
client = NetworkClient(self.ioloop, self.klongloop, klong, conn_provider)
|
|
527
|
-
client.run_client()
|
|
528
|
-
|
|
529
|
-
response = client.call(msg)
|
|
530
|
-
|
|
531
|
-
self.assertEqual(response, msg)
|
|
532
|
-
|
|
533
|
-
client.close()
|
|
534
|
-
|
|
535
|
-
# test that when the server closes the connection in the middle of a call, the client raises an exception
|
|
536
|
-
def test_call_server_fail(self):
|
|
537
|
-
pass
|
|
538
|
-
|
|
539
|
-
# test that when the server has a KlongException, the client raises an exception
|
|
540
|
-
def test_call_server_exception(self):
|
|
541
|
-
pass
|
|
542
|
-
|
|
543
|
-
# test wrapping the NetworkClient in a NetworkClientDictHandle
|
|
544
|
-
def test_network_client_dict_handler(self):
|
|
545
|
-
pass
|
|
546
|
-
|
|
547
|
-
# test client reconnect on connection failure
|
|
548
|
-
def test_client_reconnect(self):
|
|
549
|
-
pass
|
|
550
|
-
|
|
551
|
-
# test client reconnect on connection failure with pending requests
|
|
552
|
-
def test_client_reconnect_with_pending_requests(self):
|
|
553
|
-
pass
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
# class TestServerNetworkClient(unittest):
|
|
558
|
-
|
|
559
|
-
# def setUp(self):
|
|
560
|
-
# self.ioloop = asyncio.new_event_loop()
|
|
561
|
-
# self.ioloop_thread = threading.Thread(target=self.start_ioloop)
|
|
562
|
-
# self.ioloop_thread.start()
|
|
563
|
-
|
|
564
|
-
# self.klongloop = asyncio.new_event_loop()
|
|
565
|
-
# self.klongloop_thread = threading.Thread(target=self.start_klongloop)
|
|
566
|
-
# self.klongloop_thread.start()
|
|
567
|
-
|
|
568
|
-
# def tearDown(self):
|
|
569
|
-
# self.ioloop.call_soon_threadsafe(self.ioloop.stop)
|
|
570
|
-
# self.ioloop_thread.join()
|
|
571
|
-
|
|
572
|
-
# self.klongloop.call_soon_threadsafe(self.klongloop.stop)
|
|
573
|
-
# self.klongloop_thread.join()
|
|
574
|
-
|
|
575
|
-
# def start_ioloop(self):
|
|
576
|
-
# asyncio.set_event_loop(self.ioloop)
|
|
577
|
-
# self.ioloop.run_forever()
|
|
578
|
-
|
|
579
|
-
# def start_klongloop(self):
|
|
580
|
-
# asyncio.set_event_loop(self.klongloop)
|
|
581
|
-
# self.klongloop.run_forever()
|
|
582
|
-
|
|
583
|
-
# def test_initialization(self):
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
if __name__ == '__main__':
|
|
587
|
-
unittest.main()
|