From f6279c23ac5f124f64d530631d3027d05c9c4d28 Mon Sep 17 00:00:00 2001 From: Khwahish Patel Date: Sun, 2 Mar 2025 18:08:34 +0530 Subject: [PATCH] added : demos to test ci --- .github/workflows/tox.yml | 2 +- newsfragments/524.feature.rst | 1 + tests/core/examples/test_examples.py | 118 ++++++++++++++++++++++++--- tox.ini | 1 + 4 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 newsfragments/524.feature.rst diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 9df47a9c..3915538a 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: python: ['3.9', '3.10', '3.11', '3.12', '3.13'] - toxenv: [core, lint, wheel] + toxenv: [core, lint, wheel, demos] include: - python: '3.10' toxenv: docs diff --git a/newsfragments/524.feature.rst b/newsfragments/524.feature.rst new file mode 100644 index 00000000..910341be --- /dev/null +++ b/newsfragments/524.feature.rst @@ -0,0 +1 @@ +Added automated testing of ``demo`` applications as part of CI to prevent demos from breaking silently. Tests are located in `tests/core/examples/test_examples.py`. diff --git a/tests/core/examples/test_examples.py b/tests/core/examples/test_examples.py index 56997bad..6120572d 100644 --- a/tests/core/examples/test_examples.py +++ b/tests/core/examples/test_examples.py @@ -14,7 +14,9 @@ from libp2p.tools.utils import ( MAX_READ_LEN, ) -PROTOCOL_ID = "/chat/1.0.0" +CHAT_PROTOCOL_ID = "/chat/1.0.0" +ECHO_PROTOCOL_ID = "/echo/1.0.0" +PING_PROTOCOL_ID = "/ipfs/ping/1.0.0" async def hello_world(host_a, host_b): @@ -27,11 +29,11 @@ async def hello_world(host_a, host_b): await stream.write(hello_world_from_host_a) await stream.close() - host_a.set_stream_handler(PROTOCOL_ID, stream_handler) + host_a.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler) # Start a stream with the destination. # Multiaddress of the destination peer is fetched from the peerstore using 'peerId'. - stream = await host_b.new_stream(host_a.get_id(), [PROTOCOL_ID]) + stream = await host_b.new_stream(host_a.get_id(), [CHAT_PROTOCOL_ID]) await stream.write(hello_world_from_host_b) read = await stream.read(MAX_READ_LEN) assert read == hello_world_from_host_a @@ -46,11 +48,11 @@ async def connect_write(host_a, host_b): for message in messages: received.append((await stream.read(len(message))).decode()) - host_a.set_stream_handler(PROTOCOL_ID, stream_handler) + host_a.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler) # Start a stream with the destination. # Multiaddress of the destination peer is fetched from the peerstore using 'peerId'. - stream = await host_b.new_stream(host_a.get_id(), [PROTOCOL_ID]) + stream = await host_b.new_stream(host_a.get_id(), [CHAT_PROTOCOL_ID]) for message in messages: await stream.write(message.encode()) @@ -69,11 +71,11 @@ async def connect_read(host_a, host_b): await stream.write(message) await stream.close() - host_a.set_stream_handler(PROTOCOL_ID, stream_handler) + host_a.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler) # Start a stream with the destination. # Multiaddress of the destination peer is fetched from the peerstore using 'peerId'. - stream = await host_b.new_stream(host_a.get_id(), [PROTOCOL_ID]) + stream = await host_b.new_stream(host_a.get_id(), [CHAT_PROTOCOL_ID]) received = [] for message in messages: received.append(await stream.read(len(message))) @@ -89,18 +91,114 @@ async def no_common_protocol(host_a, host_b): await stream.write(message) await stream.close() - host_a.set_stream_handler(PROTOCOL_ID, stream_handler) + host_a.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler) # try to creates a new new with a procotol not known by the other host with pytest.raises(StreamFailure): await host_b.new_stream(host_a.get_id(), ["/fakeproto/0.0.1"]) +async def chat_demo(host_a, host_b): + messages_received_a = [] + messages_received_b = [] + + async def stream_handler_a(stream): + while True: + try: + data = await stream.read(MAX_READ_LEN) + if not data: + break + messages_received_a.append(data) + await stream.write(b"ack_a:" + data) + except Exception: + break + + async def stream_handler_b(stream): + while True: + try: + data = await stream.read(MAX_READ_LEN) + if not data: + break + messages_received_b.append(data) + await stream.write(b"ack_b:" + data) + except Exception: + break + + host_a.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler_a) + host_b.set_stream_handler(CHAT_PROTOCOL_ID, stream_handler_b) + + stream_a = await host_a.new_stream(host_b.get_id(), [CHAT_PROTOCOL_ID]) + stream_b = await host_b.new_stream(host_a.get_id(), [CHAT_PROTOCOL_ID]) + + test_messages = [b"hello", b"world", b"test"] + for msg in test_messages: + await stream_a.write(msg) + await stream_b.write(msg) + + await trio.sleep(0.1) + + assert len(messages_received_a) == len(test_messages) + assert len(messages_received_b) == len(test_messages) + + +async def echo_demo(host_a, host_b): + async def echo_handler(stream): + while True: + try: + data = await stream.read(MAX_READ_LEN) + if not data: + break + await stream.write(data) + except Exception: + break + + host_b.set_stream_handler(ECHO_PROTOCOL_ID, echo_handler) + + stream = await host_a.new_stream(host_b.get_id(), [ECHO_PROTOCOL_ID]) + test_message = b"hello, echo!" + + await stream.write(test_message) + response = await stream.read(MAX_READ_LEN) + + assert response == test_message + + +async def ping_demo(host_a, host_b): + async def ping_handler(stream): + while True: + try: + data = await stream.read(32) # PING_LENGTH = 32 + if not data: + break + await stream.write(data) + except Exception: + break + + host_b.set_stream_handler(PING_PROTOCOL_ID, ping_handler) + + stream = await host_a.new_stream(host_b.get_id(), [PING_PROTOCOL_ID]) + ping_data = b"x" * 32 # 32 bytes of data + + await stream.write(ping_data) + response = await stream.read(32) + + assert response == ping_data + + @pytest.mark.parametrize( - "test", [(hello_world), (connect_write), (connect_read), (no_common_protocol)] + "test", + [ + hello_world, + connect_write, + connect_read, + no_common_protocol, + chat_demo, + echo_demo, + ping_demo, + ], ) @pytest.mark.trio -async def test_chat(test, security_protocol): +async def test_protocols(test, security_protocol): print("!@# ", security_protocol) async with HostFactory.create_batch_and_listen( 2, security_protocol=security_protocol diff --git a/tox.ini b/tox.ini index f7e7fb42..983c3ee4 100644 --- a/tox.ini +++ b/tox.ini @@ -22,6 +22,7 @@ commands= core: pytest {posargs:tests/core} interop: pytest {posargs:tests/interop} docs: make check-docs-ci + demos: pytest {posargs:tests/core/examples/test_examples.py} basepython= docs: python windows-wheel: python