Skip to content

Commit 38b9808

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

File tree

13 files changed

+1533
-45
lines changed

13 files changed

+1533
-45
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: 182 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,90 @@ 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+
# Build a single sketch for multi-device tests
36+
function build_multi_device_sketch {
37+
local test_name=$1
38+
local sketch_path=$2
39+
local target=$3
40+
shift 3
41+
local build_args=("$@")
42+
local sketch_dir
43+
local sketch_name
44+
local test_dir
45+
local build_dir
46+
47+
sketch_dir=$(dirname "$sketch_path")
48+
sketch_name=$(basename "$sketch_dir")
49+
test_dir=$(dirname "$sketch_dir")
50+
51+
# Override build directory to use <test_name>_<sketch_name> pattern
52+
build_dir="$HOME/.arduino/tests/$target/${test_name}_${sketch_name}/build.tmp"
53+
54+
echo "Building multi-device sketch $sketch_name for test $test_name"
55+
56+
# Call sketch_utils.sh build function with custom build directory
57+
ARDUINO_BUILD_DIR="$build_dir" ${SCRIPTS_DIR}/sketch_utils.sh build "${build_args[@]}" -s "$sketch_dir"
58+
return $?
59+
}
60+
61+
# Build all sketches for a multi-device test
62+
function build_multi_device_test {
63+
local test_dir=$1
64+
local target=$2
65+
shift 2
66+
local build_args=("$@")
67+
local test_name
68+
local devices
69+
70+
test_name=$(basename "$test_dir")
71+
72+
echo "Building multi-device test $test_name"
73+
74+
# Get the list of devices from ci.yml
75+
devices=$(yq eval '.multi_device | keys | .[]' "$test_dir/ci.yml" 2>/dev/null)
76+
77+
if [[ -z "$devices" ]]; then
78+
echo "ERROR: No devices found in multi_device configuration for $test_name"
79+
return 1
80+
fi
81+
82+
local result=0
83+
local sketch_name
84+
local sketch_path
85+
for device in $devices; do
86+
sketch_name=$(yq eval ".multi_device.$device" "$test_dir/ci.yml" 2>/dev/null)
87+
sketch_path="$test_dir/$sketch_name/$sketch_name.ino"
88+
89+
if [ ! -f "$sketch_path" ]; then
90+
echo "ERROR: Sketch not found: $sketch_path"
91+
return 1
92+
fi
93+
94+
build_multi_device_sketch "$test_name" "$sketch_path" "$target" "${build_args[@]}"
95+
result=$?
96+
if [ $result -ne 0 ]; then
97+
echo "ERROR: Failed to build sketch $sketch_name for test $test_name"
98+
return $result
99+
fi
100+
done
101+
102+
return 0
103+
}
104+
21105
SCRIPTS_DIR="./.github/scripts"
22106
BUILD_CMD=""
23107

@@ -58,10 +142,25 @@ args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH")
58142

59143
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
60144
if [ -n "$sketch" ]; then
61-
tmp_sketch_path=$(find tests -name "$sketch".ino)
62-
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
145+
# For multi-device tests, we need to find the test directory, not the device sketch directory
146+
# First, try to find a test directory with this name
147+
if [ -d "tests/validation/$sketch" ] && [ -f "tests/validation/$sketch/ci.yml" ]; then
148+
test_type="validation"
149+
test_folder="$PWD/tests/$test_type"
150+
elif [ -d "tests/performance/$sketch" ] && [ -f "tests/performance/$sketch/ci.yml" ]; then
151+
test_type="performance"
152+
test_folder="$PWD/tests/$test_type"
153+
else
154+
# Fall back to finding by .ino file (for regular tests)
155+
tmp_sketch_path=$(find tests -name "$sketch".ino | head -1)
156+
if [ -z "$tmp_sketch_path" ]; then
157+
echo "ERROR: Sketch $sketch not found"
158+
exit 1
159+
fi
160+
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
161+
test_folder="$PWD/tests/$test_type"
162+
fi
63163
echo "Sketch $sketch test type: $test_type"
64-
test_folder="$PWD/tests/$test_type"
65164
else
66165
test_folder="$PWD/tests"
67166
fi
@@ -70,11 +169,86 @@ else
70169
fi
71170

72171
if [ $chunk_build -eq 1 ]; then
172+
# For chunk builds, we need to handle multi-device tests separately
173+
# First, build all multi-device tests, then build regular tests
174+
175+
# Extract target from remaining arguments
176+
target=""
177+
remaining_args=()
178+
while [ -n "$1" ]; do
179+
case $1 in
180+
-t )
181+
shift
182+
target=$1
183+
remaining_args+=("-t" "$target")
184+
;;
185+
* )
186+
remaining_args+=("$1")
187+
;;
188+
esac
189+
shift
190+
done
191+
192+
if [ -z "$target" ]; then
193+
echo "ERROR: Target (-t) is required for chunk builds"
194+
exit 1
195+
fi
196+
197+
# Find and build all multi-device tests in the test folder
198+
multi_device_error=0
199+
if [ -d "$test_folder" ]; then
200+
for test_dir in "$test_folder"/*; do
201+
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
202+
build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
203+
result=$?
204+
if [ $result -ne 0 ]; then
205+
multi_device_error=$result
206+
fi
207+
fi
208+
done
209+
fi
210+
211+
# Now build regular (non-multi-device) tests using chunk_build
73212
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
74-
args+=("-p" "$test_folder" "-i" "0" "-m" "1")
213+
args+=("-p" "$test_folder")
214+
${BUILD_CMD} "${args[@]}" "${remaining_args[@]}"
215+
regular_error=$?
216+
217+
# Return error if either multi-device or regular builds failed
218+
if [ $multi_device_error -ne 0 ]; then
219+
exit $multi_device_error
220+
fi
221+
exit $regular_error
75222
else
76-
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
77-
args+=("-s" "$test_folder/$sketch")
78-
fi
223+
# Check if this is a multi-device test
224+
test_dir="$test_folder/$sketch"
225+
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
226+
# Extract target from remaining arguments
227+
target=""
228+
remaining_args=()
229+
while [ -n "$1" ]; do
230+
case $1 in
231+
-t )
232+
shift
233+
target=$1
234+
remaining_args+=("-t" "$target")
235+
;;
236+
* )
237+
remaining_args+=("$1")
238+
;;
239+
esac
240+
shift
241+
done
79242

80-
${BUILD_CMD} "${args[@]}" "$@"
243+
if [ -z "$target" ]; then
244+
echo "ERROR: Target (-t) is required for multi-device tests"
245+
exit 1
246+
fi
247+
248+
build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
249+
else
250+
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
251+
args+=("-s" "$test_folder/$sketch")
252+
${BUILD_CMD} "${args[@]}" "$@"
253+
fi
254+
fi

0 commit comments

Comments
 (0)