diff --git a/.github/test_requirements.txt b/.github/test_requirements.txt new file mode 100644 index 0000000000..581bb9c19c --- /dev/null +++ b/.github/test_requirements.txt @@ -0,0 +1,10 @@ +# Generic requirements for all tests +pytest-embedded==1.11.7 +pytest-embedded-serial-esp==1.11.7 +pytest-embedded-idf==1.11.7 +pytest-embedded-qemu==1.11.7 +pytest-custom_exit_code==0.3.0 + +# Test-specific requirements +cryptography==43.0.3 +pillow==10.3.0 diff --git a/.github/workflows/build_and_run_apps.yml b/.github/workflows/build_and_run_apps.yml index c993b1c892..c118f1fcf9 100644 --- a/.github/workflows/build_and_run_apps.yml +++ b/.github/workflows/build_and_run_apps.yml @@ -72,10 +72,10 @@ jobs: fail-fast: false matrix: idf_ver: - - "release-v5.0" - - "release-v5.1" - - "release-v5.2" - - "release-v5.3" + # - "release-v5.0" + # - "release-v5.1" + # - "release-v5.2" + # - "release-v5.3" - "latest" parallel_index: [1,2,3,4,5] # Update --parallel-count below when changing this runs-on: ubuntu-22.04 @@ -122,27 +122,30 @@ jobs: fail-fast: false matrix: idf_ver: - - "release-v5.0" - - "release-v5.1" - - "release-v5.2" - - "release-v5.3" + # - "release-v5.0" + # - "release-v5.1" + # - "release-v5.2" + # - "release-v5.3" - "latest" runner: - - runs-on: "esp32" + - runs-on: '["self-hosted", "linux", "docker", "esp32"]' marker: "generic" target: "esp32" - - runs-on: "ESP32-ETHERNET-KIT" + - runs-on: '["self-hosted", "linux", "docker", "ESP32-ETHERNET-KIT"]' marker: "ethernet" target: "esp32" - - runs-on: "spi_nand_flash" + - runs-on: '["self-hosted", "linux", "docker", "spi_nand_flash"]' marker: "spi_nand_flash" target: "esp32" + - runs-on: '["ubuntu-22.04"]' + marker: "qemu" + target: "esp32" env: TEST_RESULT_NAME: test_results_${{ matrix.runner.target }}_${{ matrix.runner.marker }}_${{ matrix.idf_ver }} TEST_RESULT_FILE: test_results_${{ matrix.runner.target }}_${{ matrix.runner.marker }}_${{ matrix.idf_ver }}.xml - runs-on: [self-hosted, linux, docker, "${{ matrix.runner.runs-on }}"] + runs-on: ${{ fromjson(matrix.runner.runs-on) }} container: - image: python:3.11-bookworm + image: 'python:3.11-bookworm' options: --privileged # Privileged mode has access to serial ports steps: - uses: actions/checkout@v4 @@ -153,7 +156,17 @@ jobs: - name: Install Python packages env: PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/" - run: pip install --prefer-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pytest-custom_exit_code + run: python3 -m pip install --prefer-binary -r .github/test_requirements.txt + - name: Install QEMU + if: matrix.runner.marker == 'qemu' + env: + QEMU_VERSION: "esp-develop-9.0.0-20240606" + QEMU_ARCHIVE: "qemu-xtensa-softmmu-esp_develop_9.0.0_20240606-x86_64-linux-gnu.tar.xz" + run: | + curl -sSL -o ${QEMU_ARCHIVE} https://github.com/espressif/qemu/releases/download/${QEMU_VERSION}/${QEMU_ARCHIVE} + tar -xf ${QEMU_ARCHIVE} + rm ${QEMU_ARCHIVE} + echo "$PWD/qemu/bin" >> $GITHUB_PATH - name: Run apps run: | python3 .github/get_pytest_args.py --target=${{ matrix.runner.target }} -v 'build_info*.json' pytest-args.txt diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/README.md b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/README.md index 10f10a0213..847a2e4553 100644 --- a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/README.md +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/README.md @@ -16,9 +16,12 @@ By default, the example will use the target internal RAM as the frame buffer. To ### Build and run -To build the example, run `idf.py build` command. +To build and run the example, run: +```shell +idf.py qemu -g monitor +``` -Please refer to the [QEMU Guide](https://github.com/espressif/esp-toolchain-docs/blob/main/qemu/README.md) for the detailed steps to setup and run the image. +Please refer to the [QEMU Guide](https://github.com/espressif/esp-toolchain-docs/blob/main/qemu/README.md) for more information on installing and running QEMU. ## Example Output @@ -34,3 +37,6 @@ I (55) example: Starting LVGL task I (65) example: Display LVGL Scatter Chart I (75) main_task: Returned from app_main() ``` + +The following image should be displayed: +![](doc/scatter_chart.png) diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/doc/scatter_chart.png b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/doc/scatter_chart.png new file mode 100644 index 0000000000..8b526b14ca Binary files /dev/null and b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/doc/scatter_chart.png differ diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/Kconfig.projbuild b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/Kconfig.projbuild index f318f9d3fc..b75f30e61b 100644 --- a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/Kconfig.projbuild +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/Kconfig.projbuild @@ -6,4 +6,11 @@ menu "Example Configuration" help Use QEMU RGB panel dedicated framebuffer as the framebuffer for LVGL. + config EXAMPLE_QEMU_RGB_PANEL_STATIC + bool "Static UI (for testing)" + default "n" + help + If this option is enabled, example will not update the chart after + it was drawn. This option is used in CI when testing the example. + endmenu diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lcd_qemu_rgb_panel_main.c b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lcd_qemu_rgb_panel_main.c index 60d428d595..cfe463d0f8 100644 --- a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lcd_qemu_rgb_panel_main.c +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lcd_qemu_rgb_panel_main.c @@ -173,4 +173,6 @@ void app_main(void) // Release the mutex example_lvgl_unlock(); } + + ESP_LOGI(TAG, "LVGL Scatter Chart displayed"); } diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lvgl_demo_ui.c b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lvgl_demo_ui.c index 429be09639..22a17bbc3e 100644 --- a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lvgl_demo_ui.c +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/main/lvgl_demo_ui.c @@ -34,11 +34,13 @@ static void draw_event_cb(lv_event_t *e) } } +#ifndef CONFIG_EXAMPLE_QEMU_RGB_PANEL_STATIC static void add_data(lv_timer_t *timer) { lv_obj_t *chart = timer->user_data; lv_chart_set_next_value2(chart, lv_chart_get_series_next(chart, NULL), lv_rand(0, 200), lv_rand(0, 1000)); } +#endif //CONFIG_EXAMPLE_QEMU_RGB_PANEL_STATIC void example_lvgl_demo_ui(lv_disp_t *disp) { @@ -64,5 +66,7 @@ void example_lvgl_demo_ui(lv_disp_t *disp) lv_chart_set_next_value2(chart, ser, lv_rand(0, 200), lv_rand(0, 1000)); } +#ifndef CONFIG_EXAMPLE_QEMU_RGB_PANEL_STATIC lv_timer_create(add_data, 100, chart); +#endif } diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/pytest_lcd_qemu_rgb_panel.py b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/pytest_lcd_qemu_rgb_panel.py new file mode 100644 index 0000000000..436bbbb2f3 --- /dev/null +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/pytest_lcd_qemu_rgb_panel.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + +import pytest +import os +from pytest_embedded import Dut +import time +try: + from PIL import Image + from PIL import ImageChops +except ImportError: + Image = None + +@pytest.mark.qemu +@pytest.mark.parametrize('qemu_extra_args', ['-display sdl']) +@pytest.mark.parametrize('embedded_services', ['idf,qemu']) +def test_qemu_rgb_panel(dut: Dut) -> None: + if not Image: + pytest.fail('Pillow is not installed') + + dut.expect_exact('Install RGB LCD panel driver') + dut.expect_exact('LVGL Scatter Chart displayed') + time.sleep(2) + filename = 'scatter_chart.ppm' + dut.qemu.take_screenshot(filename) + + img = Image.open(filename) + ref_img = Image.open(os.path.join(os.path.dirname(__file__), 'doc', 'scatter_chart.png')) + + diff = ImageChops.difference(img, ref_img) + assert not diff.getbbox(), 'Images are different' diff --git a/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/sdkconfig.ci b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/sdkconfig.ci new file mode 100644 index 0000000000..bf5420639a --- /dev/null +++ b/esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel/sdkconfig.ci @@ -0,0 +1 @@ +CONFIG_EXAMPLE_QEMU_RGB_PANEL_STATIC=y diff --git a/pytest.ini b/pytest.ini index 4ebe9e7d75..b272435aba 100644 --- a/pytest.ini +++ b/pytest.ini @@ -13,6 +13,7 @@ markers = generic: generic runner ethernet: ethernet runners spi_nand_flash: runner with SPI NAND flash connected + qemu: test runs in QEMU emulator # log related log_cli = True