Skip to content

Commit 8de9440

Browse files
committed
ci(performance): Add performance tests to CI
1 parent cf44890 commit 8de9440

23 files changed

+126
-20
lines changed

.github/scripts/tests_build.sh

+24-7
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
USAGE="
44
USAGE:
5-
${0} -c <chunk_build_opts>
6-
Example: ${0} -c -t esp32 -i 0 -m 15
5+
${0} -c -type <test_type> <chunk_build_opts>
6+
Example: ${0} -c -type validation -t esp32 -i 0 -m 15
77
${0} -s sketch_name <build_opts>
88
Example: ${0} -s hello_world -t esp32
99
${0} -clean
1010
Remove build and test generated files
1111
"
1212

1313
function clean(){
14-
rm -rf tests/*/build*/
14+
rm -rf tests/**/build*/
1515
rm -rf tests/.pytest_cache
16-
rm -rf tests/*/__pycache__/
17-
rm -rf tests/*/*.xml
16+
rm -rf tests/**/__pycache__/
17+
rm -rf tests/**/*.xml
1818
}
1919

2020
SCRIPTS_DIR="./.github/scripts"
@@ -35,6 +35,10 @@ while [ ! -z "$1" ]; do
3535
echo "$USAGE"
3636
exit 0
3737
;;
38+
-type )
39+
shift
40+
test_type=$1
41+
;;
3842
-clean )
3943
clean
4044
exit 0
@@ -52,12 +56,25 @@ source ${SCRIPTS_DIR}/install-arduino-core-esp32.sh
5256

5357
args="-ai $ARDUINO_IDE_PATH -au $ARDUINO_USR_PATH"
5458

59+
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
60+
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"
65+
else
66+
test_folder="$PWD/tests"
67+
fi
68+
else
69+
test_folder="$PWD/tests/$test_type"
70+
fi
71+
5572
if [ $chunk_build -eq 1 ]; then
5673
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
57-
args+=" -p $PWD/tests"
74+
args+=" -p $test_folder"
5875
else
5976
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
60-
args+=" -s $PWD/tests/$sketch"
77+
args+=" -s $test_folder/$sketch"
6178
fi
6279

6380
${BUILD_CMD} ${args} $*

.github/scripts/tests_run.sh

+28-6
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ function run_test() {
1515
fi
1616

1717
if [ $len -eq 1 ]; then
18-
# build_dir="tests/$sketchname/build"
18+
# build_dir="$sketchdir/build"
1919
build_dir="$HOME/.arduino/tests/$sketchname/build.tmp"
20-
report_file="tests/$sketchname/$sketchname.xml"
20+
report_file="$sketchdir/$sketchname.xml"
2121
fi
2222

2323
for i in `seq 0 $(($len - 1))`
@@ -28,9 +28,9 @@ function run_test() {
2828
fi
2929

3030
if [ $len -ne 1 ]; then
31-
# build_dir="tests/$sketchname/build$i"
31+
# build_dir="$sketchdir/build$i"
3232
build_dir="$HOME/.arduino/tests/$sketchname/build$i.tmp"
33-
report_file="tests/$sketchname/$sketchname$i.xml"
33+
report_file="$sketchdir/$sketchname$i.xml"
3434
fi
3535

3636
pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file
@@ -79,6 +79,10 @@ while [ ! -z "$1" ]; do
7979
echo "$USAGE"
8080
exit 0
8181
;;
82+
-type )
83+
shift
84+
test_type=$1
85+
;;
8286
* )
8387
break
8488
;;
@@ -88,8 +92,26 @@ done
8892

8993
source ${SCRIPTS_DIR}/install-arduino-ide.sh
9094

95+
# If sketch is provided and test type is not, test type is inferred from the sketch path
96+
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
97+
if [ -n "$sketch" ]; then
98+
tmp_sketch_path=$(find tests -name $sketch.ino)
99+
test_type=$(basename $(dirname $(dirname "$tmp_sketch_path")))
100+
echo "Sketch $sketch test type: $test_type"
101+
test_folder="$PWD/tests/$test_type"
102+
else
103+
test_folder="$PWD/tests"
104+
fi
105+
else
106+
test_folder="$PWD/tests/$test_type"
107+
fi
108+
91109
if [ $chunk_run -eq 0 ]; then
92-
run_test $target $PWD/tests/$sketch/$sketch.ino $options $erase
110+
if [ -z $sketch ]; then
111+
echo "ERROR: Sketch name is required for single test run"
112+
return 1
113+
fi
114+
run_test $target $test_folder/$sketch/$sketch.ino $options $erase
93115
else
94116
if [ "$chunk_max" -le 0 ]; then
95117
echo "ERROR: Chunks count must be positive number"
@@ -102,7 +124,7 @@ else
102124
fi
103125

104126
set +e
105-
${COUNT_SKETCHES} $PWD/tests $target
127+
${COUNT_SKETCHES} $test_folder $target
106128
sketchcount=$?
107129
set -e
108130
sketches=$(cat sketches.txt)

.github/workflows/hil.yml

+25-7
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ jobs:
1818
gen_chunks:
1919
if: |
2020
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
21+
contains(github.event.pull_request.labels.*.name, 'perf_test') ||
2122
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
2223
name: Generate Chunks matrix
2324
runs-on: ubuntu-latest
2425
outputs:
2526
chunks: ${{ steps.gen-chunks.outputs.chunks }}
27+
test_folder: ${{ steps.gen-chunks.outputs.test_folder }}
28+
test_type: ${{ steps.gen-chunks.outputs.test_type }}
2629
steps:
2730
- name: Checkout Repository
2831
uses: actions/checkout@v4
@@ -31,15 +34,29 @@ jobs:
3134
id: gen-chunks
3235
run: |
3336
set +e
34-
.github/scripts/sketch_utils.sh count tests
37+
if [ "${{contains(github.event.pull_request.labels.*.name, 'hil_test')}}" == "true" ] && \
38+
[ "${{contains(github.event.pull_request.labels.*.name, 'perf_test')}}" == "false" ]; then
39+
test_folder="tests/validation"
40+
test_type="validation"
41+
elif [ "${{contains(github.event.pull_request.labels.*.name, 'hil_test')}}" == "false" ] && \
42+
[ "${{contains(github.event.pull_request.labels.*.name, 'perf_test')}}" == "true" ]; then
43+
test_folder="tests/performance"
44+
test_type="performance"
45+
else
46+
test_folder="tests"
47+
test_type="all"
48+
fi
49+
.github/scripts/sketch_utils.sh count $test_folder
3550
sketches=$?
3651
if [[ $sketches -ge ${{env.MAX_CHUNKS}} ]]; then
3752
$sketches=${{env.MAX_CHUNKS}}
3853
fi
3954
set -e
4055
rm sketches.txt
4156
CHUNKS=$(jq -c -n '$ARGS.positional' --args `seq 0 1 $((sketches - 1))`)
42-
echo "chunks=${CHUNKS}" >>$GITHUB_OUTPUT
57+
echo "chunks=${CHUNKS}" >> $GITHUB_OUTPUT
58+
echo "test_folder=${test_folder}" >> $GITHUB_OUTPUT
59+
echo "test_type=${test_type}" >> $GITHUB_OUTPUT
4360
4461
Build:
4562
needs: gen_chunks
@@ -54,14 +71,14 @@ jobs:
5471
uses: actions/checkout@v4
5572
- name: Build sketches
5673
run: |
57-
bash .github/scripts/tests_build.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}}
74+
bash .github/scripts/tests_build.sh -c -type ${{ needs.gen_chunks.outputs.test_type }} -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}}
5875
- name: Upload ${{matrix.chip}}-${{matrix.chunks}} artifacts
5976
uses: actions/upload-artifact@v4
6077
with:
6178
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
6279
path: |
63-
~/.arduino/tests/*/build*.tmp/*.bin
64-
~/.arduino/tests/*/build*.tmp/*.json
80+
~/.arduino/tests/**/build*.tmp/*.bin
81+
~/.arduino/tests/**/build*.tmp/*.json
6582
if-no-files-found: error
6683
Test:
6784
needs: [gen_chunks, Build]
@@ -94,19 +111,20 @@ jobs:
94111
95112
- name: Run Tests
96113
run: |
97-
bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -e
114+
bash .github/scripts/tests_run.sh -c -type ${{ needs.gen_chunks.outputs.test_type }} -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -e
98115
99116
- name: Upload test result artifacts
100117
uses: actions/upload-artifact@v4
101118
if: always()
102119
with:
103120
name: test_results-${{matrix.chip}}-${{matrix.chunks}}
104-
path: tests/*/*.xml
121+
path: tests/**/*.xml
105122

106123
event_file:
107124
name: "Event File"
108125
if: |
109126
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
127+
contains(github.event.pull_request.labels.*.name, 'perf_test') ||
110128
github.event_name == 'schedule'
111129
needs: Test
112130
runs-on: ubuntu-latest
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <Arduino.h>
2+
3+
#define FIB_N 41
4+
#define FIB_RESULT 165580141
5+
#define N_RUNS 3 // Number of runs to average
6+
7+
uint32_t times[N_RUNS];
8+
9+
uint64_t fib(uint32_t n) {
10+
if (n < 2) return n;
11+
return fib(n - 1) + fib(n - 2);
12+
}
13+
14+
void setup(){
15+
uint64_t fibonacci;
16+
17+
Serial.begin(115200);
18+
while (!Serial) delay(10);
19+
20+
log_d("Starting fibonacci calculation");
21+
for (int i = 0; i < N_RUNS; i++) {
22+
log_d("Run %d", i);
23+
unsigned long start = millis();
24+
fibonacci = fib(FIB_N);
25+
assert(fibonacci == FIB_RESULT); // If this fails, the test is invalid
26+
unsigned long end = millis();
27+
times[i] = end - start;
28+
log_d("Run %d: %lu.%03lu s\n", i, times[i]/1000, times[i]%1000);
29+
}
30+
31+
Serial.printf("N: %d\n", FIB_N);
32+
Serial.printf("Fibonacci(N): %llu\n", fibonacci);
33+
unsigned long sum = 0;
34+
for (int i = 0; i < N_RUNS; i++) {
35+
sum += times[i];
36+
}
37+
Serial.printf("Average time: %lu.%03lu s\n", sum/(N_RUNS*1000), sum%(N_RUNS*1000));
38+
}
39+
40+
void loop(){
41+
vTaskDelete(NULL);
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
def test_fibonacci(dut):
2+
# Match "N: %d"
3+
dut.expect(r"N: (\d+)")
4+
# Match "Fibonacci(N): %llu"
5+
dut.expect(r"Fibonacci(N): (\d+)")
6+
# Match "Average time: %lu.%03lu s"
7+
dut.expect(r"Average time: (\d+)\.(\d+) s")
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)