- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
231 lines
6.9 KiB
Bash
Executable File
231 lines
6.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Unified test runner for E2E tests of EVerest.
|
|
#
|
|
# Usage: run-tests.sh [OPTIONS] SUITE
|
|
#
|
|
# Suites:
|
|
# all All tests
|
|
#
|
|
# integration Core, framework, and async API tests
|
|
# core Core tests only
|
|
# framework Framework tests only
|
|
# asyncapi Async API tests only
|
|
#
|
|
# ocpp All OCPP tests (1.6, 2.0.1, 2.1)
|
|
# ocpp16 OCPP 1.6 tests only
|
|
# ocpp201 OCPP 2.0.1 tests only
|
|
# ocpp21 OCPP 2.1 tests only
|
|
#
|
|
# Options:
|
|
# -j N Parallel workers (default: nproc)
|
|
# --serial Run tests serially
|
|
# --everest-prefix P EVerest install prefix (default: <repo>/build/dist)
|
|
# --junitxml PATH JUnit XML output (default: result.xml)
|
|
# --html PATH HTML report output (default: report.html)
|
|
# --no-isolation Disable network isolation
|
|
# -h, --help Show this help
|
|
#
|
|
# Environment variables:
|
|
# PYTHON_INTERPRETER Python to use (default: python3)
|
|
# PARALLEL_TESTS Worker count (overridden by -j)
|
|
# NETWORK_ISOLATION true/false (overridden by --no-isolation)
|
|
# EVEREST_PREFIX Install prefix (overridden by --everest-prefix)
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd)"
|
|
EVEREST_CORE_DIR="$(dirname "$SCRIPT_DIR")"
|
|
PYTHON="${PYTHON_INTERPRETER:-python3}"
|
|
|
|
# Defaults
|
|
WORKERS="${PARALLEL_TESTS:-$(nproc)}"
|
|
SERIAL=false
|
|
PREFIX="${EVEREST_PREFIX:-${EVEREST_CORE_DIR}/build/dist}"
|
|
JUNITXML="result.xml"
|
|
HTML="report.html"
|
|
ISOLATION="${NETWORK_ISOLATION:-true}"
|
|
SUITE=""
|
|
|
|
usage() {
|
|
sed -n '3,/^$/s/^# \?//p' "$0"
|
|
exit 0
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-j) WORKERS="$2"; shift 2;;
|
|
--serial) SERIAL=true; shift;;
|
|
--everest-prefix) PREFIX="$2"; shift 2;;
|
|
--junitxml) JUNITXML="$2"; shift 2;;
|
|
--html) HTML="$2"; shift 2;;
|
|
--no-isolation) ISOLATION=false; shift;;
|
|
-h|--help) usage;;
|
|
-*) echo "Unknown option: $1" >&2; exit 1;;
|
|
*) SUITE="$1"; shift;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$SUITE" ]]; then
|
|
echo "Error: no suite specified." >&2
|
|
echo "Run '$(basename "$0") --help' for usage." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Suite: $SUITE"
|
|
echo "Python: $PYTHON"
|
|
echo "Prefix: $PREFIX"
|
|
|
|
# Network isolation
|
|
ISOLATION_FLAG=""
|
|
if [[ "$ISOLATION" == "true" && "$SERIAL" == "false" ]]; then
|
|
SETUP_SCRIPT="$SCRIPT_DIR/setup-network-isolation.sh"
|
|
|
|
if ip link show ev_test0 >/dev/null 2>&1; then
|
|
# Veth pairs already exist (e.g. leftover from a previous run or created by CI).
|
|
echo "Network isolation: detected pre-existing veth pairs."
|
|
ISOLATION_FLAG="--network-isolation"
|
|
elif [[ -x "$SETUP_SCRIPT" ]]; then
|
|
echo "Setting up network isolation (veth pairs)..."
|
|
# Try without sudo first (for CI).
|
|
# CTRL+C at the sudo prompt cancels it and falls back to sequential execution.
|
|
if "$SETUP_SCRIPT" setup "$WORKERS" 2>/dev/null; then
|
|
ISOLATION_FLAG="--network-isolation"
|
|
elif sudo "$SETUP_SCRIPT" setup "$WORKERS"; then
|
|
ISOLATION_FLAG="--network-isolation"
|
|
else
|
|
echo "Warning: Could not set up network isolation (no sudo / CAP_NET_ADMIN)."
|
|
echo " ISO 15118 tests will run sequentially via xdist_group markers."
|
|
fi
|
|
fi
|
|
|
|
if [[ -n "$ISOLATION_FLAG" ]]; then
|
|
# Try without sudo (CI/root), then sudo -n (local NOPASSWD), then warn.
|
|
teardown_network_isolation() {
|
|
echo "Tearing down network isolation..."
|
|
"$SETUP_SCRIPT" teardown "$WORKERS" 2>/dev/null \
|
|
|| sudo -n "$SETUP_SCRIPT" teardown "$WORKERS" 2>/dev/null \
|
|
|| echo "Warning: Could not tear down network isolation. Run manually: sudo $SETUP_SCRIPT teardown"
|
|
}
|
|
trap teardown_network_isolation EXIT
|
|
fi
|
|
fi
|
|
|
|
# Common pytest arguments
|
|
PYTEST_ARGS=(
|
|
-rA
|
|
--self-contained-html
|
|
--max-worker-restart=0
|
|
--timeout=300
|
|
--everest-prefix "$PREFIX"
|
|
--config-file "$SCRIPT_DIR/pytest.ini"
|
|
)
|
|
|
|
if [[ "$SERIAL" == "false" ]]; then
|
|
echo "Workers: $WORKERS"
|
|
PYTEST_ARGS+=(-n "$WORKERS" --dist=loadgroup)
|
|
else
|
|
echo "Workers: serial"
|
|
fi
|
|
|
|
[[ -n "$ISOLATION_FLAG" ]] && PYTEST_ARGS+=("$ISOLATION_FLAG")
|
|
|
|
# OCPP setup (certs + configs)
|
|
setup_ocpp() {
|
|
local aux_dir="$SCRIPT_DIR/ocpp_tests/test_sets/everest-aux"
|
|
if [[ -d "$aux_dir" ]]; then
|
|
echo "Installing OCPP test certs and configs..."
|
|
(cd "$aux_dir" && ./install_certs.sh "$PREFIX" && ./install_configs.sh "$PREFIX")
|
|
fi
|
|
}
|
|
|
|
# Run
|
|
case "$SUITE" in
|
|
|
|
all)
|
|
echo "Running all test suites"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
setup_ocpp
|
|
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
core_tests/*.py \
|
|
framework_tests/*.py \
|
|
async_api_tests/*.py \
|
|
ocpp_tests/test_sets/ocpp16/*.py \
|
|
ocpp_tests/test_sets/ocpp201/*.py \
|
|
ocpp_tests/test_sets/ocpp21/*.py
|
|
;;
|
|
|
|
integration)
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
core_tests/*.py \
|
|
framework_tests/*.py \
|
|
async_api_tests/*.py
|
|
;;
|
|
|
|
core)
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
core_tests/*.py
|
|
;;
|
|
|
|
framework)
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
framework_tests/*.py
|
|
;;
|
|
|
|
asyncapi)
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
async_api_tests/*.py
|
|
;;
|
|
|
|
ocpp)
|
|
setup_ocpp
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
ocpp_tests/test_sets/ocpp16/*.py \
|
|
ocpp_tests/test_sets/ocpp201/*.py \
|
|
ocpp_tests/test_sets/ocpp21/*.py
|
|
;;
|
|
|
|
ocpp16)
|
|
setup_ocpp
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
ocpp_tests/test_sets/ocpp16/*.py
|
|
;;
|
|
|
|
ocpp201)
|
|
setup_ocpp
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
ocpp_tests/test_sets/ocpp201/*.py
|
|
;;
|
|
|
|
ocpp21)
|
|
setup_ocpp
|
|
cd "$SCRIPT_DIR"
|
|
"$PYTHON" -m pytest "${PYTEST_ARGS[@]}" \
|
|
--junitxml="$JUNITXML" --html="$HTML" \
|
|
ocpp_tests/test_sets/ocpp21/*.py
|
|
;;
|
|
|
|
*)
|
|
echo "Unknown suite: $SUITE" >&2
|
|
echo "Valid suites: all, integration, core, framework, asyncapi, ocpp, ocpp16, ocpp201, ocpp21" >&2
|
|
exit 1
|
|
;;
|
|
|
|
esac
|