From b18b5501d204dbc4dd2a444fc12a3f1e7a5fa519 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 24 Sep 2024 16:19:53 +0200 Subject: [PATCH 1/3] Add Fast-DDS CLI package Signed-off-by: Juan Lopez Fernandez --- fastdds_cli/fastdds_cli/__init__.py | 0 fastdds_cli/fastdds_cli/discovery_server.py | 10 +++++++ fastdds_cli/fastdds_cli/executor.py | 30 +++++++++++++++++++++ fastdds_cli/fastdds_cli/shm.py | 10 +++++++ fastdds_cli/fastdds_cli/xml.py | 10 +++++++ fastdds_cli/package.xml | 23 ++++++++++++++++ fastdds_cli/resource/fastdds_cli | 0 fastdds_cli/setup.cfg | 4 +++ fastdds_cli/setup.py | 28 +++++++++++++++++++ 9 files changed, 115 insertions(+) create mode 100644 fastdds_cli/fastdds_cli/__init__.py create mode 100644 fastdds_cli/fastdds_cli/discovery_server.py create mode 100644 fastdds_cli/fastdds_cli/executor.py create mode 100644 fastdds_cli/fastdds_cli/shm.py create mode 100644 fastdds_cli/fastdds_cli/xml.py create mode 100644 fastdds_cli/package.xml create mode 100644 fastdds_cli/resource/fastdds_cli create mode 100644 fastdds_cli/setup.cfg create mode 100644 fastdds_cli/setup.py diff --git a/fastdds_cli/fastdds_cli/__init__.py b/fastdds_cli/fastdds_cli/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fastdds_cli/fastdds_cli/discovery_server.py b/fastdds_cli/fastdds_cli/discovery_server.py new file mode 100644 index 00000000..b589f1ee --- /dev/null +++ b/fastdds_cli/fastdds_cli/discovery_server.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from fastdds_cli.executor import Executor + +def main(): + exec = Executor("discovery") + exec.execute() + +if __name__ == '__main__': + main() diff --git a/fastdds_cli/fastdds_cli/executor.py b/fastdds_cli/fastdds_cli/executor.py new file mode 100644 index 00000000..9f84732c --- /dev/null +++ b/fastdds_cli/fastdds_cli/executor.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import os +import signal +import subprocess +import sys + +class Executor: + + def __init__(self, command_arg): + self.command_arg = command_arg + + def execute(self): + + def signal_handler(sig, frame): + print("\nSignal captured, ending node execution...") + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + try: + + result = subprocess.run( + ["fastdds", self.command_arg] + sys.argv[1:], + env=os.environ + ) + + except Exception as e: + print('Error:', e) + return diff --git a/fastdds_cli/fastdds_cli/shm.py b/fastdds_cli/fastdds_cli/shm.py new file mode 100644 index 00000000..3da1c289 --- /dev/null +++ b/fastdds_cli/fastdds_cli/shm.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from fastdds_cli.executor import Executor + +def main(): + exec = Executor("shm") + exec.execute() + +if __name__ == '__main__': + main() diff --git a/fastdds_cli/fastdds_cli/xml.py b/fastdds_cli/fastdds_cli/xml.py new file mode 100644 index 00000000..343d9b99 --- /dev/null +++ b/fastdds_cli/fastdds_cli/xml.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from fastdds_cli.executor import Executor + +def main(): + exec = Executor("xml") + exec.execute() + +if __name__ == '__main__': + main() diff --git a/fastdds_cli/package.xml b/fastdds_cli/package.xml new file mode 100644 index 00000000..1fb6a0de --- /dev/null +++ b/fastdds_cli/package.xml @@ -0,0 +1,23 @@ + + + + fastdds_cli + 0.0.1 + + A command line interface for Fast DDS. + + juan + Apache 2.0 + + https://www.eprosima.com/ + https://github.com/eProsima/vulcanexus/issues + https://github.com/eProsima/vulcanexus + + fastdds + + python3-pytest + + + ament_python + + diff --git a/fastdds_cli/resource/fastdds_cli b/fastdds_cli/resource/fastdds_cli new file mode 100644 index 00000000..e69de29b diff --git a/fastdds_cli/setup.cfg b/fastdds_cli/setup.cfg new file mode 100644 index 00000000..e5786b9b --- /dev/null +++ b/fastdds_cli/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script_dir=$base/lib/fastdds_cli +[install] +install_scripts=$base/lib/fastdds_cli diff --git a/fastdds_cli/setup.py b/fastdds_cli/setup.py new file mode 100644 index 00000000..8dc75c90 --- /dev/null +++ b/fastdds_cli/setup.py @@ -0,0 +1,28 @@ +from setuptools import find_packages, setup + +package_name = 'fastdds_cli' + +setup( + name=package_name, + version='0.0.1', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/ament_index/resource_index/packages', + ['resource/' + package_name]), + ('share/' + package_name, ['package.xml']), + ], + install_requires=['setuptools'], + zip_safe=True, + maintainer='eprosima', + maintainer_email='juanlopez@eprosima.com', + description='Fast DDS CLI', + license='Apache License, Version 2.0', + tests_require=['pytest'], + entry_points={ + 'console_scripts': [ + 'discovery_server = fastdds_cli.discovery_server:main', + 'shm = fastdds_cli.shm:main', + 'xml = fastdds_cli.xml:main' + ], + }, +) From fd2ba0d46e4508a429124897b0461d762469bf33 Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Tue, 24 Sep 2024 16:21:00 +0200 Subject: [PATCH 2/3] Update Vulcanexus repo folder name Signed-off-by: Juan Lopez Fernandez --- docs/resources/scripts/linux_source_installation.bash | 4 ++-- vulcanexus.repos | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/resources/scripts/linux_source_installation.bash b/docs/resources/scripts/linux_source_installation.bash index 98b06229..0b1f31bb 100755 --- a/docs/resources/scripts/linux_source_installation.bash +++ b/docs/resources/scripts/linux_source_installation.bash @@ -119,8 +119,8 @@ vcs import --force src < vulcanexus.repos # Avoid compilation of some documentation and demo packages touch src/eProsima/Fast-DDS-QoS-Profiles-Manager/docs/COLCON_IGNORE -touch src/eProsima/Vulcanexus-Base/docs/COLCON_IGNORE -touch src/eProsima/Vulcanexus-Base/code/COLCON_IGNORE +touch src/eProsima/Vulcanexus/docs/COLCON_IGNORE +touch src/eProsima/Vulcanexus/code/COLCON_IGNORE ##! ##LINUX_SOURCE_VULCA_DEPS diff --git a/vulcanexus.repos b/vulcanexus.repos index df59cbbb..42800a5c 100644 --- a/vulcanexus.repos +++ b/vulcanexus.repos @@ -83,7 +83,7 @@ repositories: type: git url: https://github.com/eProsima/ShapesDemo-TypeSupport.git version: v1.0.0 - eProsima/Vulcanexus-Base: + eProsima/Vulcanexus: type: git url: https://github.com/eProsima/vulcanexus.git version: v3.3.0 From cace03c0f4efe6aeb74b00a8483b62e6fbdfd11a Mon Sep 17 00:00:00 2001 From: Juan Lopez Fernandez Date: Thu, 26 Sep 2024 15:12:17 +0200 Subject: [PATCH 3/3] Add Docker tests Signed-off-by: Juan Lopez Fernandez --- .github/docker/Dockerfile | 22 +++ .../docker/linux_bisource_installation.bash | 142 ++++++++++++++ .github/docker/run.bash | 7 + .github/workflows/test_docker.yaml | 65 +++++++ .../scripts/linux_bisource_installation.bash | 142 ++++++++++++++ vulcanexus_test/CMakeLists.txt | 28 +++ vulcanexus_test/compose/CMakeLists.txt | 51 ++++++ vulcanexus_test/compose/docker-compose.sh | 129 +++++++++++++ .../compose/scripts/execute_and_validate.py | 173 ++++++++++++++++++ vulcanexus_test/compose/scripts/log.py | 32 ++++ vulcanexus_test/compose/scripts/utils.py | 39 ++++ .../fastdds_cli/discovery_server/compose.yml | 12 ++ .../test_cases/fastdds_cli/shm/compose.yml | 12 ++ .../test_cases/fastdds_cli/xml/compose.yml | 12 ++ vulcanexus_test/package.xml | 21 +++ 15 files changed, 887 insertions(+) create mode 100644 .github/docker/Dockerfile create mode 100755 .github/docker/linux_bisource_installation.bash create mode 100644 .github/docker/run.bash create mode 100644 .github/workflows/test_docker.yaml create mode 100755 docs/resources/scripts/linux_bisource_installation.bash create mode 100644 vulcanexus_test/CMakeLists.txt create mode 100644 vulcanexus_test/compose/CMakeLists.txt create mode 100755 vulcanexus_test/compose/docker-compose.sh create mode 100644 vulcanexus_test/compose/scripts/execute_and_validate.py create mode 100644 vulcanexus_test/compose/scripts/log.py create mode 100644 vulcanexus_test/compose/scripts/utils.py create mode 100644 vulcanexus_test/compose/test_cases/fastdds_cli/discovery_server/compose.yml create mode 100644 vulcanexus_test/compose/test_cases/fastdds_cli/shm/compose.yml create mode 100644 vulcanexus_test/compose/test_cases/fastdds_cli/xml/compose.yml create mode 100644 vulcanexus_test/package.xml diff --git a/.github/docker/Dockerfile b/.github/docker/Dockerfile new file mode 100644 index 00000000..3794d1e6 --- /dev/null +++ b/.github/docker/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:22.04 +LABEL author=juanlopez@eprosima.com + +# Avoid interactuation with installation of some package that needs the locale. +ENV TZ=Europe/Madrid +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Avoids using interactions during building +ENV DEBIAN_FRONTEND=noninteractive + +# Use a bash shell so it is possigle to run things like `source` (required for colcon builds) +SHELL ["/bin/bash", "-c"] + +COPY linux_bisource_installation.bash /tmp/linux_bisource_installation.bash +RUN chmod +x /tmp/linux_bisource_installation.bash +RUN /tmp/linux_bisource_installation.bash +RUN rm /tmp/linux_bisource_installation.bash + +COPY run.bash /root/run.bash +RUN chmod +x /root/run.bash + +ENTRYPOINT ["/root/run.bash" ] diff --git a/.github/docker/linux_bisource_installation.bash b/.github/docker/linux_bisource_installation.bash new file mode 100755 index 00000000..ba75e510 --- /dev/null +++ b/.github/docker/linux_bisource_installation.bash @@ -0,0 +1,142 @@ +#!/bin/bash + +set -e + +if (( $EUID == 0 )); then + shopt -s expand_aliases + alias sudo='' +fi + +if !(locale | grep -e 'utf8' -e 'UTF-8') >/dev/null 2>&1; then + +##LINUX_BINARY_LOCALE +locale # check for UTF-8 + +sudo apt update && sudo apt install -y locales +# Any UTF-8 locale will work. Using en_US as an example +sudo locale-gen en_US en_US.UTF-8 +sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +export LANG=en_US.UTF-8 +##! + +locale + +fi + +##LINUX_BINARY_UBUNTU_UNIVERSE +apt-cache policy | grep universe + +# This should print something similar to: +# +# 500 http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages +# release v=22.04,o=Ubuntu,a=jammy,n=jammy,l=Ubuntu,c=universe,b=amd64 +# +# Otherwise run + +sudo apt install -y software-properties-common +sudo add-apt-repository universe -y +##! + +##LINUX_BINARY_KEYSTORE +sudo apt update && sudo apt install -y curl gnupg lsb-release +sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg +##! + +##LINUX_BINARY_REPO_SOURCELIST +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null +##! + +##LINUX_BINARY_ROS_UPDATE +sudo apt update -y +##! + +##LINUX_BINARY_ROS_INSTALL +sudo apt install -y ros-iron-desktop +##! + +##SETUP_ROS_ENV +source "/opt/ros/iron/setup.bash" +##! + +##CREATE_WORKSPACE +mkdir -p ~/vulcanexus_iron/src +cd ~/vulcanexus_iron +##! + +##LINUX_SOURCE_ROS2_DEPS +sudo apt update && sudo apt install -y \ + build-essential \ + cmake \ + git \ + python3-colcon-common-extensions \ + python3-flake8 \ + python3-flake8-blind-except \ + python3-flake8-builtins \ + python3-flake8-class-newline \ + python3-flake8-comprehensions \ + python3-flake8-deprecated \ + python3-flake8-docstrings \ + python3-flake8-import-order \ + python3-flake8-quotes \ + python3-pip \ + python3-pytest \ + python3-pytest-cov \ + python3-pytest-repeat \ + python3-pytest-rerunfailures \ + python3-rosdep \ + python3-setuptools \ + python3-vcstool \ + wget +##! + +##LINUX_SOURCE_VULCA_DEPS +sudo apt update && sudo apt install -y \ + libasio-dev \ + libdocopt-dev \ + libengine-pkcs11-openssl \ + liblog4cxx-dev \ + liblz4-dev \ + libp11-dev \ + libqt5charts5-dev \ + libssl-dev \ + libtinyxml2-dev \ + libxerces-c-dev \ + libyaml-cpp-dev \ + libzstd-dev \ + openjdk-8-jdk \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + qtbase5-dev \ + qtdeclarative5-dev \ + qtquickcontrols2-5-dev \ + swig +##! + +# Get Vulcanexus sources +wget https://raw.githubusercontent.com/eProsima/vulcanexus/iron/vulcanexus.repos +wget https://raw.githubusercontent.com/eProsima/vulcanexus/iron/colcon.meta +vcs import --force src < vulcanexus.repos + +# Avoid compilation of some documentation and demo packages +touch src/eProsima/Fast-DDS-QoS-Profiles-Manager/docs/COLCON_IGNORE +touch src/eProsima/Vulcanexus-Base/docs/COLCON_IGNORE +touch src/eProsima/Vulcanexus-Base/code/COLCON_IGNORE +##! + +################################################################################################# +################################################################################################# +################################################################################################# +###### TEMP ###### +cd /tmp +git clone https://github.com/eProsima/vulcanexus.git +cd vulcanexus +git checkout feature/fastdds-cli-package +mv fastdds_cli ~/vulcanexus_iron/src/eProsima/Vulcanexus-Base +################################################################################################# +################################################################################################# +################################################################################################# + +##LINUX_SOURCE_VULCA_COMPILE +cd ~/vulcanexus_iron +colcon build --cmake-args -DBUILD_TESTING=OFF +##! diff --git a/.github/docker/run.bash b/.github/docker/run.bash new file mode 100644 index 00000000..b866d7d1 --- /dev/null +++ b/.github/docker/run.bash @@ -0,0 +1,7 @@ +#!/bin/bash + +# Setup environment +source "/opt/ros/iron/setup.bash" +source "/root/vulcanexus_iron/install/setup.bash" + +exec "$@" diff --git a/.github/workflows/test_docker.yaml b/.github/workflows/test_docker.yaml new file mode 100644 index 00000000..5671269c --- /dev/null +++ b/.github/workflows/test_docker.yaml @@ -0,0 +1,65 @@ +name: test-docker-workflow +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + - humble + - iron + - jazzy + + schedule: + - cron: '0 0 * * *' + +jobs: + docker-tests: + runs-on: ubuntu-22.04 + + env: + VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE: "vulcanexus:ci" + + steps: + + - name: Sync repository + uses: eProsima/eProsima-CI/external/checkout@v0 + with: + path: src + # ref: main + ref: feature/fastdds-cli-package + + - name: Build Vulcanexus Docker image + run: | + cd ./src/.github/docker + docker build \ + --no-cache \ + -t ${{ env.VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE }} \ + -f Dockerfile . + + - name: Check if Docker images exist + run: | + [ -n "$(docker images -q ${{ env.VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE }})" ] || echo "Vulcanexus Docker image does not exist" + + - name: Install colcon + uses: eProsima/eProsima-CI/ubuntu/install_colcon@main + + - name: Install GTest + uses: eProsima/eProsima-CI/ubuntu/install_gtest@main + + - name: Compile docker tests + uses: eProsima/eProsima-CI/multiplatform/colcon_build@v0 + with: + workspace: ${{ github.workspace }} + colcon_build_args: --packages-up-to vulcanexus_test + cmake_args: -DBUILD_COMPOSE_TESTS=ON + + - name: Run tests + run: | + export VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE=${{ env.VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE }} + source install/setup.bash + colcon test \ + --packages-select vulcanexus_test \ + --event-handlers console_direct+ \ + --return-code-on-test-failure \ + --ctest-args \ + --timeout 120 diff --git a/docs/resources/scripts/linux_bisource_installation.bash b/docs/resources/scripts/linux_bisource_installation.bash new file mode 100755 index 00000000..ba75e510 --- /dev/null +++ b/docs/resources/scripts/linux_bisource_installation.bash @@ -0,0 +1,142 @@ +#!/bin/bash + +set -e + +if (( $EUID == 0 )); then + shopt -s expand_aliases + alias sudo='' +fi + +if !(locale | grep -e 'utf8' -e 'UTF-8') >/dev/null 2>&1; then + +##LINUX_BINARY_LOCALE +locale # check for UTF-8 + +sudo apt update && sudo apt install -y locales +# Any UTF-8 locale will work. Using en_US as an example +sudo locale-gen en_US en_US.UTF-8 +sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +export LANG=en_US.UTF-8 +##! + +locale + +fi + +##LINUX_BINARY_UBUNTU_UNIVERSE +apt-cache policy | grep universe + +# This should print something similar to: +# +# 500 http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 Packages +# release v=22.04,o=Ubuntu,a=jammy,n=jammy,l=Ubuntu,c=universe,b=amd64 +# +# Otherwise run + +sudo apt install -y software-properties-common +sudo add-apt-repository universe -y +##! + +##LINUX_BINARY_KEYSTORE +sudo apt update && sudo apt install -y curl gnupg lsb-release +sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg +##! + +##LINUX_BINARY_REPO_SOURCELIST +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null +##! + +##LINUX_BINARY_ROS_UPDATE +sudo apt update -y +##! + +##LINUX_BINARY_ROS_INSTALL +sudo apt install -y ros-iron-desktop +##! + +##SETUP_ROS_ENV +source "/opt/ros/iron/setup.bash" +##! + +##CREATE_WORKSPACE +mkdir -p ~/vulcanexus_iron/src +cd ~/vulcanexus_iron +##! + +##LINUX_SOURCE_ROS2_DEPS +sudo apt update && sudo apt install -y \ + build-essential \ + cmake \ + git \ + python3-colcon-common-extensions \ + python3-flake8 \ + python3-flake8-blind-except \ + python3-flake8-builtins \ + python3-flake8-class-newline \ + python3-flake8-comprehensions \ + python3-flake8-deprecated \ + python3-flake8-docstrings \ + python3-flake8-import-order \ + python3-flake8-quotes \ + python3-pip \ + python3-pytest \ + python3-pytest-cov \ + python3-pytest-repeat \ + python3-pytest-rerunfailures \ + python3-rosdep \ + python3-setuptools \ + python3-vcstool \ + wget +##! + +##LINUX_SOURCE_VULCA_DEPS +sudo apt update && sudo apt install -y \ + libasio-dev \ + libdocopt-dev \ + libengine-pkcs11-openssl \ + liblog4cxx-dev \ + liblz4-dev \ + libp11-dev \ + libqt5charts5-dev \ + libssl-dev \ + libtinyxml2-dev \ + libxerces-c-dev \ + libyaml-cpp-dev \ + libzstd-dev \ + openjdk-8-jdk \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + qtbase5-dev \ + qtdeclarative5-dev \ + qtquickcontrols2-5-dev \ + swig +##! + +# Get Vulcanexus sources +wget https://raw.githubusercontent.com/eProsima/vulcanexus/iron/vulcanexus.repos +wget https://raw.githubusercontent.com/eProsima/vulcanexus/iron/colcon.meta +vcs import --force src < vulcanexus.repos + +# Avoid compilation of some documentation and demo packages +touch src/eProsima/Fast-DDS-QoS-Profiles-Manager/docs/COLCON_IGNORE +touch src/eProsima/Vulcanexus-Base/docs/COLCON_IGNORE +touch src/eProsima/Vulcanexus-Base/code/COLCON_IGNORE +##! + +################################################################################################# +################################################################################################# +################################################################################################# +###### TEMP ###### +cd /tmp +git clone https://github.com/eProsima/vulcanexus.git +cd vulcanexus +git checkout feature/fastdds-cli-package +mv fastdds_cli ~/vulcanexus_iron/src/eProsima/Vulcanexus-Base +################################################################################################# +################################################################################################# +################################################################################################# + +##LINUX_SOURCE_VULCA_COMPILE +cd ~/vulcanexus_iron +colcon build --cmake-args -DBUILD_TESTING=OFF +##! diff --git a/vulcanexus_test/CMakeLists.txt b/vulcanexus_test/CMakeLists.txt new file mode 100644 index 00000000..a19e4a4f --- /dev/null +++ b/vulcanexus_test/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +cmake_minimum_required(VERSION 3.8) +project(vulcanexus_test) + +############################################################################### +# Test +############################################################################### +# Compile tests if CMake options requires it +option(BUILD_COMPOSE_TESTS "Compile compose tests" OFF) + +if(BUILD_COMPOSE_TESTS) + enable_testing() + message(STATUS "Compiling Compose Tests of ${PROJECT_NAME}") + add_subdirectory(compose) +endif() diff --git a/vulcanexus_test/compose/CMakeLists.txt b/vulcanexus_test/compose/CMakeLists.txt new file mode 100644 index 00000000..9201aa1d --- /dev/null +++ b/vulcanexus_test/compose/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Name of files to test +set(TESTS + fastdds_cli/discovery_server + fastdds_cli/shm + fastdds_cli/xml +) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test_cases DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docker-compose.sh + ${CMAKE_CURRENT_BINARY_DIR}/docker-compose.sh + COPYONLY) + +file( + COPY + ${CMAKE_CURRENT_SOURCE_DIR}/scripts + DESTINATION + ${CMAKE_CURRENT_BINARY_DIR} + ) + +find_program (BASH_PROGRAM bash) + +# Populate the tests +foreach(TEST IN LISTS TESTS) + + set(TEST_NAME "vulcanexus.compose.${TEST}") + string(REPLACE "/" "_" TEST_NAME ${TEST_NAME}) + + message(STATUS "Building test ${TEST_NAME}") + + add_test( + NAME ${TEST_NAME} + COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_BINARY_DIR}/docker-compose.sh + -t ${TEST_NAME} + -f ${CMAKE_CURRENT_BINARY_DIR}/test_cases/${TEST}/compose.yml) + +endforeach() diff --git a/vulcanexus_test/compose/docker-compose.sh b/vulcanexus_test/compose/docker-compose.sh new file mode 100755 index 00000000..49f65e46 --- /dev/null +++ b/vulcanexus_test/compose/docker-compose.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +print_usage() +{ + echo "----------------------------------------------------------------------------------" + echo "Script that retrieves the exit code of the Vulcanexus docker compose tests." + echo "----------------------------------------------------------------------------------" + echo "REQUIRED ARGUMENTS:" + echo " -t --test-name [string] Name of the Vulcanexus test." + echo " -f --compose-file [filename] The Docker compose file" + echo "" + echo "OPTIONAL ARGUMENTS:" + echo " -d --debug Print debug traces." + echo " -h --help Print this same help." + echo "" + echo "EXAMPLE: bash docker-compose.sh -t -f " + echo "" + exit ${1} +} + +parse_options() +{ + + if (($# == 0)) ; then print_usage 1 ; fi + if [ $? != 0 ] ; then print_usage 1 ; fi + + TEMP=`getopt \ + -o t:f:hd \ + --long test-name:,compose-file:,help,debug \ + -n 'Error' \ + -- "$@"` + + eval set -- "${TEMP}" + + TEST_NAME= + COMPOSE_FILE= + DEBUG=false + while true; do + case "$1" in + # Mandatory args + -t | --test-name ) TEST_NAME="$2"; shift 2;; + -f | --compose-file ) COMPOSE_FILE="$2"; shift 2;; + # Optional args + -h | --help ) print_usage 0; shift ;; + -d | --debug ) DEBUG=true; shift ;; + # Wrong args + -- ) shift; break ;; + * ) break ;; + esac + done + + if [[ ${TEST_NAME} == "" ]] + then + echo "----------------------------------------------------------------------------------" + echo "No test name defined" + print_usage 1 + fi + + if [[ ${COMPOSE_FILE} == "" ]] + then + echo "----------------------------------------------------------------------------------" + echo "No Docker compose file provided" + print_usage 1 + fi + + if [[ ! -f "${COMPOSE_FILE}" ]] + then + echo "----------------------------------------------------------------------------------" + echo "-f --compose-file must specify an existing file" + print_usage 1 + fi +} + +full_path () +{ + if [[ -f ${1} ]] + then + echo "$(realpath ${1})" + else + echo "$(dirname ${1})" + fi +} + +main () +{ + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" + parse_options ${@} + EXIT_CODE=0 + + set -e + + echo "Docker compose file: ${COMPOSE_FILE}" + + # Run docker compose + docker compose -f ${COMPOSE_FILE} up + + # First this command gets the ids of every container listed on the docker compose file. + # Then it checks the exist code of every container listed before, remove the exit codes equal + # to 0 and count how many containers exited with an exit code different than 0. + # As a result, the EXIT_CODE is the number of containers that exited with an exit code + # different than 0. + EXIT_CODE=$(docker compose -f ${COMPOSE_FILE} ps -aq | + xargs docker inspect -f '{{ .State.ExitCode }}' | + grep -vx "^0$" | wc -l | tr -d ' ') + + echo "${TEST_NAME} exited with code ${EXIT_CODE}" + + # Clean containers and networks before exiting and do not prompt for confirmation + docker container prune --force + docker network prune --force + + exit ${EXIT_CODE} +} + +main ${@} diff --git a/vulcanexus_test/compose/scripts/execute_and_validate.py b/vulcanexus_test/compose/scripts/execute_and_validate.py new file mode 100644 index 00000000..d8dd53b0 --- /dev/null +++ b/vulcanexus_test/compose/scripts/execute_and_validate.py @@ -0,0 +1,173 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from enum import Enum +from typing import List +import argparse +import signal +import subprocess +import time + +import log + +import utils + + +DESCRIPTION = """Script to run commands and validate their output.""" +USAGE = ('python3 execute_and_validate.py ' + '[-c ] [-t ] [-d]') + + +class ReturnCode(Enum): + """Enumeration for return codes of this script.""" + + SUCCESS = 0 + TIMEOUT = 1 + HARD_TIMEOUT = 2 + COMMAND_FAIL = 3 + STDERR_OUTPUT = 4 + + +def parse_options(): + """ + Parse arguments. + + :return: The arguments parsed. + """ + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + add_help=True, + description=(DESCRIPTION), + usage=(USAGE) + ) + parser.add_argument( + '-c', + '--command', + type=str, + help='Command to execute.' + ) + parser.add_argument( + '-t', + '--timeout', + type=int, + default=5, + help='Timeout for the command execution.' + ) + parser.add_argument( + '--delay', + type=float, + default=0, + help='Time to wait before starting execution.' + ) + parser.add_argument( + '-d', + '--debug', + action='store_true', + help='Print test debugging info.' + ) + + return parser.parse_args() + + +def run_command( + command: 'list[str]', + timeout: float, + delay: float = 0, + timeout_as_error: bool = True): + """ + Run command with timeout. + + :param command: Command to run in list format + :param timeout: Timeout for the process + :return: + - ret_code - The process exit code + - stdout - Output of the process + - stderr - Error output of the process + """ + ret_code = ReturnCode.SUCCESS + + # Delay + utils.delay(delay) + + log.logger.debug(f'Running command: {command}') + + proc = subprocess.Popen(command, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + + try: + proc.wait(timeout=timeout) + + except subprocess.TimeoutExpired: + if timeout_as_error: + log.logger.error( + 'Timeout expired, killing process...') + proc.send_signal(signal.SIGINT) + ret_code = ReturnCode.TIMEOUT + + else: + proc.send_signal(signal.SIGINT) + + else: + if not timeout_as_error: + log.logger.error('Command finished before expected.') + ret_code = ReturnCode.COMMAND_FAIL + + # Wait a minimum elapsed time to the signal to be received + time.sleep(0.2) + + stdout, stderr = proc.communicate() + + # Check whether SIGINT was able to terminate the process + if proc.poll() is None: + # SIGINT couldn't terminate the process + log.logger.error( + 'SIGINT could not kill process. ' + 'Killing process hardly...') + proc.kill() + ret_code = ReturnCode.HARD_TIMEOUT + + log.logger.info(f'Process exited with code {proc.returncode}') + + # Set return code to COMMAND_FAIL if the process returned 1 + ret_code = ReturnCode.COMMAND_FAIL if proc.returncode == 1 else ret_code + + if not stdout: + stdout = '' + if not stderr: + stderr = '' + + return (ret_code, stdout, stderr) + + +if __name__ == '__main__': + + # Parse arguments + args = parse_options() + + # Set log level + if args.debug: + log.activate_debug() + + command = args.command.split() + + (ret_code, stdout, stderr) = run_command( + command=command, + timeout=args.timeout, + delay=args.delay) + + log.logger.info(f'Command exited with code {ret_code}') + + exit(ret_code.value) diff --git a/vulcanexus_test/compose/scripts/log.py b/vulcanexus_test/compose/scripts/log.py new file mode 100644 index 00000000..8ff5d317 --- /dev/null +++ b/vulcanexus_test/compose/scripts/log.py @@ -0,0 +1,32 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +# Create a custom logger +logger = logging.getLogger('VALIDATION') +# Create handlers +l_handler = logging.StreamHandler() +# Create formatters and add it to handlers +l_format = '[%(asctime)s][%(name)s][%(levelname)s] %(message)s' +l_format = logging.Formatter(l_format) +l_handler.setFormatter(l_format) +# Add handlers to the logger +logger.addHandler(l_handler) +logger.setLevel(logging.INFO) + + +def activate_debug(): + """Activate debug mode.""" + logger.setLevel(logging.DEBUG) diff --git a/vulcanexus_test/compose/scripts/utils.py b/vulcanexus_test/compose/scripts/utils.py new file mode 100644 index 00000000..605d8dd8 --- /dev/null +++ b/vulcanexus_test/compose/scripts/utils.py @@ -0,0 +1,39 @@ +# Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import random +import time + + +def sleep_random_time( + min_time_seconds: int, + max_time_seconds: int): + """Sleep a random time between min_time_seconds and max_time in seconds.""" + time.sleep( + min_time_seconds + + ((max_time_seconds - min_time_seconds) * random.random())) + + +def print_with_timestamp( + msg: str): + """Print a message with a timestamp.""" + print(f'{time.time()}$ {msg}') + # This has been made by copilot... Respect + + +def delay( + time_s: float): + """Wait for time_s seconds.""" + if (time_s > 0): + time.sleep(time_s) diff --git a/vulcanexus_test/compose/test_cases/fastdds_cli/discovery_server/compose.yml b/vulcanexus_test/compose/test_cases/fastdds_cli/discovery_server/compose.yml new file mode 100644 index 00000000..03e46ace --- /dev/null +++ b/vulcanexus_test/compose/test_cases/fastdds_cli/discovery_server/compose.yml @@ -0,0 +1,12 @@ +# Test description: +# This test checks that running fastdds CLI discovery option results in no error (process return code is not 1). +# + +services: + + vulcanexus: + image: ${VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE} + container_name: vulcanexus + volumes: + - ../../../scripts:/scripts + command: python3 /scripts/execute_and_validate.py --command "timeout 1 ros2 run fastdds_cli discovery_server" diff --git a/vulcanexus_test/compose/test_cases/fastdds_cli/shm/compose.yml b/vulcanexus_test/compose/test_cases/fastdds_cli/shm/compose.yml new file mode 100644 index 00000000..6afc73e5 --- /dev/null +++ b/vulcanexus_test/compose/test_cases/fastdds_cli/shm/compose.yml @@ -0,0 +1,12 @@ +# Test description: +# This test checks that running fastdds CLI shm option results in no error (process return code is not 1). +# + +services: + + vulcanexus: + image: ${VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE} + container_name: vulcanexus + volumes: + - ../../../scripts:/scripts + command: python3 /scripts/execute_and_validate.py --command "ros2 run fastdds_cli shm" diff --git a/vulcanexus_test/compose/test_cases/fastdds_cli/xml/compose.yml b/vulcanexus_test/compose/test_cases/fastdds_cli/xml/compose.yml new file mode 100644 index 00000000..90b1f876 --- /dev/null +++ b/vulcanexus_test/compose/test_cases/fastdds_cli/xml/compose.yml @@ -0,0 +1,12 @@ +# Test description: +# This test checks that running fastdds CLI xml option results in no error (process return code is not 1). +# + +services: + + vulcanexus: + image: ${VULCANEXUS_COMPOSE_TEST_DOCKER_IMAGE} + container_name: vulcanexus + volumes: + - ../../../scripts:/scripts + command: python3 /scripts/execute_and_validate.py --command "ros2 run fastdds_cli xml" diff --git a/vulcanexus_test/package.xml b/vulcanexus_test/package.xml new file mode 100644 index 00000000..f996be43 --- /dev/null +++ b/vulcanexus_test/package.xml @@ -0,0 +1,21 @@ + + + + vulcanexus_test + 0.0.1 + + Vulcanexus tests. + + Juan López + Apache 2.0 + + https://www.eprosima.com/ + https://github.com/eProsima/vulcanexus/issues + https://github.com/eProsima/vulcanexus + + cmake + + + cmake + +