Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / browser / dom_storage / session_storage_database_unittest.cc
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.
4
5
6 #include "content/browser/dom_storage/session_storage_database.h"
7
8 #include <algorithm>
9 #include <map>
10 #include <string>
11
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"
23
24 namespace content {
25
26 class SessionStorageDatabaseTest : public testing::Test {
27  public:
28   SessionStorageDatabaseTest();
29   virtual ~SessionStorageDatabaseTest();
30   virtual void SetUp() OVERRIDE;
31
32  protected:
33   typedef std::map<std::string, std::string> DataMap;
34
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;
62
63   base::ScopedTempDir temp_dir_;
64   scoped_refptr<SessionStorageDatabase> db_;
65
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;
80
81   DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabaseTest);
82 };
83
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) { }
97
98 SessionStorageDatabaseTest::~SessionStorageDatabaseTest() { }
99
100 void SessionStorageDatabaseTest::SetUp() {
101   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
102   ResetDatabase();
103 }
104
105 void SessionStorageDatabaseTest::ResetDatabase() {
106   db_ = new SessionStorageDatabase(temp_dir_.path());
107   ASSERT_TRUE(db_->LazyOpen(true));
108 }
109
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;
118
119   size_t second_dash = key.find('-', namespace_prefix.length());
120   if (second_dash != key.length() - 1)
121     return false;
122
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;
128 }
129
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;
140
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;
147 }
148
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;
164 }
165
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;
181 }
182
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();
189   }
190 }
191
192 void SessionStorageDatabaseTest::CheckDatabaseConsistency() const {
193   DataMap data;
194   ReadData(&data);
195   // Empty db is ok.
196   if (data.empty())
197     return;
198
199   // For detecting rubbish keys.
200   size_t valid_keys = 0;
201
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);
209     }
210     return;
211   }
212   ++valid_keys;
213
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;
219
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;
239     }
240   }
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());
244
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);
253   }
254
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;
275     }
276   }
277   // Check that all maps referred to exist.
278   ASSERT_TRUE(expected_map_refcounts.empty());
279
280   if (data.find(next_map_id_key) != data.end())
281     ++valid_keys;
282
283   ASSERT_EQ(data.size(), valid_keys);
284 }
285
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());
295 }
296
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();
313     }
314   }
315   LOG(WARNING) << "----";
316 }
317
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);
324 }
325
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());
338   }
339 }
340
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());
351   }
352 }
353
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());
364   }
365 }
366
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;
375 }
376
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;
382 }
383
384 TEST_F(SessionStorageDatabaseTest, EmptyDatabaseSanityCheck) {
385   // An empty database should be valid.
386   CheckDatabaseConsistency();
387 }
388
389 TEST_F(SessionStorageDatabaseTest, WriteDataForOneOrigin) {
390   // Keep track on what the values should look like.
391   DOMStorageValuesMap reference;
392   // Write data.
393   {
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));
402   }
403   CheckDatabaseConsistency();
404   CheckAreaData(kNamespace1, kOrigin1, reference);
405
406   // Overwrite and delete values.
407   {
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));
414   }
415   CheckDatabaseConsistency();
416   CheckAreaData(kNamespace1, kOrigin1, reference);
417
418   // Clear data before writing.
419   {
420     DOMStorageValuesMap changes;
421     changes[kKey2] = kValue2;
422     reference.erase(kKey1);
423     reference[kKey2] = kValue2;
424     EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, true, changes));
425   }
426   CheckDatabaseConsistency();
427   CheckAreaData(kNamespace1, kOrigin1, reference);
428 }
429
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));
437
438   DOMStorageValuesMap data2;
439   data2[kKey1] = kValue4;
440   data2[kKey2] = kValue1;
441   data2[kKey3] = kValue2;
442   EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
443
444   CheckDatabaseConsistency();
445   CheckAreaData(kNamespace1, kOrigin1, data1);
446   CheckAreaData(kNamespace1, kOrigin2, data2);
447 }
448
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);
473 }
474
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)));
501 }
502
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));
509
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));
520
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);
525
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)));
531 }
532
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));
544
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));
549
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));
553
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);
564
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));
578
579   // Check the ref counts.
580   EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
581   EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin2)));
582 }
583
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));
590
591   // Disassoaciate the shallow copy.
592   EXPECT_TRUE(db_->DeleteArea(kNamespaceClone, kOrigin1));
593   CheckDatabaseConsistency();
594
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));
605
606   // Values in the original map were not changed.
607   CheckAreaData(kNamespace1, kOrigin1, data1);
608
609   // But values in the disassociated map were.
610   CheckAreaData(kNamespaceClone, kOrigin1, reference);
611 }
612
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();
626 }
627
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));
639
640   // Make a shallow copy and delete the original namespace.
641   EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
642   EXPECT_TRUE(db_->DeleteNamespace(kNamespace1));
643
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);
651 }
652
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));
664
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());
671 }
672
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));
684
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();
689
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);
696 }
697
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]);
713 }
714
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.
718
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));
723
724   // Delete the namespace with ID 1.
725   EXPECT_TRUE(db_->DeleteNamespace("foobar"));
726 }
727
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;
734
735   ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
736   expected_namespace_ids.insert(kNamespace1);
737   CheckNamespaceIds(expected_namespace_ids);
738
739   ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
740   expected_namespace_ids.insert(kNamespaceClone);
741   CheckNamespaceIds(expected_namespace_ids);
742
743   ASSERT_TRUE(db_->DeleteNamespace(kNamespace1));
744   expected_namespace_ids.erase(kNamespace1);
745   CheckNamespaceIds(expected_namespace_ids);
746
747   CheckDatabaseConsistency();
748 }
749
750 TEST_F(SessionStorageDatabaseTest, ReadNamespaceIdsInEmptyDatabase) {
751   std::set<std::string> expected_namespace_ids;
752   CheckNamespaceIds(expected_namespace_ids);
753 }
754
755 TEST_F(SessionStorageDatabaseTest, ReadOriginsInNamespace) {
756   DOMStorageValuesMap data1;
757   data1[kKey1] = kValue1;
758   data1[kKey2] = kValue2;
759   data1[kKey3] = kValue3;
760
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);
767
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);
772
773   ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
774   CheckOrigins(kNamespaceClone, expected_origins1);
775
776   ASSERT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
777   expected_origins1.erase(kOrigin2);
778   CheckOrigins(kNamespace1, expected_origins1);
779
780   CheckDatabaseConsistency();
781 }
782
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));
791
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();
796 }
797
798
799 }  // namespace content