#!/usr/bin/env bash # # test.sh -- Build and run all host-side tests (no Arduino board needed) # # Usage: # ./test.sh Build and run all tests # ./test.sh --clean Clean rebuild # ./test.sh --verbose Verbose test output # ./test.sh --unit Run only unit tests # ./test.sh --system Run only system tests # # This script builds your application against mock_arduino (a fake Arduino # environment) and runs Google Test suites. Your app code compiles and runs # on your PC -- no board, no wires, no USB. # # Prerequisites: # cmake >= 3.14, a C++ compiler (g++, clang++, or MSVC), git # # First run downloads Google Test automatically (~30 seconds). set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" TEST_DIR="$SCRIPT_DIR/test" BUILD_DIR="$TEST_DIR/build" # Color output if [[ -t 1 ]]; then RED=$'\033[0;31m'; GRN=$'\033[0;32m'; CYN=$'\033[0;36m' YLW=$'\033[0;33m'; BLD=$'\033[1m'; RST=$'\033[0m' else RED=''; GRN=''; CYN=''; YLW=''; BLD=''; RST='' fi info() { echo -e "${CYN}[TEST]${RST} $*"; } ok() { echo -e "${GRN}[PASS]${RST} $*"; } warn() { echo -e "${YLW}[WARN]${RST} $*"; } die() { echo -e "${RED}[FAIL]${RST} $*" >&2; exit 1; } DO_CLEAN=0 VERBOSE="" FILTER="" for arg in "$@"; do case "$arg" in --clean) DO_CLEAN=1 ;; --verbose) VERBOSE="--verbose" ;; --unit) FILTER="-R test_unit" ;; --system) FILTER="-R test_system" ;; -h|--help) echo "Usage: ./test.sh [--clean] [--verbose] [--unit|--system]" echo "" echo " --clean Delete build cache and rebuild from scratch" echo " --verbose Show individual test names and output" echo " --unit Run only unit tests (Google Mock)" echo " --system Run only system tests (SimHal)" exit 0 ;; *) die "Unknown option: $arg (try --help)" ;; esac done # -- Check prerequisites ---------------------------------------------------- if ! command -v cmake &>/dev/null; then die "cmake not found." echo " Install:" >&2 if [[ "$(uname)" == "Darwin" ]]; then echo " brew install cmake" >&2 else echo " sudo apt install cmake (Debian/Ubuntu)" >&2 echo " sudo dnf install cmake (Fedora)" >&2 fi echo "" >&2 echo " Or run: anvil doctor --fix" >&2 exit 1 fi if ! command -v g++ &>/dev/null && ! command -v clang++ &>/dev/null; then die "No C++ compiler found (need g++ or clang++)." echo " Or run: anvil doctor --fix" >&2 exit 1 fi if ! command -v git &>/dev/null; then die "git not found (needed to fetch Google Test)." exit 1 fi # -- Build ------------------------------------------------------------------- if [[ $DO_CLEAN -eq 1 ]] && [[ -d "$BUILD_DIR" ]]; then info "Cleaning build directory..." rm -rf "$BUILD_DIR" fi if [[ ! -f "$BUILD_DIR/CMakeCache.txt" ]]; then info "Configuring test build. First run will fetch Google Test..." cmake -S "$TEST_DIR" -B "$BUILD_DIR" -DCMAKE_BUILD_TYPE=Debug 2>&1 | \ while IFS= read -r line; do echo " $line"; done echo "" fi info "Building tests..." cmake --build "$BUILD_DIR" --parallel 2>&1 | \ while IFS= read -r line; do echo " $line"; done echo "" info "${BLD}Running tests...${RST}" echo "" # -- Run --------------------------------------------------------------------- CTEST_ARGS=("--test-dir" "$BUILD_DIR" "--output-on-failure") [[ -n "$VERBOSE" ]] && CTEST_ARGS+=("--verbose") [[ -n "$FILTER" ]] && CTEST_ARGS+=($FILTER) if ctest "${CTEST_ARGS[@]}"; then echo "" ok "${BLD}All tests passed.${RST}" else echo "" die "Some tests failed." fi