From 9234e36de53692dd8b7362a1099c61fbc3fe08cc Mon Sep 17 00:00:00 2001 From: "sonika.rathi" Date: Thu, 27 Aug 2026 09:26:31 +0200 Subject: [PATCH] fix(esp_partition): migrate classic tests to test_apps, drop legacy test/ remove unused components/esp_partition/test sources that were only built by the retired unit-test-app path. --- components/esp_partition/test/CMakeLists.txt | 4 - .../esp_partition/test/test_partition.c | 255 ------------------ .../esp_partition/test/test_partition_ext.c | 52 ---- .../esp_partition/test/test_partitions.c | 180 ------------- components/esp_partition/test_apps/README.md | 1 + .../test_apps/main/CMakeLists.txt | 4 +- .../test_apps/main/test_part_app.c | 4 + .../test_apps/main/test_partition_ops.c | 180 +++++++++++++ .../test_apps/pytest_esp_partition.py | 3 +- 9 files changed, 189 insertions(+), 494 deletions(-) delete mode 100644 components/esp_partition/test/CMakeLists.txt delete mode 100644 components/esp_partition/test/test_partition.c delete mode 100644 components/esp_partition/test/test_partition_ext.c delete mode 100644 components/esp_partition/test/test_partitions.c create mode 100644 components/esp_partition/test_apps/main/test_partition_ops.c diff --git a/components/esp_partition/test/CMakeLists.txt b/components/esp_partition/test/CMakeLists.txt deleted file mode 100644 index 4c14df5b1c9..00000000000 --- a/components/esp_partition/test/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -idf_component_register(SRC_DIRS "." - PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES test_utils esp_partition esp_system app_update bootloader_support - spi_flash esp_mspi) diff --git a/components/esp_partition/test/test_partition.c b/components/esp_partition/test/test_partition.c deleted file mode 100644 index 48ce8cc3a51..00000000000 --- a/components/esp_partition/test/test_partition.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include "unity.h" -#include "test_utils.h" -#include "esp_partition.h" - - -TEST_CASE("Can read partition table", "[partition]") -{ - - const esp_partition_t *p = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); - TEST_ASSERT_NOT_NULL(p); - TEST_ASSERT_EQUAL(0x20000, p->address); - TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, p->subtype); - - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL); - TEST_ASSERT_NOT_NULL(it); - int count = 0; - const esp_partition_t* prev = NULL; - for (; it != NULL; it = esp_partition_next(it)) { - const esp_partition_t *p = esp_partition_get(it); - TEST_ASSERT_NOT_NULL(p); - if (prev) { - TEST_ASSERT_TRUE_MESSAGE(prev->address < p->address, "incorrect partition order"); - } - prev = p; - ++count; - } - esp_partition_iterator_release(it); - TEST_ASSERT_EQUAL(5, count); - - it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); - TEST_ASSERT_NOT_NULL(it); - count = 0; - for (; it != NULL; it = esp_partition_next(it)) { - ++count; - } - esp_partition_iterator_release(it); - TEST_ASSERT_EQUAL(8, count); -} - -TEST_CASE("Test esp_partition_find_err API", "[partition]") -{ - // Test successful partition finding - esp_partition_iterator_t iter = NULL; - esp_err_t err = esp_partition_find_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, &iter); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(iter); - - const esp_partition_t *part = esp_partition_get(iter); - TEST_ASSERT_NOT_NULL(part); - TEST_ASSERT_EQUAL(ESP_PARTITION_TYPE_APP, part->type); - - esp_partition_iterator_release(iter); - - // Test partition not found (returns ESP_ERR_NOT_FOUND) - err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent_partition", &iter); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(iter); - - // Test invalid argument - wrong type/subtype combination - err = esp_partition_find_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL, &iter); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - TEST_ASSERT_NULL(iter); - - // Test NULL pointer argument - err = esp_partition_find_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, NULL); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - TEST_ASSERT_NULL(iter); - - // Test finding data partitions with error reporting - iter = NULL; - err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL, &iter); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(iter); - - int data_count = 0; - for (; iter != NULL; iter = esp_partition_next(iter)) { - const esp_partition_t *data_part = esp_partition_get(iter); - TEST_ASSERT_NOT_NULL(data_part); - TEST_ASSERT_EQUAL(ESP_PARTITION_TYPE_DATA, data_part->type); - data_count++; - } - esp_partition_iterator_release(iter); - TEST_ASSERT_TRUE(data_count > 0); -} - -TEST_CASE("Test esp_partition_find_first_err API", "[partition]") -{ - // Test successful partition finding - const esp_partition_t *part = NULL; - esp_err_t err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, &part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(part); - TEST_ASSERT_EQUAL(ESP_PARTITION_TYPE_APP, part->type); - TEST_ASSERT_EQUAL(0x20000, part->address); - TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, part->subtype); - - // Test finding specific factory partition - part = NULL; - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL, &part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(part); - TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, part->subtype); - - // Test partition not found (returns ESP_ERR_NOT_FOUND) - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent_partition", &part); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(part); - - // Test invalid argument - wrong type/subtype combination - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL, &part); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - TEST_ASSERT_NULL(part); - - // Test NULL pointer argument - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, NULL); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - - // Test finding data partitions - part = NULL; - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL, &part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(part); - TEST_ASSERT_EQUAL(ESP_PARTITION_TYPE_DATA, part->type); - - // Compare with legacy API to ensure consistency - const esp_partition_t *legacy_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); - part = NULL; - err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, &part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_EQUAL(legacy_part, part); // Should return the same partition -} - -TEST_CASE("Test esp_partition_verify_err API", "[partition]") -{ - // Test successful partition verification - const esp_partition_t *app_part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL); - TEST_ASSERT_NOT_NULL(app_part); - - const esp_partition_t *verified_part = NULL; - esp_err_t err = esp_partition_verify_err(app_part, &verified_part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_NOT_NULL(verified_part); - TEST_ASSERT_EQUAL(app_part, verified_part); // Should return the same partition pointer - - // Test both parameters NULL - err = esp_partition_verify_err(NULL, NULL); - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - - // Test with wrong address (should not match) - esp_partition_t app_copy = *app_part; - app_copy.address = 0xFFFFFFFF; - err = esp_partition_verify_err(&app_copy, &verified_part); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(verified_part); - - // Test with wrong type (should not match) - app_copy = *app_part; - app_copy.type = ESP_PARTITION_TYPE_DATA; - err = esp_partition_verify_err(&app_copy, &verified_part); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(verified_part); - - // Test with different readonly flag (should not match) - app_copy = *app_part; - app_copy.readonly = !app_part->readonly; - err = esp_partition_verify_err(&app_copy, &verified_part); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(verified_part); - - // Test output parameter is properly initialized - verified_part = (const esp_partition_t *)0xDEADBEEF; - err = esp_partition_verify_err(&app_copy, &verified_part); - TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err); - TEST_ASSERT_NULL(verified_part); // Should be set to NULL - - // Compare with legacy API for consistency - const esp_partition_t *legacy_verified = esp_partition_verify(app_part); - verified_part = NULL; - err = esp_partition_verify_err(app_part, &verified_part); - TEST_ASSERT_EQUAL(ESP_OK, err); - TEST_ASSERT_EQUAL(legacy_verified, verified_part); -} - -TEST_CASE("Can write, read, mmap partition", "[partition][ignore]") -{ - const esp_partition_t *p = get_test_data_partition(); - printf("Using partition %s at 0x%x, size 0x%x\n", p->label, p->address, p->size); - TEST_ASSERT_NOT_NULL(p); - const size_t max_size = 2 * p->erase_size; - uint8_t *data = (uint8_t *) malloc(max_size); - TEST_ASSERT_NOT_NULL(data); - - TEST_ASSERT_EQUAL(ESP_OK, esp_partition_erase_range(p, 0, p->size)); - - srand(0); - size_t block_size; - for (size_t offset = 0; offset < p->size; offset += block_size) { - block_size = ((rand() + 4) % max_size) & (~0x3); - size_t left = p->size - offset; - if (block_size > left) { - block_size = left; - } - for (size_t i = 0; i < block_size / 4; ++i) { - ((uint32_t *) (data))[i] = rand(); - } - TEST_ASSERT_EQUAL(ESP_OK, esp_partition_write(p, offset, data, block_size)); - } - - srand(0); - for (size_t offset = 0; offset < p->size; offset += block_size) { - block_size = ((rand() + 4) % max_size) & (~0x3); - size_t left = p->size - offset; - if (block_size > left) { - block_size = left; - } - TEST_ASSERT_EQUAL(ESP_OK, esp_partition_read(p, offset, data, block_size)); - for (size_t i = 0; i < block_size / 4; ++i) { - TEST_ASSERT_EQUAL(rand(), ((uint32_t *) data)[i]); - } - } - - free(data); - - const uint32_t *mmap_data; - esp_partition_mmap_handle_t mmap_handle; - size_t begin = 3000; - size_t size = 64000; //chosen so size is smaller than 64K but the mmap straddles 2 MMU blocks - TEST_ASSERT_EQUAL(ESP_OK, esp_partition_mmap(p, begin, size, ESP_PARTITION_MMAP_DATA | ESP_PARTITION_MMAP_BLOCKS_WRITE, - (const void **)&mmap_data, &mmap_handle)); - srand(0); - for (size_t offset = 0; offset < p->size; offset += block_size) { - block_size = ((rand() + 4) % max_size) & (~0x3); - size_t left = p->size - offset; - if (block_size > left) { - block_size = left; - } - for (size_t i = 0; i < block_size / 4; ++i) { - size_t pos = offset + i * 4; - uint32_t expected = rand(); - if (pos < begin || pos >= (begin + size)) { - continue; - } - TEST_ASSERT_EQUAL(expected, mmap_data[(pos - begin) / 4]); - } - } - - esp_partition_munmap(mmap_handle); -} diff --git a/components/esp_partition/test/test_partition_ext.c b/components/esp_partition/test/test_partition_ext.c deleted file mode 100644 index b2721c87889..00000000000 --- a/components/esp_partition/test/test_partition_ext.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include "esp_flash.h" -#include "spi_flash_mmap.h" -#include "esp_partition.h" -#include "unity.h" - -TEST_CASE("Basic handling of a partition in external flash", "[partition]") -{ - esp_flash_t flash = { - .size = 1 * 1024 * 1024, - }; - - const esp_partition_type_t t = ESP_PARTITION_TYPE_DATA; - const esp_partition_subtype_t st = ESP_PARTITION_SUBTYPE_DATA_FAT; - const char* label = "ext_fat"; - - /* can register */ - const esp_partition_t* ext_partition; - TEST_ESP_OK(esp_partition_register_external(&flash, 0, flash.size, label, t, st, &ext_partition)); - - /* can find the registered partition */ - const esp_partition_t* found = esp_partition_find_first(t, st, label); - TEST_ASSERT_EQUAL_HEX(ext_partition, found); - TEST_ASSERT_EQUAL(found->size, flash.size); - TEST_ASSERT_EQUAL(found->address, 0); - - /* can deregister */ - TEST_ESP_OK(esp_partition_deregister_external(ext_partition)); - - /* can not deregister one of the partitions on the main flash chip */ - const esp_partition_t* nvs_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL); - TEST_ASSERT_NOT_NULL(nvs_partition); - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_partition_deregister_external(nvs_partition)); - - /* can not deregister an unknown partition */ - esp_partition_t dummy_partition = {}; - TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_partition_deregister_external(&dummy_partition)); - - /* can not register a partition larger than the flash size */ - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, - esp_partition_register_external(&flash, 0, 2 * flash.size, "ext_fat", t, st, &ext_partition)); - - /* can not register an overlapping partition */ - TEST_ESP_OK(esp_partition_register_external(&flash, 0, 2 * SPI_FLASH_SEC_SIZE, "p1", t, st, &ext_partition)); - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_partition_register_external(&flash, SPI_FLASH_SEC_SIZE, 2 * SPI_FLASH_SEC_SIZE, - "p2", t, st, NULL)); - TEST_ESP_OK(esp_partition_deregister_external(ext_partition)); -} diff --git a/components/esp_partition/test/test_partitions.c b/components/esp_partition/test/test_partitions.c deleted file mode 100644 index e5c233ac707..00000000000 --- a/components/esp_partition/test/test_partitions.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// Test for spi_flash_{read,write}. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "esp_flash.h" -#include "spi_flash_mmap.h" - -TEST_CASE("Test erase partition", "[spi_flash][esp_flash]") -{ - const esp_partition_t *part = get_test_data_partition(); - -#if CONFIG_SPI_FLASH_ENABLE_COUNTERS - esp_flash_reset_counters(); -#endif - - // erase whole partition - ESP_ERROR_CHECK( esp_partition_erase_range(part, 0, part->size) ); - -#if CONFIG_SPI_FLASH_ENABLE_COUNTERS - esp_flash_dump_counters(stdout); -#endif - - // put some dummy data on sector boundaries - const static DRAM_ATTR char some_data[] = "abcdefghijklmn"; - for (int i = 0; i < part->size; i+= 4096) { - ESP_ERROR_CHECK( esp_partition_write(part, i, some_data, strlen(some_data)) ); - } - - // check it's there! - char buf[strlen(some_data)]; - for (int i = 0; i < part->size; i+= 4096) { - memset(buf, 0x00, sizeof(buf)); - ESP_ERROR_CHECK( esp_partition_read(part, i, buf, sizeof(buf)) ); - TEST_ASSERT_EQUAL_INT(0, strncmp(buf, some_data, sizeof(buf))); - } - - // erase the whole thing again - ESP_ERROR_CHECK( esp_partition_erase_range(part, 0, part->size) ); - - // check it's gone - for (int i = 0; i < part->size; i+= 4096) { - memset(buf, 0x00, sizeof(buf)); - ESP_ERROR_CHECK( esp_partition_read(part, i, buf, sizeof(buf)) ); - for (int i = 0; i < sizeof(buf); i++) { - TEST_ASSERT_EQUAL_HEX8(0xFF, buf[i]); - } - } -} - -static bool s_test_nonzero_sha_of_partition(const esp_partition_t *part, bool allow_invalid_image) -{ - uint8_t sha256[32] = { 0 }; - - TEST_ASSERT_NOT_NULL(part); - - esp_err_t err = esp_partition_get_sha256(part, sha256); - - if (allow_invalid_image && err == ESP_ERR_IMAGE_INVALID) { - printf("App partition at 0x%x doesn't hold a valid app\n", part->address); - return false; - } - - // Otherwise, err should be ESP_OK - ESP_ERROR_CHECK(err); - - ESP_LOG_BUFFER_HEX("sha", sha256, sizeof(sha256)); - - for (int i = 0; i < sizeof(sha256); i++) { - if (sha256[i] != 0) { - return true; // At least one non-zero byte! - } - } - TEST_FAIL_MESSAGE("SHA-256 of data partition should not be all zeroes"); - abort(); // unreachable -} - -TEST_CASE("Test esp_partition_get_sha256() with data", "[spi_flash]") -{ - const esp_partition_t *part = get_test_data_partition(); - s_test_nonzero_sha_of_partition(part, false); -} - -TEST_CASE("Test esp_partition_get_sha256() with app", "[spi_flash]") -{ - bool found_valid_app = false; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_ANY, - NULL); - TEST_ASSERT_NOT_NULL(it); /* has to be at least one app partition */ - - while (it != NULL) { - const esp_partition_t *part = esp_partition_get(it); - printf("Hashing app partition at 0x%x\n", part->address); - bool valid = s_test_nonzero_sha_of_partition(part, true); - found_valid_app |= valid; - - it = esp_partition_next(it); - } - - TEST_ASSERT_MESSAGE(found_valid_app, "At least one app partition should be a valid app partition"); -} - -TEST_CASE("Test esp_partition_get_sha256() that it can handle a big partition", "[spi_flash]") -{ - /* This test verifies the function 'esp_partition_get_sha256()' working correctly under the following conditions: - * - there is only 1 MMU page left for memory mapping (ideal case) - * - the partition to hash is significantly larger than a common use-case partition size - * The test case is implemented as follows: - * 1. SPI Flash space is mmapped by MMU page size chunks, one by one - * 2. the iteration stops when either whole SPI Flash range is exhausted or the MMU page pool is fully occupied (ESP_ERR_NO_MEM) - * 3. the last successfully mapped MMU page is released, all the rest remains occupied - * 4. pseudo partition of DATA type is created over all the SPI Flash capacity - * 5. esp_partition_get_sha256() is calculated for the partition defined in 4. (printed to standard output on successful completion) - * 6. all the resources allocated directly by the test are released - * NOTE: the test is chip-agnostic - * */ - - uint32_t size_flash_chip; - TEST_ESP_OK(esp_flash_get_size(NULL, &size_flash_chip)); - printf("flash size = %d bytes\n", size_flash_chip); - - uint32_t page_reservation_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); - printf("available page pool = %d pages\n", page_reservation_count); - - spi_flash_mmap_handle_t* handles = malloc(page_reservation_count * sizeof(spi_flash_mmap_handle_t)); - TEST_ASSERT_NOT_NULL(handles); - - const void *ptr = NULL; - size_t flash_offset = 0; - size_t mapped_pages_count = 0; - - esp_err_t err = ESP_FAIL; - for (; mapped_pages_count0); - mapped_pages_count--; - spi_flash_munmap(handles[mapped_pages_count]); - } - else { - TEST_ESP_OK(err); - } - - esp_partition_t partition = { - .address = 0x00000000, - .size = size_flash_chip, - .type = ESP_PARTITION_TYPE_DATA - }; - - uint8_t sha256[32] = {0}; - TEST_ESP_OK(esp_partition_get_sha256(&partition, sha256)); - ESP_LOG_BUFFER_HEX("sha", sha256, sizeof(sha256)); - - for(size_t y=0; y +#include +#include +#include +#include + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_flash.h" +#include "esp_image_format.h" +#include "esp_log.h" +#include "esp_partition.h" +#include "esp_task_wdt.h" +#include "spi_flash_mmap.h" +#include "unity.h" +#include "unity_fixture.h" + +/* Same Unity group as test_part_app.c; setup/teardown live there. */ +TEST_GROUP(esp_partition); +void TEST_esp_partition_SETUP(void); +void TEST_esp_partition_TEAR_DOWN(void); + +static const esp_partition_t *s_get_data_partition(void) +{ + const esp_partition_t *part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_ANY, + "storage1"); + TEST_ASSERT_NOT_NULL(part); + return part; +} + +static bool s_test_nonzero_sha_of_partition(const esp_partition_t *part, bool allow_invalid_image) +{ + uint8_t sha256[32] = {0}; + + TEST_ASSERT_NOT_NULL(part); + + esp_err_t err = esp_partition_get_sha256(part, sha256); + + if (allow_invalid_image && err == ESP_ERR_IMAGE_INVALID) { + printf("App partition at 0x%" PRIx32 " doesn't hold a valid app\n", part->address); + return false; + } + + TEST_ESP_OK(err); + ESP_LOG_BUFFER_HEX("sha", sha256, sizeof(sha256)); + + for (size_t i = 0; i < sizeof(sha256); i++) { + if (sha256[i] != 0) { + return true; + } + } + TEST_FAIL_MESSAGE("SHA-256 of partition should not be all zeroes"); + abort(); +} + +TEST(esp_partition, test_erase_partition) +{ + const esp_partition_t *part = s_get_data_partition(); + + TEST_ESP_OK(esp_partition_erase_range(part, 0, part->size)); + + const static DRAM_ATTR char some_data[] = "abcdefghijklmn"; + const size_t data_len = strlen(some_data); + for (size_t i = 0; i < part->size; i += 4096) { + TEST_ESP_OK(esp_partition_write(part, i, some_data, data_len)); + } + + char buf[sizeof(some_data)]; + for (size_t i = 0; i < part->size; i += 4096) { + memset(buf, 0x00, sizeof(buf)); + TEST_ESP_OK(esp_partition_read(part, i, buf, data_len)); + TEST_ASSERT_EQUAL_INT(0, strncmp(buf, some_data, data_len)); + } + + TEST_ESP_OK(esp_partition_erase_range(part, 0, part->size)); + + for (size_t i = 0; i < part->size; i += 4096) { + memset(buf, 0x00, sizeof(buf)); + TEST_ESP_OK(esp_partition_read(part, i, buf, data_len)); + for (size_t j = 0; j < data_len; j++) { + TEST_ASSERT_EQUAL_HEX8(0xFF, buf[j]); + } + } +} + +TEST(esp_partition, test_get_sha256_data) +{ + const esp_partition_t *part = s_get_data_partition(); + TEST_ASSERT_TRUE(s_test_nonzero_sha_of_partition(part, false)); +} + +TEST(esp_partition, test_get_sha256_app) +{ + bool found_valid_app = false; + esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_APP, + ESP_PARTITION_SUBTYPE_ANY, + NULL); + TEST_ASSERT_NOT_NULL(it); + + while (it != NULL) { + const esp_partition_t *part = esp_partition_get(it); + printf("Hashing app partition at 0x%" PRIx32 "\n", part->address); + found_valid_app |= s_test_nonzero_sha_of_partition(part, true); + it = esp_partition_next(it); + } + + TEST_ASSERT_MESSAGE(found_valid_app, "At least one app partition should be a valid app partition"); +} + +TEST(esp_partition, test_get_sha256_big_partition) +{ + /* Leave one MMU page free, then hash a partition spanning the whole flash. */ + uint32_t size_flash_chip; + TEST_ESP_OK(esp_flash_get_size(NULL, &size_flash_chip)); + printf("flash size = %" PRIu32 " bytes\n", size_flash_chip); + + uint32_t page_reservation_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); + printf("available page pool = %" PRIu32 " pages\n", page_reservation_count); + + spi_flash_mmap_handle_t *handles = malloc(page_reservation_count * sizeof(spi_flash_mmap_handle_t)); + TEST_ASSERT_NOT_NULL(handles); + + const void *ptr = NULL; + size_t flash_offset = 0; + size_t mapped_pages_count = 0; + + esp_err_t err = ESP_FAIL; + for (; mapped_pages_count < page_reservation_count && flash_offset < size_flash_chip; + mapped_pages_count++, flash_offset += SPI_FLASH_MMU_PAGE_SIZE) { + err = spi_flash_mmap(flash_offset, SPI_FLASH_MMU_PAGE_SIZE, + SPI_FLASH_MMAP_FLAG_DATA | SPI_FLASH_MMAP_FLAG_BLOCKS_WRITE, + &ptr, &handles[mapped_pages_count]); + if (err != ESP_OK) { + break; + } + TEST_ASSERT_NOT_NULL(ptr); + ptr = NULL; + } + + if (err == ESP_OK || err == ESP_ERR_NO_MEM) { + TEST_ASSERT(mapped_pages_count > 0); + mapped_pages_count--; + spi_flash_munmap(handles[mapped_pages_count]); + } else { + TEST_ESP_OK(err); + } + + esp_partition_t partition = { + .address = 0x00000000, + .size = size_flash_chip, + .type = ESP_PARTITION_TYPE_DATA, + }; + + uint8_t sha256[32] = {0}; +#if CONFIG_ESP_TASK_WDT_EN + /* Whole-flash SHA with most MMU pages held can exceed the default TWDT + * (idle does not run during this loop). Bump timeout for this case only. */ + const esp_task_wdt_config_t twdt_cfg = { + .timeout_ms = 60 * 1000, + .idle_core_mask = (1U << CONFIG_FREERTOS_NUMBER_OF_CORES) - 1U, + .trigger_panic = true, + }; + TEST_ESP_OK(esp_task_wdt_reconfigure(&twdt_cfg)); +#endif + TEST_ESP_OK(esp_partition_get_sha256(&partition, sha256)); + ESP_LOG_BUFFER_HEX("sha", sha256, sizeof(sha256)); + + for (size_t y = 0; y < mapped_pages_count; y++) { + spi_flash_munmap(handles[y]); + } + + free(handles); +} diff --git a/components/esp_partition/test_apps/pytest_esp_partition.py b/components/esp_partition/test_apps/pytest_esp_partition.py index 38ad47694a3..027220d6968 100644 --- a/components/esp_partition/test_apps/pytest_esp_partition.py +++ b/components/esp_partition/test_apps/pytest_esp_partition.py @@ -9,4 +9,5 @@ from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.flaky(reruns=2, reruns_delay=5) @idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_esp_partition(dut: Dut) -> None: - dut.expect_unity_test_output() + # Erase + whole-flash get_sha256 can exceed the default Unity expect window + dut.expect_unity_test_output(timeout=120)