diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d116bdb98..d1d54a1d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,31 @@ jobs: if-no-files-found: error retention-days: 10 + test_start_ursim: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' # Not needed with a .ruby-version, .tool-versions or mise.toml + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Setup Bats and bats libs + id: setup-bats + uses: bats-core/bats-action@3.0.0 + - name: Install Ruby dependencies + run: bundle update --bundler && bundle install + - name: Run unittests + shell: bash + env: + BATS_LIB_PATH: ${{ steps.setup-bats.outputs.lib-path }} + run: bundle exec bashcov --skip-uncovered bats tests/test_start_ursim.bats + - name: Upload reports to Codecov + uses: codecov/codecov-action@v5 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + flags: start_ursim + check_links: runs-on: ubuntu-latest steps: diff --git a/.simplecov b/.simplecov new file mode 100644 index 000000000..f40bc1c47 --- /dev/null +++ b/.simplecov @@ -0,0 +1,4 @@ +require 'simplecov' +require 'simplecov-cobertura' + +SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..327d39a62 --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +# Used vor bashcov coverage tool for the shell script +# frozen_string_literal: true + +source 'https://rubygems.org' + +gem 'bashcov' +gem 'simplecov' +gem 'simplecov-cobertura' diff --git a/scripts/start_ursim.sh b/scripts/start_ursim.sh index 014dc315a..ca14796f2 100755 --- a/scripts/start_ursim.sh +++ b/scripts/start_ursim.sh @@ -31,8 +31,17 @@ PERSISTENT_BASE="${HOME}/.ursim" URCAP_VERSION="1.0.5" IP_ADDRESS="192.168.56.101" -PORT_FORWARDING="-p 30001-30004:30001-30004 -p 29999:29999" +PORT_FORWARDING_WITH_DASHBOARD="-p 30001-30004:30001-30004 -p 29999:29999" +PORT_FORWARDING_WITHOUT_DASHBOARD="-p 30001-30004:30001-30004" CONTAINER_NAME="ursim" +TEST_RUN=false + +# TODO: Add support for more URSim PolyScopeX versions once released +# The PolyScopeX URSim containers follow the SDK versioning scheme. This maps those to marketing +# versions +#declare -Ag POLYSCOPE_X_MAP=( ["10.7.0"]="0.12.159" + #["10.8.0"]="not.there.yet") +declare -Ag POLYSCOPE_X_MAP=( ["10.7.0"]="0.12.159" ) help() { @@ -57,43 +66,84 @@ help() echo } -ROBOT_MODEL=ur5e -ROBOT_SERIES=e-series +ROBOT_MODEL="" +ROBOT_SERIES="" URSIM_VERSION=latest +PORT_FORWARDING="" +PROGRAM_STORAGE_ARG="" +URCAP_STORAGE_ARG="" DETACHED=false +verlte() +{ + [ "$1" = $(printf "$1\n$2" | sort -V | head -n1) ] +} -validate_model() +# Infer the robot series from a model name, e.g. ur3 -> cb3, ur5e -> e-series +# For Robots potentially bein e-series or polyscopex, this defaults to e-series +# $1 robot model e.g. ur5e +# sets ROBOT_SERIES +get_series_from_model() { - case $ROBOT_MODEL in + local robot_model=$1 + case $robot_model in ur3|ur5|ur10) - ROBOT_MODEL=${ROBOT_MODEL^^} ROBOT_SERIES=cb3 ;; ur3e|ur5e|ur10e|ur16e) - ROBOT_MODEL=${ROBOT_MODEL^^} - ROBOT_MODEL=$(echo ${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}) ROBOT_SERIES=e-series ;; ur20|ur30) - ROBOT_MODEL=${ROBOT_MODEL^^} ROBOT_SERIES=e-series ;; *) - echo "Not a valid robot model: $ROBOT_MODEL" - exit + echo "Not a valid robot model: $robot_model" + exit 1 ;; esac - URCAP_STORAGE="${PERSISTENT_BASE}/${ROBOT_SERIES}/urcaps" - PROGRAM_STORAGE="${PERSISTENT_BASE}/${ROBOT_SERIES}/${ROBOT_MODEL}/programs" } -verlte() +# Infer the robot series based on the URSim version +# uses $URSIM_VERSION +# sets ROBOT_SERIES +get_series_from_version() { - [ "$1" = $(printf "$1\n$2" | sort -V | head -n1) ] + if [[ "$URSIM_VERSION" == "latest" ]]; then + ROBOT_SERIES=e-series && return + else + verlte "10.0.0" "$URSIM_VERSION" && verlte "$URSIM_VERSION" "11.0.0" && ROBOT_SERIES=polyscopex && return + verlte "5.0.0" "$URSIM_VERSION" && verlte "$URSIM_VERSION" "6.0.0" && ROBOT_SERIES=e-series && return + verlte "3.0.0" "$URSIM_VERSION" && verlte "$URSIM_VERSION" "4.0.0" && ROBOT_SERIES=cb3 && return + fi + # If nothing above matched + echo "URSim version $URSIM_VERSION is not supported" + exit 1 +} + +# Bring the model into a format that is used internally by URSim +# $1 robot model e.g. ur5e +# $2 robot series e.g. e-series +# sets ROBOT_MODEL +strip_robot_model() +{ + local robot_model=$1 + local robot_series=$2 + if [[ "$robot_series" == "cb3" ]]; then + ROBOT_MODEL=${robot_model^^} + else + ROBOT_MODEL=${robot_model^^} + # UR20 and UR30 need no further adjustment + if [[ "$robot_model" = @(ur3e|ur5e|ur10e|ur16e) ]]; then + ROBOT_MODEL=$(echo "${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}") + fi + fi } -validate_ursim_version() +# Make sure that all parameters match together. This checks +# - URSIM_VERSION +# - ROBOT_MODEL +# - ROBOT_SERIES +validate_parameters() { local IMAGE_URSIM_VERSION # Inspect the image's URSim version if the image is locally available. This is especially @@ -111,129 +161,266 @@ validate_ursim_version() local MIN_VERSION="0.0" - case $ROBOT_SERIES in cb3) - verlte "4.0.0" "$IMAGE_URSIM_VERSION" && echo "$IMAGE_URSIM_VERSION is no valid CB3 version!" && exit - verlte "$MIN_CB3" "$IMAGE_URSIM_VERSION" && return 0 MIN_VERSION=$MIN_CB3 + if [[ $ROBOT_MODEL != @(ur3|ur5|ur10) ]]; then + echo "$ROBOT_MODEL is no valid CB3 model!" && exit 1 + fi + verlte "4.0.0" "$IMAGE_URSIM_VERSION" && echo "$IMAGE_URSIM_VERSION is no valid CB3 version!" && exit 1 + verlte "$MIN_CB3" "$IMAGE_URSIM_VERSION" && return 0 ;; e-series) - if [[ $ROBOT_MODEL == "UR20" ]]; then - verlte "$MIN_UR20" "$IMAGE_URSIM_VERSION" && return 0 + if [[ $ROBOT_MODEL != @(ur3e|ur5e|ur10e|ur16e|ur20|ur30) ]]; then + echo "$ROBOT_MODEL is no valid e-series model!" && exit 1 + fi + if [[ $ROBOT_MODEL == "ur20" ]]; then MIN_VERSION=$MIN_UR20 - elif [[ $ROBOT_MODEL == "UR30" ]]; then - verlte "$MIN_UR30" "$IMAGE_URSIM_VERSION" && return 0 + elif [[ $ROBOT_MODEL == "ur30" ]]; then MIN_VERSION=$MIN_UR30 else - verlte "$MIN_E_SERIES" "$URSIM_VERSION" && return 0 MIN_VERSION=$MIN_E_SERIES fi ;; + polyscopex) + if [[ -z "${POLYSCOPE_X_MAP[${URSIM_VERSION}]}" ]]; then + echo "URSim version $URSIM_VERSION is not supported" + exit 1 + fi + if [[ $ROBOT_MODEL != @(ur3e|ur5e|ur10e|ur16e|ur20|ur30) ]]; then + echo "$ROBOT_MODEL is no valid PolyscopeX model!" && exit 1 + else + return 0 + fi + ;; esac + verlte "$MIN_VERSION" "$URSIM_VERSION" && return 0 + echo "Illegal version given. For $ROBOT_SERIES $ROBOT_MODEL the software version must be greater or equal to $MIN_VERSION. Given version: $IMAGE_URSIM_VERSION." - exit + exit 1 } +post_setup_cb3() +{ + echo "Docker URSim is running" + echo -e "\nTo access PolyScope, open the following URL in a web browser." + printf "\n\n\thttp://%s:6080/vnc.html\n\n" "$IP_ADDRESS" +} +post_setup_e-series() +{ + post_setup_cb3 +} -while getopts ":hm:v:p:u:i:f:n:d" option; do - case $option in - h) # display Help - help - exit;; - m) # robot model - ROBOT_MODEL=${OPTARG} - ;; - v) # ursim_version - URSIM_VERSION=${OPTARG} - ;; - p) # program_folder - PROGRAM_STORAGE_ARG=${OPTARG} - ;; - u) # urcaps_folder - URCAP_STORAGE_ARG=${OPTARG} - ;; - i) # IP address - IP_ADDRESS=${OPTARG} - ;; - f) # forward ports - PORT_FORWARDING=${OPTARG} - ;; - n) # container_name - CONTAINER_NAME=${OPTARG} - ;; - d) # detached mode - DETACHED=true - ;; - \?) # invalid option - echo "Error: Invalid option" - help - exit;; - esac -done -validate_model -validate_ursim_version +post_setup_polyscopex() +{ -if [ -n "$PROGRAM_STORAGE_ARG" ]; then - PROGRAM_STORAGE="$PROGRAM_STORAGE_ARG" -fi -if [ -n "$URCAP_STORAGE_ARG" ]; then - URCAP_STORAGE="$URCAP_STORAGE_ARG" -fi + echo -ne "Starting URSim. Waiting for UrService to be up..." + curl_cmd="curl --retry-connrefused -f --write-out %{http_code} --silent --output /dev/null $IP_ADDRESS/universal-robots/urservice/api/v1/urcaps" + status_code=$(eval "$curl_cmd") -# Create local storage for programs and URCaps -mkdir -p "${URCAP_STORAGE}" -mkdir -p "${PROGRAM_STORAGE}" -URCAP_STORAGE=$(realpath "$URCAP_STORAGE") -PROGRAM_STORAGE=$(realpath "$PROGRAM_STORAGE") + until [ "$status_code" == "200" ] + do + sleep 1 + echo -ne "." + status_code=$(eval "$curl_cmd") + done -# Download external_control URCap -if [[ ! -f "${URCAP_STORAGE}/externalcontrol-${URCAP_VERSION}.jar" ]]; then - curl -L -o "${URCAP_STORAGE}/externalcontrol-${URCAP_VERSION}.jar" \ - "https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCap/releases/download/v${URCAP_VERSION}/externalcontrol-${URCAP_VERSION}.jar" -fi + echo ""; echo "UrService is up" + # TODO: Once we have a downloadable URCapX, we can use the following code to install it + #urcapx_file="${HOME}/Downloads/external-control-0.1.0.urcapx" + #echo "Installing URCapX $urcapx_file" + #curl --location --request POST --silent --output /dev/null "$IP_ADDRESS/universal-robots/urservice/api/v1/urcaps" --form urcapxFile=@"${urcapx_file}" + #echo ""; -# Check whether network already exists -docker network inspect ursim_net > /dev/null -if [ $? -eq 0 ]; then - echo "ursim_net already exists" -else - echo "Creating ursim_net" - docker network create --subnet=192.168.56.0/24 ursim_net -fi + echo -e "\nTo access PolyScopeX, open the following URL in a web browser." + printf "\n\n\thttp://%s\n\n" "$IP_ADDRESS" +} -docker_cmd="docker run --rm -d --net ursim_net --ip $IP_ADDRESS\ - -v ${URCAP_STORAGE}:/urcaps \ - -v ${PROGRAM_STORAGE}:/ursim/programs \ - -e ROBOT_MODEL=${ROBOT_MODEL} \ - $PORT_FORWARDING \ - --name $CONTAINER_NAME \ - universalrobots/ursim_${ROBOT_SERIES}:$URSIM_VERSION || exit" - -#echo $docker_cmd -$docker_cmd - -# Stop container when interrupted -TRAP_CMD=" -echo \"killing ursim\"; -docker container kill $CONTAINER_NAME >> /dev/null; -docker container wait $CONTAINER_NAME >> /dev/null; -echo \"done\"; -exit -" -trap "$TRAP_CMD" SIGINT SIGTERM - -echo "Docker URSim is running" -printf "\nTo access Polyscope, open the following URL in a web browser.\n\thttp://$IP_ADDRESS:6080/vnc.html\n\n" - -if [ "$DETACHED" = false ]; then -echo "To exit, press CTRL+C" - while : - do - sleep 1 +parse_arguments(){ + while getopts ":hm:v:p:u:i:f:n:dt" option; do + case $option in + h) # display Help + help + exit;; + m) # robot model + ROBOT_MODEL=${OPTARG} + ;; + v) # ursim_version + URSIM_VERSION=${OPTARG} + ;; + p) # program_folder + PROGRAM_STORAGE_ARG=${OPTARG} + ;; + u) # urcaps_folder + URCAP_STORAGE_ARG=${OPTARG} + ;; + i) # IP address + IP_ADDRESS=${OPTARG} + ;; + f) # forward ports + PORT_FORWARDING=${OPTARG} + ;; + n) # container_name + CONTAINER_NAME=${OPTARG} + ;; + d) # detached mode + DETACHED=true + ;; + t) # test run + TEST_RUN=true + ;; + \?) # invalid option + echo "Error: Invalid option" + help + exit;; + esac done -else - echo "To kill it, please execute 'docker stop $CONTAINER_NAME'" +} + +# As users can specify the model and / or URSim version, we can infer the rest of the parameters +# based on that. If no model is specified it should default to a ur5 / ur5e. +fill_information() { + # If no robot model is given, set a ur5 based on the series + if [ -z "$ROBOT_MODEL" ]; then + echo "No robot model given. Inferring from series" + if [ -z "$ROBOT_SERIES" ]; then + get_series_from_version + fi + if [[ "$ROBOT_SERIES" == "cb3" ]]; then + ROBOT_MODEL=ur5 + else + ROBOT_MODEL=ur5e + fi + elif [ "$URSIM_VERSION" == "latest" ]; then + get_series_from_model "$ROBOT_MODEL" + else + get_series_from_version + fi +} + +test_input_handling() { + parse_arguments "$@" + fill_information + + echo "Running in test mode" + echo "ROBOT_MODEL: $ROBOT_MODEL" + echo "ROBOT_SERIES: $ROBOT_SERIES" + echo "URSIM_VERSION: $URSIM_VERSION" + + validate_parameters +} + +main() { + parse_arguments "$@" + + + fill_information + + echo "ROBOT_MODEL: $ROBOT_MODEL" + echo "ROBOT_SERIES: $ROBOT_SERIES" + echo "URSIM_VERSION: $URSIM_VERSION" + + validate_parameters + + URCAP_STORAGE="${PERSISTENT_BASE}/${ROBOT_SERIES}/urcaps" + PROGRAM_STORAGE="${PERSISTENT_BASE}/${ROBOT_SERIES}/${ROBOT_MODEL}/programs" + + strip_robot_model "$ROBOT_MODEL" "$ROBOT_SERIES" + + if [ -z "$PORT_FORWARDING" ]; then + if [ "$ROBOT_SERIES" == "polyscopex" ]; then + PORT_FORWARDING=$PORT_FORWARDING_WITHOUT_DASHBOARD + else + PORT_FORWARDING=$PORT_FORWARDING_WITH_DASHBOARD + fi + fi + + DOCKER_ARGS="" + + if [ "$ROBOT_SERIES" == "polyscopex" ]; then + URSIM_VERSION=${POLYSCOPE_X_MAP[$URSIM_VERSION]} + DOCKER_ARGS="$DOCKER_ARGS --privileged" + fi + + if [ -n "$PROGRAM_STORAGE_ARG" ]; then + PROGRAM_STORAGE="$PROGRAM_STORAGE_ARG" + fi + if [ -n "$URCAP_STORAGE_ARG" ]; then + URCAP_STORAGE="$URCAP_STORAGE_ARG" + fi + + # Check whether network already exists + if ! docker network inspect ursim_net &> /dev/null; then + #if [ $? -ne 0 ]; then + echo "Creating ursim_net" + docker network create --subnet=192.168.56.0/24 ursim_net + fi + if [ "$ROBOT_SERIES" == "polyscopex" ]; then + mkdir -p "${PROGRAM_STORAGE}" + PROGRAM_STORAGE=$(realpath "$PROGRAM_STORAGE") + + docker_cmd="docker run --rm -d \ + --net ursim_net --ip $IP_ADDRESS \ + -v ${PROGRAM_STORAGE}:/ur/bin/backend/applications \ + -e ROBOT_TYPE=${ROBOT_MODEL} \ + $PORT_FORWARDING \ + $DOCKER_ARGS \ + --name $CONTAINER_NAME \ + universalrobots/ursim_${ROBOT_SERIES}:$URSIM_VERSION" + else + # Create local storage for programs and URCaps + mkdir -p "${URCAP_STORAGE}" + mkdir -p "${PROGRAM_STORAGE}" + URCAP_STORAGE=$(realpath "$URCAP_STORAGE") + PROGRAM_STORAGE=$(realpath "$PROGRAM_STORAGE") + + # Download external_control URCap + if [[ ! -f "${URCAP_STORAGE}/externalcontrol-${URCAP_VERSION}.jar" ]]; then + curl -L -o "${URCAP_STORAGE}/externalcontrol-${URCAP_VERSION}.jar" \ + "https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCap/releases/download/v${URCAP_VERSION}/externalcontrol-${URCAP_VERSION}.jar" + fi + docker_cmd="docker run --rm -d --net ursim_net --ip $IP_ADDRESS\ + -v ${URCAP_STORAGE}:/urcaps \ + -v ${PROGRAM_STORAGE}:/ursim/programs \ + -e ROBOT_MODEL=${ROBOT_MODEL} \ + $PORT_FORWARDING \ + --name $CONTAINER_NAME \ + universalrobots/ursim_${ROBOT_SERIES}:$URSIM_VERSION" + fi + + if [ "$TEST_RUN" = true ]; then + echo "$docker_cmd" | tr -s ' ' + exit + fi + $docker_cmd || exit 2 + + # Stop container when interrupted + TRAP_CMD=" + echo \"killing ursim\"; + docker container kill $CONTAINER_NAME >> /dev/null; + docker container wait $CONTAINER_NAME >> /dev/null; + echo \"done\"; + exit + " + trap "$TRAP_CMD" SIGINT SIGTERM + + + eval "post_setup_${ROBOT_SERIES}" + + if [ "$DETACHED" = false ]; then + echo "To exit, press CTRL+C" + while : + do + sleep 1 + done + else + echo "To kill it, please execute 'docker stop $CONTAINER_NAME'" + fi +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]] +then + main "$@" fi diff --git a/tests/test_start_ursim.bats b/tests/test_start_ursim.bats new file mode 100644 index 000000000..e3d5666b2 --- /dev/null +++ b/tests/test_start_ursim.bats @@ -0,0 +1,296 @@ +setup() { + # get the containing directory of this file + # use $BATS_TEST_FILENAME instead of ${BASH_SOURCE[0]} or $0, + # as those will point to the bats executable's location or the preprocessed file respectively + DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" + # make executables in src/ visible to PATH + source $DIR/../scripts/start_ursim.sh +} + +@test "test get_series_from_model" { + get_series_from_model "ur10e" + echo "ROBOT_SERIES: $ROBOT_SERIES" + [ "$ROBOT_SERIES" = "e-series" ] + + get_series_from_model "ur3" + echo "ROBOT_SERIES: $ROBOT_SERIES" + [ "$ROBOT_SERIES" = "cb3" ] + + get_series_from_model "ur20" + echo "ROBOT_SERIES: $ROBOT_SERIES" + [ "$ROBOT_SERIES" = "e-series" ] + + get_series_from_model "ur30" + echo "ROBOT_SERIES: $ROBOT_SERIES" + [ "$ROBOT_SERIES" = "e-series" ] + + run get_series_from_model "notarobotname" + [ $status -eq 1 ] +} + +@test "latest cb3" { + test_input_handling -m ur3 + [ "$ROBOT_MODEL" = "ur3" ] + [ "$ROBOT_SERIES" = "cb3" ] + [ "$URSIM_VERSION" = "latest" ] +} + +@test "specific cb3" { + test_input_handling -m ur10 -v 3.14.3 + [ "$ROBOT_MODEL" = "ur10" ] + [ "$ROBOT_SERIES" = "cb3" ] + [ "$URSIM_VERSION" = "3.14.3" ] +} + +@test "cb3_version too low fails" { + run test_input_handling -m ur10 -v 3.10.1 + echo "$output" + [ $status -eq 1 ] +} + +@test "cb3 version with e-series-model fails" { + run test_input_handling -m ur10e -v 3.12.1 + echo "$output" + [ $status -eq 1 ] + + run test_input_handling -m ur20 -v 3.12.1 + echo "$output" + [ $status -eq 1 ] +} + +@test "cb3 series from version string" { + test_input_handling -v 3.14.3 + [ "$ROBOT_SERIES" = "cb3" ] +} + +@test "latest e-series" { + test_input_handling -m ur5e + [ "$ROBOT_MODEL" = "ur5e" ] + [ "$ROBOT_SERIES" = "e-series" ] + [ "$URSIM_VERSION" = "latest" ] +} + +@test "specific e-series" { + test_input_handling -m ur10e -v 5.18.0 + [ "$ROBOT_MODEL" = "ur10e" ] + [ "$ROBOT_SERIES" = "e-series" ] + [ "$URSIM_VERSION" = "5.18.0" ] +} + +@test "e-series too low fails" { + run test_input_handling -m ur10e -v 5.1.0 + echo "$output" + [ $status -eq 1 ] +} + +@test "e-series version with cb3 model fails" { + run test_input_handling -m ur10 -v 5.21.0 + echo "$output" + [ $status -eq 1 ] +} + +@test "e-series series from version string" { + test_input_handling -v 5.18.0 + [ "$ROBOT_SERIES" = "e-series" ] +} + + +@test "specific polyscopex" { + test_input_handling -m ur10e -v 10.7.0 + [ "$ROBOT_MODEL" = "ur10e" ] + [ "$ROBOT_SERIES" = "polyscopex" ] + [ "$URSIM_VERSION" = "10.7.0" ] +} + +@test "polyscopex too low fails" { + run test_input_handling -m ur10e -v 10.1.0 + echo "$output" + [ $status -eq 1 ] +} + +@test "polyscopex version with cb3 model fails" { + run test_input_handling -m ur10 -v 10.7.0 + echo "$output" + [ $status -eq 1 ] +} + +@test "polyscopex series from version string" { + test_input_handling -v 10.7.0 + [ "$ROBOT_SERIES" = "polyscopex" ] +} + +@test "no arguments results in e-series ur5e" { + test_input_handling + [ "$ROBOT_MODEL" = "ur5e" ] + [ "$ROBOT_SERIES" = "e-series" ] + [ "$URSIM_VERSION" = "latest" ] +} + +@test "test ur20 min version" { + run test_input_handling -m ur20 -v 3.14.3 + echo "$output" + [ $status -eq 1 ] + run test_input_handling -m ur20 -v 5.13.9 + echo "$output" + [ $status -eq 1 ] + run test_input_handling -m ur20 -v 5.14.0 + echo "$output" + [ $status -eq 0 ] + run test_input_handling -m ur20 -v 10.7.0 + echo "$output" + [ $status -eq 0 ] +} + +@test "test ur30 min version" { + run test_input_handling -m ur30 -v 3.14.3 + echo "$output" + [ $status -eq 1 ] + run test_input_handling -m ur30 -v 5.14.9 + echo "$output" + [ $status -eq 1 ] + run test_input_handling -m ur30 -v 5.15.0 + echo "$output" + [ $status -eq 0 ] + run test_input_handling -m ur30 -v 10.7.0 + echo "$output" + [ $status -eq 0 ] +} + +@test "unsupported versions raise error" { + run main -v 1.2.3 -t + echo "$output" + [ $status -eq 1 ] + run main -v 2.0.0 -t + echo "$output" + [ $status -eq 1 ] + run main -v 10.1.0 -t + echo "$output" + [ $status -eq 1 ] + run main -v 6.99.123 -t + echo "$output" + [ $status -eq 1 ] +} + +@test "docker image polyscopex" { + run main -v 10.7.0 -t + echo "$output" + image=$(echo "$output" | tail -n1 | awk '{ print $NF }') + [ $status -eq 0 ] + [ "$image" == "universalrobots/ursim_polyscopex:0.12.159" ] +} + +@test "docker image cb3 latest" { + run main -m ur3 -t + echo "$output" + image=$(echo "$output" | tail -n1 | awk '{ print $NF }') + [ $status -eq 0 ] + [ "$image" == "universalrobots/ursim_cb3:latest" ] +} + +@test "docker image e-series latest" { + run main -m ur3e -t + echo "$output" + image=$(echo "$output" | tail -n1 | awk '{ print $NF }') + [ $status -eq 0 ] + [ "$image" == "universalrobots/ursim_e-series:latest" ] +} + +@test "docker image cb3 specific" { + run main -v 3.14.3 -t + echo "$output" + image=$(echo "$output" | tail -n1 | awk '{ print $NF }') + [ $status -eq 0 ] + [ "$image" == "universalrobots/ursim_cb3:3.14.3" ] +} + +@test "docker image e-series specific" { + run main -v 5.21.0 -t + echo "$output" + image=$(echo "$output" | tail -n1 | awk '{ print $NF }') + [ $status -eq 0 ] + [ "$image" == "universalrobots/ursim_e-series:5.21.0" ] +} + +@test "strip robot model cb3" { + run main -m ur3 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_MODEL=\w+' | cut -d '=' -f2) + [ "$model" == "UR3" ] + + run main -m ur10 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_MODEL=\w+' | cut -d '=' -f2) + [ "$model" == "UR10" ] +} + +@test "strip robot model e-series" { + run main -m ur3e -v 5.21.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_MODEL=\w+' | cut -d '=' -f2) + [ "$model" == "UR3" ] + + run main -m ur10e -v 5.21.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_MODEL=\w+' | cut -d '=' -f2) + [ "$model" == "UR10" ] + + run main -m ur30 -v 5.21.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_MODEL=\w+' | cut -d '=' -f2) + [ "$model" == "UR30" ] +} + +@test "strip robot model polyscopex" { + run main -m ur3e -v 10.7.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_TYPE=\w+' | cut -d '=' -f2) + [ "$model" == "UR3" ] + + run main -m ur10e -v 10.7.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_TYPE=\w+' | cut -d '=' -f2) + [ "$model" == "UR10" ] + + run main -m ur30 -v 10.7.0 -t + echo "$output" + [ $status -eq 0 ] + model=$(echo "$output" | tail -n1 | grep -Po '-e ROBOT_TYPE=\w+' | cut -d '=' -f2) + [ "$model" == "UR30" ] +} + +@test "strip_robot_model" { + strip_robot_model ur3 cb3 + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR3" ] + + strip_robot_model ur3e e-series + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR3" ] + + strip_robot_model ur3e polyscopex + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR3" ] + + strip_robot_model ur20 e-series + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR20" ] + + strip_robot_model ur30 e-series + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR30" ] + + strip_robot_model ur20 polyscopex + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR20" ] + + strip_robot_model ur30 polyscopex + echo "Robot model is: $ROBOT_MODEL" + [ "$ROBOT_MODEL" = "UR30" ] +}