OLD | NEW |
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 "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 10 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
9 | 11 |
10 namespace content { | 12 namespace content { |
11 | 13 |
12 class NotificationDatabaseTest : public ::testing::Test { | 14 class NotificationDatabaseTest : public ::testing::Test { |
13 protected: | 15 protected: |
14 // Creates a new NotificationDatabase instance in memory. | 16 // Creates a new NotificationDatabase instance in memory. |
15 NotificationDatabase* CreateDatabaseInMemory() { | 17 NotificationDatabase* CreateDatabaseInMemory() { |
16 return new NotificationDatabase(base::FilePath()); | 18 return new NotificationDatabase(base::FilePath()); |
17 } | 19 } |
18 | 20 |
19 // Creates a new NotificationDatabase instance in |path|. | 21 // Creates a new NotificationDatabase instance in |path|. |
20 NotificationDatabase* CreateDatabaseOnFileSystem( | 22 NotificationDatabase* CreateDatabaseOnFileSystem( |
21 const base::FilePath& path) { | 23 const base::FilePath& path) { |
22 return new NotificationDatabase(path); | 24 return new NotificationDatabase(path); |
23 } | 25 } |
24 | 26 |
25 // Returns if |database| has been opened. | 27 // Returns if |database| has been opened. |
26 bool IsDatabaseOpen(NotificationDatabase* database) { | 28 bool IsDatabaseOpen(NotificationDatabase* database) { |
27 return database->IsOpen(); | 29 return database->IsOpen(); |
28 } | 30 } |
29 | 31 |
30 // Returns if |database| is an in-memory only database. | 32 // Returns if |database| is an in-memory only database. |
31 bool IsInMemoryDatabase(NotificationDatabase* database) { | 33 bool IsInMemoryDatabase(NotificationDatabase* database) { |
32 return database->IsInMemoryDatabase(); | 34 return database->IsInMemoryDatabase(); |
33 } | 35 } |
| 36 |
| 37 // Writes a LevelDB key-value pair directly to the LevelDB backing the |
| 38 // notification database in |database|. |
| 39 void WriteLevelDBKeyValuePair(NotificationDatabase* database, |
| 40 const std::string& key, |
| 41 const std::string& value) { |
| 42 leveldb::Status status = |
| 43 database->GetDBForTesting()->Put(leveldb::WriteOptions(), key, value); |
| 44 ASSERT_TRUE(status.ok()); |
| 45 } |
| 46 |
| 47 // Increments the next available notification id. For testing, we require |
| 48 // the |current_notification_id| to be known in order to verify that the |
| 49 // counts don't accidentially go off. Normally this is managed by the |
| 50 // NotificationDatabase when writing notification data. |
| 51 // |
| 52 // TODO(peter): Stop doing this manually when writing notification data will |
| 53 // do this for us, except for tests verifying corruption behavior. |
| 54 void IncrementNextNotificationId(NotificationDatabase* database, |
| 55 int64_t current_notification_id) { |
| 56 leveldb::WriteBatch batch; |
| 57 database->IncrementNextNotificationId(&batch); |
| 58 |
| 59 leveldb::Status status = |
| 60 database->GetDBForTesting()->Write(leveldb::WriteOptions(), &batch); |
| 61 ASSERT_TRUE(status.ok()); |
| 62 |
| 63 int64_t next_notification_id; |
| 64 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 65 database->GetNextNotificationId(&next_notification_id)); |
| 66 |
| 67 EXPECT_EQ(current_notification_id + 1, next_notification_id); |
| 68 } |
34 }; | 69 }; |
35 | 70 |
36 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { | 71 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { |
37 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); | 72 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); |
38 | 73 |
39 // Should return false because the database does not exist in memory. | 74 // Should return false because the database does not exist in memory. |
40 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 75 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
41 database->Open(false /* create_if_missing */)); | 76 database->Open(false /* create_if_missing */)); |
42 | 77 |
43 // Should return true, indicating that the database could be created. | 78 // Should return true, indicating that the database could be created. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy()); | 129 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy()); |
95 EXPECT_FALSE(IsDatabaseOpen(database.get())); | 130 EXPECT_FALSE(IsDatabaseOpen(database.get())); |
96 | 131 |
97 // Try to re-open the database (but not re-create it). This should fail as | 132 // Try to re-open the database (but not re-create it). This should fail as |
98 // the files associated with the database should have been blown away. | 133 // the files associated with the database should have been blown away. |
99 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); | 134 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); |
100 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 135 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
101 database->Open(false /* create_if_missing */)); | 136 database->Open(false /* create_if_missing */)); |
102 } | 137 } |
103 | 138 |
| 139 TEST_F(NotificationDatabaseTest, GetNextNotificationIdIncrements) { |
| 140 base::ScopedTempDir database_dir; |
| 141 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); |
| 142 |
| 143 scoped_ptr<NotificationDatabase> database( |
| 144 CreateDatabaseOnFileSystem(database_dir.path())); |
| 145 |
| 146 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 147 database->Open(true /* create_if_missing */)); |
| 148 |
| 149 int64_t notification_id = 0; |
| 150 |
| 151 // Verify that getting two ids on the same database instance results in |
| 152 // incrementing values. Notification ids will start at 1. |
| 153 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 154 database->GetNextNotificationId(¬ification_id)); |
| 155 EXPECT_EQ(1, notification_id); |
| 156 |
| 157 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get(), |
| 158 notification_id)); |
| 159 |
| 160 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 161 database->GetNextNotificationId(¬ification_id)); |
| 162 EXPECT_EQ(2, notification_id); |
| 163 |
| 164 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get(), |
| 165 notification_id)); |
| 166 |
| 167 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); |
| 168 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 169 database->Open(false /* create_if_missing */)); |
| 170 |
| 171 // Verify that the next notification id was stored in the database, and |
| 172 // continues where we expect it to be, even after closing and opening it. |
| 173 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 174 database->GetNextNotificationId(¬ification_id)); |
| 175 EXPECT_EQ(3, notification_id); |
| 176 } |
| 177 |
| 178 TEST_F(NotificationDatabaseTest, GetNextNotificationIdCorruption) { |
| 179 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); |
| 180 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 181 database->Open(true /* create_if_missing */)); |
| 182 |
| 183 int64_t notification_id = 0; |
| 184 |
| 185 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 186 database->GetNextNotificationId(¬ification_id)); |
| 187 EXPECT_EQ(1, notification_id); |
| 188 |
| 189 // Deliberately write an invalid value as the next notification id to the |
| 190 // database, which should cause GetNextNotificationId to realize that |
| 191 // something is wrong with the data it's reading. |
| 192 ASSERT_NO_FATAL_FAILURE(WriteLevelDBKeyValuePair(database.get(), |
| 193 "NEXT_NOTIFICATION_ID", |
| 194 "-42")); |
| 195 |
| 196 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED, |
| 197 database->GetNextNotificationId(¬ification_id)); |
| 198 } |
| 199 |
104 } // namespace content | 200 } // namespace content |
OLD | NEW |