| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Unit tests for PersistentLookupTable. |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "cryptohome/persistent_lookup_table.h" |
| |
| using ::testing::_; |
| |
| namespace { |
| |
| const uint64_t kKey1 = 123456; |
| const uint64_t kKey2 = 0; |
| const uint64_t kKey3 = 123; |
| const std::vector<uint8_t> kValue1_1 = {{0x34, 0x32, 0x31}}; |
| const std::vector<uint8_t> kValue1_2 = {{0x12, 0x13, 0x14}}; |
| const std::vector<uint8_t> kValue1_3 = {{0xDE, 0xAD, 0xBE, 0xEF}}; |
| const std::vector<uint8_t> kValue1_4 = {{0xED, 0xDA, 0xEB, 0xFE}}; |
| const std::vector<uint8_t> kValue2_1 = {{0x97, 0x98, 0x99}}; |
| const std::vector<uint8_t> kValue2_2 = {{0xAB, 0xCD, 0xEF}}; |
| const std::vector<uint8_t> kValue2_3 = {{0xBA, 0xDC, 0xFE}}; |
| const std::vector<uint8_t> kValue3_1 = {{0x01, 0x02, 0x03}}; |
| |
| } // namespace |
| |
| namespace cryptohome { |
| |
| // Check whether we can successfully create a new directory for the lookup |
| // table at specified location. Also tests whether basic Store and Get |
| // operations work correctly. |
| TEST(PersistentLookupTableTest, CreateDirStoreValues) { |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| std::unique_ptr<Platform> platform(new Platform()); |
| PersistentLookupTable lookup_table(platform.get(), temp_dir.GetPath()); |
| lookup_table.InitOnBoot(); |
| |
| // Verify basic Store and Get. |
| std::vector<uint8_t> result; |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_1)); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table.GetValue(kKey1, &result)); |
| EXPECT_EQ(kValue1_1, result); |
| |
| // Verify non-existent key returns correct values. |
| result.clear(); |
| EXPECT_FALSE(lookup_table.KeyExists(kKey2)); |
| EXPECT_EQ(PLT_KEY_NOT_FOUND, lookup_table.GetValue(kKey2, &result)); |
| |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_1)); |
| |
| // Verify overwrite of earlier key. |
| result.clear(); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_2)); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table.GetValue(kKey1, &result)); |
| EXPECT_EQ(kValue1_2, result); |
| } |
| |
| // Check whether we can restore a pre-existing table. |
| TEST(PersistentLookupTableTest, RestoreTable) { |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| std::unique_ptr<Platform> platform(new Platform()); |
| std::unique_ptr<PersistentLookupTable> lookup_table = |
| std::make_unique<PersistentLookupTable>(platform.get(), |
| temp_dir.GetPath()); |
| lookup_table->InitOnBoot(); |
| |
| // Add some entries. |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey1, kValue1_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey1, kValue1_2)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey2, kValue2_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey3, kValue3_1)); |
| |
| // Destroy old object, now instantiate a new table object and restore old |
| // table. |
| lookup_table.reset(); |
| platform.reset(new Platform()); |
| lookup_table = std::make_unique<PersistentLookupTable>(platform.get(), |
| temp_dir.GetPath()); |
| lookup_table->InitOnBoot(); |
| |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey1, kValue1_3)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->StoreValue(kKey2, kValue2_2)); |
| // Deleting a key (we check later whether the delete worked). |
| ASSERT_EQ(PLT_SUCCESS, lookup_table->RemoveKey(kKey3)); |
| |
| // Destroy it one last time, then reload it. |
| lookup_table.reset(); |
| platform.reset(new Platform()); |
| lookup_table = std::make_unique<PersistentLookupTable>(platform.get(), |
| temp_dir.GetPath()); |
| lookup_table->InitOnBoot(); |
| |
| // Check that the values are as expected. |
| std::vector<uint8_t> result; |
| EXPECT_EQ(PLT_SUCCESS, lookup_table->GetValue(kKey1, &result)); |
| EXPECT_EQ(kValue1_3, result); |
| result.clear(); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table->GetValue(kKey1, &result)); |
| EXPECT_NE(kValue1_1, result); |
| result.clear(); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table->GetValue(kKey2, &result)); |
| EXPECT_NE(kValue2_1, result); |
| result.clear(); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table->GetValue(kKey2, &result)); |
| EXPECT_EQ(kValue2_2, result); |
| EXPECT_FALSE(lookup_table->KeyExists(kKey3)); |
| result.clear(); |
| } |
| |
| // Tests whether we can delete keys from a table. |
| TEST(PersistentLookupTableTest, DeleteKeys) { |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| std::unique_ptr<Platform> platform(new Platform()); |
| PersistentLookupTable lookup_table(platform.get(), temp_dir.GetPath()); |
| lookup_table.InitOnBoot(); |
| |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_2)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_3)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_2)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_3)); |
| |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.RemoveKey(kKey1)); |
| EXPECT_FALSE(lookup_table.KeyExists(kKey1)); |
| |
| std::vector<uint8_t> result; |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_4)); |
| EXPECT_EQ(PLT_SUCCESS, lookup_table.GetValue(kKey1, &result)); |
| EXPECT_EQ(kValue1_4, result); |
| } |
| |
| // Tests whether we can list the number of currently used keys. |
| TEST(PersistentLookupTableTest, GetUsedKeys) { |
| base::ScopedTempDir temp_dir; |
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| |
| std::unique_ptr<Platform> platform(new Platform()); |
| PersistentLookupTable lookup_table(platform.get(), temp_dir.GetPath()); |
| lookup_table.InitOnBoot(); |
| |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_1)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey1, kValue1_2)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey2, kValue2_2)); |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.StoreValue(kKey3, kValue3_1)); |
| |
| std::vector<uint64_t> key_list; |
| lookup_table.GetUsedKeys(&key_list); |
| EXPECT_EQ(std::set<uint64_t>({kKey1, kKey2, kKey3}), |
| std::set<uint64_t>(key_list.begin(), key_list.end())); |
| |
| // Remove a key and make sure the number of keys is correct. |
| ASSERT_EQ(PLT_SUCCESS, lookup_table.RemoveKey(kKey2)); |
| key_list.clear(); |
| lookup_table.GetUsedKeys(&key_list); |
| EXPECT_EQ(std::set<uint64_t>({kKey1, kKey3}), |
| std::set<uint64_t>(key_list.begin(), key_list.end())); |
| } |
| |
| } // namespace cryptohome |