1 // Copyright (c) 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.
5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
7 #include "base/logging.h"
8 #include "base/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
18 class IndexedDBBackingStoreTest : public testing::Test {
20 IndexedDBBackingStoreTest() {}
21 virtual void SetUp() {
22 const GURL origin("http://localhost:81");
23 backing_store_ = IndexedDBBackingStore::OpenInMemory(origin);
25 // useful keys and values during tests
29 m_key1 = IndexedDBKey(99, WebKit::WebIDBKeyTypeNumber);
30 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
31 m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
35 scoped_refptr<IndexedDBBackingStore> backing_store_;
37 // Sample keys and values that are consistent.
46 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
49 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
51 IndexedDBBackingStore::Transaction transaction1(backing_store_);
53 IndexedDBBackingStore::RecordIdentifier record;
54 bool ok = backing_store_->PutRecord(
55 &transaction1, 1, 1, m_key1, m_value1, &record);
57 transaction1.Commit();
61 IndexedDBBackingStore::Transaction transaction2(backing_store_);
63 std::string result_value;
65 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value);
66 transaction2.Commit();
68 EXPECT_EQ(m_value1, result_value);
72 // Make sure that using very high ( more than 32 bit ) values for database_id
73 // and object_store_id still work.
74 TEST_F(IndexedDBBackingStoreTest, HighIds) {
75 const int64 high_database_id = 1ULL << 35;
76 const int64 high_object_store_id = 1ULL << 39;
77 // index_ids are capped at 32 bits for storage purposes.
78 const int64 high_index_id = 1ULL << 29;
80 const int64 invalid_high_index_id = 1ULL << 37;
82 const IndexedDBKey& index_key = m_key2;
83 std::string index_key_raw;
84 EncodeIDBKey(index_key, &index_key_raw);
86 IndexedDBBackingStore::Transaction transaction1(backing_store_);
88 IndexedDBBackingStore::RecordIdentifier record;
89 bool ok = backing_store_->PutRecord(&transaction1,
97 ok = backing_store_->PutIndexDataForRecord(&transaction1,
100 invalid_high_index_id,
105 ok = backing_store_->PutIndexDataForRecord(&transaction1,
107 high_object_store_id,
113 ok = transaction1.Commit();
118 IndexedDBBackingStore::Transaction transaction2(backing_store_);
119 transaction2.Begin();
120 std::string result_value;
121 bool ok = backing_store_->GetRecord(&transaction2,
123 high_object_store_id,
127 EXPECT_EQ(m_value1, result_value);
129 scoped_ptr<IndexedDBKey> new_primary_key;
130 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
132 high_object_store_id,
133 invalid_high_index_id,
138 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
140 high_object_store_id,
145 EXPECT_TRUE(new_primary_key->IsEqual(m_key1));
147 ok = transaction2.Commit();
152 // Make sure that other invalid ids do not crash.
153 TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
154 // valid ids for use when testing invalid ids
155 const int64 database_id = 1;
156 const int64 object_store_id = 1;
157 const int64 index_id = kMinimumIndexId;
158 const int64 invalid_low_index_id = 19; // index_ids must be > kMinimumIndexId
160 std::string result_value;
162 IndexedDBBackingStore::Transaction transaction1(backing_store_);
163 transaction1.Begin();
165 IndexedDBBackingStore::RecordIdentifier record;
166 bool ok = backing_store_->PutRecord(&transaction1,
168 KeyPrefix::kInvalidId,
173 ok = backing_store_->PutRecord(
174 &transaction1, database_id, 0, m_key1, m_value1, &record);
176 ok = backing_store_->PutRecord(&transaction1,
177 KeyPrefix::kInvalidId,
183 ok = backing_store_->PutRecord(
184 &transaction1, 0, object_store_id, m_key1, m_value1, &record);
187 ok = backing_store_->GetRecord(
188 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
190 ok = backing_store_->GetRecord(
191 &transaction1, database_id, 0, m_key1, &result_value);
193 ok = backing_store_->GetRecord(&transaction1,
194 KeyPrefix::kInvalidId,
199 ok = backing_store_->GetRecord(
200 &transaction1, 0, object_store_id, m_key1, &result_value);
203 scoped_ptr<IndexedDBKey> new_primary_key;
204 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
207 KeyPrefix::kInvalidId,
211 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
214 invalid_low_index_id,
218 ok = backing_store_->GetPrimaryKeyViaIndex(
219 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
222 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
223 KeyPrefix::kInvalidId,
229 ok = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
231 KeyPrefix::kInvalidId,
238 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
239 const string16 database_name(ASCIIToUTF16("db1"));
241 const string16 version(ASCIIToUTF16("old_string_version"));
242 const int64 int_version = 9;
244 const int64 object_store_id = 99;
245 const string16 object_store_name(ASCIIToUTF16("object_store1"));
246 const bool auto_increment = true;
247 const IndexedDBKeyPath object_store_key_path(
248 ASCIIToUTF16("object_store_key"));
250 const int64 index_id = 999;
251 const string16 index_name(ASCIIToUTF16("index1"));
252 const bool unique = true;
253 const bool multi_entry = true;
254 const IndexedDBKeyPath index_key_path(ASCIIToUTF16("index_key"));
257 bool ok = backing_store_->CreateIDBDatabaseMetaData(
258 database_name, version, int_version, &database_id);
260 EXPECT_GT(database_id, 0);
262 IndexedDBBackingStore::Transaction transaction(backing_store_);
265 ok = backing_store_->CreateObjectStore(&transaction,
269 object_store_key_path,
273 ok = backing_store_->CreateIndex(&transaction,
283 ok = transaction.Commit();
288 IndexedDBDatabaseMetadata database;
290 bool ok = backing_store_->GetIDBDatabaseMetaData(
291 database_name, &database, &found);
295 // database.name is not filled in by the implementation.
296 EXPECT_EQ(version, database.version);
297 EXPECT_EQ(int_version, database.int_version);
298 EXPECT_EQ(database_id, database.id);
300 ok = backing_store_->GetObjectStores(database.id, &database.object_stores);
303 EXPECT_EQ(1UL, database.object_stores.size());
304 IndexedDBObjectStoreMetadata object_store =
305 database.object_stores[object_store_id];
306 EXPECT_EQ(object_store_name, object_store.name);
307 EXPECT_EQ(object_store_key_path, object_store.key_path);
308 EXPECT_EQ(auto_increment, object_store.auto_increment);
310 EXPECT_EQ(1UL, object_store.indexes.size());
311 IndexedDBIndexMetadata index = object_store.indexes[index_id];
312 EXPECT_EQ(index_name, index.name);
313 EXPECT_EQ(index_key_path, index.key_path);
314 EXPECT_EQ(unique, index.unique);
315 EXPECT_EQ(multi_entry, index.multi_entry);
321 } // namespace content