Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: content/browser/notifications/notification_database_unittest.cc

Issue 999933002: Store the actual notification data in the notification database. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@n-db-GetNextNotificationId
Patch Set: comments Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/notifications/notification_database.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/browser/notifications/notification_database.h" 5 #include "content/browser/notifications/notification_database.h"
6 6
7 #include "base/files/scoped_temp_dir.h" 7 #include "base/files/scoped_temp_dir.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/notifications/notification_database_data.h"
11 #include "content/public/common/platform_notification_data.h"
8 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/leveldatabase/src/include/leveldb/db.h" 13 #include "third_party/leveldatabase/src/include/leveldb/db.h"
10 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 14 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
15 #include "url/gurl.h"
11 16
12 namespace content { 17 namespace content {
13 18
14 class NotificationDatabaseTest : public ::testing::Test { 19 class NotificationDatabaseTest : public ::testing::Test {
15 protected: 20 protected:
16 // Creates a new NotificationDatabase instance in memory. 21 // Creates a new NotificationDatabase instance in memory.
17 NotificationDatabase* CreateDatabaseInMemory() { 22 NotificationDatabase* CreateDatabaseInMemory() {
18 return new NotificationDatabase(base::FilePath()); 23 return new NotificationDatabase(base::FilePath());
19 } 24 }
20 25
(...skipping 15 matching lines...) Expand all
36 41
37 // Writes a LevelDB key-value pair directly to the LevelDB backing the 42 // Writes a LevelDB key-value pair directly to the LevelDB backing the
38 // notification database in |database|. 43 // notification database in |database|.
39 void WriteLevelDBKeyValuePair(NotificationDatabase* database, 44 void WriteLevelDBKeyValuePair(NotificationDatabase* database,
40 const std::string& key, 45 const std::string& key,
41 const std::string& value) { 46 const std::string& value) {
42 leveldb::Status status = 47 leveldb::Status status =
43 database->GetDBForTesting()->Put(leveldb::WriteOptions(), key, value); 48 database->GetDBForTesting()->Put(leveldb::WriteOptions(), key, value);
44 ASSERT_TRUE(status.ok()); 49 ASSERT_TRUE(status.ok());
45 } 50 }
46
47 // Increments the next notification id value in the database. Normally this
48 // is managed by the NotificationDatabase when writing notification data.
49 //
50 // TODO(peter): Stop doing this manually when writing notification data will
51 // do this for us, except for tests verifying corruption behavior.
52 void IncrementNextNotificationId(NotificationDatabase* database) {
53 int64_t next_notification_id;
54 ASSERT_EQ(NotificationDatabase::STATUS_OK,
55 database->GetNextNotificationId(&next_notification_id));
56
57 leveldb::WriteBatch batch;
58 database->WriteNextNotificationId(&batch, next_notification_id + 1);
59
60 leveldb::Status status =
61 database->GetDBForTesting()->Write(leveldb::WriteOptions(), &batch);
62
63 ASSERT_TRUE(status.ok());
64 }
65 }; 51 };
66 52
67 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { 53 TEST_F(NotificationDatabaseTest, OpenCloseMemory) {
68 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); 54 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
69 55
70 // Should return false because the database does not exist in memory. 56 // Should return false because the database does not exist in memory.
71 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, 57 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND,
72 database->Open(false /* create_if_missing */)); 58 database->Open(false /* create_if_missing */));
73 59
74 // Should return true, indicating that the database could be created. 60 // Should return true, indicating that the database could be created.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy()); 111 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy());
126 EXPECT_FALSE(IsDatabaseOpen(database.get())); 112 EXPECT_FALSE(IsDatabaseOpen(database.get()));
127 113
128 // Try to re-open the database (but not re-create it). This should fail as 114 // Try to re-open the database (but not re-create it). This should fail as
129 // the files associated with the database should have been blown away. 115 // the files associated with the database should have been blown away.
130 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); 116 database.reset(CreateDatabaseOnFileSystem(database_dir.path()));
131 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, 117 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND,
132 database->Open(false /* create_if_missing */)); 118 database->Open(false /* create_if_missing */));
133 } 119 }
134 120
135 TEST_F(NotificationDatabaseTest, GetNextNotificationIdIncrements) { 121 TEST_F(NotificationDatabaseTest, NotificationIdIncrements) {
136 base::ScopedTempDir database_dir; 122 base::ScopedTempDir database_dir;
137 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); 123 ASSERT_TRUE(database_dir.CreateUniqueTempDir());
138 124
139 scoped_ptr<NotificationDatabase> database( 125 scoped_ptr<NotificationDatabase> database(
140 CreateDatabaseOnFileSystem(database_dir.path())); 126 CreateDatabaseOnFileSystem(database_dir.path()));
141 127
142 ASSERT_EQ(NotificationDatabase::STATUS_OK, 128 ASSERT_EQ(NotificationDatabase::STATUS_OK,
143 database->Open(true /* create_if_missing */)); 129 database->Open(true /* create_if_missing */));
144 130
131 GURL origin("https://example.com");
132
133 NotificationDatabaseData database_data;
145 int64_t notification_id = 0; 134 int64_t notification_id = 0;
146 135
147 // Verify that getting two ids on the same database instance results in 136 // Verify that getting two ids on the same database instance results in
148 // incrementing values. Notification ids will start at 1. 137 // incrementing values. Notification ids will start at 1.
149 ASSERT_EQ(NotificationDatabase::STATUS_OK, 138 ASSERT_EQ(NotificationDatabase::STATUS_OK,
150 database->GetNextNotificationId(&notification_id)); 139 database->WriteNotificationData(origin,
151 EXPECT_EQ(1, notification_id); 140 database_data,
152 141 &notification_id));
153 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get())); 142 EXPECT_EQ(notification_id, 1);
154 143
155 ASSERT_EQ(NotificationDatabase::STATUS_OK, 144 ASSERT_EQ(NotificationDatabase::STATUS_OK,
156 database->GetNextNotificationId(&notification_id)); 145 database->WriteNotificationData(origin,
157 EXPECT_EQ(2, notification_id); 146 database_data,
158 147 &notification_id));
159 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get())); 148 EXPECT_EQ(notification_id, 2);
160 149
161 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); 150 database.reset(CreateDatabaseOnFileSystem(database_dir.path()));
162 ASSERT_EQ(NotificationDatabase::STATUS_OK, 151 ASSERT_EQ(NotificationDatabase::STATUS_OK,
163 database->Open(false /* create_if_missing */)); 152 database->Open(false /* create_if_missing */));
164 153
165 // Verify that the next notification id was stored in the database, and 154 // Verify that the next notification id was stored in the database, and
166 // continues where we expect it to be, even after closing and opening it. 155 // continues where we expect it to be, even after closing and opening it.
167 ASSERT_EQ(NotificationDatabase::STATUS_OK, 156 ASSERT_EQ(NotificationDatabase::STATUS_OK,
168 database->GetNextNotificationId(&notification_id)); 157 database->WriteNotificationData(origin,
169 EXPECT_EQ(3, notification_id); 158 database_data,
170 } 159 &notification_id));
171 160 EXPECT_EQ(notification_id, 3);
172 TEST_F(NotificationDatabaseTest, GetNextNotificationIdCorruption) { 161 }
173 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); 162
174 ASSERT_EQ(NotificationDatabase::STATUS_OK, 163 TEST_F(NotificationDatabaseTest, NotificationIdCorruption) {
175 database->Open(true /* create_if_missing */)); 164 base::ScopedTempDir database_dir;
176 165 ASSERT_TRUE(database_dir.CreateUniqueTempDir());
177 int64_t notification_id = 0; 166
178 167 scoped_ptr<NotificationDatabase> database(
179 ASSERT_EQ(NotificationDatabase::STATUS_OK, 168 CreateDatabaseOnFileSystem(database_dir.path()));
180 database->GetNextNotificationId(&notification_id)); 169
181 EXPECT_EQ(1, notification_id); 170 ASSERT_EQ(NotificationDatabase::STATUS_OK,
182 171 database->Open(true /* create_if_missing */));
183 // Deliberately write an invalid value as the next notification id to the 172
184 // database, which should cause GetNextNotificationId to realize that 173 GURL origin("https://example.com");
185 // something is wrong with the data it's reading. 174
175 NotificationDatabaseData database_data;
176 int64_t notification_id = 0;
177
178 ASSERT_EQ(NotificationDatabase::STATUS_OK,
179 database->WriteNotificationData(origin,
180 database_data,
181 &notification_id));
182 EXPECT_EQ(notification_id, 1);
183
184 // Deliberately write an invalid value as the next notification id. When
185 // re-opening the database, the Open() method should realize that an invalid
186 // value is being read, and mark the database as corrupted.
186 ASSERT_NO_FATAL_FAILURE(WriteLevelDBKeyValuePair(database.get(), 187 ASSERT_NO_FATAL_FAILURE(WriteLevelDBKeyValuePair(database.get(),
187 "NEXT_NOTIFICATION_ID", 188 "NEXT_NOTIFICATION_ID",
188 "-42")); 189 "-42"));
189 190
191 database.reset(CreateDatabaseOnFileSystem(database_dir.path()));
190 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED, 192 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED,
191 database->GetNextNotificationId(&notification_id)); 193 database->Open(false /* create_if_missing */));
194 }
195
196 TEST_F(NotificationDatabaseTest, ReadInvalidNotificationData) {
197 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
198 ASSERT_EQ(NotificationDatabase::STATUS_OK,
199 database->Open(true /* create_if_missing */));
200
201 NotificationDatabaseData database_data;
202
203 // Reading the notification data for a notification that does not exist should
204 // return the ERROR_NOT_FOUND status code.
205 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND,
206 database->ReadNotificationData(9001,
207 GURL("https://chrome.com"),
208 &database_data));
209 }
210
211 TEST_F(NotificationDatabaseTest, ReadNotificationDataDifferentOrigin) {
212 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
213 ASSERT_EQ(NotificationDatabase::STATUS_OK,
214 database->Open(true /* create_if_missing */));
215
216 int64_t notification_id = 0;
217 GURL origin("https://example.com");
218
219 NotificationDatabaseData database_data, read_database_data;
220 database_data.notification_data.title = base::UTF8ToUTF16("My Notification");
221
222 ASSERT_EQ(NotificationDatabase::STATUS_OK,
223 database->WriteNotificationData(origin,
224 database_data,
225 &notification_id));
226
227 // Reading the notification from the database when given a different origin
228 // should return the ERROR_NOT_FOUND status code.
229 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND,
230 database->ReadNotificationData(notification_id,
231 GURL("https://chrome.com"),
232 &read_database_data));
233
234 // However, reading the notification from the database with the same origin
235 // should return STATUS_OK and the associated notification data.
236 ASSERT_EQ(NotificationDatabase::STATUS_OK,
237 database->ReadNotificationData(notification_id,
238 origin,
239 &read_database_data));
240
241 EXPECT_EQ(database_data.notification_data.title,
242 read_database_data.notification_data.title);
243 }
244
245 TEST_F(NotificationDatabaseTest, ReadNotificationDataReflection) {
246 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
247 ASSERT_EQ(NotificationDatabase::STATUS_OK,
248 database->Open(true /* create_if_missing */));
249
250 int64_t notification_id = 0;
251
252 GURL origin("https://example.com");
253
254 PlatformNotificationData notification_data;
255 notification_data.title = base::UTF8ToUTF16("My Notification");
256 notification_data.direction =
257 PlatformNotificationData::NotificationDirectionRightToLeft;
258 notification_data.lang = "nl-NL";
259 notification_data.body = base::UTF8ToUTF16("Hello, world!");
260 notification_data.tag = "replace id";
261 notification_data.icon = GURL("https://example.com/icon.png");
262 notification_data.silent = true;
263
264 NotificationDatabaseData database_data;
265 database_data.notification_id = notification_id;
266 database_data.origin = origin;
267 database_data.service_worker_registration_id = 42;
268 database_data.notification_data = notification_data;
269
270 // Write the constructed notification to the database, and then immediately
271 // read it back from the database again as well.
272 ASSERT_EQ(NotificationDatabase::STATUS_OK,
273 database->WriteNotificationData(origin,
274 database_data,
275 &notification_id));
276
277 NotificationDatabaseData read_database_data;
278 ASSERT_EQ(NotificationDatabase::STATUS_OK,
279 database->ReadNotificationData(notification_id,
280 origin,
281 &read_database_data));
282
283 // Verify that all members retrieved from the database are exactly the same
284 // as the ones that were written to it. This tests the serialization behavior.
285
286 EXPECT_EQ(database_data.notification_id, read_database_data.notification_id);
287 EXPECT_EQ(database_data.origin, read_database_data.origin);
288 EXPECT_EQ(database_data.service_worker_registration_id,
289 read_database_data.service_worker_registration_id);
290
291 const PlatformNotificationData& read_notification_data =
292 read_database_data.notification_data;
293
294 EXPECT_EQ(notification_data.title, read_notification_data.title);
295 EXPECT_EQ(notification_data.direction, read_notification_data.direction);
296 EXPECT_EQ(notification_data.lang, read_notification_data.lang);
297 EXPECT_EQ(notification_data.body, read_notification_data.body);
298 EXPECT_EQ(notification_data.tag, read_notification_data.tag);
299 EXPECT_EQ(notification_data.icon, read_notification_data.icon);
300 EXPECT_EQ(notification_data.silent, read_notification_data.silent);
301 }
302
303 TEST_F(NotificationDatabaseTest, ReadWriteMultipleNotificationData) {
304 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
305 ASSERT_EQ(NotificationDatabase::STATUS_OK,
306 database->Open(true /* create_if_missing */));
307
308 NotificationDatabaseData database_data;
309 GURL origin("https://example.com");
310
311 // Write ten notifications to the database, each with a unique title and
312 // notification id (it is the responsibility of the user to increment this).
313 for (int i = 1; i <= 10; ++i) {
314 database_data.notification_id = i;
315 database_data.notification_data.title = base::IntToString16(i);
316
317 int64_t notification_id = 0;
318 ASSERT_EQ(NotificationDatabase::STATUS_OK,
319 database->WriteNotificationData(origin,
320 database_data,
321 &notification_id));
322 EXPECT_EQ(notification_id, i);
323 }
324
325 // Read the ten notifications from the database, and verify that the titles
326 // of each of them matches with how they were created.
327 for (int i = 1; i <= 10; ++i) {
328 ASSERT_EQ(NotificationDatabase::STATUS_OK,
329 database->ReadNotificationData(i /* notification_id */,
330 origin,
331 &database_data));
332
333 EXPECT_EQ(base::IntToString16(i), database_data.notification_data.title);
334 }
335 }
336
337 TEST_F(NotificationDatabaseTest, DeleteInvalidNotificationData) {
338 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
339 ASSERT_EQ(NotificationDatabase::STATUS_OK,
340 database->Open(true /* create_if_missing */));
341
342 // Deleting non-existing notifications is not considered to be a failure.
343 ASSERT_EQ(NotificationDatabase::STATUS_OK,
344 database->DeleteNotificationData(9001,
345 GURL("https://chrome.com")));
346 }
347
348 TEST_F(NotificationDatabaseTest, DeleteNotificationDataSameOrigin) {
349 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
350 ASSERT_EQ(NotificationDatabase::STATUS_OK,
351 database->Open(true /* create_if_missing */));
352
353 int64_t notification_id = 0;
354
355 NotificationDatabaseData database_data;
356 GURL origin("https://example.com");
357
358 ASSERT_EQ(NotificationDatabase::STATUS_OK,
359 database->WriteNotificationData(origin,
360 database_data,
361 &notification_id));
362
363 // Reading a notification after writing one should succeed.
364 EXPECT_EQ(NotificationDatabase::STATUS_OK,
365 database->ReadNotificationData(notification_id,
366 origin,
367 &database_data));
368
369 // Delete the notification which was just written to the database, and verify
370 // that reading it again will fail.
371 EXPECT_EQ(NotificationDatabase::STATUS_OK,
372 database->DeleteNotificationData(notification_id, origin));
373 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND,
374 database->ReadNotificationData(notification_id,
375 origin,
376 &database_data));
377 }
378
379 TEST_F(NotificationDatabaseTest, DeleteNotificationDataDifferentOrigin) {
380 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory());
381 ASSERT_EQ(NotificationDatabase::STATUS_OK,
382 database->Open(true /* create_if_missing */));
383
384 int64_t notification_id = 0;
385
386 NotificationDatabaseData database_data;
387 GURL origin("https://example.com");
388
389 ASSERT_EQ(NotificationDatabase::STATUS_OK,
390 database->WriteNotificationData(origin,
391 database_data,
392 &notification_id));
393
394 // Attempting to delete the notification with a different origin, but with the
395 // same |notification_id|, should not return an error (the notification could
396 // not be found, but that's not considered a failure). However, it should not
397 // remove the notification either.
398 EXPECT_EQ(NotificationDatabase::STATUS_OK,
399 database->DeleteNotificationData(notification_id,
400 GURL("https://chrome.com")));
401
402 EXPECT_EQ(NotificationDatabase::STATUS_OK,
403 database->ReadNotificationData(notification_id,
404 origin,
405 &database_data));
192 } 406 }
193 407
194 } // namespace content 408 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/notifications/notification_database.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698