| // Copyright 2021 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. |
| |
| #include <string> |
| |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/json/json_string_value_serializer.h> |
| #include <base/memory/scoped_refptr.h> |
| #include <base/values.h> |
| #include <gtest/gtest.h> |
| |
| #include "rmad/utils/json_store.h" |
| |
| namespace rmad { |
| |
| // File name. |
| const char kTestFileName[] = "test.json"; |
| |
| // Valid JSON dictionary. |
| const char kValidJson[] = R"( |
| { |
| "trigger": true, |
| "state": "RMAD_STATE_RMA_NOT_REQUIRED", |
| "replaced_components": [ |
| "screen", |
| "keyboard" |
| ] |
| })"; |
| // Invalid JSON string, missing '}'. |
| const char kInvalidFormatJson[] = "{ \"trigger\": true"; |
| // Invalid JSON dictionary. |
| const char kWrongTypeJson[] = "[1, 2]"; |
| |
| const char kExistingKey[] = "trigger"; |
| const bool kExistingValue = true; |
| const char kNewKey[] = "NewKey"; |
| const int kNewValue = 10; |
| const char kNewStringValue[] = "value"; |
| const char kNotStringValue[] = "not value"; |
| |
| class JsonStoreTest : public testing::Test { |
| public: |
| JsonStoreTest() {} |
| |
| base::FilePath CreateInputFile(std::string file_name, |
| const char* str, |
| int size) { |
| base::FilePath file_path = temp_dir_.GetPath().AppendASCII(file_name); |
| base::WriteFile(file_path, str, size); |
| return file_path; |
| } |
| |
| protected: |
| void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } |
| |
| base::ScopedTempDir temp_dir_; |
| }; |
| |
| TEST_F(JsonStoreTest, InitializeNormal) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| EXPECT_EQ(json_store->GetReadError(), JsonStore::READ_ERROR_NONE); |
| EXPECT_FALSE(json_store->ReadOnly()); |
| |
| JSONStringValueDeserializer deserializer(kValidJson); |
| int error_code; |
| std::string error_message; |
| std::unique_ptr<base::Value> expected_value = |
| deserializer.Deserialize(&error_code, &error_message); |
| EXPECT_EQ(json_store->GetValues(), *expected_value); |
| } |
| |
| TEST_F(JsonStoreTest, InitializeInvalidString) { |
| base::FilePath input_file = CreateInputFile( |
| kTestFileName, kInvalidFormatJson, std::size(kInvalidFormatJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| EXPECT_EQ(json_store->GetReadError(), JsonStore::READ_ERROR_JSON_PARSE); |
| EXPECT_TRUE(json_store->ReadOnly()); |
| EXPECT_EQ(json_store->GetValues(), |
| base::Value(base::Value::Type::DICTIONARY)); |
| } |
| |
| TEST_F(JsonStoreTest, InitializeInvalidType) { |
| base::FilePath input_file = CreateInputFile(kTestFileName, kWrongTypeJson, |
| std::size(kWrongTypeJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| EXPECT_EQ(json_store->GetReadError(), JsonStore::READ_ERROR_JSON_TYPE); |
| EXPECT_TRUE(json_store->ReadOnly()); |
| EXPECT_EQ(json_store->GetValues(), |
| base::Value(base::Value::Type::DICTIONARY)); |
| } |
| |
| TEST_F(JsonStoreTest, InitializeNoFile) { |
| base::FilePath input_file = temp_dir_.GetPath().AppendASCII(kTestFileName); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| EXPECT_EQ(json_store->GetReadError(), JsonStore::READ_ERROR_NO_SUCH_FILE); |
| EXPECT_FALSE(json_store->ReadOnly()); |
| EXPECT_EQ(json_store->GetValues(), |
| base::Value(base::Value::Type::DICTIONARY)); |
| } |
| |
| TEST_F(JsonStoreTest, GetValue) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| // Get by const pointer. |
| const base::Value* value_ptr; |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &value_ptr)); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value_ptr)); |
| EXPECT_EQ(*value_ptr, base::Value(kExistingValue)); |
| // Get by copy. |
| base::Value value; |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| EXPECT_EQ(value, base::Value(kExistingValue)); |
| } |
| |
| TEST_F(JsonStoreTest, SetValue) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| base::Value value; |
| // Add new key. |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_TRUE(json_store->SetValue(kNewKey, base::Value(kNewValue))); |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_EQ(value, base::Value(kNewValue)); |
| // Overwrite existing key. |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| EXPECT_EQ(value, base::Value(kExistingValue)); |
| EXPECT_NE(base::Value(kExistingValue), base::Value(kNewValue)); |
| EXPECT_TRUE(json_store->SetValue(kExistingKey, base::Value(kNewValue))); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| EXPECT_EQ(value, base::Value(kNewValue)); |
| } |
| |
| TEST_F(JsonStoreTest, StoreValue) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| base::Value value; |
| // Add new key. |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_TRUE(json_store->SetValue(kNewKey, base::Value(kNewValue))); |
| // Create a new JsonStore that reads the same file. |
| auto json_store_new = base::MakeRefCounted<JsonStore>(input_file); |
| EXPECT_TRUE(json_store_new->GetValue(kNewKey, &value)); |
| EXPECT_EQ(value, base::Value(kNewValue)); |
| } |
| |
| TEST_F(JsonStoreTest, SetValue_Template) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| int value = kNewValue - 1; |
| // Add new key. |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_EQ(value, kNewValue - 1); |
| EXPECT_TRUE(json_store->SetValue(kNewKey, kNewValue)); |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &value)); |
| EXPECT_EQ(value, kNewValue); |
| // Overwrite existing key. |
| bool bool_value = !kExistingValue; |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, kExistingValue); |
| EXPECT_NE(kExistingValue, kNewValue); |
| EXPECT_TRUE(json_store->SetValue(kExistingKey, kNewValue)); |
| bool_value = !kExistingValue; |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, !kExistingValue); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| EXPECT_EQ(value, kNewValue); |
| } |
| |
| TEST_F(JsonStoreTest, GetValue_TemplateWrongType) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| std::string value = "hello"; |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &value)); |
| EXPECT_EQ(value, "hello"); |
| } |
| |
| TEST_F(JsonStoreTest, GetValue_TemplateChangeType) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| bool bool_value = !kExistingValue; |
| std::string string_value = kNotStringValue; |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, kExistingValue); |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &string_value)); |
| EXPECT_EQ(string_value, kNotStringValue); |
| EXPECT_TRUE(json_store->SetValue(kExistingKey, kNewStringValue)); |
| bool_value = !kExistingValue; |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, !kExistingValue); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &string_value)); |
| EXPECT_EQ(string_value, kNewStringValue); |
| } |
| |
| TEST_F(JsonStoreTest, SetValue_TemplateList) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| std::vector<double> values = {0.12, 34.5, 678.9}; |
| // Add new key. |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 3); |
| EXPECT_EQ(values[0], 0.12); |
| EXPECT_EQ(values[1], 34.5); |
| EXPECT_EQ(values[2], 678.9); |
| EXPECT_TRUE(json_store->SetValue(kNewKey, values)); |
| values.clear(); |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 3); |
| EXPECT_EQ(values[0], 0.12); |
| EXPECT_EQ(values[1], 34.5); |
| EXPECT_EQ(values[2], 678.9); |
| // Overwrite existing key. |
| bool bool_value = !kExistingValue; |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, kExistingValue); |
| values = {987.6, 5.43, 2.1}; |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &values)); |
| EXPECT_EQ(values.size(), 3); |
| EXPECT_EQ(values[0], 987.6); |
| EXPECT_EQ(values[1], 5.43); |
| EXPECT_EQ(values[2], 2.1); |
| EXPECT_TRUE(json_store->SetValue(kExistingKey, values)); |
| values.clear(); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &values)); |
| EXPECT_EQ(values.size(), 3); |
| EXPECT_EQ(values[0], 987.6); |
| EXPECT_EQ(values[1], 5.43); |
| EXPECT_EQ(values[2], 2.1); |
| // Confirm the new key was not modified. |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 3); |
| EXPECT_EQ(values[0], 0.12); |
| EXPECT_EQ(values[1], 34.5); |
| EXPECT_EQ(values[2], 678.9); |
| } |
| |
| TEST_F(JsonStoreTest, SetValue_TemplateNestedMapList) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| std::map<std::string, std::vector<int>> values = {{"a", {1, 2}}, |
| {"b", {3, 4}}}; |
| // Add new key. |
| EXPECT_FALSE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 2); |
| EXPECT_EQ(values["a"].size(), 2); |
| EXPECT_EQ(values["b"].size(), 2); |
| EXPECT_EQ(values["a"][0], 1); |
| EXPECT_EQ(values["a"][1], 2); |
| EXPECT_EQ(values["b"][0], 3); |
| EXPECT_EQ(values["b"][1], 4); |
| EXPECT_TRUE(json_store->SetValue(kNewKey, values)); |
| values.clear(); |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 2); |
| EXPECT_EQ(values["a"].size(), 2); |
| EXPECT_EQ(values["b"].size(), 2); |
| EXPECT_EQ(values["a"][0], 1); |
| EXPECT_EQ(values["a"][1], 2); |
| EXPECT_EQ(values["b"][0], 3); |
| EXPECT_EQ(values["b"][1], 4); |
| // Overwrite existing key. |
| bool bool_value = !kExistingValue; |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &bool_value)); |
| EXPECT_EQ(bool_value, kExistingValue); |
| values = {{"c", {9}}, {"d", {8, 7, 6}}}; |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &values)); |
| EXPECT_EQ(values.size(), 2); |
| EXPECT_EQ(values["c"].size(), 1); |
| EXPECT_EQ(values["d"].size(), 3); |
| EXPECT_EQ(values["c"][0], 9); |
| EXPECT_EQ(values["d"][0], 8); |
| EXPECT_EQ(values["d"][1], 7); |
| EXPECT_EQ(values["d"][2], 6); |
| EXPECT_TRUE(json_store->SetValue(kExistingKey, values)); |
| values.clear(); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &values)); |
| EXPECT_EQ(values.size(), 2); |
| EXPECT_EQ(values["c"].size(), 1); |
| EXPECT_EQ(values["d"].size(), 3); |
| EXPECT_EQ(values["c"][0], 9); |
| EXPECT_EQ(values["d"][0], 8); |
| EXPECT_EQ(values["d"][1], 7); |
| EXPECT_EQ(values["d"][2], 6); |
| // Confirm the new key was not modified. |
| EXPECT_TRUE(json_store->GetValue(kNewKey, &values)); |
| EXPECT_EQ(values.size(), 2); |
| EXPECT_EQ(values["a"].size(), 2); |
| EXPECT_EQ(values["b"].size(), 2); |
| EXPECT_EQ(values["a"][0], 1); |
| EXPECT_EQ(values["a"][1], 2); |
| EXPECT_EQ(values["b"][0], 3); |
| EXPECT_EQ(values["b"][1], 4); |
| } |
| |
| TEST_F(JsonStoreTest, Clear) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| |
| base::Value value; |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| |
| // Clear the data. |
| EXPECT_TRUE(json_store->Clear()); |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &value)); |
| } |
| |
| TEST_F(JsonStoreTest, ClearAndDeleteFile) { |
| base::FilePath input_file = |
| CreateInputFile(kTestFileName, kValidJson, std::size(kValidJson) - 1); |
| auto json_store = base::MakeRefCounted<JsonStore>(input_file); |
| |
| base::Value value; |
| EXPECT_TRUE(base::PathExists(input_file)); |
| EXPECT_TRUE(json_store->GetValue(kExistingKey, &value)); |
| |
| // Delete the file. |
| EXPECT_TRUE(json_store->ClearAndDeleteFile()); |
| EXPECT_FALSE(base::PathExists(input_file)); |
| EXPECT_FALSE(json_store->GetValue(kExistingKey, &value)); |
| } |
| |
| } // namespace rmad |