| /* |
| * Copyright (c) 2022 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/ztest.h> |
| #include <zephyr/sys/byteorder.h> |
| #include <zephyr/net/buf.h> |
| #include <zephyr/net/net_ip.h> |
| #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h> |
| #include <zephyr/mgmt/mcumgr/transport/smp_dummy.h> |
| #include <zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h> |
| #include <zcbor_common.h> |
| #include <zcbor_decode.h> |
| #include <mgmt/mcumgr/transport/smp_internal.h> |
| |
| #define SMP_RESPONSE_WAIT_TIME 3 |
| |
| /* Test fs_mgmt supported hash/checksum query command */ |
| static const uint8_t command[] = { |
| 0x00, 0x00, 0x00, 0x02, 0x00, 0x08, 0x01, 0x03, |
| 0xbf, 0xff, |
| }; |
| |
| struct hash_checksum_type { |
| uint8_t name[32]; |
| uint32_t format; |
| uint32_t size; |
| bool found; |
| bool entries_matched; |
| }; |
| |
| ZTEST(fs_mgmt_hash_supported, test_supported) |
| { |
| struct net_buf *nb; |
| struct hash_checksum_type expected_types[] = { |
| #ifdef CONFIG_FS_MGMT_HASH_SHA256 |
| |
| { |
| .name = "sha256", |
| .format = 1, |
| .size = 32, |
| .found = false, |
| .entries_matched = false, |
| }, |
| #endif |
| #ifdef CONFIG_FS_MGMT_CHECKSUM_IEEE_CRC32 |
| { |
| .name = "crc32", |
| .format = 0, |
| .size = 4, |
| .found = false, |
| .entries_matched = false, |
| }, |
| #endif |
| }; |
| |
| /* Register os_mgmt mcumgr group */ |
| fs_mgmt_register_group(); |
| |
| /* Enable dummy SMP backend and ready for usage */ |
| smp_dummy_enable(); |
| smp_dummy_clear_state(); |
| |
| /* Send test echo command to dummy SMP backend */ |
| (void)smp_dummy_tx_pkt(command, sizeof(command)); |
| smp_dummy_add_data(); |
| |
| /* For a short duration to see if response has been received */ |
| bool received = smp_dummy_wait_for_data(SMP_RESPONSE_WAIT_TIME); |
| |
| zassert_true(received, "Expected to receive data but timed out\n"); |
| |
| /* Retrieve response buffer and ensure validity */ |
| nb = smp_dummy_get_outgoing(); |
| smp_dummy_disable(); |
| |
| /* Check that the headers seem valid */ |
| struct smp_hdr *response_hdr = (struct smp_hdr *)nb->data; |
| uint16_t len = ntohs(response_hdr->nh_len); |
| uint16_t group = ntohs(response_hdr->nh_group); |
| |
| zassert_equal(response_hdr->nh_op, MGMT_OP_READ_RSP, |
| "Expected response to have rease response type"); |
| zassert_true((len > 20), "Expected response to be at least 20 bytes in length"); |
| zassert_equal(group, MGMT_GROUP_ID_FS, "Expected response to be FS group"); |
| zassert_equal(response_hdr->nh_id, FS_MGMT_ID_SUPPORTED_HASH_CHECKSUM, |
| "Expected response to be supported hash/checksum ID"); |
| |
| /* Process the payload with zcbor and check expected types are present */ |
| zcbor_state_t state[10]; |
| struct zcbor_string key; |
| uint32_t format_value; |
| bool format_found; |
| uint32_t size_value; |
| bool size_found; |
| int8_t entry = 0; |
| bool ok = true; |
| |
| /* Search expected type array for this type and update details */ |
| zcbor_new_decode_state(state, 10, &nb->data[sizeof(struct smp_hdr)], |
| (nb->len - sizeof(struct smp_hdr)), 1); |
| |
| ok = zcbor_map_start_decode(state); |
| |
| ok = zcbor_tstr_decode(state, &key); |
| |
| zassert_equal(key.len, strlen("types"), |
| "Expected CBOR response 'types' value length to match"); |
| zassert_mem_equal(key.value, "types", strlen("types"), |
| "Expected CBOR response 'types' value to match"); |
| |
| ok = zcbor_map_start_decode(state); |
| |
| while (ok == true) { |
| ok = zcbor_tstr_decode(state, &key); |
| if (!ok) { |
| break; |
| } |
| |
| entry = 0; |
| while (entry < ARRAY_SIZE(expected_types)) { |
| if (memcmp(key.value, expected_types[entry].name, MIN(key.len, |
| strlen(expected_types[entry].name))) == 0) { |
| zassert_equal(expected_types[entry].found, false, |
| "Found entry multiple times"); |
| expected_types[entry].found = true; |
| break; |
| } |
| |
| ++entry; |
| } |
| |
| zassert_equal(entry < ARRAY_SIZE(expected_types), true, |
| "Did not find entry for type"); |
| |
| ok = zcbor_map_start_decode(state); |
| format_found = false; |
| size_found = false; |
| |
| while (ok == true) { |
| ok = zcbor_tstr_decode(state, &key); |
| |
| if (!ok) { |
| break; |
| } |
| |
| if (memcmp(key.value, "format", strlen("format")) == 0) { |
| zassert_false(format_found, |
| "Expected format to only be found once"); |
| ok &= zcbor_uint32_decode(state, &format_value); |
| format_found = true; |
| } else if (memcmp(key.value, "size", strlen("size")) == 0) { |
| zassert_false(size_found, "Expected size to be only found once"); |
| ok &= zcbor_uint32_decode(state, &size_value); |
| size_found = true; |
| } else { |
| zassert_true(false, "Unexpected field in CBOR response"); |
| } |
| |
| if (format_found == true && size_found == true) { |
| zassert_equal(expected_types[entry].format, format_value, |
| "Format value mismatch with expected value"); |
| zassert_equal(expected_types[entry].size, size_value, |
| "Size value mismatch with expected value"); |
| expected_types[entry].entries_matched = true; |
| } |
| } |
| |
| ok = zcbor_map_end_decode(state); |
| } |
| |
| ok = zcbor_map_end_decode(state); |
| } |
| |
| ZTEST_SUITE(fs_mgmt_hash_supported, NULL, NULL, NULL, NULL, NULL); |