Skip to content

Commit 0bea36f

Browse files
committed
ci(tests): Add support for multiple duts
1 parent 56be13b commit 0bea36f

File tree

17 files changed

+1531
-51
lines changed

17 files changed

+1531
-51
lines changed

.github/scripts/sketch_utils.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,14 +396,25 @@ function count_sketches { # count_sketches <path> [target] [ignore-requirements]
396396
local sketchdirname
397397
local sketchname
398398
local has_requirements
399+
local parent_dir
399400

400401
sketchdir=$(dirname "$sketch")
401402
sketchdirname=$(basename "$sketchdir")
402403
sketchname=$(basename "$sketch")
404+
parent_dir=$(dirname "$sketchdir")
403405

404406
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
405407
continue
406-
elif [[ -n $target ]] && [[ -f $sketchdir/ci.yml ]]; then
408+
# Skip sketches that are part of multi-device tests (they are built separately)
409+
elif [[ -f "$parent_dir/ci.yml" ]]; then
410+
local has_multi_device
411+
has_multi_device=$(yq eval '.multi_device' "$parent_dir/ci.yml" 2>/dev/null)
412+
if [[ "$has_multi_device" != "null" && "$has_multi_device" != "" ]]; then
413+
continue
414+
fi
415+
fi
416+
417+
if [[ -n $target ]] && [[ -f $sketchdir/ci.yml ]]; then
407418
# If the target is listed as false, skip the sketch. Otherwise, include it.
408419
is_target=$(yq eval ".targets.${target}" "$sketchdir"/ci.yml 2>/dev/null)
409420
if [[ "$is_target" == "false" ]]; then

.github/scripts/tests_build.sh

Lines changed: 159 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,111 @@ function clean {
1818
find tests/ -name 'result_*.json' -exec rm -rf "{}" \+
1919
}
2020

21+
# Check if a test is a multi-device test
22+
function is_multi_device_test {
23+
local test_dir=$1
24+
local has_multi_device
25+
if [ -f "$test_dir/ci.yml" ]; then
26+
has_multi_device=$(yq eval '.multi_device' "$test_dir/ci.yml" 2>/dev/null)
27+
if [[ "$has_multi_device" != "null" && "$has_multi_device" != "" ]]; then
28+
echo "1"
29+
return
30+
fi
31+
fi
32+
echo "0"
33+
}
34+
35+
# Extract target from arguments and return target and remaining arguments
36+
# Usage: extract_target_and_args "$@"
37+
# Returns: Sets global variables 'target' and 'remaining_args' array
38+
function extract_target_and_args {
39+
target=""
40+
remaining_args=()
41+
while [ -n "$1" ]; do
42+
case $1 in
43+
-t )
44+
shift
45+
target=$1
46+
remaining_args+=("-t" "$target")
47+
;;
48+
* )
49+
remaining_args+=("$1")
50+
;;
51+
esac
52+
shift
53+
done
54+
}
55+
56+
# Build a single sketch for multi-device tests
57+
function build_multi_device_sketch {
58+
local test_name=$1
59+
local sketch_path=$2
60+
local target=$3
61+
shift 3
62+
local build_args=("$@")
63+
local sketch_dir
64+
local sketch_name
65+
local test_dir
66+
local build_dir
67+
68+
sketch_dir=$(dirname "$sketch_path")
69+
sketch_name=$(basename "$sketch_dir")
70+
test_dir=$(dirname "$sketch_dir")
71+
72+
# Override build directory to use <test_name>_<sketch_name> pattern
73+
build_dir="$HOME/.arduino/tests/$target/${test_name}_${sketch_name}/build.tmp"
74+
75+
echo "Building sketch $sketch_name for multi-device test $test_name"
76+
77+
# Call sketch_utils.sh build function with custom build directory
78+
ARDUINO_BUILD_DIR="$build_dir" ${SCRIPTS_DIR}/sketch_utils.sh build "${build_args[@]}" -s "$sketch_dir"
79+
return $?
80+
}
81+
82+
# Build all sketches for a multi-device test
83+
function build_multi_device_test {
84+
local test_dir=$1
85+
local target=$2
86+
shift 2
87+
local build_args=("$@")
88+
local test_name
89+
local devices
90+
91+
test_name=$(basename "$test_dir")
92+
93+
echo "Building multi-device test $test_name"
94+
95+
# Get the list of devices from ci.yml
96+
devices=$(yq eval '.multi_device | keys | .[]' "$test_dir/ci.yml" 2>/dev/null)
97+
98+
if [[ -z "$devices" ]]; then
99+
echo "ERROR: No devices found in multi_device configuration for $test_name"
100+
return 1
101+
fi
102+
103+
local result=0
104+
local sketch_name
105+
local sketch_path
106+
for device in $devices; do
107+
sketch_name=$(yq eval ".multi_device.$device" "$test_dir/ci.yml" 2>/dev/null)
108+
sketch_path="$test_dir/$sketch_name/$sketch_name.ino"
109+
110+
if [ ! -f "$sketch_path" ]; then
111+
echo "ERROR: Sketch not found: $sketch_path"
112+
return 1
113+
fi
114+
115+
build_multi_device_sketch "$test_name" "$sketch_path" "$target" "${build_args[@]}"
116+
result=$?
117+
if [ $result -ne 0 ]; then
118+
echo "ERROR: Failed to build sketch $sketch_name for test $test_name"
119+
return $result
120+
fi
121+
done
122+
123+
return 0
124+
}
125+
21126
SCRIPTS_DIR="./.github/scripts"
22127
BUILD_CMD=""
23128

@@ -53,15 +158,13 @@ done
53158

54159
source "${SCRIPTS_DIR}/install-arduino-cli.sh"
55160
source "${SCRIPTS_DIR}/install-arduino-core-esp32.sh"
161+
source "${SCRIPTS_DIR}/tests_utils.sh"
56162

57163
args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH")
58164

59165
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
60166
if [ -n "$sketch" ]; then
61-
tmp_sketch_path=$(find tests -name "$sketch".ino)
62-
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
63-
echo "Sketch $sketch test type: $test_type"
64-
test_folder="$PWD/tests/$test_type"
167+
detect_test_type_and_folder "$sketch"
65168
else
66169
test_folder="$PWD/tests"
67170
fi
@@ -70,11 +173,58 @@ else
70173
fi
71174

72175
if [ $chunk_build -eq 1 ]; then
176+
# For chunk builds, we need to handle multi-device tests separately
177+
# First, build all multi-device tests, then build regular tests
178+
179+
# Extract target from remaining arguments
180+
extract_target_and_args "$@"
181+
182+
if [ -z "$target" ]; then
183+
echo "ERROR: Target (-t) is required for chunk builds"
184+
exit 1
185+
fi
186+
187+
# Find and build all multi-device tests in the test folder
188+
multi_device_error=0
189+
if [ -d "$test_folder" ]; then
190+
for test_dir in "$test_folder"/*; do
191+
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
192+
build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
193+
result=$?
194+
if [ $result -ne 0 ]; then
195+
multi_device_error=$result
196+
fi
197+
fi
198+
done
199+
fi
200+
201+
# Now build regular (non-multi-device) tests using chunk_build
73202
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
74-
args+=("-p" "$test_folder" "-i" "0" "-m" "1")
203+
args+=("-p" "$test_folder")
204+
${BUILD_CMD} "${args[@]}" "${remaining_args[@]}"
205+
regular_error=$?
206+
207+
# Return error if either multi-device or regular builds failed
208+
if [ $multi_device_error -ne 0 ]; then
209+
exit $multi_device_error
210+
fi
211+
exit $regular_error
75212
else
76-
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
77-
args+=("-s" "$test_folder/$sketch")
78-
fi
213+
# Check if this is a multi-device test
214+
test_dir="$test_folder/$sketch"
215+
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
216+
# Extract target from remaining arguments
217+
extract_target_and_args "$@"
79218

80-
${BUILD_CMD} "${args[@]}" "$@"
219+
if [ -z "$target" ]; then
220+
echo "ERROR: Target (-t) is required for multi-device tests"
221+
exit 1
222+
fi
223+
224+
build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
225+
else
226+
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
227+
args+=("-s" "$test_folder/$sketch")
228+
${BUILD_CMD} "${args[@]}" "$@"
229+
fi
230+
fi

0 commit comments

Comments
 (0)