OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/dom_distiller/core/dom_distiller_database.h" | 5 #include "components/leveldb_proto/core/proto_database_impl.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/threading/thread.h" | 13 #include "base/threading/thread.h" |
14 #include "components/dom_distiller/core/article_entry.h" | 14 #include "components/leveldb_proto/testing/proto/test.pb.h" |
15 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 | 17 |
18 using base::MessageLoop; | 18 using base::MessageLoop; |
19 using base::ScopedTempDir; | 19 using base::ScopedTempDir; |
20 using testing::Invoke; | 20 using testing::Invoke; |
21 using testing::Return; | 21 using testing::Return; |
22 using testing::_; | 22 using testing::_; |
23 | 23 |
24 namespace dom_distiller { | 24 namespace leveldb_proto { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 typedef std::map<std::string, ArticleEntry> EntryMap; | 28 typedef std::map<std::string, TestProto> EntryMap; |
29 | 29 |
30 class MockDB : public DomDistillerDatabase::Database { | 30 class MockDB : public ProtoDatabaseImpl<TestProto>::Database { |
31 public: | 31 public: |
32 MOCK_METHOD1(Init, bool(const base::FilePath&)); | 32 MOCK_METHOD1(Init, bool(const base::FilePath&)); |
33 MOCK_METHOD2(Save, bool(const EntryVector&, const EntryVector&)); | 33 MOCK_METHOD2(Save, bool(const KeyValueVector&, const KeyVector&)); |
34 MOCK_METHOD1(Load, bool(EntryVector*)); | 34 MOCK_METHOD1(Load, bool(std::vector<std::string>*)); |
35 | 35 |
36 MockDB() { | 36 MockDB() { |
37 ON_CALL(*this, Init(_)).WillByDefault(Return(true)); | 37 ON_CALL(*this, Init(_)).WillByDefault(Return(true)); |
38 ON_CALL(*this, Save(_, _)).WillByDefault(Return(true)); | 38 ON_CALL(*this, Save(_, _)).WillByDefault(Return(true)); |
39 ON_CALL(*this, Load(_)).WillByDefault(Return(true)); | 39 ON_CALL(*this, Load(_)).WillByDefault(Return(true)); |
40 } | 40 } |
41 | |
42 bool LoadEntries(EntryVector* entries); | |
43 }; | 41 }; |
44 | 42 |
45 class MockDatabaseCaller { | 43 class MockDatabaseCaller { |
46 public: | 44 public: |
47 MOCK_METHOD1(InitCallback, void(bool)); | 45 MOCK_METHOD1(InitCallback, void(bool)); |
48 MOCK_METHOD1(SaveCallback, void(bool)); | 46 MOCK_METHOD1(SaveCallback, void(bool)); |
49 void LoadCallback(bool success, scoped_ptr<EntryVector> entries) { | 47 void LoadCallback(bool success, scoped_ptr<std::vector<TestProto>> entries) { |
50 LoadCallback1(success, entries.get()); | 48 LoadCallback1(success, entries.get()); |
51 } | 49 } |
52 MOCK_METHOD2(LoadCallback1, void(bool, EntryVector*)); | 50 MOCK_METHOD2(LoadCallback1, void(bool, std::vector<TestProto>*)); |
53 }; | 51 }; |
54 | 52 |
55 } // namespace | 53 } // namespace |
56 | 54 |
57 EntryMap GetSmallModel() { | 55 EntryMap GetSmallModel() { |
58 EntryMap model; | 56 EntryMap model; |
59 | 57 |
60 model["key0"].set_entry_id("key0"); | 58 model["0"].set_id("0"); |
61 model["key0"].add_pages()->set_url("http://foo.com/1"); | 59 model["0"].set_data("http://foo.com/1"); |
62 model["key0"].add_pages()->set_url("http://foo.com/2"); | |
63 model["key0"].add_pages()->set_url("http://foo.com/3"); | |
64 | 60 |
65 model["key1"].set_entry_id("key1"); | 61 model["1"].set_id("1"); |
66 model["key1"].add_pages()->set_url("http://bar.com/all"); | 62 model["1"].set_data("http://bar.com/all"); |
67 | 63 |
68 model["key2"].set_entry_id("key2"); | 64 model["2"].set_id("2"); |
69 model["key2"].add_pages()->set_url("http://baz.com/1"); | 65 model["2"].set_data("http://baz.com/1"); |
70 | 66 |
71 return model; | 67 return model; |
72 } | 68 } |
73 | 69 |
74 void ExpectEntryPointersEquals(EntryMap expected, const EntryVector& actual) { | 70 void ExpectEntryPointersEquals(EntryMap expected, |
| 71 const std::vector<TestProto>& actual) { |
75 EXPECT_EQ(expected.size(), actual.size()); | 72 EXPECT_EQ(expected.size(), actual.size()); |
76 for (size_t i = 0; i < actual.size(); i++) { | 73 for (size_t i = 0; i < actual.size(); i++) { |
77 EntryMap::iterator expected_it = | 74 EntryMap::iterator expected_it = expected.find(actual[i].id()); |
78 expected.find(std::string(actual[i].entry_id())); | |
79 EXPECT_TRUE(expected_it != expected.end()); | 75 EXPECT_TRUE(expected_it != expected.end()); |
80 std::string serialized_expected = expected_it->second.SerializeAsString(); | 76 std::string serialized_expected = expected_it->second.SerializeAsString(); |
81 std::string serialized_actual = actual[i].SerializeAsString(); | 77 std::string serialized_actual = actual[i].SerializeAsString(); |
82 EXPECT_EQ(serialized_expected, serialized_actual); | 78 EXPECT_EQ(serialized_expected, serialized_actual); |
83 expected.erase(expected_it); | 79 expected.erase(expected_it); |
84 } | 80 } |
85 } | 81 } |
86 | 82 |
87 class DomDistillerDatabaseTest : public testing::Test { | 83 class ProtoDatabaseImplTest : public testing::Test { |
88 public: | 84 public: |
89 virtual void SetUp() { | 85 virtual void SetUp() { |
90 main_loop_.reset(new MessageLoop()); | 86 main_loop_.reset(new MessageLoop()); |
91 db_.reset(new DomDistillerDatabase(main_loop_->message_loop_proxy())); | 87 db_.reset( |
| 88 new ProtoDatabaseImpl<TestProto>(main_loop_->message_loop_proxy())); |
92 } | 89 } |
93 | 90 |
94 virtual void TearDown() { | 91 virtual void TearDown() { |
95 db_.reset(); | 92 db_.reset(); |
96 base::RunLoop().RunUntilIdle(); | 93 base::RunLoop().RunUntilIdle(); |
97 main_loop_.reset(); | 94 main_loop_.reset(); |
98 } | 95 } |
99 | 96 |
100 scoped_ptr<DomDistillerDatabase> db_; | 97 scoped_ptr<ProtoDatabaseImpl<TestProto>> db_; |
101 scoped_ptr<MessageLoop> main_loop_; | 98 scoped_ptr<MessageLoop> main_loop_; |
102 }; | 99 }; |
103 | 100 |
104 // Test that DomDistillerDatabase calls Init on the underlying database and that | 101 // Test that ProtoDatabaseImpl calls Init on the underlying database and that |
105 // the caller's InitCallback is called with the correct value. | 102 // the caller's InitCallback is called with the correct value. |
106 TEST_F(DomDistillerDatabaseTest, TestDBInitSuccess) { | 103 TEST_F(ProtoDatabaseImplTest, TestDBInitSuccess) { |
107 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 104 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
108 | 105 |
109 MockDB* mock_db = new MockDB(); | 106 MockDB* mock_db = new MockDB(); |
110 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(true)); | 107 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(true)); |
111 | 108 |
112 MockDatabaseCaller caller; | 109 MockDatabaseCaller caller; |
113 EXPECT_CALL(caller, InitCallback(true)); | 110 EXPECT_CALL(caller, InitCallback(true)); |
114 | 111 |
115 db_->InitWithDatabase( | 112 db_->InitWithDatabase( |
116 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 113 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
117 base::FilePath(path), | 114 base::FilePath(path), |
118 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 115 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
119 | 116 |
120 base::RunLoop().RunUntilIdle(); | 117 base::RunLoop().RunUntilIdle(); |
121 } | 118 } |
122 | 119 |
123 TEST_F(DomDistillerDatabaseTest, TestDBInitFailure) { | 120 TEST_F(ProtoDatabaseImplTest, TestDBInitFailure) { |
124 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 121 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
125 | 122 |
126 MockDB* mock_db = new MockDB(); | 123 MockDB* mock_db = new MockDB(); |
127 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(false)); | 124 EXPECT_CALL(*mock_db, Init(path)).WillOnce(Return(false)); |
128 | 125 |
129 MockDatabaseCaller caller; | 126 MockDatabaseCaller caller; |
130 EXPECT_CALL(caller, InitCallback(false)); | 127 EXPECT_CALL(caller, InitCallback(false)); |
131 | 128 |
132 db_->InitWithDatabase( | 129 db_->InitWithDatabase( |
133 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 130 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
134 base::FilePath(path), | 131 base::FilePath(path), |
135 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 132 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
136 | 133 |
137 base::RunLoop().RunUntilIdle(); | 134 base::RunLoop().RunUntilIdle(); |
138 } | 135 } |
139 | 136 |
140 ACTION_P(AppendLoadEntries, model) { | 137 ACTION_P(AppendLoadEntries, model) { |
141 EntryVector* output = arg0; | 138 std::vector<std::string>* output = arg0; |
142 for (EntryMap::const_iterator it = model.begin(); it != model.end(); ++it) { | 139 for (EntryMap::const_iterator it = model.begin(); it != model.end(); ++it) { |
143 output->push_back(it->second); | 140 output->push_back(it->second.SerializeAsString()); |
144 } | 141 } |
145 return true; | 142 return true; |
146 } | 143 } |
147 | 144 |
148 ACTION_P(VerifyLoadEntries, expected) { | 145 ACTION_P(VerifyLoadEntries, expected) { |
149 EntryVector* actual = arg1; | 146 std::vector<TestProto>* actual = arg1; |
150 ExpectEntryPointersEquals(expected, *actual); | 147 ExpectEntryPointersEquals(expected, *actual); |
151 } | 148 } |
152 | 149 |
153 // Test that DomDistillerDatabase calls Load on the underlying database and that | 150 // Test that ProtoDatabaseImpl calls Load on the underlying database and that |
154 // the caller's LoadCallback is called with the correct success value. Also | 151 // the caller's LoadCallback is called with the correct success value. Also |
155 // confirms that on success, the expected entries are passed to the caller's | 152 // confirms that on success, the expected entries are passed to the caller's |
156 // LoadCallback. | 153 // LoadCallback. |
157 TEST_F(DomDistillerDatabaseTest, TestDBLoadSuccess) { | 154 TEST_F(ProtoDatabaseImplTest, TestDBLoadSuccess) { |
158 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 155 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
159 | 156 |
160 MockDB* mock_db = new MockDB(); | 157 MockDB* mock_db = new MockDB(); |
161 MockDatabaseCaller caller; | 158 MockDatabaseCaller caller; |
162 EntryMap model = GetSmallModel(); | 159 EntryMap model = GetSmallModel(); |
163 | 160 |
164 EXPECT_CALL(*mock_db, Init(_)); | 161 EXPECT_CALL(*mock_db, Init(_)); |
165 EXPECT_CALL(caller, InitCallback(_)); | 162 EXPECT_CALL(caller, InitCallback(_)); |
166 db_->InitWithDatabase( | 163 db_->InitWithDatabase( |
167 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 164 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
168 base::FilePath(path), | 165 base::FilePath(path), |
169 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 166 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
170 | 167 |
171 EXPECT_CALL(*mock_db, Load(_)).WillOnce(AppendLoadEntries(model)); | 168 EXPECT_CALL(*mock_db, Load(_)).WillOnce(AppendLoadEntries(model)); |
172 EXPECT_CALL(caller, LoadCallback1(true, _)) | 169 EXPECT_CALL(caller, LoadCallback1(true, _)) |
173 .WillOnce(VerifyLoadEntries(testing::ByRef(model))); | 170 .WillOnce(VerifyLoadEntries(testing::ByRef(model))); |
174 db_->LoadEntries( | 171 db_->LoadEntries( |
175 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller))); | 172 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller))); |
176 | 173 |
177 base::RunLoop().RunUntilIdle(); | 174 base::RunLoop().RunUntilIdle(); |
178 } | 175 } |
179 | 176 |
180 TEST_F(DomDistillerDatabaseTest, TestDBLoadFailure) { | 177 TEST_F(ProtoDatabaseImplTest, TestDBLoadFailure) { |
181 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 178 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
182 | 179 |
183 MockDB* mock_db = new MockDB(); | 180 MockDB* mock_db = new MockDB(); |
184 MockDatabaseCaller caller; | 181 MockDatabaseCaller caller; |
185 | 182 |
186 EXPECT_CALL(*mock_db, Init(_)); | 183 EXPECT_CALL(*mock_db, Init(_)); |
187 EXPECT_CALL(caller, InitCallback(_)); | 184 EXPECT_CALL(caller, InitCallback(_)); |
188 db_->InitWithDatabase( | 185 db_->InitWithDatabase( |
189 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 186 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
190 base::FilePath(path), | 187 base::FilePath(path), |
191 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 188 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
192 | 189 |
193 EXPECT_CALL(*mock_db, Load(_)).WillOnce(Return(false)); | 190 EXPECT_CALL(*mock_db, Load(_)).WillOnce(Return(false)); |
194 EXPECT_CALL(caller, LoadCallback1(false, _)); | 191 EXPECT_CALL(caller, LoadCallback1(false, _)); |
195 db_->LoadEntries( | 192 db_->LoadEntries( |
196 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller))); | 193 base::Bind(&MockDatabaseCaller::LoadCallback, base::Unretained(&caller))); |
197 | 194 |
198 base::RunLoop().RunUntilIdle(); | 195 base::RunLoop().RunUntilIdle(); |
199 } | 196 } |
200 | 197 |
201 ACTION_P(VerifyUpdateEntries, expected) { | 198 ACTION_P(VerifyUpdateEntries, expected) { |
202 const EntryVector& actual = arg0; | 199 const KeyValueVector actual = arg0; |
203 ExpectEntryPointersEquals(expected, actual); | 200 // Create a vector of TestProto from |actual| to reuse the comparison |
| 201 // function. |
| 202 std::vector<TestProto> extracted_entries; |
| 203 for (KeyValueVector::const_iterator it = actual.begin(); it != actual.end(); |
| 204 ++it) { |
| 205 TestProto entry; |
| 206 entry.ParseFromString(it->second); |
| 207 extracted_entries.push_back(entry); |
| 208 } |
| 209 ExpectEntryPointersEquals(expected, extracted_entries); |
204 return true; | 210 return true; |
205 } | 211 } |
206 | 212 |
207 // Test that DomDistillerDatabase calls Save on the underlying database with the | 213 // Test that ProtoDatabaseImpl calls Save on the underlying database with the |
208 // correct entries to save and that the caller's SaveCallback is called with the | 214 // correct entries to save and that the caller's SaveCallback is called with the |
209 // correct success value. | 215 // correct success value. |
210 TEST_F(DomDistillerDatabaseTest, TestDBSaveSuccess) { | 216 TEST_F(ProtoDatabaseImplTest, TestDBSaveSuccess) { |
211 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 217 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
212 | 218 |
213 MockDB* mock_db = new MockDB(); | 219 MockDB* mock_db = new MockDB(); |
214 MockDatabaseCaller caller; | 220 MockDatabaseCaller caller; |
215 EntryMap model = GetSmallModel(); | 221 EntryMap model = GetSmallModel(); |
216 | 222 |
217 EXPECT_CALL(*mock_db, Init(_)); | 223 EXPECT_CALL(*mock_db, Init(_)); |
218 EXPECT_CALL(caller, InitCallback(_)); | 224 EXPECT_CALL(caller, InitCallback(_)); |
219 db_->InitWithDatabase( | 225 db_->InitWithDatabase( |
220 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 226 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
221 base::FilePath(path), | 227 base::FilePath(path), |
222 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 228 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
223 | 229 |
224 scoped_ptr<EntryVector> entries(new EntryVector()); | 230 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( |
| 231 new ProtoDatabase<TestProto>::KeyEntryVector()); |
225 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { | 232 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { |
226 entries->push_back(it->second); | 233 entries->push_back(std::make_pair(it->second.id(), it->second)); |
227 } | 234 } |
228 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 235 scoped_ptr<KeyVector> keys_to_remove(new KeyVector()); |
229 | 236 |
230 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(VerifyUpdateEntries(model)); | 237 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(VerifyUpdateEntries(model)); |
231 EXPECT_CALL(caller, SaveCallback(true)); | 238 EXPECT_CALL(caller, SaveCallback(true)); |
232 db_->UpdateEntries( | 239 db_->UpdateEntries( |
233 entries.Pass(), | 240 entries.Pass(), keys_to_remove.Pass(), |
234 entries_to_remove.Pass(), | |
235 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); | 241 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); |
236 | 242 |
237 base::RunLoop().RunUntilIdle(); | 243 base::RunLoop().RunUntilIdle(); |
238 } | 244 } |
239 | 245 |
240 TEST_F(DomDistillerDatabaseTest, TestDBSaveFailure) { | 246 TEST_F(ProtoDatabaseImplTest, TestDBSaveFailure) { |
241 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 247 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
242 | 248 |
243 MockDB* mock_db = new MockDB(); | 249 MockDB* mock_db = new MockDB(); |
244 MockDatabaseCaller caller; | 250 MockDatabaseCaller caller; |
245 scoped_ptr<EntryVector> entries(new EntryVector()); | 251 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( |
246 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 252 new ProtoDatabase<TestProto>::KeyEntryVector()); |
| 253 scoped_ptr<KeyVector> keys_to_remove(new KeyVector()); |
247 | 254 |
248 EXPECT_CALL(*mock_db, Init(_)); | 255 EXPECT_CALL(*mock_db, Init(_)); |
249 EXPECT_CALL(caller, InitCallback(_)); | 256 EXPECT_CALL(caller, InitCallback(_)); |
250 db_->InitWithDatabase( | 257 db_->InitWithDatabase( |
251 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 258 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
252 base::FilePath(path), | 259 base::FilePath(path), |
253 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 260 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
254 | 261 |
255 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false)); | 262 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false)); |
256 EXPECT_CALL(caller, SaveCallback(false)); | 263 EXPECT_CALL(caller, SaveCallback(false)); |
257 db_->UpdateEntries( | 264 db_->UpdateEntries( |
258 entries.Pass(), | 265 entries.Pass(), keys_to_remove.Pass(), |
259 entries_to_remove.Pass(), | |
260 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); | 266 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); |
261 | 267 |
262 base::RunLoop().RunUntilIdle(); | 268 base::RunLoop().RunUntilIdle(); |
263 } | 269 } |
264 | 270 |
265 ACTION_P(VerifyRemoveEntries, expected) { | 271 // Test that ProtoDatabaseImpl calls Save on the underlying database with the |
266 const EntryVector& actual = arg1; | |
267 ExpectEntryPointersEquals(expected, actual); | |
268 return true; | |
269 } | |
270 | |
271 // Test that DomDistillerDatabase calls Save on the underlying database with the | |
272 // correct entries to delete and that the caller's SaveCallback is called with | 272 // correct entries to delete and that the caller's SaveCallback is called with |
273 // the correct success value. | 273 // the correct success value. |
274 TEST_F(DomDistillerDatabaseTest, TestDBRemoveSuccess) { | 274 TEST_F(ProtoDatabaseImplTest, TestDBRemoveSuccess) { |
275 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 275 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
276 | 276 |
277 MockDB* mock_db = new MockDB(); | 277 MockDB* mock_db = new MockDB(); |
278 MockDatabaseCaller caller; | 278 MockDatabaseCaller caller; |
279 EntryMap model = GetSmallModel(); | 279 EntryMap model = GetSmallModel(); |
280 | 280 |
281 EXPECT_CALL(*mock_db, Init(_)); | 281 EXPECT_CALL(*mock_db, Init(_)); |
282 EXPECT_CALL(caller, InitCallback(_)); | 282 EXPECT_CALL(caller, InitCallback(_)); |
283 db_->InitWithDatabase( | 283 db_->InitWithDatabase( |
284 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 284 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
285 base::FilePath(path), | 285 base::FilePath(path), |
286 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 286 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
287 | 287 |
288 scoped_ptr<EntryVector> entries(new EntryVector()); | 288 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( |
289 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 289 new ProtoDatabase<TestProto>::KeyEntryVector()); |
| 290 scoped_ptr<KeyVector> keys_to_remove(new KeyVector()); |
290 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { | 291 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { |
291 entries_to_remove->push_back(it->second); | 292 keys_to_remove->push_back(it->second.id()); |
292 } | 293 } |
293 | 294 |
294 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(VerifyRemoveEntries(model)); | 295 KeyVector keys_copy(*keys_to_remove.get()); |
| 296 EXPECT_CALL(*mock_db, Save(_, keys_copy)).WillOnce(Return(true)); |
295 EXPECT_CALL(caller, SaveCallback(true)); | 297 EXPECT_CALL(caller, SaveCallback(true)); |
296 db_->UpdateEntries( | 298 db_->UpdateEntries( |
297 entries.Pass(), | 299 entries.Pass(), keys_to_remove.Pass(), |
298 entries_to_remove.Pass(), | |
299 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); | 300 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); |
300 | 301 |
301 base::RunLoop().RunUntilIdle(); | 302 base::RunLoop().RunUntilIdle(); |
302 } | 303 } |
303 | 304 |
304 TEST_F(DomDistillerDatabaseTest, TestDBRemoveFailure) { | 305 TEST_F(ProtoDatabaseImplTest, TestDBRemoveFailure) { |
305 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); | 306 base::FilePath path(FILE_PATH_LITERAL("/fake/path")); |
306 | 307 |
307 MockDB* mock_db = new MockDB(); | 308 MockDB* mock_db = new MockDB(); |
308 MockDatabaseCaller caller; | 309 MockDatabaseCaller caller; |
309 scoped_ptr<EntryVector> entries(new EntryVector()); | 310 scoped_ptr<ProtoDatabase<TestProto>::KeyEntryVector> entries( |
310 scoped_ptr<EntryVector> entries_to_remove(new EntryVector()); | 311 new ProtoDatabase<TestProto>::KeyEntryVector()); |
| 312 scoped_ptr<KeyVector> keys_to_remove(new KeyVector()); |
311 | 313 |
312 EXPECT_CALL(*mock_db, Init(_)); | 314 EXPECT_CALL(*mock_db, Init(_)); |
313 EXPECT_CALL(caller, InitCallback(_)); | 315 EXPECT_CALL(caller, InitCallback(_)); |
314 db_->InitWithDatabase( | 316 db_->InitWithDatabase( |
315 scoped_ptr<DomDistillerDatabase::Database>(mock_db), | 317 scoped_ptr<ProtoDatabaseImpl<TestProto>::Database>(mock_db), |
316 base::FilePath(path), | 318 base::FilePath(path), |
317 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | 319 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); |
318 | 320 |
319 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false)); | 321 EXPECT_CALL(*mock_db, Save(_, _)).WillOnce(Return(false)); |
320 EXPECT_CALL(caller, SaveCallback(false)); | 322 EXPECT_CALL(caller, SaveCallback(false)); |
321 db_->UpdateEntries( | 323 db_->UpdateEntries( |
322 entries.Pass(), | 324 entries.Pass(), keys_to_remove.Pass(), |
323 entries_to_remove.Pass(), | |
324 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); | 325 base::Bind(&MockDatabaseCaller::SaveCallback, base::Unretained(&caller))); |
325 | 326 |
326 base::RunLoop().RunUntilIdle(); | 327 base::RunLoop().RunUntilIdle(); |
327 } | 328 } |
328 | 329 |
329 | |
330 // This tests that normal usage of the real database does not cause any | 330 // This tests that normal usage of the real database does not cause any |
331 // threading violations. | 331 // threading violations. |
332 TEST(DomDistillerDatabaseThreadingTest, TestDBDestruction) { | 332 TEST(ProtoDatabaseImplThreadingTest, TestDBDestruction) { |
333 base::MessageLoop main_loop; | 333 base::MessageLoop main_loop; |
334 | 334 |
335 ScopedTempDir temp_dir; | 335 ScopedTempDir temp_dir; |
336 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 336 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
337 | 337 |
338 base::Thread db_thread("dbthread"); | 338 base::Thread db_thread("dbthread"); |
339 ASSERT_TRUE(db_thread.Start()); | 339 ASSERT_TRUE(db_thread.Start()); |
340 | 340 |
341 scoped_ptr<DomDistillerDatabase> db( | 341 scoped_ptr<ProtoDatabaseImpl<TestProto>> db( |
342 new DomDistillerDatabase(db_thread.message_loop_proxy())); | 342 new ProtoDatabaseImpl<TestProto>(db_thread.message_loop_proxy())); |
343 | 343 |
344 MockDatabaseCaller caller; | 344 MockDatabaseCaller caller; |
345 EXPECT_CALL(caller, InitCallback(_)); | 345 EXPECT_CALL(caller, InitCallback(_)); |
346 db->Init( | 346 db->Init(temp_dir.path(), base::Bind(&MockDatabaseCaller::InitCallback, |
347 temp_dir.path(), | 347 base::Unretained(&caller))); |
348 base::Bind(&MockDatabaseCaller::InitCallback, base::Unretained(&caller))); | |
349 | 348 |
350 db.reset(); | 349 db.reset(); |
351 | 350 |
352 base::RunLoop run_loop; | 351 base::RunLoop run_loop; |
353 db_thread.message_loop_proxy()->PostTaskAndReply( | 352 db_thread.message_loop_proxy()->PostTaskAndReply( |
354 FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure()); | 353 FROM_HERE, base::Bind(base::DoNothing), run_loop.QuitClosure()); |
355 run_loop.Run(); | 354 run_loop.Run(); |
356 } | 355 } |
357 | 356 |
358 // Test that the LevelDB properly saves entries and that load returns the saved | 357 // Test that the LevelDB properly saves entries and that load returns the saved |
359 // entries. If |close_after_save| is true, the database will be closed after | 358 // entries. If |close_after_save| is true, the database will be closed after |
360 // saving and then re-opened to ensure that the data is properly persisted. | 359 // saving and then re-opened to ensure that the data is properly persisted. |
361 void TestLevelDBSaveAndLoad(bool close_after_save) { | 360 void TestLevelDBSaveAndLoad(bool close_after_save) { |
362 ScopedTempDir temp_dir; | 361 ScopedTempDir temp_dir; |
363 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 362 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
364 | 363 |
365 EntryMap model = GetSmallModel(); | 364 EntryMap model = GetSmallModel(); |
366 EntryVector save_entries; | 365 |
367 EntryVector load_entries; | 366 KeyValueVector save_entries; |
368 EntryVector remove_entries; | 367 std::vector<std::string> load_entries; |
| 368 KeyVector remove_keys; |
369 | 369 |
370 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { | 370 for (EntryMap::iterator it = model.begin(); it != model.end(); ++it) { |
371 save_entries.push_back(it->second); | 371 save_entries.push_back( |
| 372 std::make_pair(it->second.id(), it->second.SerializeAsString())); |
372 } | 373 } |
373 | 374 |
374 scoped_ptr<DomDistillerDatabase::LevelDB> db( | 375 scoped_ptr<ProtoDatabaseImpl<TestProto>::LevelDB> db( |
375 new DomDistillerDatabase::LevelDB()); | 376 new ProtoDatabaseImpl<TestProto>::LevelDB()); |
376 EXPECT_TRUE(db->Init(temp_dir.path())); | 377 EXPECT_TRUE(db->Init(temp_dir.path())); |
377 EXPECT_TRUE(db->Save(save_entries, remove_entries)); | 378 EXPECT_TRUE(db->Save(save_entries, remove_keys)); |
378 | 379 |
379 if (close_after_save) { | 380 if (close_after_save) { |
380 db.reset(new DomDistillerDatabase::LevelDB()); | 381 db.reset(new ProtoDatabaseImpl<TestProto>::LevelDB()); |
381 EXPECT_TRUE(db->Init(temp_dir.path())); | 382 EXPECT_TRUE(db->Init(temp_dir.path())); |
382 } | 383 } |
383 | 384 |
384 EXPECT_TRUE(db->Load(&load_entries)); | 385 EXPECT_TRUE(db->Load(&load_entries)); |
385 | 386 // Convert the strings back to TestProto. |
386 ExpectEntryPointersEquals(model, load_entries); | 387 std::vector<TestProto> loaded_protos; |
| 388 for (std::vector<std::string>::iterator it = load_entries.begin(); |
| 389 it != load_entries.end(); ++it) { |
| 390 TestProto entry; |
| 391 entry.ParseFromString(*it); |
| 392 loaded_protos.push_back(entry); |
| 393 } |
| 394 ExpectEntryPointersEquals(model, loaded_protos); |
387 } | 395 } |
388 | 396 |
389 TEST(DomDistillerDatabaseLevelDBTest, TestDBSaveAndLoad) { | 397 TEST(ProtoDatabaseImplLevelDBTest, TestDBSaveAndLoad) { |
390 TestLevelDBSaveAndLoad(false); | 398 TestLevelDBSaveAndLoad(false); |
391 } | 399 } |
392 | 400 |
393 TEST(DomDistillerDatabaseLevelDBTest, TestDBCloseAndReopen) { | 401 TEST(ProtoDatabaseImplLevelDBTest, TestDBCloseAndReopen) { |
394 TestLevelDBSaveAndLoad(true); | 402 TestLevelDBSaveAndLoad(true); |
395 } | 403 } |
396 | 404 |
397 } // namespace dom_distiller | 405 } // namespace leveldb_proto |
OLD | NEW |