feat(esp_partition): add error-returning variants for partition find APIs

Add esp_partition_find_err() and esp_partition_find_first_err() to provide
error reporting while maintaining backward compatibility.

Closes https://github.com/espressif/esp-idf/issues/9281
This commit is contained in:
sonika.rathi
2025-09-22 12:03:58 +02:00
parent 9ef6d3eac4
commit 5b65634b49
4 changed files with 442 additions and 27 deletions

View File

@@ -88,6 +88,62 @@ TEST(partition_api, test_partition_find_first)
TEST_ASSERT_NOT_NULL(partition_data); TEST_ASSERT_NOT_NULL(partition_data);
} }
TEST(partition_api, test_partition_find_err)
{
esp_partition_iterator_t iter = NULL;
esp_err_t err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", &iter);
TEST_ESP_OK(err);
TEST_ASSERT_NOT_NULL(iter);
const esp_partition_t *part = esp_partition_get(iter);
TEST_ASSERT_NOT_NULL(part);
esp_partition_iterator_release(iter);
// Test error cases
err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent", &iter);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
TEST_ASSERT_NULL(iter); // But iterator should be NULL
// Test invalid argument
err = esp_partition_find_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL, &iter);
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
TEST_ASSERT_NULL(iter); // But iterator should be NULL
// Test NULL pointer
err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", NULL);
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
TEST_ASSERT_NULL(iter); // But iterator should be NULL
}
TEST(partition_api, test_partition_find_first_err)
{
const esp_partition_t *partition_app = NULL;
esp_err_t err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, &partition_app);
TEST_ESP_OK(err);
TEST_ASSERT_NOT_NULL(partition_app);
const esp_partition_t *partition_data = NULL;
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", &partition_data);
TEST_ESP_OK(err);
TEST_ASSERT_NOT_NULL(partition_data);
// Test partition not found
const esp_partition_t *partition_nonexistent = NULL;
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent", &partition_nonexistent);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
TEST_ASSERT_NULL(partition_nonexistent); // But partition should be NULL
// Test error cases
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL, &partition_data);
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
TEST_ASSERT_NULL(partition_data); // But partition should be NULL
// Test NULL pointer
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", NULL);
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
}
TEST(partition_api, test_partition_ops) TEST(partition_api, test_partition_ops)
{ {
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage"); const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
@@ -122,6 +178,59 @@ TEST(partition_api, test_partition_ops)
TEST_ASSERT_NOT_NULL(verified_partition); TEST_ASSERT_NOT_NULL(verified_partition);
} }
TEST(partition_api, test_partition_verify_err)
{
// Get a valid partition for testing
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
TEST_ASSERT_NOT_NULL(partition_data);
const esp_partition_t *verified_partition = NULL;
esp_err_t err;
// Test 1: Valid partition verification
err = esp_partition_verify_err(partition_data, &verified_partition);
TEST_ESP_OK(err);
TEST_ASSERT_EQUAL_PTR(partition_data, verified_partition);
// Test 2: Both parameters NULL
err = esp_partition_verify_err(NULL, NULL);
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
// Test 3: Partition with wrong address should not match
esp_partition_t partition_copy = *partition_data;
partition_copy.address = 0xFFFFFFFF; // Invalid address
verified_partition = NULL;
err = esp_partition_verify_err(&partition_copy, &verified_partition);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
TEST_ASSERT_NULL(verified_partition);
// Test 4: Partition with wrong size should not match
partition_copy = *partition_data;
partition_copy.size = 0xFFFFFFFF; // Invalid size
verified_partition = NULL;
err = esp_partition_verify_err(&partition_copy, &verified_partition);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
TEST_ASSERT_NULL(verified_partition);
// Test 5: Partition with wrong type should not match
partition_copy = *partition_data;
partition_copy.type = ESP_PARTITION_TYPE_APP; // Wrong type
verified_partition = NULL;
err = esp_partition_verify_err(&partition_copy, &verified_partition);
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
TEST_ASSERT_NULL(verified_partition);
// Test 6: Test with a partition that has empty label
const esp_partition_t *app_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
if (app_partition != NULL && strlen(app_partition->label) == 0) {
verified_partition = NULL;
err = esp_partition_verify_err(app_partition, &verified_partition);
TEST_ESP_OK(err);
TEST_ASSERT_NOT_NULL(verified_partition);
TEST_ASSERT_EQUAL_PTR(app_partition, verified_partition);
}
}
TEST(partition_api, test_partition_mmap) TEST(partition_api, test_partition_mmap)
{ {
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage"); const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
@@ -750,8 +859,11 @@ TEST_GROUP_RUNNER(partition_api)
RUN_TEST_CASE(partition_api, test_partition_find_app); RUN_TEST_CASE(partition_api, test_partition_find_app);
RUN_TEST_CASE(partition_api, test_partition_find_data); RUN_TEST_CASE(partition_api, test_partition_find_data);
RUN_TEST_CASE(partition_api, test_partition_find_first); RUN_TEST_CASE(partition_api, test_partition_find_first);
RUN_TEST_CASE(partition_api, test_partition_find_err);
RUN_TEST_CASE(partition_api, test_partition_find_first_err);
RUN_TEST_CASE(partition_api, test_partition_ops); RUN_TEST_CASE(partition_api, test_partition_ops);
RUN_TEST_CASE(partition_api, test_partition_mmap); RUN_TEST_CASE(partition_api, test_partition_mmap);
RUN_TEST_CASE(partition_api, test_partition_verify_err);
RUN_TEST_CASE(partition_api, test_partition_mmap_support_for_greater_than_4M); RUN_TEST_CASE(partition_api, test_partition_mmap_support_for_greater_than_4M);
RUN_TEST_CASE(partition_api, test_partition_mmap_diff_size); RUN_TEST_CASE(partition_api, test_partition_mmap_diff_size);
RUN_TEST_CASE(partition_api, test_partition_mmap_reopen); RUN_TEST_CASE(partition_api, test_partition_mmap_reopen);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -169,6 +169,35 @@ typedef struct {
*/ */
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label); esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
/**
* @brief Find partition based on one or more parameters with error reporting
*
* This function provides the same functionality as esp_partition_find() but returns
* error information instead of just NULL on failure. This allows applications
* to distinguish between "no partitions found" and actual error conditions.
*
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer.
* To find all partitions, no matter the type, use ESP_PARTITION_TYPE_ANY, and set
* subtype argument to ESP_PARTITION_SUBTYPE_ANY.
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer.
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
* @param label (optional) Partition label. Set this value if looking
* for partition with a specific name. Pass NULL otherwise.
* @param[out] it Output iterator which can be used to enumerate all the partitions found. Must not be NULL.
* Set to NULL if no partitions were found or on error.
* If not NULL after successful call, iterator must be released using
* esp_partition_iterator_release when not used any more.
*
* @return
* - ESP_OK: Operation completed successfully
* - ESP_ERR_INVALID_ARG: if param[out] it is NULL, or if type is ESP_PARTITION_TYPE_ANY
* but subtype is not ESP_PARTITION_SUBTYPE_ANY
* - ESP_ERR_NO_MEM: if memory allocation failed
* - ESP_ERR_NOT_FOUND: if no partition were found
* - Other error codes from partition loading functions
*/
esp_err_t esp_partition_find_err(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label, esp_partition_iterator_t* it);
/** /**
* @brief Find first partition based on one or more parameters * @brief Find first partition based on one or more parameters
* *
@@ -185,6 +214,34 @@ esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_parti
*/ */
const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label); const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
/**
* @brief Find first partition based on one or more parameters with error reporting
*
* This function provides the same functionality as esp_partition_find_first() but returns
* error information instead of just NULL on failure. This allows applications
* to distinguish between "no partition found" and actual error conditions.
*
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer.
* To find all partitions, no matter the type, use ESP_PARTITION_TYPE_ANY, and set
* subtype argument to ESP_PARTITION_SUBTYPE_ANY.
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
* @param label (optional) Partition label. Set this value if looking
* for partition with a specific name. Pass NULL otherwise.
* @param[out] partition Output pointer to esp_partition_t structure. Must not be NULL.
* Set to NULL if no partition is found or on error.
* If not NULL after successful call, this pointer is valid for the lifetime of the application.
*
* @return
* - ESP_OK: Operation completed successfully (regardless of whether partition was found)
* - ESP_ERR_INVALID_ARG: if param[out] partition is NULL, or if type is ESP_PARTITION_TYPE_ANY
* but subtype is not ESP_PARTITION_SUBTYPE_ANY
* - ESP_ERR_NO_MEM: if memory allocation failed
* - ESP_ERR_NOT_FOUND: if no partition were found
* - Other error codes from partition loading functions
*/
esp_err_t esp_partition_find_first_err(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label, const esp_partition_t** partition);
/** /**
* @brief Get esp_partition_t structure for given partition * @brief Get esp_partition_t structure for given partition
* *
@@ -236,6 +293,45 @@ void esp_partition_iterator_release(esp_partition_iterator_t iterator);
*/ */
const esp_partition_t* esp_partition_verify(const esp_partition_t* partition); const esp_partition_t* esp_partition_verify(const esp_partition_t* partition);
/**
* @brief Verify partition data with error reporting
*
* This function provides the same functionality as esp_partition_verify() but returns
* error information instead of just NULL on failure. This allows applications
* to distinguish between "partition not found" and actual error conditions
*
* Given a pointer to partition data, verify this partition exists in the partition table
* by comparing all key fields (flash_chip, address, size, encrypted status). The function
* searches through all registered partitions with matching type, subtype, and label.
*
* This function is useful to:
* - Take partition data from RAM buffer and convert to permanent flash-based pointer
* - Validate partition structures obtained from external sources
* - Ensure partition data integrity before performing operations
*
* @param partition Pointer to partition data to verify. Must be non-NULL.
* The following fields are used for verification:
* - type: Partition type
* - subtype: Partition subtype
* - label: Partition label (if non-empty)
* - flash_chip: Flash chip pointer
* - address: Starting address
* - size: Partition size
* - encrypted: Encryption status
* @param[out] out_partition Output pointer to verified esp_partition_t structure. Must not be NULL.
* Set to NULL if partition is not found or on error.
* If not NULL after successful call, this pointer is valid for the
* lifetime of the application and points to the permanent partition
* structure in flash.
*
* @return
* - ESP_OK: Partition verified successfully and found in partition table
* - ESP_ERR_INVALID_ARG: if partition or out_partition is NULL
* - ESP_ERR_NO_MEM: if memory allocation failed during partition search
* - ESP_ERR_NOT_FOUND: if no matching partition found in partition table
*/
esp_err_t esp_partition_verify_err(const esp_partition_t* partition, const esp_partition_t** out_partition);
/** /**
* @brief Read data from the partition * @brief Read data from the partition
* *

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -300,26 +300,47 @@ static esp_partition_iterator_opaque_t *iterator_create(esp_partition_type_t typ
return it; return it;
} }
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_err_t esp_partition_find_err(esp_partition_type_t type,
esp_partition_subtype_t subtype, const char *label) esp_partition_subtype_t subtype, const char *label, esp_partition_iterator_t *it)
{ {
if (ensure_partitions_loaded() != ESP_OK) { if (it == NULL) {
return NULL; return ESP_ERR_INVALID_ARG;
}
*it = NULL;
esp_err_t err = ensure_partitions_loaded();
if (err != ESP_OK) {
return err;
} }
// Searching for a specific subtype without specifying the type doesn't make // Searching for a specific subtype without specifying the type doesn't make
// sense, and is likely a usage error. // sense, and is likely a usage error.
if (type == ESP_PARTITION_TYPE_ANY && subtype != ESP_PARTITION_SUBTYPE_ANY) { if (type == ESP_PARTITION_TYPE_ANY && subtype != ESP_PARTITION_SUBTYPE_ANY) {
return NULL; return ESP_ERR_INVALID_ARG;
} }
// create an iterator pointing to the start of the list // create an iterator pointing to the start of the list
// (next item will be the first one) // (next item will be the first one)
esp_partition_iterator_t it = iterator_create(type, subtype, label); *it = iterator_create(type, subtype, label);
if (it == NULL) { if (*it == NULL) {
return NULL; return ESP_ERR_NO_MEM;
} }
// advance iterator to the next item which matches constraints // advance iterator to the next item which matches constraints
it = esp_partition_next(it); *it = esp_partition_next(*it);
if (*it == NULL) {
return ESP_ERR_NOT_FOUND;
}
// if nothing found, it == NULL and iterator has been released // if nothing found, it == NULL and iterator has been released
return ESP_OK;
}
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type,
esp_partition_subtype_t subtype, const char *label)
{
esp_partition_iterator_t it;
esp_err_t err = esp_partition_find_err(type, subtype, label, &it);
if (err != ESP_OK) {
return NULL;
}
return it; return it;
} }
@@ -356,16 +377,36 @@ esp_partition_iterator_t esp_partition_next(esp_partition_iterator_t it)
return it; return it;
} }
esp_err_t esp_partition_find_first_err(esp_partition_type_t type,
esp_partition_subtype_t subtype, const char *label, const esp_partition_t **partition)
{
if (partition == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_partition_iterator_t it = NULL;
esp_err_t err = esp_partition_find_err(type, subtype, label, &it);
if (err != ESP_OK || it == NULL) {
*partition = NULL;
return err;
}
*partition = esp_partition_get(it);
esp_partition_iterator_release(it);
if (*partition == NULL) {
return ESP_ERR_NOT_FOUND;
}
return ESP_OK;
}
const esp_partition_t *esp_partition_find_first(esp_partition_type_t type, const esp_partition_t *esp_partition_find_first(esp_partition_type_t type,
esp_partition_subtype_t subtype, const char *label) esp_partition_subtype_t subtype, const char *label)
{ {
esp_partition_iterator_t it = esp_partition_find(type, subtype, label); const esp_partition_t *partition;
if (it == NULL) { esp_err_t err = esp_partition_find_first_err(type, subtype, label, &partition);
if (err != ESP_OK) {
return NULL; return NULL;
} }
const esp_partition_t *res = esp_partition_get(it); return partition;
esp_partition_iterator_release(it);
return res;
} }
void esp_partition_iterator_release(esp_partition_iterator_t iterator) void esp_partition_iterator_release(esp_partition_iterator_t iterator)
@@ -380,28 +421,50 @@ const esp_partition_t *esp_partition_get(esp_partition_iterator_t iterator)
return iterator->info; return iterator->info;
} }
const esp_partition_t *esp_partition_verify(const esp_partition_t *partition) esp_err_t esp_partition_verify_err(const esp_partition_t *partition, const esp_partition_t **out_partition)
{ {
assert(partition != NULL); // Validate input parameters
if (partition == NULL || out_partition == NULL) {
return ESP_ERR_INVALID_ARG;
}
*out_partition = NULL;
const char *label = (strlen(partition->label) > 0) ? partition->label : NULL; const char *label = (strlen(partition->label) > 0) ? partition->label : NULL;
esp_partition_iterator_t it = esp_partition_find(partition->type, esp_partition_iterator_t it = NULL;
esp_err_t err = esp_partition_find_err(partition->type,
partition->subtype, partition->subtype,
label); label, &it);
if (err != ESP_OK) {
return err;
}
while (it != NULL) { while (it != NULL) {
const esp_partition_t *p = esp_partition_get(it); const esp_partition_t *p = esp_partition_get(it);
/* Can't memcmp() whole structure here as padding contents may be different */ /* Can't memcmp() whole structure here as padding contents may be different */
if (p->flash_chip == partition->flash_chip if (p->flash_chip == partition->flash_chip
&& p->address == partition->address && p->address == partition->address
&& partition->size == p->size && p->size == partition->size
&& partition->encrypted == p->encrypted) { && p->encrypted == partition->encrypted) {
esp_partition_iterator_release(it); esp_partition_iterator_release(it);
return p; *out_partition = p;
return ESP_OK;
} }
it = esp_partition_next(it); it = esp_partition_next(it);
} }
esp_partition_iterator_release(it);
// Iterator is automatically released by esp_partition_next when it reaches the end
return ESP_ERR_NOT_FOUND;
}
const esp_partition_t *esp_partition_verify(const esp_partition_t *partition)
{
const esp_partition_t *out_partition;
esp_err_t err = esp_partition_verify_err(partition, &out_partition);
if (err != ESP_OK) {
return NULL; return NULL;
} }
return out_partition;
}
esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset, size_t size, esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset, size_t size,
const char *label, esp_partition_type_t type, esp_partition_subtype_t subtype, const char *label, esp_partition_type_t type, esp_partition_subtype_t subtype,

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2016-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -44,6 +44,150 @@ TEST_CASE("Can read partition table", "[partition]")
TEST_ASSERT_EQUAL(8, count); 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]") TEST_CASE("Can write, read, mmap partition", "[partition][ignore]")
{ {
const esp_partition_t *p = get_test_data_partition(); const esp_partition_t *p = get_test_data_partition();