Chromium Code Reviews| 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|. Returns whether the pair could | |
| 39 // be written to the database successfully. | |
| 40 bool WriteLevelDBKeyValuePair(NotificationDatabase* database, | |
| 41 const std::string& key, | |
| 42 const std::string& value) { | |
| 43 leveldb::Status status = database->db()->Put(leveldb::WriteOptions(), | |
| 44 key, value); | |
| 45 if (status.ok()) | |
|
Bernhard Bauer
2015/03/11 22:02:38
Change the return type to void and ASSERT? You can
Peter Beverloo
2015/03/11 22:33:33
ASSERT_NO_FATAL_FAILURE! Awesome! Changed :-).
| |
| 46 return true; | |
| 47 | |
| 48 LOG(ERROR) << "Unable to write to the database: " << status.ToString(); | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 // Increments the next available notification id. |current_notification_id| | |
| 53 // must be the most recently used notification id. Returns whether the new | |
| 54 // value was written successfully. | |
| 55 // | |
| 56 // TODO(peter): Stop doing this manually when writing notification data will | |
| 57 // do this for us, except for tests verifying corruption behavior. | |
| 58 bool IncrementNextNotificationId(NotificationDatabase* database, | |
| 59 int64_t current_notification_id) { | |
| 60 leveldb::WriteBatch batch; | |
| 61 database->IncrementNextNotificationId(&batch, current_notification_id); | |
| 62 | |
| 63 leveldb::Status status = database->db()->Write(leveldb::WriteOptions(), | |
| 64 &batch); | |
| 65 if (status.ok()) | |
| 66 return true; | |
| 67 | |
| 68 LOG(ERROR) << "Unable to increment the next notification id: " | |
| 69 << status.ToString(); | |
| 70 return false; | |
| 71 } | |
| 34 }; | 72 }; |
| 35 | 73 |
| 36 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { | 74 TEST_F(NotificationDatabaseTest, OpenCloseMemory) { |
| 37 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); | 75 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); |
| 38 | 76 |
| 39 // Should return false because the database does not exist in memory. | 77 // Should return false because the database does not exist in memory. |
| 40 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 78 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
| 41 database->Open(false /* create_if_missing */)); | 79 database->Open(false /* create_if_missing */)); |
| 42 | 80 |
| 43 // Should return true, indicating that the database could be created. | 81 // 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()); | 132 ASSERT_EQ(NotificationDatabase::STATUS_OK, database->Destroy()); |
| 95 EXPECT_FALSE(IsDatabaseOpen(database.get())); | 133 EXPECT_FALSE(IsDatabaseOpen(database.get())); |
| 96 | 134 |
| 97 // Try to re-open the database (but not re-create it). This should fail as | 135 // 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. | 136 // the files associated with the database should have been blown away. |
| 99 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); | 137 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); |
| 100 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, | 138 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_NOT_FOUND, |
| 101 database->Open(false /* create_if_missing */)); | 139 database->Open(false /* create_if_missing */)); |
| 102 } | 140 } |
| 103 | 141 |
| 142 TEST_F(NotificationDatabaseTest, GetNextNotificationIdIncrements) { | |
| 143 base::ScopedTempDir database_dir; | |
| 144 ASSERT_TRUE(database_dir.CreateUniqueTempDir()); | |
| 145 | |
| 146 scoped_ptr<NotificationDatabase> database( | |
| 147 CreateDatabaseOnFileSystem(database_dir.path())); | |
| 148 | |
| 149 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 150 database->Open(true /* create_if_missing */)); | |
| 151 | |
| 152 int64_t notification_id = 0; | |
| 153 | |
| 154 // Verify that getting two ids on the same database instance results in | |
| 155 // incrementing values. Notification ids will start at 1. | |
| 156 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 157 database->GetNextNotificationId(¬ification_id)); | |
| 158 EXPECT_EQ(1, notification_id); | |
| 159 | |
| 160 EXPECT_TRUE(IncrementNextNotificationId(database.get(), notification_id)); | |
| 161 | |
| 162 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 163 database->GetNextNotificationId(¬ification_id)); | |
| 164 EXPECT_EQ(2, notification_id); | |
| 165 | |
| 166 EXPECT_TRUE(IncrementNextNotificationId(database.get(), notification_id)); | |
| 167 | |
| 168 database.reset(CreateDatabaseOnFileSystem(database_dir.path())); | |
| 169 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 170 database->Open(false /* create_if_missing */)); | |
| 171 | |
| 172 // Verify that the next notification id was stored in the database, and | |
| 173 // continues where we expect it to be, even after closing and opening it. | |
| 174 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 175 database->GetNextNotificationId(¬ification_id)); | |
| 176 EXPECT_EQ(3, notification_id); | |
| 177 } | |
| 178 | |
| 179 TEST_F(NotificationDatabaseTest, GetNextNotificationIdCorruption) { | |
| 180 scoped_ptr<NotificationDatabase> database(CreateDatabaseInMemory()); | |
| 181 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 182 database->Open(true /* create_if_missing */)); | |
| 183 | |
| 184 int64_t notification_id = 0; | |
| 185 | |
| 186 ASSERT_EQ(NotificationDatabase::STATUS_OK, | |
| 187 database->GetNextNotificationId(¬ification_id)); | |
| 188 EXPECT_EQ(1, notification_id); | |
| 189 | |
| 190 // Deliberately write an invalid value as the next notification id to the | |
|
Bernhard Bauer
2015/03/11 22:02:38
Nit: "ID" in uppercase.
Peter Beverloo
2015/03/11 22:33:33
I've got it in lowercase everywhere in Notificatio
| |
| 191 // database, which should cause GetNextNotificationId to realize that | |
| 192 // something is wrong with the data it's reading. | |
| 193 ASSERT_TRUE(WriteLevelDBKeyValuePair(database.get(), | |
| 194 "NEXT_NOTIFICATION_ID", | |
| 195 "-42")); | |
| 196 | |
| 197 EXPECT_EQ(NotificationDatabase::STATUS_ERROR_CORRUPTED, | |
| 198 database->GetNextNotificationId(¬ification_id)); | |
| 199 } | |
| 200 | |
| 104 } // namespace content | 201 } // namespace content |
| OLD | NEW |