blob: 8b1725edbf6058b76785cdac8377aa202bdd25fd [file] [log] [blame]
// 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