Skip to content

Commit

Permalink
ci(wokwi): Add wokwi emulator to CI
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasssvaz committed Apr 19, 2024
1 parent b32daff commit d4a90d9
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 13 deletions.
20 changes: 19 additions & 1 deletion .github/scripts/tests_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ function run_test() {
local sketchdir=$(dirname $sketch)
local sketchname=$(basename $sketchdir)

if [[ -f "$sketchdir/.skip.$platform" ]]; then
echo "Skipping $sketchname tests in $target"
exit 0
fi

if [ $options -eq 0 ] && [ -f $sketchdir/cfg.json ]; then
len=`jq -r --arg chip $target '.targets[] | select(.name==$chip) | .fqbn | length' $sketchdir/cfg.json`
else
Expand All @@ -33,7 +38,13 @@ function run_test() {
report_file="tests/$sketchname/$sketchname$i.xml"
fi

pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file
if [ $platform == "wokwi" ]; then
extra_args="--target $target --embedded-services arduino,wokwi --wokwi-timeout=$wokwi_timeout"
else
extra_args="--embedded-services esp,arduino"
fi

pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args
result=$?
if [ $result -ne 0 ]; then
return $result
Expand All @@ -44,6 +55,8 @@ function run_test() {
SCRIPTS_DIR="./.github/scripts"
COUNT_SKETCHES="${SCRIPTS_DIR}/sketch_utils.sh count"

platform="hardware"
wokwi_timeout=60000
chunk_run=0
options=0
erase=0
Expand All @@ -53,6 +66,11 @@ while [ ! -z "$1" ]; do
-c )
chunk_run=1
;;
-w )
shift
wokwi_timeout=$1
platform="wokwi"
;;
-o )
options=1
;;
Expand Down
63 changes: 53 additions & 10 deletions .github/workflows/hil.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Run tests in hardware
name: Run tests

on:
pull_request:
Expand All @@ -9,16 +9,15 @@ on:

env:
MAX_CHUNKS: 15
WOKWI_TIMEOUT: 120000 # Milliseconds

concurrency:
group: hil-${{github.event.pull_request.number || github.ref}}
cancel-in-progress: true

jobs:
gen_chunks:
if: |
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
(github.event_name == 'schedule' && github.repository == 'espressif/arduino-esp32')
if: github.repository == 'espressif/arduino-esp32'
name: Generate Chunks matrix
runs-on: ubuntu-latest
outputs:
Expand All @@ -41,7 +40,7 @@ jobs:
CHUNKS=$(jq -c -n '$ARGS.positional' --args `seq 0 1 $((sketches - 1))`)
echo "chunks=${CHUNKS}" >>$GITHUB_OUTPUT
Build:
build:
needs: gen_chunks
name: ${{matrix.chip}}-Build#${{matrix.chunks}}
runs-on: ubuntu-latest
Expand All @@ -63,9 +62,53 @@ jobs:
~/.arduino/tests/*/build*.tmp/*.bin
~/.arduino/tests/*/build*.tmp/*.json
if-no-files-found: error
Test:
needs: [gen_chunks, Build]
name: ${{matrix.chip}}-Test#${{matrix.chunks}}

wokwi-test:
needs: [gen_chunks, build]
name: ${{matrix.chip}}-Wokwi_Test#${{matrix.chunks}}
strategy:
fail-fast: false
matrix:
chip: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3', 'esp32c6', 'esp32h2']
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Download ${{matrix.chip}}-${{matrix.chunks}} artifacts
uses: actions/download-artifact@v4
with:
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
path: ~/.arduino/tests/

- name: Install Wokwi CLI
run: curl -L https://wokwi.com/ci/install.sh | sh

- name: Install dependencies
run: |
pip install -U pip
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
apt update && apt install -y -qq jq
- name: Run Tests
env:
WOKWI_CLI_TOKEN: ${{ secrets.WOKWI_CLI_TOKEN }}
run: |
bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -w ${{env.WOKWI_TIMEOUT}}
- name: Upload test result artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: wokwi_results-${{matrix.chip}}-${{matrix.chunks}}
path: tests/*/*.xml

hardware-test:
needs: [gen_chunks, build]
name: ${{matrix.chip}}-Hardware_Test#${{matrix.chunks}}
if: |
contains(github.event.pull_request.labels.*.name, 'hil_test') || github.event_name == 'schedule'
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -100,15 +143,15 @@ jobs:
uses: actions/upload-artifact@v4
if: always()
with:
name: test_results-${{matrix.chip}}-${{matrix.chunks}}
name: hw_results-${{matrix.chip}}-${{matrix.chunks}}
path: tests/*/*.xml

event_file:
name: "Event File"
if: |
contains(github.event.pull_request.labels.*.name, 'hil_test') ||
github.event_name == 'schedule'
needs: Test
needs: hardware-test
runs-on: ubuntu-latest
steps:
- name: Upload
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Unit Test Results

on:
workflow_run:
workflows: [Run tests in hardware]
workflows: [Run tests]
branches-ignore: [master]

types:
Expand Down
2 changes: 1 addition & 1 deletion tests/pytest.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[pytest]
addopts = --embedded-services esp,arduino
addopts = --embedded-services esp,arduino,wokwi

# log related
log_cli = True
Expand Down
1 change: 1 addition & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ cryptography>=2.1.4
pytest-cov
pytest-embedded-serial-esp>=1.3.4
pytest-embedded-arduino>=1.3.4
pytest-embedded-wokwi>=1.3.5
Empty file added tests/wifi/.skip.hardware
Empty file.
2 changes: 2 additions & 0 deletions tests/wifi/test_wifi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test_wifi(dut):
dut.expect_unity_test_output(timeout=240)
132 changes: 132 additions & 0 deletions tests/wifi/wifi.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/* HW Timer test */
#include <unity.h>

#define TIMER_FREQUENCY 4000000
#define TIMER_FREQUENCY_XTAL_CLK 1000

/*
* ESP32 - APB clk only (1kHz not possible)
* C3 - APB + XTAL clk
* S2 - APB + XTAL clk
* S3 - APB + XTAL clk
*/

static hw_timer_t *timer = NULL;
static volatile bool alarm_flag;

/* setUp / tearDown functions are intended to be called before / after each test. */
void setUp(void) {
timer = timerBegin(TIMER_FREQUENCY);
if (timer == NULL) {
TEST_FAIL_MESSAGE("Timer init failed in setUp()");
}
timerStop(timer);
timerRestart(timer);
}

void tearDown(void) {
timerEnd(timer);
}

void ARDUINO_ISR_ATTR onTimer() {
alarm_flag = true;
}

void timer_interrupt_test(void) {

alarm_flag = false;
timerAttachInterrupt(timer, &onTimer);
timerAlarm(timer, (1.2 * TIMER_FREQUENCY), true, 0);
timerStart(timer);

delay(2000);

TEST_ASSERT_EQUAL(true, alarm_flag);

timerStop(timer);
timerRestart(timer);
alarm_flag = false;
timerDetachInterrupt(timer);
timerStart(timer);

delay(2000);
TEST_ASSERT_EQUAL(false, alarm_flag);
}

void timer_divider_test(void) {

uint64_t time_val;
uint64_t comp_time_val;

timerStart(timer);

delay(1000);
time_val = timerRead(timer);

// compare divider 16 and 8, value should be double
timerEnd(timer);

timer = timerBegin(2 * TIMER_FREQUENCY);
if (timer == NULL) {
TEST_FAIL_MESSAGE("Timer init failed!");
}
timerRestart(timer);
delay(1000);
comp_time_val = timerRead(timer);

TEST_ASSERT_INT_WITHIN(4000, 4000000, time_val);
TEST_ASSERT_INT_WITHIN(8000, 8000000, comp_time_val);

// divider is 256, value should be 2^4
timerEnd(timer);

timer = timerBegin(TIMER_FREQUENCY / 16);
if (timer == NULL) {
TEST_FAIL_MESSAGE("Timer init failed!");
}
timerRestart(timer);
delay(1000);
comp_time_val = timerRead(timer);

TEST_ASSERT_INT_WITHIN(4000, 4000000, time_val);
TEST_ASSERT_INT_WITHIN(2500, 250000, comp_time_val);
}

void timer_read_test(void) {

uint64_t set_timer_val = 0xFF;
uint64_t get_timer_val = 0;

timerWrite(timer, set_timer_val);
get_timer_val = timerRead(timer);

TEST_ASSERT_EQUAL(set_timer_val, get_timer_val);
}

void timer_clock_select_test(void) {
// Set timer frequency that can be achieved using XTAL clock source (autoselected)
timer = timerBegin(TIMER_FREQUENCY_XTAL_CLK);

uint32_t resolution = timerGetFrequency(timer);
TEST_ASSERT_EQUAL(TIMER_FREQUENCY_XTAL_CLK, resolution);
}

void setup() {

// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
;
}

UNITY_BEGIN();
RUN_TEST(timer_read_test);
RUN_TEST(timer_interrupt_test);
RUN_TEST(timer_divider_test);
#if !CONFIG_IDF_TARGET_ESP32
RUN_TEST(timer_clock_select_test);
#endif
UNITY_END();
}

void loop() {}

0 comments on commit d4a90d9

Please sign in to comment.