blob: 234809deecdd593f40c899ba212b34c02f587453 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_
#define COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "components/leveldb_proto/proto_database.h"
namespace leveldb_proto {
namespace test {
template <typename T>
class FakeDB : public ProtoDatabase<T> {
using Callback = base::OnceCallback<void(bool)>;
public:
using EntryMap = std::map<std::string, T>;
explicit FakeDB(EntryMap* db);
~FakeDB() override;
// ProtoDatabase implementation.
void Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) override;
void UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) override;
void UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector>
entries_to_save,
const LevelDB::KeyFilter& filter,
typename ProtoDatabase<T>::UpdateCallback callback) override;
void LoadEntries(typename ProtoDatabase<T>::LoadCallback callback) override;
void LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoDatabase<T>::LoadCallback callback) override;
void LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) override;
void GetEntry(const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) override;
void Destroy(typename ProtoDatabase<T>::DestroyCallback callback) override;
base::FilePath& GetDirectory();
void InitCallback(bool success);
void LoadCallback(bool success);
void LoadKeysCallback(bool success);
void GetCallback(bool success);
void UpdateCallback(bool success);
void DestroyCallback(bool success);
static base::FilePath DirectoryForTestDB();
private:
static void RunLoadCallback(typename ProtoDatabase<T>::LoadCallback callback,
std::unique_ptr<typename std::vector<T>> entries,
bool success);
static void RunLoadKeysCallback(
typename ProtoDatabase<T>::LoadKeysCallback callback,
std::unique_ptr<std::vector<std::string>> keys,
bool success);
static void RunGetCallback(typename ProtoDatabase<T>::GetCallback callback,
std::unique_ptr<T> entry,
bool success);
base::FilePath dir_;
EntryMap* db_;
Callback init_callback_;
Callback load_callback_;
Callback load_keys_callback_;
Callback get_callback_;
Callback update_callback_;
Callback destroy_callback_;
};
template <typename T>
FakeDB<T>::FakeDB(EntryMap* db)
: db_(db) {}
template <typename T>
FakeDB<T>::~FakeDB() {}
template <typename T>
void FakeDB<T>::Init(const char* client_name,
const base::FilePath& database_dir,
const leveldb_env::Options& options,
typename ProtoDatabase<T>::InitCallback callback) {
dir_ = database_dir;
init_callback_ = std::move(callback);
}
template <typename T>
void FakeDB<T>::UpdateEntries(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
std::unique_ptr<std::vector<std::string>> keys_to_remove,
typename ProtoDatabase<T>::UpdateCallback callback) {
for (const auto& pair : *entries_to_save)
(*db_)[pair.first] = pair.second;
for (const auto& key : *keys_to_remove)
db_->erase(key);
update_callback_ = std::move(callback);
}
template <typename T>
void FakeDB<T>::UpdateEntriesWithRemoveFilter(
std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save,
const LevelDB::KeyFilter& delete_key_filter,
typename ProtoDatabase<T>::UpdateCallback callback) {
for (const auto& pair : *entries_to_save)
(*db_)[pair.first] = pair.second;
auto it = db_->begin();
while (it != db_->end()) {
if (!delete_key_filter.is_null() && delete_key_filter.Run(it->first))
db_->erase(it++);
else
++it;
}
update_callback_ = std::move(callback);
}
template <typename T>
void FakeDB<T>::LoadEntries(typename ProtoDatabase<T>::LoadCallback callback) {
LoadEntriesWithFilter(LevelDB::KeyFilter(), std::move(callback));
}
template <typename T>
void FakeDB<T>::LoadEntriesWithFilter(
const LevelDB::KeyFilter& key_filter,
typename ProtoDatabase<T>::LoadCallback callback) {
std::unique_ptr<std::vector<T>> entries(new std::vector<T>());
for (const auto& pair : *db_) {
if (key_filter.is_null() || key_filter.Run(pair.first))
entries->push_back(pair.second);
}
load_callback_ =
base::BindOnce(RunLoadCallback, std::move(callback), std::move(entries));
}
template <typename T>
void FakeDB<T>::LoadKeys(typename ProtoDatabase<T>::LoadKeysCallback callback) {
std::unique_ptr<std::vector<std::string>> keys(
new std::vector<std::string>());
for (const auto& pair : *db_)
keys->push_back(pair.first);
load_keys_callback_ =
base::BindOnce(RunLoadKeysCallback, std::move(callback), std::move(keys));
}
template <typename T>
void FakeDB<T>::GetEntry(const std::string& key,
typename ProtoDatabase<T>::GetCallback callback) {
std::unique_ptr<T> entry;
auto it = db_->find(key);
if (it != db_->end())
entry.reset(new T(it->second));
get_callback_ =
base::BindOnce(RunGetCallback, std::move(callback), std::move(entry));
}
template <typename T>
void FakeDB<T>::Destroy(typename ProtoDatabase<T>::DestroyCallback callback) {
db_->clear();
destroy_callback_ = std::move(callback);
}
template <typename T>
base::FilePath& FakeDB<T>::GetDirectory() {
return dir_;
}
template <typename T>
void FakeDB<T>::InitCallback(bool success) {
std::move(init_callback_).Run(success);
}
template <typename T>
void FakeDB<T>::LoadCallback(bool success) {
std::move(load_callback_).Run(success);
}
template <typename T>
void FakeDB<T>::LoadKeysCallback(bool success) {
std::move(load_keys_callback_).Run(success);
}
template <typename T>
void FakeDB<T>::GetCallback(bool success) {
std::move(get_callback_).Run(success);
}
template <typename T>
void FakeDB<T>::UpdateCallback(bool success) {
std::move(update_callback_).Run(success);
}
template <typename T>
void FakeDB<T>::DestroyCallback(bool success) {
std::move(destroy_callback_).Run(success);
}
// static
template <typename T>
void FakeDB<T>::RunLoadCallback(
typename ProtoDatabase<T>::LoadCallback callback,
std::unique_ptr<typename std::vector<T>> entries,
bool success) {
std::move(callback).Run(success, std::move(entries));
}
// static
template <typename T>
void FakeDB<T>::RunLoadKeysCallback(
typename ProtoDatabase<T>::LoadKeysCallback callback,
std::unique_ptr<std::vector<std::string>> keys,
bool success) {
std::move(callback).Run(success, std::move(keys));
}
// static
template <typename T>
void FakeDB<T>::RunGetCallback(typename ProtoDatabase<T>::GetCallback callback,
std::unique_ptr<T> entry,
bool success) {
std::move(callback).Run(success, std::move(entry));
}
// static
template <typename T>
base::FilePath FakeDB<T>::DirectoryForTestDB() {
return base::FilePath(FILE_PATH_LITERAL("/fake/path"));
}
} // namespace test
} // namespace leveldb_proto
#endif // COMPONENTS_LEVELDB_PROTO_TESTING_FAKE_DB_H_