Newer
Older
mbed-os / storage / kvstore / tests / UNITTESTS / TDBStore / moduletest.cpp
@Lingkai Dong Lingkai Dong on 9 Dec 2020 4 KB Update include paths
/* Copyright (c) 2020 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */

#include "gtest/gtest.h"
#include "blockdevice/HeapBlockDevice.h"
#include "blockdevice/FlashSimBlockDevice.h"
#include "tdbstore/TDBStore.h"
#include <stdlib.h>

#define BLOCK_SIZE (256)
#define DEVICE_SIZE (BLOCK_SIZE*200)

using namespace mbed;

class TDBStoreModuleTest : public testing::Test {
protected:
    HeapBlockDevice heap{DEVICE_SIZE, BLOCK_SIZE};
    FlashSimBlockDevice flash{&heap};
    TDBStore tdb{&flash};

    virtual void SetUp()
    {
        EXPECT_EQ(tdb.init(), MBED_SUCCESS);
        EXPECT_EQ(tdb.reset(), MBED_SUCCESS);
    }

    virtual void TearDown()
    {
        EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
    }
};

TEST_F(TDBStoreModuleTest, init)
{
    EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
    EXPECT_EQ(tdb.init(), MBED_SUCCESS);
    EXPECT_EQ(tdb.init(), MBED_SUCCESS);
}

TEST_F(TDBStoreModuleTest, set_get)
{
    char buf[100];
    size_t size;
    EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
    EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
    EXPECT_EQ(size, 5);
    EXPECT_STREQ("data", buf);
}

TEST_F(TDBStoreModuleTest, erased_set_get)
{
    EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
    EXPECT_EQ(flash.init(), MBED_SUCCESS);
    EXPECT_EQ(flash.erase(0, flash.size()), MBED_SUCCESS);
    EXPECT_EQ(flash.deinit(), MBED_SUCCESS);
    EXPECT_EQ(tdb.init(), MBED_SUCCESS);
    char buf[100];
    size_t size;
    EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
    EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
    EXPECT_EQ(size, 5);
    EXPECT_STREQ("data", buf);
}

TEST_F(TDBStoreModuleTest, set_deinit_init_get)
{
    size_t size;
    for (int i = 0; i < 100; ++i) {
        char str[11] = {0};
        char buf[100] = {0};
        int len = snprintf(str, 11, "data%d", i) + 1;
        EXPECT_EQ(tdb.set("key", str, len, 0), MBED_SUCCESS);
        EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
        EXPECT_EQ(tdb.init(), MBED_SUCCESS);
        EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
        EXPECT_EQ(size, len);
        EXPECT_STREQ(str, buf);
        EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
    }
}

TEST_F(TDBStoreModuleTest, corrupted_set_deinit_init_get)
{
    char buf[100];
    char *block = new char[BLOCK_SIZE];
    size_t size;
    EXPECT_EQ(heap.init(), MBED_SUCCESS); // Extra init, so the heap will not be deinitialized

    srand(0); // Prefer to have always the same pattern

    for (int i = 0; i < 100; ++i) {
        EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
        // Corrupt the first part of the storage
        for (int j = 0; j < heap.size()/BLOCK_SIZE/2; j++) {
            for (int k = 0; k < BLOCK_SIZE; k++) {
                block[k] = rand();
            }
            EXPECT_EQ(heap.program(block, BLOCK_SIZE * j, BLOCK_SIZE), MBED_SUCCESS);
        }
        EXPECT_EQ(tdb.init(), MBED_SUCCESS);
        for (int j = 0; j < 100; ++j) {
            // Use random data, so the data has to be updated
            EXPECT_EQ(tdb.set("key", block+j, 50, 0), MBED_SUCCESS);
            EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
            EXPECT_EQ(tdb.init(), MBED_SUCCESS);
            EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
            EXPECT_EQ(size, 50);
            EXPECT_EQ(0, memcmp(buf, block+j, size));
        }
        EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
    }

    EXPECT_EQ(heap.deinit(), MBED_SUCCESS);
    delete[] block;
}

TEST_F(TDBStoreModuleTest, set_multiple_iterate)
{
    char buf[100];
    KVStore::iterator_t iterator;
    EXPECT_EQ(tdb.set("primary_key", "data", 5, 0), MBED_SUCCESS);
    EXPECT_EQ(tdb.set("primary_second_key", "value", 6, 0), MBED_SUCCESS);
    EXPECT_EQ(tdb.iterator_open(&iterator, "primary"), MBED_SUCCESS);
    EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_SUCCESS);
    EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_SUCCESS);
    EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_ERROR_ITEM_NOT_FOUND);
    EXPECT_EQ(tdb.iterator_close(iterator), MBED_SUCCESS);
}

TEST_F(TDBStoreModuleTest, reserved_data_set_get)
{
    char reserved_key[] = "value";
    char buf[64];
    size_t size;
    EXPECT_EQ(tdb.reserved_data_set(reserved_key, 6), MBED_SUCCESS);
    EXPECT_EQ(tdb.reserved_data_get(buf, 64, &size), MBED_SUCCESS);
    EXPECT_STREQ("value", buf);
    EXPECT_EQ(size, 6);
    EXPECT_EQ(tdb.reserved_data_set(reserved_key, 6), MBED_ERROR_WRITE_FAILED);
}