diff options
-rw-r--r-- | sync/BUILD.gn | 2 | ||||
-rw-r--r-- | sync/api/mock_model_type_store.cc | 149 | ||||
-rw-r--r-- | sync/api/mock_model_type_store.h | 118 | ||||
-rw-r--r-- | sync/api/model_type_store.cc | 13 | ||||
-rw-r--r-- | sync/api/model_type_store.h | 118 | ||||
-rw-r--r-- | sync/sync_tests.gypi | 2 |
6 files changed, 396 insertions, 6 deletions
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index cfc2846..2307dbf 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn @@ -573,6 +573,8 @@ static_library("test_support_sync_api") { "api/fake_sync_change_processor.h", "api/fake_syncable_service.cc", "api/fake_syncable_service.h", + "api/mock_model_type_store.cc", + "api/mock_model_type_store.h", "api/sync_change_processor_wrapper_for_test.cc", "api/sync_change_processor_wrapper_for_test.h", "api/sync_error_factory_mock.cc", diff --git a/sync/api/mock_model_type_store.cc b/sync/api/mock_model_type_store.cc new file mode 100644 index 0000000..6759be6 --- /dev/null +++ b/sync/api/mock_model_type_store.cc @@ -0,0 +1,149 @@ +// Copyright 2015 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. + +#include "sync/api/mock_model_type_store.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" + +namespace syncer_v2 { + +MockModelTypeStore::MockModelTypeStore() {} + +MockModelTypeStore::~MockModelTypeStore() {} + +void MockModelTypeStore::ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) { + if (!read_data_handler_.is_null()) { + read_data_handler_.Run(id_list, callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()))); + } +} + +void MockModelTypeStore::ReadAllData(const ReadRecordsCallback& callback) { + if (!read_all_data_handler_.is_null()) { + read_all_data_handler_.Run(callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()))); + } +} + +void MockModelTypeStore::ReadAllMetadata(const ReadMetadataCallback& callback) { + if (!read_all_metadata_handler_.is_null()) { + read_all_metadata_handler_.Run(callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(callback, Result::SUCCESS, + base::Passed(scoped_ptr<RecordList>()), std::string())); + } +} + +scoped_ptr<MockModelTypeStore::WriteBatch> +MockModelTypeStore::CreateWriteBatch() { + return make_scoped_ptr(new MockModelTypeStore::WriteBatch()); +} + +void MockModelTypeStore::CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) { + if (!commit_write_batch_handler_.is_null()) { + commit_write_batch_handler_.Run(write_batch.Pass(), callback); + } else { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(callback, Result::SUCCESS)); + } +} + +void MockModelTypeStore::WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + if (!write_data_handler_.is_null()) { + write_data_handler_.Run(write_batch, id, value); + } +} + +void MockModelTypeStore::WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) { + if (!write_metadata_handler_.is_null()) { + write_metadata_handler_.Run(write_batch, id, value); + } +} + +void MockModelTypeStore::WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) { + if (!write_global_metadata_handler_.is_null()) { + write_global_metadata_handler_.Run(write_batch, value); + } +} + +void MockModelTypeStore::DeleteData(WriteBatch* write_batch, + const std::string& id) { + if (!delete_data_handler_.is_null()) { + delete_data_handler_.Run(write_batch, id); + } +} + +void MockModelTypeStore::DeleteMetadata(WriteBatch* write_batch, + const std::string& id) { + if (!delete_metadata_handler_.is_null()) { + delete_metadata_handler_.Run(write_batch, id); + } +} + +void MockModelTypeStore::DeleteGlobalMetadata(WriteBatch* write_batch) { + if (!delete_global_metadata_handler_.is_null()) { + delete_global_metadata_handler_.Run(write_batch); + } +} + +void MockModelTypeStore::RegisterReadDataHandler( + const ReadRecordsSignature& handler) { + read_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterReadAllDataHandler( + const ReadAllRecordsSignature& handler) { + read_all_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterReadAllMetadataHandler( + const ReadAllMetadataSignature& handler) { + read_all_metadata_handler_ = handler; +} + +void MockModelTypeStore::RegisterCommitWriteBatchHandler( + const CommitWriteBatchSignature& handler) { + commit_write_batch_handler_ = handler; +} + +void MockModelTypeStore::RegisterWriteDataHandler( + const WriteRecordSignature& handler) { + write_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterWriteMetadataHandler( + const WriteRecordSignature& handler) { + write_metadata_handler_ = handler; +} + +void MockModelTypeStore::RegisterDeleteDataHandler( + const DeleteRecordSignature& handler) { + delete_data_handler_ = handler; +} + +void MockModelTypeStore::RegisterDeleteMetadataHandler( + const DeleteRecordSignature& handler) { + delete_metadata_handler_ = handler; +} + +} // namespace syncer_v2 diff --git a/sync/api/mock_model_type_store.h b/sync/api/mock_model_type_store.h new file mode 100644 index 0000000..123d456 --- /dev/null +++ b/sync/api/mock_model_type_store.h @@ -0,0 +1,118 @@ +// Copyright 2015 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 SYNC_API_MOCK_MODEL_TYPE_STORE_H_ +#define SYNC_API_MOCK_MODEL_TYPE_STORE_H_ + +#include <string> + +#include "base/callback.h" +#include "sync/api/model_type_store.h" + +namespace syncer_v2 { + +// MockModelTypeStore is implementation of ModelTypeStore that does nothing. +// Use it when testing components that depend on ModelTypeStore. +// +// By default all methods return SUCCESS and empty results. It is possible to +// register custom handlers for certain functions to override behavior. It is +// responsibility of handler to post callback with result. +// Here is an example: +// === +// void OnReadData(const ModelTypeStore::IdList& id_list, +// const ModelTypeStore::ReadRecordsCallback& callback) { +// // Verify id_list here. +// // Prepare fake response. +// scoped_ptr<ModelTypeStore::RecordList> record_list( +// new ModelTypeStore::RecordList); +// record_list->push_back(ModelTypeStore::Record("id1", "value1")); +// base::ThreadTaskRunnerHandle::Get()->PostTask( +// FROM_HERE, base::Bind(callback, Result::SUCCESS, +// base::Passed(record_list))); +// } +// +// MockModelTypeStore mock_model_type_store; +// mock_model_type_store.RegisterReadDataHandler(base::Bind(&OnReadData)); +// ModelTypeStore::IdList id_list; +// id_list.push_back("id1"); +// mock_model_type_store.ReadData(id_list, base::Bind(&ReadDone)); +// === +// TODO(pavel): When in-memory store is available this class should delegate all +// calls to it instead of returning empty successful results. +class MockModelTypeStore : public ModelTypeStore { + public: + // Signatures for all ModelTypeStore virtual functions. + typedef base::Callback<void(const ReadRecordsCallback&)> + ReadAllRecordsSignature; + typedef base::Callback<void(const IdList&, const ReadRecordsCallback&)> + ReadRecordsSignature; + typedef base::Callback<void(const ReadMetadataCallback& callback)> + ReadAllMetadataSignature; + typedef base::Callback<void(scoped_ptr<WriteBatch>, CallbackWithResult)> + CommitWriteBatchSignature; + typedef base::Callback<void(WriteBatch*, + const std::string&, + const std::string&)> WriteRecordSignature; + typedef base::Callback<void(WriteBatch*, const std::string&)> + WriteGlobalMetadataSignature; + typedef base::Callback<void(WriteBatch*, const std::string&)> + DeleteRecordSignature; + typedef base::Callback<void(WriteBatch*)> DeleteGlobalMetadataSignature; + + MockModelTypeStore(); + ~MockModelTypeStore() override; + + // ModelTypeStore implementation. + void ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) override; + void ReadAllData(const ReadRecordsCallback& callback) override; + void ReadAllMetadata(const ReadMetadataCallback& callback) override; + + scoped_ptr<WriteBatch> CreateWriteBatch() override; + void CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) override; + + void WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) override; + void WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) override; + void DeleteData(WriteBatch* write_batch, const std::string& id) override; + void DeleteMetadata(WriteBatch* write_batch, const std::string& id) override; + void DeleteGlobalMetadata(WriteBatch* write_batch) override; + + // Register handler functions. + void RegisterReadDataHandler(const ReadRecordsSignature& handler); + void RegisterReadAllDataHandler(const ReadAllRecordsSignature& handler); + void RegisterReadAllMetadataHandler(const ReadAllMetadataSignature& handler); + void RegisterCommitWriteBatchHandler( + const CommitWriteBatchSignature& handler); + void RegisterWriteDataHandler(const WriteRecordSignature& handler); + void RegisterWriteMetadataHandler(const WriteRecordSignature& handler); + void RegisterWriteGlobalMetadataHandler( + const WriteGlobalMetadataSignature& handler); + void RegisterDeleteDataHandler(const DeleteRecordSignature& handler); + void RegisterDeleteMetadataHandler(const DeleteRecordSignature& handler); + void RegisterDeleteGlobalMetadataHandler( + const DeleteGlobalMetadataSignature& handler); + + private: + ReadRecordsSignature read_data_handler_; + ReadAllRecordsSignature read_all_data_handler_; + ReadAllMetadataSignature read_all_metadata_handler_; + CommitWriteBatchSignature commit_write_batch_handler_; + WriteRecordSignature write_data_handler_; + WriteRecordSignature write_metadata_handler_; + WriteGlobalMetadataSignature write_global_metadata_handler_; + DeleteRecordSignature delete_data_handler_; + DeleteRecordSignature delete_metadata_handler_; + DeleteGlobalMetadataSignature delete_global_metadata_handler_; +}; + +} // namespace syncer_v2 + +#endif // SYNC_API_MOCK_MODEL_TYPE_STORE_H_ diff --git a/sync/api/model_type_store.cc b/sync/api/model_type_store.cc index 2555ddc..657932d 100644 --- a/sync/api/model_type_store.cc +++ b/sync/api/model_type_store.cc @@ -4,10 +4,19 @@ #include "sync/api/model_type_store.h" +#include "base/logging.h" + namespace syncer_v2 { -ModelTypeStore::ModelTypeStore() {} +// static +void ModelTypeStore::CreateInMemoryStoreForTest(const InitCallback& callback) { + NOTIMPLEMENTED(); +} ModelTypeStore::~ModelTypeStore() {} -} // namespace sync_v2 +ModelTypeStore::WriteBatch::WriteBatch() {} + +ModelTypeStore::WriteBatch::~WriteBatch() {} + +} // namespace syncer_v2 diff --git a/sync/api/model_type_store.h b/sync/api/model_type_store.h index 817238e..2c0e4d3 100644 --- a/sync/api/model_type_store.h +++ b/sync/api/model_type_store.h @@ -5,14 +5,124 @@ #ifndef SYNC_API_MODEL_TYPE_STORE_H_ #define SYNC_API_MODEL_TYPE_STORE_H_ +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/macros.h" +#include "sync/base/sync_export.h" + namespace syncer_v2 { -// Interface for store used by ModelTypeProcessor for persisting sync related -// data (entity state and data type state). -class ModelTypeStore { +// ModelTypeStore is leveldb backed store for model type's data, metadata and +// global metadata. +// +// Store keeps records for entries identified by ids. For each entry store keeps +// data and metadata. Also store keeps one record for global metadata. +// +// To create store call one of Create*Store static factory functions. Model type +// controls store's lifetime with returned scoped_ptr. Call to Create*Store +// function triggers asynchronous store backend initialization, callback will be +// called with results when initialization is done. +// +// Read operations are asynchronous, initiated with one of Read* functions, +// provided callback will be called with result code and output of read +// operation. +// +// Write operations are done in context of write batch. To get one call +// CreateWriteBatch(). After that pass write batch object to Write/Delete +// functions. WriteBatch only accumulates pending changes, doesn't actually do +// data modification. Calling CommitWriteBatch writes all accumulated changes to +// disk atomically. Callback passed to CommitWriteBatch will be called with +// result of write operation. If write batch object is destroyed without +// comitting accumulated write operations will not be persisted. +// +// Destroying store object doesn't necessarily cancel asynchronous operations +// issued previously. You should be prepared to handle callbacks from those +// operations. +class SYNC_EXPORT ModelTypeStore { public: - ModelTypeStore(); + // Result of store operations. + enum class Result { + SUCCESS, + UNSPECIFIED_ERROR, + }; + + // Output of read operations is passed back as list of Record structures. + struct Record { + Record(const std::string& id, const std::string& value) + : id(id), value(value) {} + + std::string id; + std::string value; + }; + + // WriteBatch object is used in all modification operations. + class SYNC_EXPORT WriteBatch { + public: + virtual ~WriteBatch(); + + protected: + friend class MockModelTypeStore; + WriteBatch(); + }; + + typedef std::vector<Record> RecordList; + typedef std::vector<std::string> IdList; + + typedef base::Callback<void(Result, scoped_ptr<ModelTypeStore>)> InitCallback; + typedef base::Callback<void(Result)> CallbackWithResult; + typedef base::Callback<void(Result, scoped_ptr<RecordList>)> + ReadRecordsCallback; + typedef base::Callback<void(Result, + scoped_ptr<RecordList>, + const std::string&)> ReadMetadataCallback; + + // Creates store object backed by in-memory leveldb database. It is used in + // tests. + static void CreateInMemoryStoreForTest(const InitCallback& callback); + virtual ~ModelTypeStore(); + + // Read operations return records either for all entries or only for ones + // identified in |id_list|. Result is SUCCESS if all records were read + // successfully. If reading any of records fails result is UNSPECIFIED_ERROR + // and RecordList contains some records that were read successfully. There is + // no guarantee that RecordList will contain all successfully read records in + // this case. + virtual void ReadData(const IdList& id_list, + const ReadRecordsCallback& callback) = 0; + virtual void ReadAllData(const ReadRecordsCallback& callback) = 0; + // ReadMetadataCallback will be invoked with three parameters: result of + // operation, list of metadata records and global metadata. + virtual void ReadAllMetadata(const ReadMetadataCallback& callback) = 0; + + // Creates write batch for write operations. + virtual scoped_ptr<WriteBatch> CreateWriteBatch() = 0; + + // Commits write operations accumulated in write batch. If write operation + // fails result is UNSPECIFIED_ERROR and write operations will not be + // reflected in the store. + virtual void CommitWriteBatch(scoped_ptr<WriteBatch> write_batch, + const CallbackWithResult& callback) = 0; + + // Write operations. + virtual void WriteData(WriteBatch* write_batch, + const std::string& id, + const std::string& value) = 0; + virtual void WriteMetadata(WriteBatch* write_batch, + const std::string& id, + const std::string& value) = 0; + virtual void WriteGlobalMetadata(WriteBatch* write_batch, + const std::string& value) = 0; + virtual void DeleteData(WriteBatch* write_batch, const std::string& id) = 0; + virtual void DeleteMetadata(WriteBatch* write_batch, + const std::string& id) = 0; + virtual void DeleteGlobalMetadata(WriteBatch* write_batch) = 0; + // TODO(pavely): Consider implementing DeleteAllMetadata with following + // signature: + // virtual void DeleteAllMetadata(const CallbackWithResult& callback) = 0. + // It will delete all metadata records and global metadata record. }; } // namespace syncer_v2 diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index 6983456..0c96d9c 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi @@ -224,6 +224,8 @@ 'api/fake_sync_change_processor.h', 'api/fake_syncable_service.cc', 'api/fake_syncable_service.h', + 'api/mock_model_type_store.cc', + 'api/mock_model_type_store.h', 'api/sync_change_processor_wrapper_for_test.cc', 'api/sync_change_processor_wrapper_for_test.h', 'api/sync_error_factory_mock.cc', |