diff --git a/.github/scripts/on-push.sh b/.github/scripts/on-push.sh index 30fd1653d..dabfc3f35 100755 --- a/.github/scripts/on-push.sh +++ b/.github/scripts/on-push.sh @@ -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 diff --git a/.github/scripts/sketch_utils.sh b/.github/scripts/sketch_utils.sh index 73a9ef8a7..9837d5974 100755 --- a/.github/scripts/sketch_utils.sh +++ b/.github/scripts/sketch_utils.sh @@ -78,10 +78,10 @@ function build_sketch(){ # build_sketch [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" diff --git a/.github/scripts/tests_run.sh b/.github/scripts/tests_run.sh index 2ac3ee7cd..62fdcfd5a 100755 --- a/.github/scripts/tests_run.sh +++ b/.github/scripts/tests_run.sh @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/.github/workflows/hil.yml b/.github/workflows/hil.yml index ead36a7fe..4f3d3ac4d 100644 --- a/.github/workflows/hil.yml +++ b/.github/workflows/hil.yml @@ -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/github-action-get-latest-release@v0.7.0 + 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' @@ -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 @@ -205,4 +282,3 @@ jobs: with: name: Event File path: ${{github.event_path}} - diff --git a/platform.txt b/platform.txt index b6cae322e..4e379e865 100644 --- a/platform.txt +++ b/platform.txt @@ -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 diff --git a/tests/performance/coremark/.skip.qemu b/tests/performance/coremark/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/performance/fibonacci/.skip.qemu b/tests/performance/fibonacci/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/performance/psramspeed/.skip.qemu b/tests/performance/psramspeed/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/performance/ramspeed/.skip.qemu b/tests/performance/ramspeed/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/performance/superpi/.skip.qemu b/tests/performance/superpi/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/pytest.ini b/tests/pytest.ini index 530533b12..b507b4377 100644 --- a/tests/pytest.ini +++ b/tests/pytest.ini @@ -1,5 +1,5 @@ [pytest] -addopts = --embedded-services esp,arduino,wokwi +addopts = --embedded-services esp,arduino,wokwi,qemu # log related log_cli = True diff --git a/tests/requirements.txt b/tests/requirements.txt index 524af4cd2..29efc7721 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -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 diff --git a/tests/validation/democfg/.skip.qemu b/tests/validation/democfg/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/validation/nvs/.skip.qemu b/tests/validation/nvs/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/validation/periman/.skip.qemu b/tests/validation/periman/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/validation/touch/.skip.qemu b/tests/validation/touch/.skip.qemu new file mode 100644 index 000000000..e69de29bb diff --git a/tests/validation/uart/.skip.qemu b/tests/validation/uart/.skip.qemu new file mode 100644 index 000000000..e69de29bb