From 4f4b952ef9e9f5e1fec2e0f282ae08614562c886 Mon Sep 17 00:00:00 2001 From: Jean-Roland Date: Fri, 14 Jun 2024 16:25:28 +0200 Subject: [PATCH] ci: add attachment test --- .github/workflows/build-check.yaml | 35 ++++++- CMakeLists.txt | 1 + tests/attachment.py | 157 +++++++++++++++++++++++++++++ tests/modularity.py | 27 +---- 4 files changed, 195 insertions(+), 25 deletions(-) create mode 100644 tests/attachment.py diff --git a/.github/workflows/build-check.yaml b/.github/workflows/build-check.yaml index 854c65e35..3e1f3d69d 100644 --- a/.github/workflows/build-check.yaml +++ b/.github/workflows/build-check.yaml @@ -115,7 +115,7 @@ jobs: run: | sudo apt install -y ninja-build CMAKE_GENERATOR=Ninja make - python3 ./build/tests/modularity.py --pub $Z_FEATURE_PUBLICATION --sub $Z_FEATURE_SUBSCRIPTION --queryable $Z_FEATURE_QUERYABLE --query $Z_FEATURE_QUERY --attachment 0 + python3 ./build/tests/modularity.py --pub $Z_FEATURE_PUBLICATION --sub $Z_FEATURE_SUBSCRIPTION --queryable $Z_FEATURE_QUERYABLE --query $Z_FEATURE_QUERY timeout-minutes: 5 env: Z_FEATURE_PUBLICATION: ${{ matrix.feature_publication }} @@ -195,3 +195,36 @@ jobs: - name: Kill Zenoh router if: always() run: kill ${{ steps.run-zenoh.outputs.zenohd-pid }} + + attachment_test: + needs: zenoh_build + name: Test attachments + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download Zenoh artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ needs.zenoh_build.outputs.artifact-name }} + + - name: Unzip Zenoh artifacts + run: unzip ${{ needs.zenoh_build.outputs.artifact-name }} -d zenoh-standalone + + - id: run-zenoh + name: Run Zenoh router + run: | + RUST_LOG=debug ./zenoh-standalone/zenohd & + echo "zenohd-pid=$!" >> $GITHUB_OUTPUT + + - name: Build project and run test + run: | + sudo apt install -y ninja-build + CMAKE_GENERATOR=Ninja make + python3 ./build/tests/attachment.py + timeout-minutes: 5 + + - name: Kill Zenoh router + if: always() + run: kill ${{ steps.run-zenoh.outputs.zenohd-pid }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c7af19fe..cf15dadea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,6 +361,7 @@ if(UNIX OR MSVC) configure_file(${PROJECT_SOURCE_DIR}/tests/raweth.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/raweth.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/fragment.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fragment.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/single_thread.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/single_thread.py COPYONLY) + configure_file(${PROJECT_SOURCE_DIR}/tests/attachment.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/attachment.py COPYONLY) enable_testing() add_test(z_data_struct_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_data_struct_test) diff --git a/tests/attachment.py b/tests/attachment.py new file mode 100644 index 000000000..2c85490af --- /dev/null +++ b/tests/attachment.py @@ -0,0 +1,157 @@ +import argparse +import os +from signal import SIGINT +import subprocess +import sys +import time + +# Specify the directory for the binaries +DIR_EXAMPLES = "build/examples" + + +def pub_and_sub(): + print("*** Pub & sub test ***") + test_status = 0 + + # Expected z_pub output & status + z_pub_expected_status = 0 + z_pub_expected_output = '''Opening session... +Declaring publisher for 'demo/example/zenoh-pico-pub'... +Press CTRL-C to quit... +Putting Data ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 1] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 2] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 3] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 4] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 5] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 6] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 7] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')...''' + + # Expected z_sub output & status + z_sub_expected_status = 0 + z_sub_expected_output = '''Opening session... +Declaring Subscriber on 'demo/example/**'... +Press CTRL-C to quit... +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 0 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 1] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 1 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 2] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 2 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 3] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 3 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 4] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 4 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 5] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 5 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 6] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 6 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 7] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 7 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 8 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!') + with attachment: + 0: source, C + 1: index, 9''' + + print("Start subscriber") + # Start z_sub in the background + z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub_attachment -n 10" + + z_sub_process = subprocess.Popen( + z_sub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Introduce a delay to ensure z_sub starts + time.sleep(2) + + print("Start publisher") + # Start z_pub + z_pub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub_attachment -n 10" + z_pub_process = subprocess.Popen( + z_pub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Wait for z_pub to finish + z_pub_process.wait() + + print("Stop subscriber") + time.sleep(2) + if z_sub_process.poll() is None: + # send SIGINT to group + z_sub_process_gid = os.getpgid(z_sub_process.pid) + os.killpg(z_sub_process_gid, SIGINT) + + # Wait for z_sub to finish + z_sub_process.wait() + + print("Check publisher status & output") + # Check the exit status of z_pub + z_pub_status = z_pub_process.returncode + if z_pub_status == z_pub_expected_status: + print("z_pub status valid") + else: + print(f"z_pub status invalid, expected: {z_pub_expected_status}, received: {z_pub_status}") + test_status = 1 + + # Check output of z_pub + z_pub_output = z_pub_process.stdout.read() + if z_pub_expected_output in z_pub_output: + print("z_pub output valid") + else: + print("z_pub output invalid:") + print(f"Expected: \"{z_pub_expected_output}\"") + print(f"Received: \"{z_pub_output}\"") + test_status = 1 + + print("Check subscriber status & output") + # Check the exit status of z_sub + z_sub_status = z_sub_process.returncode + if z_sub_status == z_sub_expected_status: + print("z_sub status valid") + else: + print(f"z_sub status invalid, expected: {z_sub_expected_status}, received: {z_sub_status}") + test_status = 1 + + # Check output of z_sub + z_sub_output = z_sub_process.stdout.read() + if z_sub_expected_output in z_sub_output: + print("z_sub output valid") + else: + print("z_sub output invalid:") + print(f"Expected: \"{z_sub_expected_output}\"") + print(f"Received: \"{z_sub_output}\"") + test_status = 1 + # Return value + return test_status + + +if __name__ == "__main__": + EXIT_STATUS = 0 + + # Test pub and sub examples + if pub_and_sub() == 1: + EXIT_STATUS = 1 + # Exit + sys.exit(EXIT_STATUS) diff --git a/tests/modularity.py b/tests/modularity.py index 226a04290..499ab817c 100644 --- a/tests/modularity.py +++ b/tests/modularity.py @@ -159,15 +159,7 @@ def query_and_queryable(args): if args.query == 1: z_query_expected_status = 0 if args.queryable == 1: - if args.attachment == 1: - z_query_expected_output = """Opening session... -Sending Query 'demo/example/**'... ->> Received ('demo/example/**': 'Queryable from Pico!') -Attachement found ->>> hello: world ->> Received query final notification""" - else: - z_query_expected_output = """Opening session... + z_query_expected_output = """Opening session... Sending Query 'demo/example/**'... >> Received ('demo/example/**': 'Queryable from Pico!') >> Received query final notification""" @@ -185,16 +177,7 @@ def query_and_queryable(args): if args.queryable == 1: z_queryable_expected_status = -2 if args.query == 1: - if args.attachment == 1: - z_queryable_expected_output = """Opening session... -Creating Queryable on 'demo/example/zenoh-pico-queryable'... -Press CTRL-C to quit... - >> [Queryable handler] Received Query 'demo/example/**' -Attachement found ->>> hi: there -""" - else: - z_queryable_expected_output = """Opening session... + z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... Press CTRL-C to quit... >> [Queryable handler] Received Query 'demo/example/**' @@ -297,13 +280,9 @@ def query_and_queryable(args): parser.add_argument("--sub", type=int, choices=[0, 1], help="Z_FEATURE_SUBSCRIPTION (0 or 1)") parser.add_argument("--queryable", type=int, choices=[0, 1], help="Z_FEATURE_QUERYABLE (0 or 1)") parser.add_argument("--query", type=int, choices=[0, 1], help="Z_FEATURE_QUERY (0 or 1)") - parser.add_argument("--attachment", type=int, choices=[0, 1], help="testing with attachment (0 or 1)") EXIT_STATUS = 0 prog_args = parser.parse_args() - print( - f"Args value, pub:{prog_args.pub}, sub:{prog_args.sub}, " - f"queryable:{prog_args.queryable}, query:{prog_args.query}, attachment:{prog_args.attachment}" - ) + print(f"Args value, pub:{prog_args.pub}, sub:{prog_args.sub}, " f"queryable:{prog_args.queryable}, query:{prog_args.query}") # Test pub and sub examples if pub_and_sub(prog_args) == 1: