| OLD | NEW |
| (Empty) | |
| 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 "content/browser/leveldb_wrapper_impl.h" |
| 6 |
| 7 #include "base/debug/stack_trace.h" |
| 8 |
| 9 #include "components/leveldb/public/cpp/util.h" |
| 10 #include "content/public/test/test_browser_thread_bundle.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 using leveldb::StdStringToUint8Vector; |
| 14 using leveldb::Uint8VectorToStdString; |
| 15 |
| 16 namespace content { |
| 17 |
| 18 namespace { |
| 19 |
| 20 const char* kTestPrefix = "abc"; |
| 21 const char* kTestSource = "source"; |
| 22 const size_t kTestSizeLimit = 512; |
| 23 |
| 24 leveldb::mojom::KeyValuePtr CreateKeyValue(std::vector<uint8_t> key, |
| 25 std::vector<uint8_t> value) { |
| 26 leveldb::mojom::KeyValuePtr result = leveldb::mojom::KeyValue::New(); |
| 27 result->key = std::move(key); |
| 28 result->value = std::move(value); |
| 29 return result; |
| 30 } |
| 31 |
| 32 base::StringPiece AsStringPiece(const std::vector<uint8_t>& data) { |
| 33 return base::StringPiece(reinterpret_cast<const char*>(data.data()), |
| 34 data.size()); |
| 35 } |
| 36 |
| 37 bool StartsWith(const std::vector<uint8_t>& key, |
| 38 const std::vector<uint8_t>& prefix) { |
| 39 return base::StartsWith(AsStringPiece(key), AsStringPiece(prefix), |
| 40 base::CompareCase::SENSITIVE); |
| 41 } |
| 42 |
| 43 class MockLevelDBDatabase : public leveldb::mojom::LevelDBDatabase { |
| 44 public: |
| 45 explicit MockLevelDBDatabase( |
| 46 std::map<std::vector<uint8_t>, std::vector<uint8_t>>* mock_data) |
| 47 : mock_data_(*mock_data) {} |
| 48 |
| 49 void Put(const std::vector<uint8_t>& key, |
| 50 const std::vector<uint8_t>& value, |
| 51 const PutCallback& callback) override { |
| 52 FAIL(); |
| 53 } |
| 54 |
| 55 void Delete(const std::vector<uint8_t>& key, |
| 56 const DeleteCallback& callback) override { |
| 57 FAIL(); |
| 58 } |
| 59 |
| 60 void DeletePrefixed(const std::vector<uint8_t>& key_prefix, |
| 61 const DeletePrefixedCallback& callback) override { |
| 62 FAIL(); |
| 63 } |
| 64 |
| 65 void Write(std::vector<leveldb::mojom::BatchedOperationPtr> operations, |
| 66 const WriteCallback& callback) override { |
| 67 for (const auto& op : operations) { |
| 68 switch (op->type) { |
| 69 case leveldb::mojom::BatchOperationType::PUT_KEY: |
| 70 mock_data_[op->key] = *op->value; |
| 71 break; |
| 72 case leveldb::mojom::BatchOperationType::DELETE_KEY: |
| 73 mock_data_.erase(op->key); |
| 74 break; |
| 75 case leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY: |
| 76 FAIL(); |
| 77 break; |
| 78 } |
| 79 } |
| 80 callback.Run(leveldb::mojom::DatabaseError::OK); |
| 81 } |
| 82 |
| 83 void Get(const std::vector<uint8_t>& key, |
| 84 const GetCallback& callback) override { |
| 85 FAIL(); |
| 86 } |
| 87 |
| 88 void GetPrefixed(const std::vector<uint8_t>& key_prefix, |
| 89 const GetPrefixedCallback& callback) override { |
| 90 std::vector<leveldb::mojom::KeyValuePtr> data; |
| 91 for (const auto& row : mock_data_) { |
| 92 if (StartsWith(row.first, key_prefix)) { |
| 93 data.push_back(CreateKeyValue(row.first, row.second)); |
| 94 } |
| 95 } |
| 96 callback.Run(leveldb::mojom::DatabaseError::OK, std::move(data)); |
| 97 } |
| 98 |
| 99 void GetSnapshot(const GetSnapshotCallback& callback) override { FAIL(); } |
| 100 |
| 101 void ReleaseSnapshot(const base::UnguessableToken& snapshot) override { |
| 102 FAIL(); |
| 103 } |
| 104 |
| 105 void GetFromSnapshot(const base::UnguessableToken& snapshot, |
| 106 const std::vector<uint8_t>& key, |
| 107 const GetCallback& callback) override { |
| 108 FAIL(); |
| 109 } |
| 110 |
| 111 void NewIterator(const NewIteratorCallback& callback) override { FAIL(); } |
| 112 |
| 113 void NewIteratorFromSnapshot( |
| 114 const base::UnguessableToken& snapshot, |
| 115 const NewIteratorFromSnapshotCallback& callback) override { |
| 116 FAIL(); |
| 117 } |
| 118 |
| 119 void ReleaseIterator(const base::UnguessableToken& iterator) override { |
| 120 FAIL(); |
| 121 } |
| 122 |
| 123 void IteratorSeekToFirst( |
| 124 const base::UnguessableToken& iterator, |
| 125 const IteratorSeekToFirstCallback& callback) override { |
| 126 FAIL(); |
| 127 } |
| 128 |
| 129 void IteratorSeekToLast(const base::UnguessableToken& iterator, |
| 130 const IteratorSeekToLastCallback& callback) override { |
| 131 FAIL(); |
| 132 } |
| 133 |
| 134 void IteratorSeek(const base::UnguessableToken& iterator, |
| 135 const std::vector<uint8_t>& target, |
| 136 const IteratorSeekToLastCallback& callback) override { |
| 137 FAIL(); |
| 138 } |
| 139 |
| 140 void IteratorNext(const base::UnguessableToken& iterator, |
| 141 const IteratorNextCallback& callback) override { |
| 142 FAIL(); |
| 143 } |
| 144 |
| 145 void IteratorPrev(const base::UnguessableToken& iterator, |
| 146 const IteratorPrevCallback& callback) override { |
| 147 FAIL(); |
| 148 } |
| 149 |
| 150 private: |
| 151 std::map<std::vector<uint8_t>, std::vector<uint8_t>>& mock_data_; |
| 152 }; |
| 153 |
| 154 void NoOp() {} |
| 155 |
| 156 void GetCallback(bool* called, |
| 157 bool* success_out, |
| 158 std::vector<uint8_t>* value_out, |
| 159 bool success, |
| 160 const std::vector<uint8_t>& value) { |
| 161 *called = true; |
| 162 *success_out = success; |
| 163 *value_out = value; |
| 164 } |
| 165 |
| 166 void GetAllCallback(bool* called, |
| 167 leveldb::mojom::DatabaseError* status_out, |
| 168 std::vector<mojom::KeyValuePtr>* data_out, |
| 169 leveldb::mojom::DatabaseError status, |
| 170 std::vector<mojom::KeyValuePtr> data) { |
| 171 *called = true; |
| 172 *status_out = status; |
| 173 *data_out = std::move(data); |
| 174 } |
| 175 |
| 176 void SuccessCallback(bool* called, bool* success_out, bool success) { |
| 177 *called = true; |
| 178 *success_out = success; |
| 179 } |
| 180 |
| 181 void NoOpSuccess(bool success) {} |
| 182 |
| 183 } // namespace |
| 184 |
| 185 class LevelDBWrapperImplTest : public testing::Test { |
| 186 public: |
| 187 LevelDBWrapperImplTest() |
| 188 : db_(&mock_data_), |
| 189 level_db_wrapper_(&db_, |
| 190 kTestPrefix, |
| 191 kTestSizeLimit, |
| 192 base::TimeDelta::FromSeconds(5), |
| 193 10 * 1024 * 1024 /* max_bytes_per_hour */, |
| 194 60 /* max_commits_per_hour */, |
| 195 base::Bind(&NoOp)) { |
| 196 set_mock_data(std::string(kTestPrefix) + "def", "defdata"); |
| 197 set_mock_data(std::string(kTestPrefix) + "123", "123data"); |
| 198 set_mock_data("123", "baddata"); |
| 199 } |
| 200 |
| 201 void set_mock_data(const std::string& key, const std::string& value) { |
| 202 mock_data_[StdStringToUint8Vector(key)] = StdStringToUint8Vector(value); |
| 203 } |
| 204 |
| 205 bool has_mock_data(const std::string& key) { |
| 206 return mock_data_.find(StdStringToUint8Vector(key)) != mock_data_.end(); |
| 207 } |
| 208 |
| 209 std::string get_mock_data(const std::string& key) { |
| 210 return has_mock_data(key) |
| 211 ? Uint8VectorToStdString(mock_data_[StdStringToUint8Vector(key)]) |
| 212 : ""; |
| 213 } |
| 214 |
| 215 mojom::LevelDBWrapper* wrapper() { return &level_db_wrapper_; } |
| 216 |
| 217 void CommitChanges() { |
| 218 ASSERT_TRUE(level_db_wrapper_.commit_batch_); |
| 219 level_db_wrapper_.CommitChanges(); |
| 220 } |
| 221 |
| 222 private: |
| 223 TestBrowserThreadBundle thread_bundle_; |
| 224 std::map<std::vector<uint8_t>, std::vector<uint8_t>> mock_data_; |
| 225 MockLevelDBDatabase db_; |
| 226 LevelDBWrapperImpl level_db_wrapper_; |
| 227 }; |
| 228 |
| 229 TEST_F(LevelDBWrapperImplTest, GetLoadedFromMap) { |
| 230 bool called = false; |
| 231 bool success; |
| 232 std::vector<uint8_t> result; |
| 233 wrapper()->Get(StdStringToUint8Vector("123"), |
| 234 base::Bind(&GetCallback, &called, &success, &result)); |
| 235 ASSERT_TRUE(called); |
| 236 EXPECT_TRUE(success); |
| 237 EXPECT_EQ(StdStringToUint8Vector("123data"), result); |
| 238 |
| 239 called = false; |
| 240 wrapper()->Get(StdStringToUint8Vector("x"), |
| 241 base::Bind(&GetCallback, &called, &success, &result)); |
| 242 ASSERT_TRUE(called); |
| 243 EXPECT_FALSE(success); |
| 244 } |
| 245 |
| 246 TEST_F(LevelDBWrapperImplTest, GetFromPutOverwrite) { |
| 247 std::vector<uint8_t> key = StdStringToUint8Vector("123"); |
| 248 std::vector<uint8_t> value = StdStringToUint8Vector("foo"); |
| 249 |
| 250 bool called = false; |
| 251 bool success; |
| 252 wrapper()->Put(key, value, kTestSource, |
| 253 base::Bind(&SuccessCallback, &called, &success)); |
| 254 ASSERT_TRUE(called); |
| 255 EXPECT_TRUE(success); |
| 256 |
| 257 called = false; |
| 258 std::vector<uint8_t> result; |
| 259 wrapper()->Get(key, base::Bind(&GetCallback, &called, &success, &result)); |
| 260 ASSERT_TRUE(called); |
| 261 EXPECT_TRUE(success); |
| 262 EXPECT_EQ(value, result); |
| 263 } |
| 264 |
| 265 TEST_F(LevelDBWrapperImplTest, GetFromPutNewKey) { |
| 266 std::vector<uint8_t> key = StdStringToUint8Vector("newkey"); |
| 267 std::vector<uint8_t> value = StdStringToUint8Vector("foo"); |
| 268 |
| 269 bool called = false; |
| 270 bool success; |
| 271 wrapper()->Put(key, value, kTestSource, |
| 272 base::Bind(&SuccessCallback, &called, &success)); |
| 273 ASSERT_TRUE(called); |
| 274 EXPECT_TRUE(success); |
| 275 |
| 276 called = false; |
| 277 std::vector<uint8_t> result; |
| 278 wrapper()->Get(key, base::Bind(&GetCallback, &called, &success, &result)); |
| 279 ASSERT_TRUE(called); |
| 280 EXPECT_TRUE(success); |
| 281 EXPECT_EQ(value, result); |
| 282 } |
| 283 |
| 284 TEST_F(LevelDBWrapperImplTest, GetAll) { |
| 285 bool called = false; |
| 286 leveldb::mojom::DatabaseError status; |
| 287 std::vector<mojom::KeyValuePtr> data; |
| 288 wrapper()->GetAll(kTestSource, |
| 289 base::Bind(&GetAllCallback, &called, &status, &data)); |
| 290 ASSERT_TRUE(called); |
| 291 EXPECT_EQ(leveldb::mojom::DatabaseError::OK, status); |
| 292 EXPECT_EQ(2u, data.size()); |
| 293 } |
| 294 |
| 295 TEST_F(LevelDBWrapperImplTest, CommitPutToDB) { |
| 296 std::string key1 = "123"; |
| 297 std::string value1 = "foo"; |
| 298 std::string key2 = "abc"; |
| 299 std::string value2 = "data abc"; |
| 300 |
| 301 wrapper()->Put(StdStringToUint8Vector(key1), StdStringToUint8Vector(value1), |
| 302 kTestSource, base::Bind(&NoOpSuccess)); |
| 303 wrapper()->Put(StdStringToUint8Vector(key2), |
| 304 StdStringToUint8Vector("old value"), kTestSource, |
| 305 base::Bind(&NoOpSuccess)); |
| 306 wrapper()->Put(StdStringToUint8Vector(key2), StdStringToUint8Vector(value2), |
| 307 kTestSource, base::Bind(&NoOpSuccess)); |
| 308 |
| 309 CommitChanges(); |
| 310 |
| 311 EXPECT_TRUE(has_mock_data(kTestPrefix + key1)); |
| 312 EXPECT_EQ(value1, get_mock_data(kTestPrefix + key1)); |
| 313 EXPECT_TRUE(has_mock_data(kTestPrefix + key2)); |
| 314 EXPECT_EQ(value2, get_mock_data(kTestPrefix + key2)); |
| 315 } |
| 316 |
| 317 } // namespace content |
| OLD | NEW |