Home | History | Annotate | Download | only in dom_storage
      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/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
    800