1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "extensions/browser/value_store/leveldb_scoped_database.h"
6 
7 #include <stddef.h>
8 
9 #include <map>
10 #include <string>
11 
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/values.h"
16 #include "content/public/test/browser_task_environment.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace {
20 const char kTestUMAClientName[] = "Test";
21 }  // namespace
22 
23 class LeveldbScopedDatabaseUnitTest : public testing::Test {
24  public:
LeveldbScopedDatabaseUnitTest()25   LeveldbScopedDatabaseUnitTest() {}
~LeveldbScopedDatabaseUnitTest()26   ~LeveldbScopedDatabaseUnitTest() override {}
27 
28  protected:
SetUp()29   void SetUp() override {
30     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
31     db_ =
32         new LeveldbScopedDatabase(kTestUMAClientName, database_dir_.GetPath());
33   }
34 
TearDown()35   void TearDown() override {
36     db_ = nullptr;
37     base::DeleteFileRecursively(database_dir_.GetPath());
38   }
39 
ReadAllValues(std::map<std::string,std::string> * values) const40   ValueStore::Status ReadAllValues(
41       std::map<std::string, std::string>* values) const {
42     values->clear();
43     leveldb::ReadOptions read_options;
44     read_options.verify_checksums = true;
45     std::unique_ptr<leveldb::Iterator> iterator;
46     ValueStore::Status status = db_->CreateIterator(read_options, &iterator);
47     if (!status.ok())
48       return status;
49     iterator->SeekToFirst();
50     while (iterator->Valid()) {
51       // The LeveldbProfileDatabase writes all values as JSON strings.
52       // This method returns the encoded strings.
53       (*values)[iterator->key().ToString()] = iterator->value().ToString();
54       iterator->Next();
55     }
56     return db_->ToValueStoreError(iterator->status());
57   }
58 
59   content::BrowserTaskEnvironment task_environment_;
60   base::ScopedTempDir database_dir_;
61   scoped_refptr<LeveldbScopedDatabase> db_;
62 };
63 
TEST_F(LeveldbScopedDatabaseUnitTest,TestSplitKey)64 TEST_F(LeveldbScopedDatabaseUnitTest, TestSplitKey) {
65   std::string scope;
66   std::string key;
67   EXPECT_TRUE(LeveldbScopedDatabase::SplitKey("s:k", &scope, &key));
68   EXPECT_EQ(scope, "s");
69   EXPECT_EQ(key, "k");
70   EXPECT_TRUE(LeveldbScopedDatabase::SplitKey("s:", &scope, &key));
71   EXPECT_EQ(scope, "s");
72   EXPECT_EQ(key, "");
73   EXPECT_TRUE(LeveldbScopedDatabase::SplitKey("s:k:o", &scope, &key));
74   EXPECT_EQ(scope, "s");
75   EXPECT_EQ(key, "k:o");
76   EXPECT_FALSE(LeveldbScopedDatabase::SplitKey("s-k", &scope, &key));
77   EXPECT_FALSE(LeveldbScopedDatabase::SplitKey("", &scope, &key));
78   EXPECT_FALSE(LeveldbScopedDatabase::SplitKey(":k", &scope, &key));
79 }
80 
TEST_F(LeveldbScopedDatabaseUnitTest,TestCreateKey)81 TEST_F(LeveldbScopedDatabaseUnitTest, TestCreateKey) {
82   std::string scoped_key;
83 
84   EXPECT_TRUE(LeveldbScopedDatabase::CreateKey("scope", "key", &scoped_key));
85   EXPECT_EQ("scope:key", scoped_key);
86   EXPECT_TRUE(LeveldbScopedDatabase::CreateKey("scope", "", &scoped_key));
87   EXPECT_EQ("scope:", scoped_key);
88   EXPECT_TRUE(LeveldbScopedDatabase::CreateKey("scope", "key:o", &scoped_key));
89   EXPECT_EQ("scope:key:o", scoped_key);
90 
91   EXPECT_FALSE(LeveldbScopedDatabase::CreateKey("", "key", &scoped_key));
92   EXPECT_FALSE(
93       LeveldbScopedDatabase::CreateKey("scope:withdelim", "key", &scoped_key));
94 }
95 
TEST_F(LeveldbScopedDatabaseUnitTest,TestWrite)96 TEST_F(LeveldbScopedDatabaseUnitTest, TestWrite) {
97   std::map<std::string, std::string> db_values;
98   EXPECT_TRUE(ReadAllValues(&db_values).ok());
99   EXPECT_EQ(0u, db_values.size());
100 
101   base::DictionaryValue scope1_values;
102   scope1_values.SetString("s1_key1", "s1_value1");
103   scope1_values.SetString("s1_key2", "s1_value2");
104   EXPECT_FALSE(db_->Write("", scope1_values).ok());
105   EXPECT_TRUE(db_->Write("scope1", scope1_values).ok());
106 
107   base::DictionaryValue scope2_values;
108   scope2_values.SetString("s2_key1", "s2_value1");
109   scope2_values.SetString("s2_key2", "s2_value2");
110   EXPECT_TRUE(db_->Write("scope2", scope2_values).ok());
111 
112   // Read all values using raw leveldb. Values are JSON strings.
113   EXPECT_TRUE(ReadAllValues(&db_values).ok());
114   EXPECT_EQ(4u, db_values.size());
115   EXPECT_EQ("\"s1_value1\"", db_values["scope1:s1_key1"]);
116   EXPECT_EQ("\"s1_value2\"", db_values["scope1:s1_key2"]);
117   EXPECT_EQ("\"s2_value1\"", db_values["scope2:s2_key1"]);
118   EXPECT_EQ("\"s2_value2\"", db_values["scope2:s2_key2"]);
119 
120   // Intentionally overwrite value (with a new value).
121   base::DictionaryValue changed_scope2_values;
122   changed_scope2_values.SetString("s2_key1", "s2_value1");
123   changed_scope2_values.SetString("s2_key2", "s2_value3");
124   EXPECT_TRUE(db_->Write("scope2", changed_scope2_values).ok());
125 
126   EXPECT_TRUE(ReadAllValues(&db_values).ok());
127   EXPECT_EQ(4u, db_values.size());
128   EXPECT_EQ("\"s1_value1\"", db_values["scope1:s1_key1"]);
129   EXPECT_EQ("\"s1_value2\"", db_values["scope1:s1_key2"]);
130   EXPECT_EQ("\"s2_value1\"", db_values["scope2:s2_key1"]);
131   EXPECT_EQ("\"s2_value3\"", db_values["scope2:s2_key2"]);
132 }
133 
TEST_F(LeveldbScopedDatabaseUnitTest,TestRead)134 TEST_F(LeveldbScopedDatabaseUnitTest, TestRead) {
135   base::DictionaryValue scope1_values;
136   scope1_values.SetString("s1_key1", "s1_value1");
137   scope1_values.SetString("s1_key2", "s1_value2");
138   EXPECT_TRUE(db_->Write("scope1", scope1_values).ok());
139 
140   base::DictionaryValue scope2_values;
141   scope2_values.SetString("s2_key1", "s2_value1");
142   scope2_values.SetString("s2_key2", "s2_value2");
143   EXPECT_TRUE(db_->Write("scope2", scope2_values).ok());
144 
145   // And test an empty scope.
146   EXPECT_FALSE(db_->Write("", scope2_values).ok());
147 
148   base::DictionaryValue read_s1_vals;
149   EXPECT_FALSE(db_->Read("", &read_s1_vals).ok());
150   EXPECT_TRUE(db_->Read("scope1", &read_s1_vals).ok());
151   EXPECT_TRUE(scope1_values.Equals(&read_s1_vals));
152 
153   base::DictionaryValue read_s2_vals;
154   EXPECT_TRUE(db_->Read("scope2", &read_s2_vals).ok());
155   EXPECT_TRUE(scope2_values.Equals(&read_s2_vals));
156 }
157 
TEST_F(LeveldbScopedDatabaseUnitTest,TestEmptyValue)158 TEST_F(LeveldbScopedDatabaseUnitTest, TestEmptyValue) {
159   base::DictionaryValue values;
160   values.SetString("s1_key1", "");
161   EXPECT_TRUE(db_->Write("scope1", values).ok());
162 
163   base::Optional<base::Value> value;
164   ASSERT_TRUE(db_->Read("scope1", "s1_key1", &value).ok());
165   ASSERT_TRUE(value.has_value());
166   ASSERT_TRUE(value->is_string());
167   EXPECT_EQ(value->GetString(), "");
168 }
169 
TEST_F(LeveldbScopedDatabaseUnitTest,TestValueContainingDelimiter)170 TEST_F(LeveldbScopedDatabaseUnitTest, TestValueContainingDelimiter) {
171   base::DictionaryValue values;
172   values.SetString("s1_key1", "with:delimiter");
173   EXPECT_TRUE(db_->Write("scope1", values).ok());
174 
175   base::Optional<base::Value> value;
176   ASSERT_TRUE(db_->Read("scope1", "s1_key1", &value).ok());
177   ASSERT_TRUE(value.has_value());
178   ASSERT_TRUE(value->is_string());
179   EXPECT_EQ(value->GetString(), "with:delimiter");
180 }
181 
TEST_F(LeveldbScopedDatabaseUnitTest,TestDeleteValues)182 TEST_F(LeveldbScopedDatabaseUnitTest, TestDeleteValues) {
183   base::DictionaryValue scope1_values;
184   scope1_values.SetString("s1_key1", "s1_value1");
185   scope1_values.SetString("s1_key2", "s1_value2");
186   EXPECT_TRUE(db_->Write("scope1", scope1_values).ok());
187 
188   base::DictionaryValue scope2_values;
189   scope2_values.SetString("s2_key1", "s2_value1");
190   scope2_values.SetString("s2_key2", "s2_value2");
191   EXPECT_TRUE(db_->Write("scope2", scope2_values).ok());
192 
193   std::vector<std::string> keys;
194   keys.push_back("s2_key1");
195   keys.push_back("s2_key2");
196   keys.push_back("s1_key1");
197   EXPECT_TRUE(db_->DeleteValues("scope2", keys).ok());
198 
199   base::DictionaryValue read_s1_vals;
200   EXPECT_TRUE(db_->Read("scope1", &read_s1_vals).ok());
201   EXPECT_TRUE(scope1_values.Equals(&read_s1_vals));
202 
203   base::DictionaryValue read_s2_vals;
204   EXPECT_TRUE(db_->Read("scope2", &read_s2_vals).ok());
205   EXPECT_TRUE(read_s2_vals.empty());
206 }
207