1 // Copyright 2014 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 #ifndef COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_
6 #define COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_
7
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/files/file_path.h"
17 #include "base/task/post_task.h"
18 #include "base/test/test_simple_task_runner.h"
19 #include "components/leveldb_proto/internal/proto_database_impl.h"
20 #include "components/leveldb_proto/public/proto_database.h"
21 #include "components/leveldb_proto/public/shared_proto_database_client_list.h"
22
23 namespace leveldb_proto {
24 namespace test {
25
26 template <typename P, typename T = P>
27 class FakeDB : public ProtoDatabaseImpl<P, T> {
28 using Callback = base::OnceCallback<void(bool)>;
29
30 public:
31 using EntryMap = std::map<std::string, P>;
32
33 explicit FakeDB(EntryMap* db);
34
35 // ProtoDatabase implementation.
36 void Init(Callbacks::InitStatusCallback callback) override;
37 void Init(const leveldb_env::Options& unique_db_options,
38 Callbacks::InitStatusCallback callback) override;
39 void UpdateEntries(std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
40 entries_to_save,
41 std::unique_ptr<std::vector<std::string>> keys_to_remove,
42 Callbacks::UpdateCallback callback) override;
43 void UpdateEntriesWithRemoveFilter(
44 std::unique_ptr<typename Util::Internal<T>::KeyEntryVector>
45 entries_to_save,
46 const KeyFilter& filter,
47 Callbacks::UpdateCallback callback) override;
48 void LoadEntries(
49 typename Callbacks::Internal<T>::LoadCallback callback) override;
50 void LoadEntriesWithFilter(
51 const KeyFilter& key_filter,
52 typename Callbacks::Internal<T>::LoadCallback callback) override;
53 void LoadEntriesWithFilter(
54 const KeyFilter& filter,
55 const leveldb::ReadOptions& options,
56 const std::string& target_prefix,
57 typename Callbacks::Internal<T>::LoadCallback callback) override;
58 void LoadKeysAndEntries(
59 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)
60 override;
61 void LoadKeysAndEntriesWithFilter(
62 const KeyFilter& filter,
63 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)
64 override;
65 void LoadKeysAndEntriesWithFilter(
66 const KeyFilter& filter,
67 const leveldb::ReadOptions& options,
68 const std::string& target_prefix,
69 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)
70 override;
71 void LoadKeysAndEntriesInRange(
72 const std::string& start,
73 const std::string& end,
74 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)
75 override;
76 void LoadKeys(Callbacks::LoadKeysCallback callback) override;
77 void GetEntry(const std::string& key,
78 typename Callbacks::Internal<T>::GetCallback callback) override;
79 void Destroy(Callbacks::DestroyCallback callback) override;
80
81 base::FilePath& GetDirectory();
82
83 void InitCallback(bool success);
84
85 void InitStatusCallback(Enums::InitStatus status);
86
87 void LoadCallback(bool success);
88
89 void LoadKeysCallback(bool success);
90
91 void GetCallback(bool success);
92
93 void UpdateCallback(bool success);
94
95 void DestroyCallback(bool success);
96
97 static base::FilePath DirectoryForTestDB();
98
99 private:
100 static void RunLoadCallback(
101 typename Callbacks::Internal<T>::LoadCallback callback,
102 std::unique_ptr<typename std::vector<T>> entries,
103 bool success);
104 static void RunLoadKeysAndEntriesCallback(
105 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback,
106 std::unique_ptr<typename std::map<std::string, T>> entries,
107 bool success);
108
109 static void RunLoadKeysCallback(
110 typename Callbacks::LoadKeysCallback callback,
111 std::unique_ptr<std::vector<std::string>> keys,
112 bool success);
113
114 static void RunGetCallback(
115 typename Callbacks::Internal<T>::GetCallback callback,
116 std::unique_ptr<T> entry,
117 bool success);
118
119 base::FilePath dir_;
120 EntryMap* db_;
121
122 Callback init_callback_;
123 Callbacks::InitStatusCallback init_status_callback_;
124 Callback load_callback_;
125 Callback load_keys_callback_;
126 Callback get_callback_;
127 Callback update_callback_;
128 Callback destroy_callback_;
129 };
130
131 namespace {
132
133 template <typename P,
134 typename T,
135 std::enable_if_t<std::is_base_of<google::protobuf::MessageLite,
136 T>::value>* = nullptr>
DataToProtoWrap(T * data,P * proto)137 void DataToProtoWrap(T* data, P* proto) {
138 proto->Swap(data);
139 }
140
141 template <typename P,
142 typename T,
143 std::enable_if_t<!std::is_base_of<google::protobuf::MessageLite,
144 T>::value>* = nullptr>
DataToProtoWrap(T * data,P * proto)145 void DataToProtoWrap(T* data, P* proto) {
146 DataToProto(data, proto);
147 }
148
149 template <typename P,
150 typename T,
151 std::enable_if_t<std::is_base_of<google::protobuf::MessageLite,
152 T>::value>* = nullptr>
ProtoToDataWrap(const P & proto,T * data)153 void ProtoToDataWrap(const P& proto, T* data) {
154 *data = proto;
155 }
156
157 template <typename P,
158 typename T,
159 std::enable_if_t<!std::is_base_of<google::protobuf::MessageLite,
160 T>::value>* = nullptr>
ProtoToDataWrap(const P & proto,T * data)161 void ProtoToDataWrap(const P& proto, T* data) {
162 P copy = proto;
163 ProtoToData(©, data);
164 }
165
166 } // namespace
167
168 template <typename P, typename T>
FakeDB(EntryMap * db)169 FakeDB<P, T>::FakeDB(EntryMap* db)
170 : ProtoDatabaseImpl<P, T>(
171 ProtoDbType::TEST_DATABASE0,
172 base::FilePath(FILE_PATH_LITERAL("db_dir")),
173 base::MakeRefCounted<base::TestSimpleTaskRunner>()) {
174 db_ = db;
175 }
176
177 template <typename P, typename T>
Init(Callbacks::InitStatusCallback callback)178 void FakeDB<P, T>::Init(Callbacks::InitStatusCallback callback) {
179 dir_ = base::FilePath(FILE_PATH_LITERAL("db_dir"));
180 init_status_callback_ = std::move(callback);
181 }
182
183 template <typename P, typename T>
Init(const leveldb_env::Options & unique_db_options,Callbacks::InitStatusCallback callback)184 void FakeDB<P, T>::Init(const leveldb_env::Options& unique_db_options,
185 Callbacks::InitStatusCallback callback) {
186 Init(std::move(callback));
187 }
188
189 template <typename P, typename T>
UpdateEntries(std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,std::unique_ptr<std::vector<std::string>> keys_to_remove,Callbacks::UpdateCallback callback)190 void FakeDB<P, T>::UpdateEntries(
191 std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
192 std::unique_ptr<std::vector<std::string>> keys_to_remove,
193 Callbacks::UpdateCallback callback) {
194 for (auto& pair : *entries_to_save)
195 DataToProtoWrap(&pair.second, &(*db_)[pair.first]);
196
197 for (const auto& key : *keys_to_remove)
198 db_->erase(key);
199
200 update_callback_ = std::move(callback);
201 }
202
203 template <typename P, typename T>
UpdateEntriesWithRemoveFilter(std::unique_ptr<typename Util::Internal<T>::KeyEntryVector> entries_to_save,const KeyFilter & delete_key_filter,Callbacks::UpdateCallback callback)204 void FakeDB<P, T>::UpdateEntriesWithRemoveFilter(
205 std::unique_ptr<typename Util::Internal<T>::KeyEntryVector> entries_to_save,
206 const KeyFilter& delete_key_filter,
207 Callbacks::UpdateCallback callback) {
208 for (auto& pair : *entries_to_save)
209 DataToProtoWrap(&pair.second, &(*db_)[pair.first]);
210
211 auto it = db_->begin();
212 while (it != db_->end()) {
213 if (!delete_key_filter.is_null() && delete_key_filter.Run(it->first))
214 db_->erase(it++);
215 else
216 ++it;
217 }
218
219 update_callback_ = std::move(callback);
220 }
221
222 template <typename P, typename T>
LoadEntries(typename Callbacks::Internal<T>::LoadCallback callback)223 void FakeDB<P, T>::LoadEntries(
224 typename Callbacks::Internal<T>::LoadCallback callback) {
225 LoadEntriesWithFilter(KeyFilter(), std::move(callback));
226 }
227
228 template <typename P, typename T>
LoadEntriesWithFilter(const KeyFilter & key_filter,typename Callbacks::Internal<T>::LoadCallback callback)229 void FakeDB<P, T>::LoadEntriesWithFilter(
230 const KeyFilter& key_filter,
231 typename Callbacks::Internal<T>::LoadCallback callback) {
232 LoadEntriesWithFilter(key_filter, leveldb::ReadOptions(), std::string(),
233 std::move(callback));
234 }
235
236 template <typename P, typename T>
LoadEntriesWithFilter(const KeyFilter & key_filter,const leveldb::ReadOptions & options,const std::string & target_prefix,typename Callbacks::Internal<T>::LoadCallback callback)237 void FakeDB<P, T>::LoadEntriesWithFilter(
238 const KeyFilter& key_filter,
239 const leveldb::ReadOptions& options,
240 const std::string& target_prefix,
241 typename Callbacks::Internal<T>::LoadCallback callback) {
242 std::unique_ptr<std::vector<T>> entries(new std::vector<T>());
243 for (const auto& pair : *db_) {
244 if (key_filter.is_null() || key_filter.Run(pair.first)) {
245 if (pair.first.compare(0, target_prefix.length(), target_prefix) == 0) {
246 entries->emplace_back(T());
247 ProtoToDataWrap<P, T>(pair.second, &entries->back());
248 }
249 }
250 }
251
252 load_callback_ =
253 base::BindOnce(RunLoadCallback, std::move(callback), std::move(entries));
254 }
255
256 template <typename P, typename T>
LoadKeysAndEntries(typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)257 void FakeDB<P, T>::LoadKeysAndEntries(
258 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback) {
259 LoadKeysAndEntriesWithFilter(KeyFilter(), std::move(callback));
260 }
261
262 template <typename P, typename T>
LoadKeysAndEntriesWithFilter(const KeyFilter & key_filter,typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)263 void FakeDB<P, T>::LoadKeysAndEntriesWithFilter(
264 const KeyFilter& key_filter,
265 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback) {
266 LoadKeysAndEntriesWithFilter(key_filter, leveldb::ReadOptions(),
267 std::string(), std::move(callback));
268 }
269
270 template <typename P, typename T>
LoadKeysAndEntriesWithFilter(const KeyFilter & key_filter,const leveldb::ReadOptions & options,const std::string & target_prefix,typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)271 void FakeDB<P, T>::LoadKeysAndEntriesWithFilter(
272 const KeyFilter& key_filter,
273 const leveldb::ReadOptions& options,
274 const std::string& target_prefix,
275 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback) {
276 auto keys_entries = std::make_unique<std::map<std::string, T>>();
277 for (const auto& pair : *db_) {
278 if (key_filter.is_null() || key_filter.Run(pair.first)) {
279 if (pair.first.compare(0, target_prefix.length(), target_prefix) == 0)
280 ProtoToDataWrap<P, T>(pair.second, &(*keys_entries)[pair.first]);
281 }
282 }
283
284 load_callback_ = base::BindOnce(RunLoadKeysAndEntriesCallback,
285 std::move(callback), std::move(keys_entries));
286 }
287
288 template <typename P, typename T>
LoadKeysAndEntriesInRange(const std::string & start,const std::string & end,typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback)289 void FakeDB<P, T>::LoadKeysAndEntriesInRange(
290 const std::string& start,
291 const std::string& end,
292 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback) {
293 auto keys_entries = std::make_unique<std::map<std::string, T>>();
294 for (const auto& pair : *db_) {
295 if (pair.first >= start && pair.first <= end)
296 ProtoToDataWrap<P, T>(pair.second, &(*keys_entries)[pair.first]);
297 }
298
299 load_callback_ = base::BindOnce(RunLoadKeysAndEntriesCallback,
300 std::move(callback), std::move(keys_entries));
301 }
302
303 template <typename P, typename T>
LoadKeys(Callbacks::LoadKeysCallback callback)304 void FakeDB<P, T>::LoadKeys(Callbacks::LoadKeysCallback callback) {
305 std::unique_ptr<std::vector<std::string>> keys(
306 new std::vector<std::string>());
307 for (const auto& pair : *db_)
308 keys->push_back(pair.first);
309
310 load_keys_callback_ =
311 base::BindOnce(RunLoadKeysCallback, std::move(callback), std::move(keys));
312 }
313
314 template <typename P, typename T>
GetEntry(const std::string & key,typename Callbacks::Internal<T>::GetCallback callback)315 void FakeDB<P, T>::GetEntry(
316 const std::string& key,
317 typename Callbacks::Internal<T>::GetCallback callback) {
318 std::unique_ptr<T> entry;
319 auto it = db_->find(key);
320 if (it != db_->end()) {
321 entry.reset(new T());
322 ProtoToDataWrap<P, T>(it->second, entry.get());
323 }
324
325 get_callback_ =
326 base::BindOnce(RunGetCallback, std::move(callback), std::move(entry));
327 }
328
329 template <typename P, typename T>
Destroy(Callbacks::DestroyCallback callback)330 void FakeDB<P, T>::Destroy(Callbacks::DestroyCallback callback) {
331 db_->clear();
332 destroy_callback_ = std::move(callback);
333 }
334
335 template <typename P, typename T>
GetDirectory()336 base::FilePath& FakeDB<P, T>::GetDirectory() {
337 return dir_;
338 }
339
340 template <typename P, typename T>
InitCallback(bool success)341 void FakeDB<P, T>::InitCallback(bool success) {
342 std::move(init_callback_).Run(success);
343 }
344
345 template <typename P, typename T>
InitStatusCallback(Enums::InitStatus status)346 void FakeDB<P, T>::InitStatusCallback(Enums::InitStatus status) {
347 std::move(init_status_callback_).Run(status);
348 }
349
350 template <typename P, typename T>
LoadCallback(bool success)351 void FakeDB<P, T>::LoadCallback(bool success) {
352 std::move(load_callback_).Run(success);
353 }
354
355 template <typename P, typename T>
LoadKeysCallback(bool success)356 void FakeDB<P, T>::LoadKeysCallback(bool success) {
357 std::move(load_keys_callback_).Run(success);
358 }
359
360 template <typename P, typename T>
GetCallback(bool success)361 void FakeDB<P, T>::GetCallback(bool success) {
362 std::move(get_callback_).Run(success);
363 }
364
365 template <typename P, typename T>
UpdateCallback(bool success)366 void FakeDB<P, T>::UpdateCallback(bool success) {
367 std::move(update_callback_).Run(success);
368 }
369
370 template <typename P, typename T>
DestroyCallback(bool success)371 void FakeDB<P, T>::DestroyCallback(bool success) {
372 std::move(destroy_callback_).Run(success);
373 }
374
375 // static
376 template <typename P, typename T>
RunLoadCallback(typename Callbacks::Internal<T>::LoadCallback callback,std::unique_ptr<typename std::vector<T>> entries,bool success)377 void FakeDB<P, T>::RunLoadCallback(
378 typename Callbacks::Internal<T>::LoadCallback callback,
379 std::unique_ptr<typename std::vector<T>> entries,
380 bool success) {
381 std::move(callback).Run(success, std::move(entries));
382 }
383
384 // static
385 template <typename P, typename T>
RunLoadKeysAndEntriesCallback(typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback,std::unique_ptr<typename std::map<std::string,T>> keys_entries,bool success)386 void FakeDB<P, T>::RunLoadKeysAndEntriesCallback(
387 typename Callbacks::Internal<T>::LoadKeysAndEntriesCallback callback,
388 std::unique_ptr<typename std::map<std::string, T>> keys_entries,
389 bool success) {
390 std::move(callback).Run(success, std::move(keys_entries));
391 }
392
393 // static
394 template <typename P, typename T>
RunLoadKeysCallback(Callbacks::LoadKeysCallback callback,std::unique_ptr<std::vector<std::string>> keys,bool success)395 void FakeDB<P, T>::RunLoadKeysCallback(
396 Callbacks::LoadKeysCallback callback,
397 std::unique_ptr<std::vector<std::string>> keys,
398 bool success) {
399 std::move(callback).Run(success, std::move(keys));
400 }
401
402 // static
403 template <typename P, typename T>
RunGetCallback(typename Callbacks::Internal<T>::GetCallback callback,std::unique_ptr<T> entry,bool success)404 void FakeDB<P, T>::RunGetCallback(
405 typename Callbacks::Internal<T>::GetCallback callback,
406 std::unique_ptr<T> entry,
407 bool success) {
408 std::move(callback).Run(success, std::move(entry));
409 }
410
411 // static
412 template <typename P, typename T>
DirectoryForTestDB()413 base::FilePath FakeDB<P, T>::DirectoryForTestDB() {
414 return base::FilePath(FILE_PATH_LITERAL("/fake/path"));
415 }
416
417 } // namespace test
418 } // namespace leveldb_proto
419
420 #endif // COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_
421