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 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 } |
34 }; | 65 }; |
35 | 66 |
36 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { | 67 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { |
37 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); | 68 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); |
38 | 69 |
39 // Should return false because the database does not exist in memory. | 70 // Should return false because the database does not exist in memory. |
40 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 71 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
41 database->Open(false /* create_if_missing */)); | 72 database->Open(false /* create_if_missing */)); |
42 | 73 |
43 // Should return true, indicating that the database could be created. | 74 // 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()); | 125 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy()); |
95 EXPECT_FALSE(IsDatabaseOpen(database.get())); | 126 EXPECT_FALSE(IsDatabaseOpen(database.get())); |
96 | 127 |
97 // Try to re-open the database (but not re-create it). This should fail as | 128 // 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. | 129 // the files associated with the database should have been blown away. |
99 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); | 130 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); |
100 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 131 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
101 database->Open(false /* create_if_missing */)); | 132 database->Open(false /* create_if_missing */)); |
102 } | 133 } |
103 | 134 |
| 135 TEST_F(NotificationDatabaseTest, GetNextNotificationIdIncrements) { |
| 136 base::ScopedTempDir database_dir; |
| 137 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); |
| 138 |
| 139 scoped_ptr<NotificationDatabase> database( |
| 140 CreateDatabaseOnFileSystem(database_dir.path())); |
| 141 |
| 142 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 143 database->Open(true /* create_if_missing */)); |
| 144 |
| 145 int64_t notification_id = 0; |
| 146 |
| 147 // Verify that getting two ids on the same database instance results in |
| 148 // incrementing values. Notification ids will start at 1. |
| 149 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 150 database->GetNextNotificationId(¬ification_id)); |
| 151 EXPECT_EQ(1, notification_id); |
| 152 |
| 153 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get())); |
| 154 |
| 155 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 156 database->GetNextNotificationId(¬ification_id)); |
| 157 EXPECT_EQ(2, notification_id); |
| 158 |
| 159 ASSERT_NO_FATAL_FAILURE(IncrementNextNotificationId(database.get())); |
| 160 |
| 161 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); |
| 162 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 163 database->Open(false /* create_if_missing */)); |
| 164 |
| 165 // 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. |
| 167 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 168 database->GetNextNotificationId(¬ification_id)); |
| 169 EXPECT_EQ(3, notification_id); |
| 170 } |
| 171 |
| 172 TEST_F(NotificationDatabaseTest, GetNextNotificationIdCorruption) { |
| 173 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); |
| 174 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 175 database->Open(true /* create_if_missing */)); |
| 176 |
| 177 int64_t notification_id = 0; |
| 178 |
| 179 ASSERT_EQ(NotificationDatabase::STATUS_OK, |
| 180 database->GetNextNotificationId(¬ification_id)); |
| 181 EXPECT_EQ(1, notification_id); |
| 182 |
| 183 // Deliberately write an invalid value as the next notification id to the |
| 184 // database, which should cause GetNextNotificationId to realize that |
| 185 // something is wrong with the data it's reading. |
| 186 ASSERT_NO_FATAL_FAILURE(WriteLevelDBKeyValuePair(database.get(), |
| 187 "NEXT_NOTIFICATION_ID", |
| 188 "-42")); |
| 189 |
| 190 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED, |
| 191 database->GetNextNotificationId(¬ification_id)); |
| 192 } |
| 193 |
104 } // namespace content | 194 } // namespace content |
OLD | NEW |