/* * * Copyright (c) 2021 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * This file implements a unit test suite for the Key Value Store Manager * code functionality. * */ #include #include #include #include #include using namespace chip; using namespace chip::DeviceLayer; using namespace chip::DeviceLayer::PersistedStorage; struct TestKeyValueStoreMgr : public ::testing::Test { static void SetUpTestSuite() { CHIP_ERROR err = chip::Platform::MemoryInit(); EXPECT_EQ(err, CHIP_NO_ERROR); } static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); } }; TEST_F(TestKeyValueStoreMgr, EmptyString) { static constexpr char kTestKey[] = "str_key"; static constexpr char kTestValue[] = ""; constexpr size_t kTestValueLen = 0; char readValue[sizeof(kTestValue)]; size_t readSize; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue, kTestValueLen); EXPECT_EQ(err, CHIP_NO_ERROR); // Verify if read value is the same as wrote one err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(readSize, kTestValueLen); // Verify that read succeeds even if 0-length buffer is provided err = KeyValueStoreMgr().Get(kTestKey, readValue, 0, &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(readSize, kTestValueLen); err = KeyValueStoreMgr().Get(kTestKey, nullptr, 0, &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(readSize, kTestValueLen); // Verify deletion err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); // Try to get deleted key and verify if CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND is returned err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } TEST_F(TestKeyValueStoreMgr, String) { static constexpr char kTestKey[] = "str_key"; static constexpr char kTestValue[] = "test_value"; char readValue[sizeof(kTestValue)]; size_t readSize; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); // Verify if read value is the same as wrote one err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_STREQ(kTestValue, readValue); EXPECT_EQ(readSize, sizeof(kTestValue)); // Verify deletion err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); // Try to get deleted key and verify if CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND is returned err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } TEST_F(TestKeyValueStoreMgr, Uint32) { static constexpr char kTestKey[] = "uint32_key"; constexpr const uint32_t kTestValue = 5; uint32_t readValue = UINT32_MAX; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); // Verify if read value is the same as wrote one err = KeyValueStoreMgr().Get(kTestKey, &readValue); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(kTestValue, readValue); // Verify deletion err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); // Try to get deleted key and verify if CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND is returned err = KeyValueStoreMgr().Get(kTestKey, &readValue); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } TEST_F(TestKeyValueStoreMgr, Array) { static constexpr char kTestKey[] = "array_key"; constexpr uint32_t kTestValue[5] = { 1, 2, 3, 4, 5 }; uint32_t readValue[5]; size_t readSize; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); // Verify if read value is the same as wrote one err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(memcmp(kTestValue, readValue, sizeof(kTestValue)), 0); EXPECT_EQ(readSize, sizeof(kTestValue)); // Verify deletion err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); // Try to get deleted key and verify if CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND is returned err = KeyValueStoreMgr().Get(kTestKey, readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } TEST_F(TestKeyValueStoreMgr, Struct) { struct TestStruct { uint8_t value1; uint32_t value2; }; static constexpr char kTestKey[] = "struct_key"; constexpr TestStruct kTestValue{ 1, 2 }; TestStruct readValue; size_t readSize; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); // Verify if read value is the same as wrote one err = KeyValueStoreMgr().Get(kTestKey, &readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(kTestValue.value1, readValue.value1); EXPECT_EQ(kTestValue.value2, readValue.value2); EXPECT_EQ(readSize, sizeof(kTestValue)); // Verify deletion err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); // Try to get deleted key and verify if CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND is returned err = KeyValueStoreMgr().Get(kTestKey, &readValue, sizeof(readValue), &readSize); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } TEST_F(TestKeyValueStoreMgr, UpdateValue) { static constexpr char kTestKey[] = "update_key"; CHIP_ERROR err; uint32_t readValue; for (uint32_t i = 0; i < 10; i++) { err = KeyValueStoreMgr().Put(kTestKey, i); EXPECT_EQ(err, CHIP_NO_ERROR); err = KeyValueStoreMgr().Get(kTestKey, &readValue); EXPECT_EQ(err, CHIP_NO_ERROR); EXPECT_EQ(i, readValue); } err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); } TEST_F(TestKeyValueStoreMgr, TooSmallBufferRead) { static constexpr char kTestKey[] = "too_small_buffer_read_key"; constexpr uint8_t kTestValue[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; uint8_t readValue[9]; size_t readSize; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); // Returns buffer too small and should read as many bytes as possible err = KeyValueStoreMgr().Get(kTestKey, &readValue, sizeof(readValue), &readSize, 0); EXPECT_EQ(err, CHIP_ERROR_BUFFER_TOO_SMALL); EXPECT_EQ(readSize, sizeof(readValue)); EXPECT_EQ(memcmp(kTestValue, readValue, readSize), 0); err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); } TEST_F(TestKeyValueStoreMgr, AllCharactersKey) { // Test that all printable characters [0x20 - 0x7f) can be part of the key constexpr size_t kKeyLength = 32; constexpr char kCharBegin = 0x20; constexpr char kCharEnd = 0x7f; constexpr uint32_t kTestValue = 5; char allChars[kCharEnd - kCharBegin]; for (char character = kCharBegin; character < kCharEnd; character++) { allChars[character - kCharBegin] = character; } for (size_t charId = 0; charId < sizeof(allChars); charId += kKeyLength) { char testKey[kKeyLength + 1] = {}; memcpy(testKey, &allChars[charId], std::min(sizeof(allChars) - charId, kKeyLength)); CHIP_ERROR err = KeyValueStoreMgr().Put(testKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); uint32_t readValue = UINT32_MAX; err = KeyValueStoreMgr().Get(testKey, &readValue); EXPECT_EQ(err, CHIP_NO_ERROR); err = KeyValueStoreMgr().Delete(testKey); EXPECT_EQ(err, CHIP_NO_ERROR); } } TEST_F(TestKeyValueStoreMgr, NonExistentDelete) { static constexpr char kTestKey[] = "non_existent"; CHIP_ERROR err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } #if !defined(__ZEPHYR__) && !defined(__MBED__) TEST_F(TestKeyValueStoreMgr, MultiRead) { static constexpr char kTestKey[] = "multi_key"; constexpr uint32_t kTestValue[5] = { 1, 2, 3, 4, 5 }; CHIP_ERROR err = KeyValueStoreMgr().Put(kTestKey, kTestValue); EXPECT_EQ(err, CHIP_NO_ERROR); for (uint32_t i = 0; i < 5; i++) { uint32_t readValue; size_t readSize; // Returns buffer too small for all but the last read. err = KeyValueStoreMgr().Get(kTestKey, &readValue, sizeof(readValue), &readSize, i * sizeof(uint32_t)); EXPECT_EQ(err, (i < 4 ? CHIP_ERROR_BUFFER_TOO_SMALL : CHIP_NO_ERROR)); EXPECT_EQ(readSize, sizeof(readValue)); EXPECT_EQ(kTestValue[i], readValue); } err = KeyValueStoreMgr().Delete(kTestKey); EXPECT_EQ(err, CHIP_NO_ERROR); } #endif #ifdef __ZEPHYR__ TEST_F(TestKeyValueStoreMgr, DoFactoryReset) { static constexpr char kStrKey[] = "string_with_weird_chars\\=_key"; static constexpr char kUintKey[] = "some_uint_key"; EXPECT_EQ(KeyValueStoreMgr().Put(kStrKey, "some_string"), CHIP_NO_ERROR); EXPECT_EQ(KeyValueStoreMgr().Put(kUintKey, uint32_t(1234)), CHIP_NO_ERROR); char readString[16]; uint32_t readValue; EXPECT_EQ(KeyValueStoreMgr().Get(kStrKey, readString, sizeof(readString)), CHIP_NO_ERROR); EXPECT_EQ(KeyValueStoreMgr().Get(kUintKey, &readValue), CHIP_NO_ERROR); EXPECT_EQ(KeyValueStoreMgrImpl().DoFactoryReset(), CHIP_NO_ERROR); EXPECT_EQ(KeyValueStoreMgr().Get(kStrKey, readString, sizeof(readString)), CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); EXPECT_EQ(KeyValueStoreMgr().Get(kUintKey, &readValue), CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND); } #endif