fake_db.h 17 KB

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