Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(qemu): Add QEMU emulator to CI #9558

Merged
merged 8 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/scripts/on-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
fi

if [ "$BUILD_LOG" -le 0 ]; then
if [ -z "$BUILD_LOG" ] || [ "$BUILD_LOG" -le 0 ]; then
BUILD_LOG=0
fi

Expand Down
4 changes: 2 additions & 2 deletions .github/scripts/sketch_utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ function build_sketch(){ # build_sketch <ide_path> <user_path> <path-to-ino> [ex

# Default FQBN options if none were passed in the command line.

esp32_opts="PSRAM=enabled,PartitionScheme=huge_app"
esp32_opts="FlashMode=dio,PSRAM=enabled,PartitionScheme=huge_app"
esp32s2_opts="PSRAM=enabled,PartitionScheme=huge_app"
esp32s3_opts="PSRAM=opi,USBMode=default,PartitionScheme=huge_app"
esp32c3_opts="PartitionScheme=huge_app"
esp32c3_opts="FlashMode=dio,PartitionScheme=huge_app"
esp32c6_opts="PartitionScheme=huge_app"
esp32h2_opts="PartitionScheme=huge_app"

Expand Down
28 changes: 25 additions & 3 deletions .github/scripts/tests_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function run_test() {
local sketchdir=$(dirname $sketch)
local sketchname=$(basename $sketchdir)

if [[ -f "$sketchdir/.skip.$platform" ]]; then
if [[ -f "$sketchdir/.skip.$platform" ]] || [[ -f "$sketchdir/.skip.$target" ]] || [[ -f "$sketchdir/.skip.$platform.$target" ]]; then
echo "Skipping $sketchname test for $target, platform: $platform"
skipfile="$sketchdir/.test_skipped"
touch $skipfile
Expand Down Expand Up @@ -45,11 +45,24 @@ function run_test() {
if [[ -f "$sketchdir/scenario.yaml" ]]; then
extra_args+=" --wokwi-scenario $sketchdir/scenario.yaml"
fi
elif [ $platform == "qemu" ]; then
PATH=$HOME/qemu/bin:$PATH
extra_args="--embedded-services qemu --qemu-image-path $build_dir/$sketchname.ino.merged.bin"

if [ $target == "esp32" ] || [ $target == "esp32s3" ]; then
extra_args+=" --qemu-prog-path qemu-system-xtensa --qemu-cli-args=\"-machine $target -m 4M -nographic\""
elif [ $target == "esp32c3" ]; then
extra_args+=" --qemu-prog-path qemu-system-riscv32 --qemu-cli-args=\"-machine $target -icount 3 -nographic\""
else
echo "Unsupported QEMU target: $target"
exit 1
fi
else
extra_args="--embedded-services esp,arduino"
fi

pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args
echo "pytest tests --build-dir $build_dir -k test_$sketchname --junit-xml=$report_file $extra_args"
bash -c "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 @@ -71,6 +84,13 @@ while [ ! -z "$1" ]; do
-c )
chunk_run=1
;;
-q )
if [ ! -d $QEMU_PATH ]; then
echo "QEMU path $QEMU_PATH does not exist"
exit 1
fi
platform="qemu"
;;
-w )
shift
wokwi_timeout=$1
Expand Down Expand Up @@ -113,7 +133,9 @@ while [ ! -z "$1" ]; do
shift
done

source ${SCRIPTS_DIR}/install-arduino-ide.sh
if [ ! $platform == "qemu" ]; then
source ${SCRIPTS_DIR}/install-arduino-ide.sh
fi

# If sketch is provided and test type is not, test type is inferred from the sketch path
if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
Expand Down
80 changes: 78 additions & 2 deletions .github/workflows/hil.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,83 @@ jobs:
~/.arduino/tests/**/build*.tmp/*.elf
~/.arduino/tests/**/build*.tmp/*.json

qemu-test:
needs: [gen_chunks, build]
name: ${{matrix.chip}}-QEMU_Test#${{matrix.chunks}}
if: ${{ false }}
strategy:
fail-fast: false
matrix:
chip: ['esp32', 'esp32c3'] # Currently only ESP32 and ESP32-C3 are supported by QEMU
chunks: ${{fromJson(needs.gen_chunks.outputs.chunks)}}
runs-on: ubuntu-latest
env:
QEMU_INSTALL_PATH: "$HOME"
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Get QEMU version
uses: pozetroninc/[email protected]
id: get-qemu-version
with:
token: ${{secrets.GITHUB_TOKEN}}
owner: espressif
repo: qemu
excludes: prerelease, draft

- name: Cache tools
id: cache-linux
uses: actions/cache@v4
with:
path: |
~/qemu
~/.cache/pip
key: qemu-${{ steps.get-qemu-version.outputs.release }}-${{ hashFiles('.github/workflows/hil.yml') }}

- name: Install dependencies
run: |
pip install -U pip
pip install -r tests/requirements.txt --extra-index-url https://dl.espressif.com/pypi
sudo apt update && sudo apt install libpixman-1-0 libnuma1 libglib2.0-0 libslirp0 libsdl2-2.0-0

- name: Download QEMU
if: steps.cache-linux.outputs.cache-hit != 'true'
run: |
cd ${{ env.QEMU_INSTALL_PATH }}
underscore_release=$(echo ${{ steps.get-qemu-version.outputs.release }} | sed 's/\-/_/g')
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-riscv32-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-riscv32.tar.xz
curl -L https://github.com/espressif/qemu/releases/download/${{ steps.get-qemu-version.outputs.release }}/qemu-xtensa-softmmu-${underscore_release}-x86_64-linux-gnu.tar.xz > qemu-xtensa.tar.xz
tar -xf qemu-riscv32.tar.xz
tar -xf qemu-xtensa.tar.xz
rm qemu-*
echo "QEMU_PATH=${{ env.QEMU_INSTALL_PATH }}/qemu" >> $GITHUB_ENV

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

- name: Run Tests
run: QEMU_PATH="${{env.QEMU_PATH}}" bash .github/scripts/tests_run.sh -c -t ${{matrix.chip}} -i ${{matrix.chunks}} -m ${{env.MAX_CHUNKS}} -q

- name: Check if tests were skipped
id: check-test-skipped
run: |
if [ $(find "tests" -name ".test_skipped") ]; then
echo "skipped=true" >> $GITHUB_OUTPUT
else
echo "skipped=false" >> $GITHUB_OUTPUT
fi

- name: Upload test result artifacts
uses: actions/upload-artifact@v4
if: ${{ always() && steps.check-test-skipped.outputs.skipped == 'false' }}
with:
name: qemu_results-${{matrix.chip}}-${{matrix.chunks}}
path: tests/*/*.xml

wokwi-test:
needs: [gen_chunks, build]
if: github.event_name == 'schedule'
Expand All @@ -105,7 +182,7 @@ jobs:
with:
name: ${{matrix.chip}}-${{matrix.chunks}}.artifacts
path: ~/

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

Expand Down Expand Up @@ -205,4 +282,3 @@ jobs:
with:
name: Event File
path: ${{github.event_path}}

5 changes: 5 additions & 0 deletions platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ recipe.hooks.objcopy.postobjcopy.1.pattern.windows=cmd /c if exist "{build.path}
recipe.hooks.objcopy.postobjcopy.2.pattern=/usr/bin/env bash -c "[ ! -d "{build.path}"/libraries/ESP_SR ] || [ ! -f "{compiler.sdk.path}"/esp_sr/srmodels.bin ] || cp -f "{compiler.sdk.path}"/esp_sr/srmodels.bin "{build.path}"/srmodels.bin"
recipe.hooks.objcopy.postobjcopy.2.pattern.windows=cmd /c if exist "{build.path}\libraries\ESP_SR" if exist "{compiler.sdk.path}\esp_sr\srmodels.bin" COPY /y "{compiler.sdk.path}\esp_sr\srmodels.bin" "{build.path}\srmodels.bin"

# Create merged binary
recipe.hooks.objcopy.postobjcopy.3.pattern_args=--chip {build.mcu} merge_bin -o "{build.path}/{build.project_name}.merged.bin" --fill-flash-size {build.flash_size} --flash_mode keep --flash_freq keep --flash_size keep {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x10000 "{build.path}/{build.project_name}.bin"
recipe.hooks.objcopy.postobjcopy.3.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args}
recipe.hooks.objcopy.postobjcopy.3.pattern.linux=python3 "{tools.esptool_py.path}/{tools.esptool_py.cmd}" {recipe.hooks.objcopy.postobjcopy.3.pattern_args}

## Save bin
recipe.output.tmp_file={build.project_name}.bin
recipe.output.save_file={build.project_name}.{build.variant}.bin
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
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,wokwi
addopts = --embedded-services esp,arduino,wokwi,qemu

# 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 @@ -4,3 +4,4 @@ pytest-cov
pytest-embedded-serial-esp>=1.10.2
pytest-embedded-arduino>=1.10.2
pytest-embedded-wokwi>=1.10.2
pytest-embedded-qemu>=1.10.2
Empty file.
Empty file added tests/validation/nvs/.skip.qemu
Empty file.
Empty file.
Empty file.
Empty file.