Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / dom_storage / session_storage_database_unittest.cc
blobf8397ace3eada5df5cd683ec6221e308b5a00b30
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
3 // found in the LICENSE file.
6 #include "content/browser/dom_storage/session_storage_database.h"
8 #include <algorithm>
9 #include <map>
10 #include <string>
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/logging.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "content/common/dom_storage/dom_storage_types.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/leveldatabase/src/include/leveldb/db.h"
20 #include "third_party/leveldatabase/src/include/leveldb/iterator.h"
21 #include "third_party/leveldatabase/src/include/leveldb/options.h"
22 #include "url/gurl.h"
24 namespace content {
26 class SessionStorageDatabaseTest : public testing::Test {
27 public:
28 SessionStorageDatabaseTest();
29 ~SessionStorageDatabaseTest() override;
30 void SetUp() override;
32 protected:
33 typedef std::map<std::string, std::string> DataMap;
35 // Helpers.
36 static bool IsNamespaceKey(const std::string& key,
37 std::string* namespace_id);
38 static bool IsNamespaceOriginKey(const std::string& key,
39 std::string* namespace_id);
40 static bool IsMapRefCountKey(const std::string& key,
41 int64* map_id);
42 static bool IsMapValueKey(const std::string& key,
43 int64* map_id);
44 void ResetDatabase();
45 void ReadData(DataMap* data) const;
46 void CheckDatabaseConsistency() const;
47 void CheckEmptyDatabase() const;
48 void DumpData() const;
49 void CheckAreaData(const std::string& namespace_id,
50 const GURL& origin,
51 const DOMStorageValuesMap& reference) const;
52 void CompareValuesMaps(const DOMStorageValuesMap& map1,
53 const DOMStorageValuesMap& map2) const;
54 void CheckNamespaceIds(
55 const std::set<std::string>& expected_namespace_ids) const;
56 void CheckOrigins(
57 const std::string& namespace_id,
58 const std::set<GURL>& expected_origins) const;
59 std::string GetMapForArea(const std::string& namespace_id,
60 const GURL& origin) const;
61 int64 GetMapRefCount(const std::string& map_id) const;
63 base::ScopedTempDir temp_dir_;
64 scoped_refptr<SessionStorageDatabase> db_;
66 // Test data.
67 const GURL kOrigin1;
68 const GURL kOrigin2;
69 const std::string kNamespace1;
70 const std::string kNamespace2;
71 const std::string kNamespaceClone;
72 const base::string16 kKey1;
73 const base::string16 kKey2;
74 const base::string16 kKey3;
75 const base::NullableString16 kValue1;
76 const base::NullableString16 kValue2;
77 const base::NullableString16 kValue3;
78 const base::NullableString16 kValue4;
79 const base::NullableString16 kValueNull;
81 DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabaseTest);
84 SessionStorageDatabaseTest::SessionStorageDatabaseTest()
85 : kOrigin1("http://www.origin1.com"),
86 kOrigin2("http://www.origin2.com"),
87 kNamespace1("namespace1"),
88 kNamespace2("namespace2"),
89 kNamespaceClone("wascloned"),
90 kKey1(base::ASCIIToUTF16("key1")),
91 kKey2(base::ASCIIToUTF16("key2")),
92 kKey3(base::ASCIIToUTF16("key3")),
93 kValue1(base::ASCIIToUTF16("value1"), false),
94 kValue2(base::ASCIIToUTF16("value2"), false),
95 kValue3(base::ASCIIToUTF16("value3"), false),
96 kValue4(base::ASCIIToUTF16("value4"), false) { }
98 SessionStorageDatabaseTest::~SessionStorageDatabaseTest() { }
100 void SessionStorageDatabaseTest::SetUp() {
101 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
102 ResetDatabase();
105 void SessionStorageDatabaseTest::ResetDatabase() {
106 db_ = new SessionStorageDatabase(temp_dir_.path());
107 ASSERT_TRUE(db_->LazyOpen(true));
110 // static
111 bool SessionStorageDatabaseTest::IsNamespaceKey(const std::string& key,
112 std::string* namespace_id) {
113 std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix();
114 if (key.find(namespace_prefix) != 0)
115 return false;
116 if (key == namespace_prefix)
117 return false;
119 size_t second_dash = key.find('-', namespace_prefix.length());
120 if (second_dash != key.length() - 1)
121 return false;
123 // Key is of the form "namespace-<namespaceid>-".
124 *namespace_id = key.substr(
125 namespace_prefix.length(),
126 second_dash - namespace_prefix.length());
127 return true;
130 // static
131 bool SessionStorageDatabaseTest::IsNamespaceOriginKey(
132 const std::string& key,
133 std::string* namespace_id) {
134 std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix();
135 if (key.find(namespace_prefix) != 0)
136 return false;
137 size_t second_dash = key.find('-', namespace_prefix.length());
138 if (second_dash == std::string::npos || second_dash == key.length() - 1)
139 return false;
141 // Key is of the form "namespace-<namespaceid>-<origin>", and the value
142 // is the map id.
143 *namespace_id = key.substr(
144 namespace_prefix.length(),
145 second_dash - namespace_prefix.length());
146 return true;
149 // static
150 bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string& key,
151 int64* map_id) {
152 std::string map_prefix = "map-";
153 if (key.find(map_prefix) != 0)
154 return false;
155 size_t second_dash = key.find('-', map_prefix.length());
156 if (second_dash != key.length() - 1)
157 return false;
158 // 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(),
160 second_dash - map_prefix.length());
161 bool conversion_ok = base::StringToInt64(map_id_str, map_id);
162 EXPECT_TRUE(conversion_ok);
163 return true;
166 // static
167 bool SessionStorageDatabaseTest::IsMapValueKey(const std::string& key,
168 int64* map_id) {
169 std::string map_prefix = "map-";
170 if (key.find(map_prefix) != 0)
171 return false;
172 size_t second_dash = key.find('-', map_prefix.length());
173 if (second_dash == std::string::npos || second_dash == key.length() - 1)
174 return false;
175 // Key is of the form "map-<mapid>-key".
176 std::string map_id_str = key.substr(map_prefix.length(),
177 second_dash - map_prefix.length());
178 bool conversion_ok = base::StringToInt64(map_id_str, map_id);
179 EXPECT_TRUE(conversion_ok);
180 return true;
183 void SessionStorageDatabaseTest::ReadData(DataMap* data) const {
184 leveldb::DB* leveldb = db_->db_.get();
185 scoped_ptr<leveldb::Iterator> it(
186 leveldb->NewIterator(leveldb::ReadOptions()));
187 for (it->SeekToFirst(); it->Valid(); it->Next()) {
188 (*data)[it->key().ToString()] = it->value().ToString();
192 void SessionStorageDatabaseTest::CheckDatabaseConsistency() const {
193 DataMap data;
194 ReadData(&data);
195 // Empty db is ok.
196 if (data.empty())
197 return;
199 // For detecting rubbish keys.
200 size_t valid_keys = 0;
202 std::string next_map_id_key = SessionStorageDatabase::NextMapIdKey();
203 // Check the namespace start key.
204 if (data.find(SessionStorageDatabase::NamespacePrefix()) == data.end()) {
205 // If there is no namespace start key, the database may contain only counter
206 // keys.
207 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
208 ASSERT_TRUE(it->first == next_map_id_key);
210 return;
212 ++valid_keys;
214 // Iterate the "namespace-" keys.
215 std::set<std::string> found_namespace_ids;
216 std::set<std::string> namespaces_with_areas;
217 std::map<int64, int64> expected_map_refcounts;
218 int64 max_map_id = -1;
220 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
221 std::string namespace_id;
222 if (IsNamespaceKey(it->first, &namespace_id)) {
223 found_namespace_ids.insert(namespace_id);
224 ++valid_keys;
225 } else if (IsNamespaceOriginKey(
226 it->first, &namespace_id)) {
227 // Check that the corresponding "namespace-<namespaceid>-" key exists. It
228 // has been read by now, since the keys are stored in order.
229 ASSERT_TRUE(found_namespace_ids.find(namespace_id) !=
230 found_namespace_ids.end());
231 namespaces_with_areas.insert(namespace_id);
232 int64 map_id;
233 bool conversion_ok = base::StringToInt64(it->second, &map_id);
234 ASSERT_TRUE(conversion_ok);
235 ASSERT_GE(map_id, 0);
236 ++expected_map_refcounts[map_id];
237 max_map_id = std::max(map_id, max_map_id);
238 ++valid_keys;
241 // Check that there are no leftover "namespace-namespaceid-" keys without
242 // associated areas.
243 ASSERT_EQ(found_namespace_ids.size(), namespaces_with_areas.size());
245 if (max_map_id != -1) {
246 // The database contains maps.
247 ASSERT_TRUE(data.find(next_map_id_key) != data.end());
248 int64 next_map_id;
249 bool conversion_ok =
250 base::StringToInt64(data[next_map_id_key], &next_map_id);
251 ASSERT_TRUE(conversion_ok);
252 ASSERT_GT(next_map_id, max_map_id);
255 // Iterate the "map-" keys.
256 std::set<int64> found_map_ids;
257 for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
258 int64 map_id;
259 if (IsMapRefCountKey(it->first, &map_id)) {
260 int64 ref_count;
261 bool conversion_ok = base::StringToInt64(it->second, &ref_count);
262 ASSERT_TRUE(conversion_ok);
263 // Check that the map is not stale.
264 ASSERT_GT(ref_count, 0);
265 ASSERT_TRUE(expected_map_refcounts.find(map_id) !=
266 expected_map_refcounts.end());
267 ASSERT_EQ(expected_map_refcounts[map_id], ref_count);
268 // Mark the map as existing.
269 expected_map_refcounts.erase(map_id);
270 found_map_ids.insert(map_id);
271 ++valid_keys;
272 } else if (IsMapValueKey(it->first, &map_id)) {
273 ASSERT_TRUE(found_map_ids.find(map_id) != found_map_ids.end());
274 ++valid_keys;
277 // Check that all maps referred to exist.
278 ASSERT_TRUE(expected_map_refcounts.empty());
280 if (data.find(next_map_id_key) != data.end())
281 ++valid_keys;
283 ASSERT_EQ(data.size(), valid_keys);
286 void SessionStorageDatabaseTest::CheckEmptyDatabase() const {
287 DataMap data;
288 ReadData(&data);
289 size_t valid_keys = 0;
290 if (data.find(SessionStorageDatabase::NamespacePrefix()) != data.end())
291 ++valid_keys;
292 if (data.find(SessionStorageDatabase::NextMapIdKey()) != data.end())
293 ++valid_keys;
294 EXPECT_EQ(valid_keys, data.size());
297 void SessionStorageDatabaseTest::DumpData() const {
298 LOG(WARNING) << "---- Session storage contents";
299 scoped_ptr<leveldb::Iterator> it(
300 db_->db_->NewIterator(leveldb::ReadOptions()));
301 for (it->SeekToFirst(); it->Valid(); it->Next()) {
302 int64 dummy_map_id;
303 if (IsMapValueKey(it->key().ToString(), &dummy_map_id)) {
304 // Convert the value back to base::string16.
305 base::string16 value;
306 size_t len = it->value().size() / sizeof(base::char16);
307 value.resize(len);
308 value.assign(
309 reinterpret_cast<const base::char16*>(it->value().data()), len);
310 LOG(WARNING) << it->key().ToString() << ": " << value;
311 } else {
312 LOG(WARNING) << it->key().ToString() << ": " << it->value().ToString();
315 LOG(WARNING) << "----";
318 void SessionStorageDatabaseTest::CheckAreaData(
319 const std::string& namespace_id, const GURL& origin,
320 const DOMStorageValuesMap& reference) const {
321 DOMStorageValuesMap values;
322 db_->ReadAreaValues(namespace_id, origin, &values);
323 CompareValuesMaps(values, reference);
326 void SessionStorageDatabaseTest::CompareValuesMaps(
327 const DOMStorageValuesMap& map1,
328 const DOMStorageValuesMap& map2) const {
329 ASSERT_EQ(map2.size(), map1.size());
330 for (DOMStorageValuesMap::const_iterator it = map1.begin();
331 it != map1.end(); ++it) {
332 base::string16 key = it->first;
333 ASSERT_TRUE(map2.find(key) != map2.end());
334 base::NullableString16 val1 = it->second;
335 base::NullableString16 val2 = map2.find(key)->second;
336 EXPECT_EQ(val2.is_null(), val1.is_null());
337 EXPECT_EQ(val2.string(), val1.string());
341 void SessionStorageDatabaseTest::CheckNamespaceIds(
342 const std::set<std::string>& expected_namespace_ids) const {
343 std::map<std::string, std::vector<GURL> > namespaces_and_origins;
344 EXPECT_TRUE(db_->ReadNamespacesAndOrigins(&namespaces_and_origins));
345 EXPECT_EQ(expected_namespace_ids.size(), namespaces_and_origins.size());
346 for (std::map<std::string, std::vector<GURL> >::const_iterator it =
347 namespaces_and_origins.begin();
348 it != namespaces_and_origins.end(); ++it) {
349 EXPECT_TRUE(expected_namespace_ids.find(it->first) !=
350 expected_namespace_ids.end());
354 void SessionStorageDatabaseTest::CheckOrigins(
355 const std::string& namespace_id,
356 const std::set<GURL>& expected_origins) const {
357 std::map<std::string, std::vector<GURL> > namespaces_and_origins;
358 EXPECT_TRUE(db_->ReadNamespacesAndOrigins(&namespaces_and_origins));
359 const std::vector<GURL>& origins = namespaces_and_origins[namespace_id];
360 EXPECT_EQ(expected_origins.size(), origins.size());
361 for (std::vector<GURL>::const_iterator it = origins.begin();
362 it != origins.end(); ++it) {
363 EXPECT_TRUE(expected_origins.find(*it) != expected_origins.end());
367 std::string SessionStorageDatabaseTest::GetMapForArea(
368 const std::string& namespace_id, const GURL& origin) const {
369 bool exists;
370 std::string map_id;
371 EXPECT_TRUE(db_->GetMapForArea(namespace_id, origin.spec(),
372 leveldb::ReadOptions(), &exists, &map_id));
373 EXPECT_TRUE(exists);
374 return map_id;
377 int64 SessionStorageDatabaseTest::GetMapRefCount(
378 const std::string& map_id) const {
379 int64 ref_count;
380 EXPECT_TRUE(db_->GetMapRefCount(map_id, &ref_count));
381 return ref_count;
384 TEST_F(SessionStorageDatabaseTest, EmptyDatabaseSanityCheck) {
385 // An empty database should be valid.
386 CheckDatabaseConsistency();
389 TEST_F(SessionStorageDatabaseTest, WriteDataForOneOrigin) {
390 // Keep track on what the values should look like.
391 DOMStorageValuesMap reference;
392 // Write data.
394 DOMStorageValuesMap changes;
395 changes[kKey1] = kValue1;
396 changes[kKey2] = kValue2;
397 changes[kKey3] = kValue3;
398 reference[kKey1] = kValue1;
399 reference[kKey2] = kValue2;
400 reference[kKey3] = kValue3;
401 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
403 CheckDatabaseConsistency();
404 CheckAreaData(kNamespace1, kOrigin1, reference);
406 // Overwrite and delete values.
408 DOMStorageValuesMap changes;
409 changes[kKey1] = kValue4;
410 changes[kKey3] = kValueNull;
411 reference[kKey1] = kValue4;
412 reference.erase(kKey3);
413 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
415 CheckDatabaseConsistency();
416 CheckAreaData(kNamespace1, kOrigin1, reference);
418 // Clear data before writing.
420 DOMStorageValuesMap changes;
421 changes[kKey2] = kValue2;
422 reference.erase(kKey1);
423 reference[kKey2] = kValue2;
424 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, true, changes));
426 CheckDatabaseConsistency();
427 CheckAreaData(kNamespace1, kOrigin1, reference);
430 TEST_F(SessionStorageDatabaseTest, WriteDataForTwoOrigins) {
431 // Write data.
432 DOMStorageValuesMap data1;
433 data1[kKey1] = kValue1;
434 data1[kKey2] = kValue2;
435 data1[kKey3] = kValue3;
436 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
438 DOMStorageValuesMap data2;
439 data2[kKey1] = kValue4;
440 data2[kKey2] = kValue1;
441 data2[kKey3] = kValue2;
442 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
444 CheckDatabaseConsistency();
445 CheckAreaData(kNamespace1, kOrigin1, data1);
446 CheckAreaData(kNamespace1, kOrigin2, data2);
449 TEST_F(SessionStorageDatabaseTest, WriteDataForTwoNamespaces) {
450 // Write data.
451 DOMStorageValuesMap data11;
452 data11[kKey1] = kValue1;
453 data11[kKey2] = kValue2;
454 data11[kKey3] = kValue3;
455 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data11));
456 DOMStorageValuesMap data12;
457 data12[kKey2] = kValue4;
458 data12[kKey3] = kValue3;
459 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data12));
460 DOMStorageValuesMap data21;
461 data21[kKey1] = kValue2;
462 data21[kKey2] = kValue4;
463 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin1, false, data21));
464 DOMStorageValuesMap data22;
465 data22[kKey2] = kValue1;
466 data22[kKey3] = kValue2;
467 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin2, false, data22));
468 CheckDatabaseConsistency();
469 CheckAreaData(kNamespace1, kOrigin1, data11);
470 CheckAreaData(kNamespace1, kOrigin2, data12);
471 CheckAreaData(kNamespace2, kOrigin1, data21);
472 CheckAreaData(kNamespace2, kOrigin2, data22);
475 TEST_F(SessionStorageDatabaseTest, ShallowCopy) {
476 // Write data for a namespace, for 2 origins.
477 DOMStorageValuesMap data1;
478 data1[kKey1] = kValue1;
479 data1[kKey2] = kValue2;
480 data1[kKey3] = kValue3;
481 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
482 DOMStorageValuesMap data2;
483 data2[kKey1] = kValue2;
484 data2[kKey3] = kValue1;
485 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
486 // Make a shallow copy.
487 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
488 // Now both namespaces should have the same data.
489 CheckDatabaseConsistency();
490 CheckAreaData(kNamespace1, kOrigin1, data1);
491 CheckAreaData(kNamespace1, kOrigin2, data2);
492 CheckAreaData(kNamespaceClone, kOrigin1, data1);
493 CheckAreaData(kNamespaceClone, kOrigin2, data2);
494 // Both the namespaces refer to the same maps.
495 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
496 GetMapForArea(kNamespaceClone, kOrigin1));
497 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
498 GetMapForArea(kNamespaceClone, kOrigin2));
499 EXPECT_EQ(2, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
500 EXPECT_EQ(2, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin2)));
503 TEST_F(SessionStorageDatabaseTest, WriteIntoShallowCopy) {
504 DOMStorageValuesMap data1;
505 data1[kKey1] = kValue1;
506 data1[kKey2] = kValue2;
507 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
508 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
510 // Write data into a shallow copy.
511 DOMStorageValuesMap changes;
512 DOMStorageValuesMap reference;
513 changes[kKey1] = kValueNull;
514 changes[kKey2] = kValue4;
515 changes[kKey3] = kValue4;
516 reference[kKey2] = kValue4;
517 reference[kKey3] = kValue4;
518 EXPECT_TRUE(db_->CommitAreaChanges(kNamespaceClone, kOrigin1, false,
519 changes));
521 // Values in the original namespace were not changed.
522 CheckAreaData(kNamespace1, kOrigin1, data1);
523 // But values in the copy were.
524 CheckAreaData(kNamespaceClone, kOrigin1, reference);
526 // The namespaces no longer refer to the same map.
527 EXPECT_NE(GetMapForArea(kNamespace1, kOrigin1),
528 GetMapForArea(kNamespaceClone, kOrigin1));
529 EXPECT_EQ(1, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
530 EXPECT_EQ(1, GetMapRefCount(GetMapForArea(kNamespaceClone, kOrigin1)));
533 TEST_F(SessionStorageDatabaseTest, ManyShallowCopies) {
534 // Write data for a namespace, for 2 origins.
535 DOMStorageValuesMap data1;
536 data1[kKey1] = kValue1;
537 data1[kKey2] = kValue2;
538 data1[kKey3] = kValue3;
539 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
540 DOMStorageValuesMap data2;
541 data2[kKey1] = kValue2;
542 data2[kKey3] = kValue1;
543 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
545 // Make a two shallow copies.
546 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
547 std::string another_clone("another_cloned");
548 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, another_clone));
550 // Make a shallow copy of a shallow copy.
551 std::string clone_of_clone("clone_of_clone");
552 EXPECT_TRUE(db_->CloneNamespace(another_clone, clone_of_clone));
554 // Now all namespaces should have the same data.
555 CheckDatabaseConsistency();
556 CheckAreaData(kNamespace1, kOrigin1, data1);
557 CheckAreaData(kNamespaceClone, kOrigin1, data1);
558 CheckAreaData(another_clone, kOrigin1, data1);
559 CheckAreaData(clone_of_clone, kOrigin1, data1);
560 CheckAreaData(kNamespace1, kOrigin2, data2);
561 CheckAreaData(kNamespaceClone, kOrigin2, data2);
562 CheckAreaData(another_clone, kOrigin2, data2);
563 CheckAreaData(clone_of_clone, kOrigin2, data2);
565 // All namespaces refer to the same maps.
566 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
567 GetMapForArea(kNamespaceClone, kOrigin1));
568 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
569 GetMapForArea(kNamespaceClone, kOrigin2));
570 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
571 GetMapForArea(another_clone, kOrigin1));
572 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
573 GetMapForArea(another_clone, kOrigin2));
574 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
575 GetMapForArea(clone_of_clone, kOrigin1));
576 EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
577 GetMapForArea(clone_of_clone, kOrigin2));
579 // Check the ref counts.
580 EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
581 EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin2)));
584 TEST_F(SessionStorageDatabaseTest, DisassociateShallowCopy) {
585 DOMStorageValuesMap data1;
586 data1[kKey1] = kValue1;
587 data1[kKey2] = kValue2;
588 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
589 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
591 // Disassoaciate the shallow copy.
592 EXPECT_TRUE(db_->DeleteArea(kNamespaceClone, kOrigin1));
593 CheckDatabaseConsistency();
595 // Now new data can be written to that map.
596 DOMStorageValuesMap reference;
597 DOMStorageValuesMap changes;
598 changes[kKey1] = kValueNull;
599 changes[kKey2] = kValue4;
600 changes[kKey3] = kValue4;
601 reference[kKey2] = kValue4;
602 reference[kKey3] = kValue4;
603 EXPECT_TRUE(db_->CommitAreaChanges(kNamespaceClone, kOrigin1, false,
604 changes));
606 // Values in the original map were not changed.
607 CheckAreaData(kNamespace1, kOrigin1, data1);
609 // But values in the disassociated map were.
610 CheckAreaData(kNamespaceClone, kOrigin1, reference);
613 TEST_F(SessionStorageDatabaseTest, DeleteNamespace) {
614 DOMStorageValuesMap data1;
615 data1[kKey1] = kValue1;
616 data1[kKey2] = kValue2;
617 data1[kKey3] = kValue3;
618 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
619 DOMStorageValuesMap data2;
620 data2[kKey2] = kValue4;
621 data2[kKey3] = kValue3;
622 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
623 EXPECT_TRUE(db_->DeleteNamespace(kNamespace1));
624 CheckDatabaseConsistency();
625 CheckEmptyDatabase();
628 TEST_F(SessionStorageDatabaseTest, DeleteNamespaceWithShallowCopy) {
629 // Write data for a namespace, for 2 origins.
630 DOMStorageValuesMap data1;
631 data1[kKey1] = kValue1;
632 data1[kKey2] = kValue2;
633 data1[kKey3] = kValue3;
634 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
635 DOMStorageValuesMap data2;
636 data2[kKey1] = kValue2;
637 data2[kKey3] = kValue1;
638 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
640 // Make a shallow copy and delete the original namespace.
641 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
642 EXPECT_TRUE(db_->DeleteNamespace(kNamespace1));
644 // The original namespace has no data.
645 CheckDatabaseConsistency();
646 CheckAreaData(kNamespace1, kOrigin1, DOMStorageValuesMap());
647 CheckAreaData(kNamespace1, kOrigin2, DOMStorageValuesMap());
648 // But the copy persists.
649 CheckAreaData(kNamespaceClone, kOrigin1, data1);
650 CheckAreaData(kNamespaceClone, kOrigin2, data2);
653 TEST_F(SessionStorageDatabaseTest, DeleteArea) {
654 // Write data for a namespace, for 2 origins.
655 DOMStorageValuesMap data1;
656 data1[kKey1] = kValue1;
657 data1[kKey2] = kValue2;
658 data1[kKey3] = kValue3;
659 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
660 DOMStorageValuesMap data2;
661 data2[kKey1] = kValue2;
662 data2[kKey3] = kValue1;
663 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
665 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
666 CheckDatabaseConsistency();
667 // The data for the non-deleted origin persists.
668 CheckAreaData(kNamespace1, kOrigin1, data1);
669 // The data for the deleted origin is gone.
670 CheckAreaData(kNamespace1, kOrigin2, DOMStorageValuesMap());
673 TEST_F(SessionStorageDatabaseTest, DeleteAreaWithShallowCopy) {
674 // Write data for a namespace, for 2 origins.
675 DOMStorageValuesMap data1;
676 data1[kKey1] = kValue1;
677 data1[kKey2] = kValue2;
678 data1[kKey3] = kValue3;
679 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
680 DOMStorageValuesMap data2;
681 data2[kKey1] = kValue2;
682 data2[kKey3] = kValue1;
683 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
685 // Make a shallow copy and delete an origin from the original namespace.
686 EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
687 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1));
688 CheckDatabaseConsistency();
690 // The original namespace has data for only the non-deleted origin.
691 CheckAreaData(kNamespace1, kOrigin1, DOMStorageValuesMap());
692 CheckAreaData(kNamespace1, kOrigin2, data2);
693 // But the copy persists.
694 CheckAreaData(kNamespaceClone, kOrigin1, data1);
695 CheckAreaData(kNamespaceClone, kOrigin2, data2);
698 TEST_F(SessionStorageDatabaseTest, WriteRawBytes) {
699 // Write data which is not valid utf8 and contains null bytes.
700 unsigned char raw_data[10] = {255, 0, 0, 0, 1, 2, 3, 4, 5, 0};
701 DOMStorageValuesMap changes;
702 base::string16 string_with_raw_data;
703 string_with_raw_data.assign(reinterpret_cast<base::char16*>(raw_data), 5);
704 changes[kKey1] = base::NullableString16(string_with_raw_data, false);
705 EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
706 CheckDatabaseConsistency();
707 DOMStorageValuesMap values;
708 db_->ReadAreaValues(kNamespace1, kOrigin1, &values);
709 const unsigned char* data =
710 reinterpret_cast<const unsigned char*>(values[kKey1].string().data());
711 for (int i = 0; i < 10; ++i)
712 EXPECT_EQ(raw_data[i], data[i]);
715 TEST_F(SessionStorageDatabaseTest, DeleteNamespaceConfusion) {
716 // Regression test for a bug where a namespace with id 10 prevented deleting
717 // the namespace with id 1.
719 DOMStorageValuesMap data1;
720 data1[kKey1] = kValue1;
721 ASSERT_TRUE(db_->CommitAreaChanges("foobar", kOrigin1, false, data1));
722 ASSERT_TRUE(db_->CommitAreaChanges("foobarbaz", kOrigin1, false, data1));
724 // Delete the namespace with ID 1.
725 EXPECT_TRUE(db_->DeleteNamespace("foobar"));
728 TEST_F(SessionStorageDatabaseTest, ReadNamespaceIds) {
729 DOMStorageValuesMap data1;
730 data1[kKey1] = kValue1;
731 data1[kKey2] = kValue2;
732 data1[kKey3] = kValue3;
733 std::set<std::string> expected_namespace_ids;
735 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
736 expected_namespace_ids.insert(kNamespace1);
737 CheckNamespaceIds(expected_namespace_ids);
739 ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
740 expected_namespace_ids.insert(kNamespaceClone);
741 CheckNamespaceIds(expected_namespace_ids);
743 ASSERT_TRUE(db_->DeleteNamespace(kNamespace1));
744 expected_namespace_ids.erase(kNamespace1);
745 CheckNamespaceIds(expected_namespace_ids);
747 CheckDatabaseConsistency();
750 TEST_F(SessionStorageDatabaseTest, ReadNamespaceIdsInEmptyDatabase) {
751 std::set<std::string> expected_namespace_ids;
752 CheckNamespaceIds(expected_namespace_ids);
755 TEST_F(SessionStorageDatabaseTest, ReadOriginsInNamespace) {
756 DOMStorageValuesMap data1;
757 data1[kKey1] = kValue1;
758 data1[kKey2] = kValue2;
759 data1[kKey3] = kValue3;
761 std::set<GURL> expected_origins1;
762 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
763 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data1));
764 expected_origins1.insert(kOrigin1);
765 expected_origins1.insert(kOrigin2);
766 CheckOrigins(kNamespace1, expected_origins1);
768 std::set<GURL> expected_origins2;
769 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin2, false, data1));
770 expected_origins2.insert(kOrigin2);
771 CheckOrigins(kNamespace2, expected_origins2);
773 ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
774 CheckOrigins(kNamespaceClone, expected_origins1);
776 ASSERT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
777 expected_origins1.erase(kOrigin2);
778 CheckOrigins(kNamespace1, expected_origins1);
780 CheckDatabaseConsistency();
783 TEST_F(SessionStorageDatabaseTest, DeleteAllOrigins) {
784 // Write data for a namespace, for 2 origins.
785 DOMStorageValuesMap data1;
786 data1[kKey1] = kValue1;
787 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
788 DOMStorageValuesMap data2;
789 data2[kKey1] = kValue2;
790 ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
792 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1));
793 EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
794 // Check that also the namespace start key was deleted.
795 CheckDatabaseConsistency();
799 } // namespace content