| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 | 5 |
| 6 #include "content/browser/dom_storage/session_storage_database.h" | 6 #include "content/browser/dom_storage/session_storage_database.h" |
| 7 | 7 |
| 8 #include <stddef.h> |
| 9 #include <stdint.h> |
| 10 |
| 8 #include <algorithm> | 11 #include <algorithm> |
| 9 #include <map> | 12 #include <map> |
| 10 #include <string> | 13 #include <string> |
| 11 | 14 |
| 12 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 13 #include "base/files/scoped_temp_dir.h" | 16 #include "base/files/scoped_temp_dir.h" |
| 14 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/macros.h" |
| 15 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 17 #include "content/common/dom_storage/dom_storage_types.h" | 21 #include "content/common/dom_storage/dom_storage_types.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 23 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 20 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" | 24 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" |
| 21 #include "third_party/leveldatabase/src/include/leveldb/options.h" | 25 #include "third_party/leveldatabase/src/include/leveldb/options.h" |
| 22 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 23 | 27 |
| 24 namespace content { | 28 namespace content { |
| 25 | 29 |
| 26 class SessionStorageDatabaseTest : public testing::Test { | 30 class SessionStorageDatabaseTest : public testing::Test { |
| 27 public: | 31 public: |
| 28 SessionStorageDatabaseTest(); | 32 SessionStorageDatabaseTest(); |
| 29 ~SessionStorageDatabaseTest() override; | 33 ~SessionStorageDatabaseTest() override; |
| 30 void SetUp() override; | 34 void SetUp() override; |
| 31 | 35 |
| 32 protected: | 36 protected: |
| 33 typedef std::map<std::string, std::string> DataMap; | 37 typedef std::map<std::string, std::string> DataMap; |
| 34 | 38 |
| 35 // Helpers. | 39 // Helpers. |
| 36 static bool IsNamespaceKey(const std::string& key, | 40 static bool IsNamespaceKey(const std::string& key, |
| 37 std::string* namespace_id); | 41 std::string* namespace_id); |
| 38 static bool IsNamespaceOriginKey(const std::string& key, | 42 static bool IsNamespaceOriginKey(const std::string& key, |
| 39 std::string* namespace_id); | 43 std::string* namespace_id); |
| 40 static bool IsMapRefCountKey(const std::string& key, | 44 static bool IsMapRefCountKey(const std::string& key, int64_t* map_id); |
| 41 int64* map_id); | 45 static bool IsMapValueKey(const std::string& key, int64_t* map_id); |
| 42 static bool IsMapValueKey(const std::string& key, | |
| 43 int64* map_id); | |
| 44 void ResetDatabase(); | 46 void ResetDatabase(); |
| 45 void ReadData(DataMap* data) const; | 47 void ReadData(DataMap* data) const; |
| 46 void CheckDatabaseConsistency() const; | 48 void CheckDatabaseConsistency() const; |
| 47 void CheckEmptyDatabase() const; | 49 void CheckEmptyDatabase() const; |
| 48 void DumpData() const; | 50 void DumpData() const; |
| 49 void CheckAreaData(const std::string& namespace_id, | 51 void CheckAreaData(const std::string& namespace_id, |
| 50 const GURL& origin, | 52 const GURL& origin, |
| 51 const DOMStorageValuesMap& reference) const; | 53 const DOMStorageValuesMap& reference) const; |
| 52 void CompareValuesMaps(const DOMStorageValuesMap& map1, | 54 void CompareValuesMaps(const DOMStorageValuesMap& map1, |
| 53 const DOMStorageValuesMap& map2) const; | 55 const DOMStorageValuesMap& map2) const; |
| 54 void CheckNamespaceIds( | 56 void CheckNamespaceIds( |
| 55 const std::set<std::string>& expected_namespace_ids) const; | 57 const std::set<std::string>& expected_namespace_ids) const; |
| 56 void CheckOrigins( | 58 void CheckOrigins( |
| 57 const std::string& namespace_id, | 59 const std::string& namespace_id, |
| 58 const std::set<GURL>& expected_origins) const; | 60 const std::set<GURL>& expected_origins) const; |
| 59 std::string GetMapForArea(const std::string& namespace_id, | 61 std::string GetMapForArea(const std::string& namespace_id, |
| 60 const GURL& origin) const; | 62 const GURL& origin) const; |
| 61 int64 GetMapRefCount(const std::string& map_id) const; | 63 int64_t GetMapRefCount(const std::string& map_id) const; |
| 62 | 64 |
| 63 base::ScopedTempDir temp_dir_; | 65 base::ScopedTempDir temp_dir_; |
| 64 scoped_refptr<SessionStorageDatabase> db_; | 66 scoped_refptr<SessionStorageDatabase> db_; |
| 65 | 67 |
| 66 // Test data. | 68 // Test data. |
| 67 const GURL kOrigin1; | 69 const GURL kOrigin1; |
| 68 const GURL kOrigin2; | 70 const GURL kOrigin2; |
| 69 const std::string kNamespace1; | 71 const std::string kNamespace1; |
| 70 const std::string kNamespace2; | 72 const std::string kNamespace2; |
| 71 const std::string kNamespaceClone; | 73 const std::string kNamespaceClone; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 // Key is of the form "namespace-<namespaceid>-<origin>", and the value | 143 // Key is of the form "namespace-<namespaceid>-<origin>", and the value |
| 142 // is the map id. | 144 // is the map id. |
| 143 *namespace_id = key.substr( | 145 *namespace_id = key.substr( |
| 144 namespace_prefix.length(), | 146 namespace_prefix.length(), |
| 145 second_dash - namespace_prefix.length()); | 147 second_dash - namespace_prefix.length()); |
| 146 return true; | 148 return true; |
| 147 } | 149 } |
| 148 | 150 |
| 149 // static | 151 // static |
| 150 bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string& key, | 152 bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string& key, |
| 151 int64* map_id) { | 153 int64_t* map_id) { |
| 152 std::string map_prefix = "map-"; | 154 std::string map_prefix = "map-"; |
| 153 if (key.find(map_prefix) != 0) | 155 if (key.find(map_prefix) != 0) |
| 154 return false; | 156 return false; |
| 155 size_t second_dash = key.find('-', map_prefix.length()); | 157 size_t second_dash = key.find('-', map_prefix.length()); |
| 156 if (second_dash != key.length() - 1) | 158 if (second_dash != key.length() - 1) |
| 157 return false; | 159 return false; |
| 158 // Key is of the form "map-<mapid>-" and the value is the ref count. | 160 // Key is of the form "map-<mapid>-" and the value is the ref count. |
| 159 std::string map_id_str = key.substr(map_prefix.length(), | 161 std::string map_id_str = key.substr(map_prefix.length(), |
| 160 second_dash - map_prefix.length()); | 162 second_dash - map_prefix.length()); |
| 161 bool conversion_ok = base::StringToInt64(map_id_str, map_id); | 163 bool conversion_ok = base::StringToInt64(map_id_str, map_id); |
| 162 EXPECT_TRUE(conversion_ok); | 164 EXPECT_TRUE(conversion_ok); |
| 163 return true; | 165 return true; |
| 164 } | 166 } |
| 165 | 167 |
| 166 // static | 168 // static |
| 167 bool SessionStorageDatabaseTest::IsMapValueKey(const std::string& key, | 169 bool SessionStorageDatabaseTest::IsMapValueKey(const std::string& key, |
| 168 int64* map_id) { | 170 int64_t* map_id) { |
| 169 std::string map_prefix = "map-"; | 171 std::string map_prefix = "map-"; |
| 170 if (key.find(map_prefix) != 0) | 172 if (key.find(map_prefix) != 0) |
| 171 return false; | 173 return false; |
| 172 size_t second_dash = key.find('-', map_prefix.length()); | 174 size_t second_dash = key.find('-', map_prefix.length()); |
| 173 if (second_dash == std::string::npos || second_dash == key.length() - 1) | 175 if (second_dash == std::string::npos || second_dash == key.length() - 1) |
| 174 return false; | 176 return false; |
| 175 // Key is of the form "map-<mapid>-key". | 177 // Key is of the form "map-<mapid>-key". |
| 176 std::string map_id_str = key.substr(map_prefix.length(), | 178 std::string map_id_str = key.substr(map_prefix.length(), |
| 177 second_dash - map_prefix.length()); | 179 second_dash - map_prefix.length()); |
| 178 bool conversion_ok = base::StringToInt64(map_id_str, map_id); | 180 bool conversion_ok = base::StringToInt64(map_id_str, map_id); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 207 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { | 209 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { |
| 208 ASSERT_TRUE(it->first == next_map_id_key); | 210 ASSERT_TRUE(it->first == next_map_id_key); |
| 209 } | 211 } |
| 210 return; | 212 return; |
| 211 } | 213 } |
| 212 ++valid_keys; | 214 ++valid_keys; |
| 213 | 215 |
| 214 // Iterate the "namespace-" keys. | 216 // Iterate the "namespace-" keys. |
| 215 std::set<std::string> found_namespace_ids; | 217 std::set<std::string> found_namespace_ids; |
| 216 std::set<std::string> namespaces_with_areas; | 218 std::set<std::string> namespaces_with_areas; |
| 217 std::map<int64, int64> expected_map_refcounts; | 219 std::map<int64_t, int64_t> expected_map_refcounts; |
| 218 int64 max_map_id = -1; | 220 int64_t max_map_id = -1; |
| 219 | 221 |
| 220 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { | 222 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { |
| 221 std::string namespace_id; | 223 std::string namespace_id; |
| 222 if (IsNamespaceKey(it->first, &namespace_id)) { | 224 if (IsNamespaceKey(it->first, &namespace_id)) { |
| 223 found_namespace_ids.insert(namespace_id); | 225 found_namespace_ids.insert(namespace_id); |
| 224 ++valid_keys; | 226 ++valid_keys; |
| 225 } else if (IsNamespaceOriginKey( | 227 } else if (IsNamespaceOriginKey( |
| 226 it->first, &namespace_id)) { | 228 it->first, &namespace_id)) { |
| 227 // Check that the corresponding "namespace-<namespaceid>-" key exists. It | 229 // Check that the corresponding "namespace-<namespaceid>-" key exists. It |
| 228 // has been read by now, since the keys are stored in order. | 230 // has been read by now, since the keys are stored in order. |
| 229 ASSERT_TRUE(found_namespace_ids.find(namespace_id) != | 231 ASSERT_TRUE(found_namespace_ids.find(namespace_id) != |
| 230 found_namespace_ids.end()); | 232 found_namespace_ids.end()); |
| 231 namespaces_with_areas.insert(namespace_id); | 233 namespaces_with_areas.insert(namespace_id); |
| 232 int64 map_id; | 234 int64_t map_id; |
| 233 bool conversion_ok = base::StringToInt64(it->second, &map_id); | 235 bool conversion_ok = base::StringToInt64(it->second, &map_id); |
| 234 ASSERT_TRUE(conversion_ok); | 236 ASSERT_TRUE(conversion_ok); |
| 235 ASSERT_GE(map_id, 0); | 237 ASSERT_GE(map_id, 0); |
| 236 ++expected_map_refcounts[map_id]; | 238 ++expected_map_refcounts[map_id]; |
| 237 max_map_id = std::max(map_id, max_map_id); | 239 max_map_id = std::max(map_id, max_map_id); |
| 238 ++valid_keys; | 240 ++valid_keys; |
| 239 } | 241 } |
| 240 } | 242 } |
| 241 // Check that there are no leftover "namespace-namespaceid-" keys without | 243 // Check that there are no leftover "namespace-namespaceid-" keys without |
| 242 // associated areas. | 244 // associated areas. |
| 243 ASSERT_EQ(found_namespace_ids.size(), namespaces_with_areas.size()); | 245 ASSERT_EQ(found_namespace_ids.size(), namespaces_with_areas.size()); |
| 244 | 246 |
| 245 if (max_map_id != -1) { | 247 if (max_map_id != -1) { |
| 246 // The database contains maps. | 248 // The database contains maps. |
| 247 ASSERT_TRUE(data.find(next_map_id_key) != data.end()); | 249 ASSERT_TRUE(data.find(next_map_id_key) != data.end()); |
| 248 int64 next_map_id; | 250 int64_t next_map_id; |
| 249 bool conversion_ok = | 251 bool conversion_ok = |
| 250 base::StringToInt64(data[next_map_id_key], &next_map_id); | 252 base::StringToInt64(data[next_map_id_key], &next_map_id); |
| 251 ASSERT_TRUE(conversion_ok); | 253 ASSERT_TRUE(conversion_ok); |
| 252 ASSERT_GT(next_map_id, max_map_id); | 254 ASSERT_GT(next_map_id, max_map_id); |
| 253 } | 255 } |
| 254 | 256 |
| 255 // Iterate the "map-" keys. | 257 // Iterate the "map-" keys. |
| 256 std::set<int64> found_map_ids; | 258 std::set<int64_t> found_map_ids; |
| 257 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { | 259 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) { |
| 258 int64 map_id; | 260 int64_t map_id; |
| 259 if (IsMapRefCountKey(it->first, &map_id)) { | 261 if (IsMapRefCountKey(it->first, &map_id)) { |
| 260 int64 ref_count; | 262 int64_t ref_count; |
| 261 bool conversion_ok = base::StringToInt64(it->second, &ref_count); | 263 bool conversion_ok = base::StringToInt64(it->second, &ref_count); |
| 262 ASSERT_TRUE(conversion_ok); | 264 ASSERT_TRUE(conversion_ok); |
| 263 // Check that the map is not stale. | 265 // Check that the map is not stale. |
| 264 ASSERT_GT(ref_count, 0); | 266 ASSERT_GT(ref_count, 0); |
| 265 ASSERT_TRUE(expected_map_refcounts.find(map_id) != | 267 ASSERT_TRUE(expected_map_refcounts.find(map_id) != |
| 266 expected_map_refcounts.end()); | 268 expected_map_refcounts.end()); |
| 267 ASSERT_EQ(expected_map_refcounts[map_id], ref_count); | 269 ASSERT_EQ(expected_map_refcounts[map_id], ref_count); |
| 268 // Mark the map as existing. | 270 // Mark the map as existing. |
| 269 expected_map_refcounts.erase(map_id); | 271 expected_map_refcounts.erase(map_id); |
| 270 found_map_ids.insert(map_id); | 272 found_map_ids.insert(map_id); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 292 if (data.find(SessionStorageDatabase::NextMapIdKey()) != data.end()) | 294 if (data.find(SessionStorageDatabase::NextMapIdKey()) != data.end()) |
| 293 ++valid_keys; | 295 ++valid_keys; |
| 294 EXPECT_EQ(valid_keys, data.size()); | 296 EXPECT_EQ(valid_keys, data.size()); |
| 295 } | 297 } |
| 296 | 298 |
| 297 void SessionStorageDatabaseTest::DumpData() const { | 299 void SessionStorageDatabaseTest::DumpData() const { |
| 298 LOG(WARNING) << "---- Session storage contents"; | 300 LOG(WARNING) << "---- Session storage contents"; |
| 299 scoped_ptr<leveldb::Iterator> it( | 301 scoped_ptr<leveldb::Iterator> it( |
| 300 db_->db_->NewIterator(leveldb::ReadOptions())); | 302 db_->db_->NewIterator(leveldb::ReadOptions())); |
| 301 for (it->SeekToFirst(); it->Valid(); it->Next()) { | 303 for (it->SeekToFirst(); it->Valid(); it->Next()) { |
| 302 int64 dummy_map_id; | 304 int64_t dummy_map_id; |
| 303 if (IsMapValueKey(it->key().ToString(), &dummy_map_id)) { | 305 if (IsMapValueKey(it->key().ToString(), &dummy_map_id)) { |
| 304 // Convert the value back to base::string16. | 306 // Convert the value back to base::string16. |
| 305 base::string16 value; | 307 base::string16 value; |
| 306 size_t len = it->value().size() / sizeof(base::char16); | 308 size_t len = it->value().size() / sizeof(base::char16); |
| 307 value.resize(len); | 309 value.resize(len); |
| 308 value.assign( | 310 value.assign( |
| 309 reinterpret_cast<const base::char16*>(it->value().data()), len); | 311 reinterpret_cast<const base::char16*>(it->value().data()), len); |
| 310 LOG(WARNING) << it->key().ToString() << ": " << value; | 312 LOG(WARNING) << it->key().ToString() << ": " << value; |
| 311 } else { | 313 } else { |
| 312 LOG(WARNING) << it->key().ToString() << ": " << it->value().ToString(); | 314 LOG(WARNING) << it->key().ToString() << ": " << it->value().ToString(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 std::string SessionStorageDatabaseTest::GetMapForArea( | 369 std::string SessionStorageDatabaseTest::GetMapForArea( |
| 368 const std::string& namespace_id, const GURL& origin) const { | 370 const std::string& namespace_id, const GURL& origin) const { |
| 369 bool exists; | 371 bool exists; |
| 370 std::string map_id; | 372 std::string map_id; |
| 371 EXPECT_TRUE(db_->GetMapForArea(namespace_id, origin.spec(), | 373 EXPECT_TRUE(db_->GetMapForArea(namespace_id, origin.spec(), |
| 372 leveldb::ReadOptions(), &exists, &map_id)); | 374 leveldb::ReadOptions(), &exists, &map_id)); |
| 373 EXPECT_TRUE(exists); | 375 EXPECT_TRUE(exists); |
| 374 return map_id; | 376 return map_id; |
| 375 } | 377 } |
| 376 | 378 |
| 377 int64 SessionStorageDatabaseTest::GetMapRefCount( | 379 int64_t SessionStorageDatabaseTest::GetMapRefCount( |
| 378 const std::string& map_id) const { | 380 const std::string& map_id) const { |
| 379 int64 ref_count; | 381 int64_t ref_count; |
| 380 EXPECT_TRUE(db_->GetMapRefCount(map_id, &ref_count)); | 382 EXPECT_TRUE(db_->GetMapRefCount(map_id, &ref_count)); |
| 381 return ref_count; | 383 return ref_count; |
| 382 } | 384 } |
| 383 | 385 |
| 384 TEST_F(SessionStorageDatabaseTest, EmptyDatabaseSanityCheck) { | 386 TEST_F(SessionStorageDatabaseTest, EmptyDatabaseSanityCheck) { |
| 385 // An empty database should be valid. | 387 // An empty database should be valid. |
| 386 CheckDatabaseConsistency(); | 388 CheckDatabaseConsistency(); |
| 387 } | 389 } |
| 388 | 390 |
| 389 TEST_F(SessionStorageDatabaseTest, WriteDataForOneOrigin) { | 391 TEST_F(SessionStorageDatabaseTest, WriteDataForOneOrigin) { |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2)); | 792 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2)); |
| 791 | 793 |
| 792 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1)); | 794 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1)); |
| 793 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2)); | 795 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2)); |
| 794 // Check that also the namespace start key was deleted. | 796 // Check that also the namespace start key was deleted. |
| 795 CheckDatabaseConsistency(); | 797 CheckDatabaseConsistency(); |
| 796 } | 798 } |
| 797 | 799 |
| 798 | 800 |
| 799 } // namespace content | 801 } // namespace content |
| OLD | NEW |