diff --git a/scripts/dev_scripts/integration_tests_docker.sh b/scripts/dev_scripts/integration_tests_docker.sh index b0afebbae..20ecd3327 100755 --- a/scripts/dev_scripts/integration_tests_docker.sh +++ b/scripts/dev_scripts/integration_tests_docker.sh @@ -15,6 +15,7 @@ RUN_MACARON_SCRIPT=$2 # The scripts to compare the results of the integration tests. COMPARE_DEPS=$WORKSPACE/tests/dependency_analyzer/compare_dependencies.py COMPARE_JSON_OUT=$WORKSPACE/tests/e2e/compare_e2e_result.py +UNIT_TEST_SCRIPT=$WORKSPACE/scripts/dev_scripts/test_run_macaron_sh.py RESULT_CODE=0 @@ -23,6 +24,11 @@ function log_fail() { RESULT_CODE=1 } +echo -e "\n----------------------------------------------------------------------------------" +echo "Run unit tests for the run_macaron.sh script" +$UNIT_TEST_SCRIPT || log_fail +echo -e "\n----------------------------------------------------------------------------------" + echo -e "\n----------------------------------------------------------------------------------" echo "timyarkov/multibuild_test: Analyzing the repo path, the branch name and the commit digest" echo "with dependency resolution using cyclonedx Gradle plugin (default)." diff --git a/scripts/dev_scripts/test_run_macaron_sh.py b/scripts/dev_scripts/test_run_macaron_sh.py new file mode 100755 index 000000000..7cba609bf --- /dev/null +++ b/scripts/dev_scripts/test_run_macaron_sh.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2023 - 2023, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/. + +"""Tests for the ``run_macaron.sh`` script. + +Note: this script is compatible with python >=3.6. +""" + +import subprocess +import sys +from collections import namedtuple + + +def test_macaron_command() -> int: + """Test if the ``macaron`` command in the container receives the correct arguments.""" + + TestCase = namedtuple("TestCase", ["name", "script_args", "expected_macaron_args"]) + + test_cases = [ + TestCase( + name="'-h' as main argument", + script_args=["-h"], + expected_macaron_args=["-h"], + ), + TestCase( + name="'-h' as action argument for 'analyze'", + script_args=["analyze", "-h"], + expected_macaron_args=["analyze", "-h"], + ), + TestCase( + name="'-h' as action argument for 'verify-policy'", + script_args=["verify-policy", "-h"], + expected_macaron_args=["verify-policy", "-h"], + ), + ] + + exit_code = 0 + + for test_case in test_cases: + name, script_args, expected_macaron_args = test_case + result = subprocess.run( + [ + "scripts/release_scripts/run_macaron.sh", + *script_args, + ], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env={"MCN_DEBUG_ARGS": "1"}, + check=True, + ) + resulting_macaron_args = list(result.stderr.decode("utf-8").split()) + + print(f"test_macaron_command[{name}]:", end=" ") + + if resulting_macaron_args != expected_macaron_args: + print("FAILED") + print(" script args : %s", str(script_args)) + print(" expected macaron args : %s", str(expected_macaron_args)) + print(" resulting macaron args: %s", str(resulting_macaron_args)) + exit_code = 1 + else: + print("PASSED") + + return exit_code + + +def main() -> int: + """Run all tests.""" + return test_macaron_command() + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/release_scripts/run_macaron.sh b/scripts/release_scripts/run_macaron.sh index 1f8962ae1..e5d44c6fd 100755 --- a/scripts/release_scripts/run_macaron.sh +++ b/scripts/release_scripts/run_macaron.sh @@ -19,36 +19,20 @@ MACARON_WORKSPACE="/home/macaron" # We use an array here to preserve the arguments as provided by the user. entrypoint=() -# The action to run for each entrypoint. -# For example: `macaron analyze` or `macaron dump-defaults` -action=() - -# `argv_main` and `argv_action` are the collections of arguments whose values changed by this script -# before being passed to the Docker image. - -# These are arguments for macaron entrypoint. -# -dp/--defaults-path DEFAULTS_PATH: The path to the defaults configuration file. -# -h/--help: Show the help message and exit. -# -lr/--local-repos-path LOCAL_REPOS_PATH: The directory where Macaron looks for already cloned repositories. -# -v/--verbose: Run Macaron with more debug logs. +# The `macaron` action to execute (e.g. `analyze`, or `verify-policy`) +action="" +# `argv_main` and `argv_action` are arguments whose values changed by this script. +# `argv_main` are arguments of the `macaron` command. +# `argv_action` are arguments of the actions in `macaron` (e.g. `analyze`, or `verify-policy`). argv_main=() - -# These are the sub-commands for a specific action. -# macaron -# analyze: -# -g/--template-path TEMPLATE_PATH: The path to the Jinja2 html template (please make sure to use .html or .j2 extensions). -# -c/--config-path CONFIG_PATH: The path to the user configuration. -# -pe/--provenance-expectation POLICY: The path to provenance expectation file or directory. -# dump-defaults: -# verify-policy: -# -f/--file FILE: Replace policy file. -# -d/--database DATABASE: Database path. - argv_action=() -# The rest of the arguments whose values are not changed by this script. -rest=() +# `rest_main` and `rest_action` are arguments whose values are not changed by this script. +# `rest_main` are arguments of the `macaron` command. +# `rest_action` are arguments of the actions in `macaron` (e.g. `analyze`, or `verify-policy`). +rest_main=() +rest_action=() # The mounted directories/files from the host machine to the runtime Macaron container. mounts=() @@ -115,8 +99,7 @@ function check_path_exists() { fi } - -# Parse arguments. +# Parse main arguments. while [[ $# -gt 0 ]]; do case $1 in # Parsing entry points. @@ -124,22 +107,12 @@ while [[ $# -gt 0 ]]; do entrypoint+=("macaron") ;; # Parsing actions for macaron entrypoint. - analyze) - action+=("analyze") - ;; - dump-defaults) - action+=("dump-defaults") - ;; - verify-policy) - action+=("verify-policy") + analyze|dump-defaults|verify-policy) + action=$1 + shift + break ;; # Main argv for main in macaron entrypoint. - -v|--verbose) - argv_main+=("-v") - ;; - -h|--help) - argv_main+=("-h") - ;; -dp|--defaults-path) arg_defaults_path="$2" shift @@ -152,51 +125,58 @@ while [[ $# -gt 0 ]]; do arg_local_repos_path="$2" shift ;; - # Action argv for macaron entrypoint. - -g|--template-path) - arg_template_path="$2" - shift - ;; - -c|--config-path) - arg_config_path="$2" - shift - ;; - -pe|--provenance-expectation) - arg_prov_exp="$2" - shift - ;; - -sbom|--sbom-path) - arg_sbom_path="$2" - shift - ;; - # This flag is duplicated for digest and database. - -d) - if [[ "${action[0]}" = "verify-policy" ]]; - then - arg_database="$2" - shift - else - rest+=("$1" "$2") - shift - fi - ;; - - # Main Argv for verify-policy action. - --database) - arg_database="$2" - shift - ;; - -f|--file) - arg_datalog_policy_file="$2" - shift - ;; *) # Pass the rest to Macaron. - rest+=("$1") + rest_main+=("$1") ;; esac shift done +# Parse action-specific arguments. +if [[ $action == "analyze" ]]; then + while [[ $# -gt 0 ]]; do + case $1 in + -sbom|--sbom-path) + arg_sbom_path="$2" + shift + ;; + -pe|--provenance-expectation) + arg_prov_exp="$2" + shift + ;; + -c|--config-path) + arg_config_path="$2" + shift + ;; + -g|--template-path) + arg_template_path="$2" + shift + ;; + *) + rest_action+=("$1") + ;; + esac + shift + done +elif [[ $action == "verify-policy" ]]; then + while [[ $# -gt 0 ]]; do + case $1 in + -d|--database) + arg_database="$2" + shift + ;; + -f|--file) + arg_datalog_policy_file="$2" + shift + ;; + *) + rest_action+=("$1") + ;; + esac + shift + done +fi + # MACARON entrypoint - Main argvs # Determine the output path to be mounted into ${MACARON_WORKSPACE}/output/ if [[ -n "${arg_output}" ]]; then @@ -431,6 +411,23 @@ fi echo "Running ${IMAGE}:${MACARON_IMAGE_TAG}" +macaron_args=( + "${argv_main[@]}" + "${rest_main[@]}" + "${action}" + "${argv_action[@]}" + "${rest_action[@]}" +) + +# For the purpose of testing the arguments passed to macaron, we can set the +# env var `MCN_DEBUG_ARGS=1`. +# In this case, the script will just print the arguments to stderr without +# running the Macaron container. +if [[ -n ${MCN_DEBUG_ARGS} ]]; then + >&2 echo "${macaron_args[@]}" + exit 0 +fi + docker run \ --pull ${DOCKER_PULL} \ --network=host \ @@ -445,7 +442,4 @@ docker run \ "${mounts[@]}" \ "${IMAGE}:${MACARON_IMAGE_TAG}" \ "${entrypoint[@]}" \ - "${argv_main[@]}" \ - "${action[@]}" \ - "${argv_action[@]}" \ - "${rest[@]}" + "${macaron_args[@]}"