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"
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"
26 class SessionStorageDatabaseTest
: public testing::Test
{
28 SessionStorageDatabaseTest();
29 ~SessionStorageDatabaseTest() override
;
30 void SetUp() override
;
33 typedef std::map
<std::string
, std::string
> DataMap
;
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
,
42 static bool IsMapValueKey(const std::string
& key
,
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
,
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;
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_
;
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());
105 void SessionStorageDatabaseTest::ResetDatabase() {
106 db_
= new SessionStorageDatabase(temp_dir_
.path());
107 ASSERT_TRUE(db_
->LazyOpen(true));
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)
116 if (key
== namespace_prefix
)
119 size_t second_dash
= key
.find('-', namespace_prefix
.length());
120 if (second_dash
!= key
.length() - 1)
123 // Key is of the form "namespace-<namespaceid>-".
124 *namespace_id
= key
.substr(
125 namespace_prefix
.length(),
126 second_dash
- namespace_prefix
.length());
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)
137 size_t second_dash
= key
.find('-', namespace_prefix
.length());
138 if (second_dash
== std::string::npos
|| second_dash
== key
.length() - 1)
141 // Key is of the form "namespace-<namespaceid>-<origin>", and the value
143 *namespace_id
= key
.substr(
144 namespace_prefix
.length(),
145 second_dash
- namespace_prefix
.length());
150 bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string
& key
,
152 std::string map_prefix
= "map-";
153 if (key
.find(map_prefix
) != 0)
155 size_t second_dash
= key
.find('-', map_prefix
.length());
156 if (second_dash
!= key
.length() - 1)
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
);
167 bool SessionStorageDatabaseTest::IsMapValueKey(const std::string
& key
,
169 std::string map_prefix
= "map-";
170 if (key
.find(map_prefix
) != 0)
172 size_t second_dash
= key
.find('-', map_prefix
.length());
173 if (second_dash
== std::string::npos
|| second_dash
== key
.length() - 1)
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
);
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 {
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
207 for (DataMap::const_iterator it
= data
.begin(); it
!= data
.end(); ++it
) {
208 ASSERT_TRUE(it
->first
== next_map_id_key
);
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
);
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
);
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
);
241 // Check that there are no leftover "namespace-namespaceid-" keys without
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());
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
) {
259 if (IsMapRefCountKey(it
->first
, &map_id
)) {
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
);
272 } else if (IsMapValueKey(it
->first
, &map_id
)) {
273 ASSERT_TRUE(found_map_ids
.find(map_id
) != found_map_ids
.end());
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())
283 ASSERT_EQ(data
.size(), valid_keys
);
286 void SessionStorageDatabaseTest::CheckEmptyDatabase() const {
289 size_t valid_keys
= 0;
290 if (data
.find(SessionStorageDatabase::NamespacePrefix()) != data
.end())
292 if (data
.find(SessionStorageDatabase::NextMapIdKey()) != data
.end())
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()) {
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
);
309 reinterpret_cast<const base::char16
*>(it
->value().data()), len
);
310 LOG(WARNING
) << it
->key().ToString() << ": " << value
;
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 {
371 EXPECT_TRUE(db_
->GetMapForArea(namespace_id
, origin
.spec(),
372 leveldb::ReadOptions(), &exists
, &map_id
));
377 int64
SessionStorageDatabaseTest::GetMapRefCount(
378 const std::string
& map_id
) const {
380 EXPECT_TRUE(db_
->GetMapRefCount(map_id
, &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
;
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
) {
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
) {
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,
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,
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