more tests

This commit is contained in:
John Smith 2023-06-14 21:06:10 -04:00
parent d053e93e72
commit 615e0ca1d0
6 changed files with 103 additions and 45 deletions

7
.vscode/launch.json vendored
View File

@ -11,6 +11,13 @@
} }
], ],
"configurations": [ "configurations": [
{
"name": "Python: Attach using Process Id",
"type": "python",
"request": "attach",
"processId": "${command:pickProcess}",
"justMyCode": true
},
{ {
"type": "lldb", "type": "lldb",
"request": "attach", "request": "attach",

View File

@ -0,0 +1,22 @@
import pytest
pytest_plugins = ('pytest_asyncio',)
import os
##################################################################
VEILID_SERVER = os.getenv("VEILID_SERVER")
if VEILID_SERVER is not None:
vsparts = VEILID_SERVER.split(":")
VEILID_SERVER = vsparts[0]
if len(vsparts) == 2:
VEILID_SERVER_PORT = int(vsparts[1])
else:
VEILID_SERVER_PORT = 5959
else:
VEILID_SERVER = "localhost"
VEILID_SERVER_PORT = 5959
##################################################################
async def simple_update_callback(update):
print("VeilidUpdate: {}".format(update))

View File

@ -2,42 +2,24 @@
import veilid_python import veilid_python
import pytest import pytest
import os from . import *
pytest_plugins = ('pytest_asyncio',)
################################################################## ##################################################################
VEILID_SERVER = os.getenv("VEILID_SERVER")
if VEILID_SERVER is not None:
vsparts = VEILID_SERVER.split(":")
VEILID_SERVER = vsparts[0]
if len(vsparts) == 2:
VEILID_SERVER_PORT = int(vsparts[1])
else:
VEILID_SERVER_PORT = 5959
else:
VEILID_SERVER = "localhost"
VEILID_SERVER_PORT = 5959
##################################################################
async def _simple_update_callback(update):
print("VeilidUpdate: {}".format(update))
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_connect(): async def test_connect():
async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, _simple_update_callback) as api: async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, simple_update_callback) as api:
pass pass
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_fail_connect(): async def test_fail_connect():
with pytest.raises(Exception): with pytest.raises(Exception):
async with await veilid_python.json_api_connect("fuahwelifuh32luhwafluehawea", 1, _simple_update_callback) as api: async with await veilid_python.json_api_connect("fuahwelifuh32luhwafluehawea", 1, simple_update_callback) as api:
pass pass
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_version(): async def test_version():
async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, _simple_update_callback) as api: async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, simple_update_callback) as api:
v = await api.veilid_version() v = await api.veilid_version()
print("veilid_version: {}".format(v.__dict__)) print("veilid_version: {}".format(v.__dict__))
vstr = await api.veilid_version_string() vstr = await api.veilid_version_string()

View File

@ -0,0 +1,28 @@
# Crypto veilid_python tests
import veilid_python
import pytest
from . import *
##################################################################
@pytest.mark.asyncio
async def test_best_crypto_system():
async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, simple_update_callback) as api:
bcs = await api.best_crypto_system()
# let handle dangle for test
# del bcs
@pytest.mark.asyncio
async def test_get_crypto_system():
async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, simple_update_callback) as api:
cs = await api.get_crypto_system(veilid_python.CryptoKind.CRYPTO_KIND_VLD0)
# clean up handle early
del cs
@pytest.mark.asyncio
async def test_get_crypto_system_invalid():
async with await veilid_python.json_api_connect(VEILID_SERVER, VEILID_SERVER_PORT, simple_update_callback) as api:
with pytest.raises(veilid_python.VeilidAPIError):
cs = await api.get_crypto_system(veilid_python.CryptoKind.CRYPTO_KIND_NONE)

View File

@ -60,14 +60,32 @@ class _JsonVeilidAPI(VeilidAPI):
async def __aexit__(self, *excinfo): async def __aexit__(self, *excinfo):
await self.close() await self.close()
async def close(self): async def _cleanup_close(self):
if self.handle_recv_messages_task is not None: await self.lock.acquire()
self.handle_recv_messages_task.cancel() try:
try: self.reader = None
await self.handle_recv_messages_task self.writer.close()
except asyncio.CancelledError: await self.writer.wait_closed()
pass self.writer = None
finally:
self.lock.release()
async def close(self):
# Take the task
await self.lock.acquire()
try:
if self.handle_recv_messages_task is None:
return
handle_recv_messages_task = self.handle_recv_messages_task
self.handle_recv_messages_task = None
finally:
self.lock.release()
# Cancel it
handle_recv_messages_task.cancel()
try:
await handle_recv_messages_task
except asyncio.CancelledError:
pass
@staticmethod @staticmethod
async def connect(host: str, port: int, update_callback: Callable[[VeilidUpdate], Awaitable]) -> Self: async def connect(host: str, port: int, update_callback: Callable[[VeilidUpdate], Awaitable]) -> Self:
@ -109,11 +127,7 @@ class _JsonVeilidAPI(VeilidAPI):
except: except:
pass pass
finally: finally:
self.reader = None await self._cleanup_close()
self.writer.close()
await self.writer.wait_closed()
self.writer = None
self.handle_recv_messages_task = None
async def allocate_request_future(self, id: int) -> asyncio.Future: async def allocate_request_future(self, id: int) -> asyncio.Future:
reqfuture = asyncio.get_running_loop().create_future() reqfuture = asyncio.get_running_loop().create_future()
@ -135,6 +149,10 @@ class _JsonVeilidAPI(VeilidAPI):
self.lock.release() self.lock.release()
def send_one_way_ndjson_request(self, op: Operation, **kwargs): def send_one_way_ndjson_request(self, op: Operation, **kwargs):
if self.writer is None:
return
# Make NDJSON string for request # Make NDJSON string for request
# Always use id 0 because no reply will be received for one-way requests # Always use id 0 because no reply will be received for one-way requests
req = { "id": 0, "op": op } req = { "id": 0, "op": op }
@ -156,6 +174,7 @@ class _JsonVeilidAPI(VeilidAPI):
try: try:
id = self.next_id id = self.next_id
self.next_id += 1 self.next_id += 1
writer = self.writer
finally: finally:
self.lock.release() self.lock.release()
@ -174,8 +193,8 @@ class _JsonVeilidAPI(VeilidAPI):
# Send to socket # Send to socket
try: try:
self.writer.write(reqbytes) writer.write(reqbytes)
await self.writer.drain() await writer.drain()
except: except:
# Send failed, release future # Send failed, release future
await self.cancel_request_future(id) await self.cancel_request_future(id)

View File

@ -102,7 +102,7 @@ impl ClientApi {
}; };
trace!("ClientApi::stop: waiting for stop"); trace!("ClientApi::stop: waiting for stop");
if let Err(err) = jh.await { if let Err(err) = jh.await {
error!("{}", err); eprintln!("{}", err);
} }
trace!("ClientApi::stop: stopped"); trace!("ClientApi::stop: stopped");
} }
@ -225,7 +225,7 @@ impl ClientApi {
// Marshal json + newline => NDJSON // Marshal json + newline => NDJSON
let response_string = serialize_json(json_api::RecvMessage::Response(response)) + "\n"; let response_string = serialize_json(json_api::RecvMessage::Response(response)) + "\n";
if let Err(e) = responses_tx.send_async(response_string).await { if let Err(e) = responses_tx.send_async(response_string).await {
warn!("response not sent: {}", e) eprintln!("response not sent: {}", e)
} }
VeilidAPIResult::Ok(None) VeilidAPIResult::Ok(None)
} }
@ -272,7 +272,7 @@ impl ClientApi {
responses_tx: responses_tx.clone(), responses_tx: responses_tx.clone(),
}; };
if let Err(e) = requests_tx.send_async(Some(request_line)).await { if let Err(e) = requests_tx.send_async(Some(request_line)).await {
error!("failed to enqueue request: {}", e); eprintln!("failed to enqueue request: {}", e);
break; break;
} }
} }
@ -291,7 +291,7 @@ impl ClientApi {
) -> VeilidAPIResult<Option<RequestLine>> { ) -> VeilidAPIResult<Option<RequestLine>> {
while let Ok(resp) = responses_rx.recv_async().await { while let Ok(resp) = responses_rx.recv_async().await {
if let Err(e) = writer.write_all(resp.as_bytes()).await { if let Err(e) = writer.write_all(resp.as_bytes()).await {
error!("failed to write response: {}", e) eprintln!("failed to write response: {}", e)
} }
} }
VeilidAPIResult::Ok(None) VeilidAPIResult::Ok(None)
@ -302,7 +302,7 @@ impl ClientApi {
let peer_addr = match stream.peer_addr() { let peer_addr = match stream.peer_addr() {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
error!("can't get peer address: {}", e); eprintln!("can't get peer address: {}", e);
return; return;
} }
}; };
@ -310,7 +310,7 @@ impl ClientApi {
let local_addr = match stream.local_addr() { let local_addr = match stream.local_addr() {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
error!("can't get local address: {}", e); eprintln!("can't get local address: {}", e);
return; return;
} }
}; };
@ -387,7 +387,7 @@ impl ClientApi {
} }
Err(e) => { Err(e) => {
// Connection processing failure, abort // Connection processing failure, abort
error!("Connection processing failure: {}", e); eprintln!("Connection processing failure: {}", e);
break; break;
} }
}; };