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 "content/browser/indexed_db/indexed_db_value.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
15 using base::ASCIIToUTF16;
21 class IndexedDBBackingStoreTest : public testing::Test {
23 IndexedDBBackingStoreTest() {}
24 virtual void SetUp() {
25 const GURL origin("http://localhost:81");
26 backing_store_ = IndexedDBBackingStore::OpenInMemory(origin);
28 // useful keys and values during tests
29 m_value1 = IndexedDBValue("value1", std::vector<IndexedDBBlobInfo>());
30 m_value2 = IndexedDBValue("value2", std::vector<IndexedDBBlobInfo>());
32 m_key1 = IndexedDBKey(99, blink::WebIDBKeyTypeNumber);
33 m_key2 = IndexedDBKey(ASCIIToUTF16("key2"));
37 scoped_refptr<IndexedDBBackingStore> backing_store_;
39 // Sample keys and values that are consistent.
42 IndexedDBValue m_value1;
43 IndexedDBValue m_value2;
46 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest);
49 TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
51 IndexedDBBackingStore::Transaction transaction1(backing_store_);
53 IndexedDBBackingStore::RecordIdentifier record;
54 leveldb::Status s = backing_store_->PutRecord(
55 &transaction1, 1, 1, m_key1, m_value1, &record);
57 transaction1.Commit();
61 IndexedDBBackingStore::Transaction transaction2(backing_store_);
63 IndexedDBValue result_value;
65 backing_store_->GetRecord(&transaction2, 1, 1, m_key1, &result_value);
66 transaction2.Commit();
68 EXPECT_EQ(m_value1.bits, result_value.bits);
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 leveldb::Status s = backing_store_->PutRecord(&transaction1,
97 s = backing_store_->PutIndexDataForRecord(&transaction1,
100 invalid_high_index_id,
103 EXPECT_FALSE(s.ok());
105 s = backing_store_->PutIndexDataForRecord(&transaction1,
107 high_object_store_id,
113 s = transaction1.Commit();
118 IndexedDBBackingStore::Transaction transaction2(backing_store_);
119 transaction2.Begin();
120 IndexedDBValue result_value;
121 leveldb::Status s = backing_store_->GetRecord(&transaction2,
123 high_object_store_id,
127 EXPECT_EQ(m_value1.bits, result_value.bits);
129 scoped_ptr<IndexedDBKey> new_primary_key;
130 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
132 high_object_store_id,
133 invalid_high_index_id,
136 EXPECT_FALSE(s.ok());
138 s = backing_store_->GetPrimaryKeyViaIndex(&transaction2,
140 high_object_store_id,
145 EXPECT_TRUE(new_primary_key->Equals(m_key1));
147 s = 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 IndexedDBValue result_value;
162 IndexedDBBackingStore::Transaction transaction1(backing_store_);
163 transaction1.Begin();
165 IndexedDBBackingStore::RecordIdentifier record;
166 leveldb::Status s = backing_store_->PutRecord(&transaction1,
168 KeyPrefix::kInvalidId,
172 EXPECT_FALSE(s.ok());
173 s = backing_store_->PutRecord(
174 &transaction1, database_id, 0, m_key1, m_value1, &record);
175 EXPECT_FALSE(s.ok());
176 s = backing_store_->PutRecord(&transaction1,
177 KeyPrefix::kInvalidId,
182 EXPECT_FALSE(s.ok());
183 s = backing_store_->PutRecord(
184 &transaction1, 0, object_store_id, m_key1, m_value1, &record);
185 EXPECT_FALSE(s.ok());
187 s = backing_store_->GetRecord(
188 &transaction1, database_id, KeyPrefix::kInvalidId, m_key1, &result_value);
189 EXPECT_FALSE(s.ok());
190 s = backing_store_->GetRecord(
191 &transaction1, database_id, 0, m_key1, &result_value);
192 EXPECT_FALSE(s.ok());
193 s = backing_store_->GetRecord(&transaction1,
194 KeyPrefix::kInvalidId,
198 EXPECT_FALSE(s.ok());
199 s = backing_store_->GetRecord(
200 &transaction1, 0, object_store_id, m_key1, &result_value);
201 EXPECT_FALSE(s.ok());
203 scoped_ptr<IndexedDBKey> new_primary_key;
204 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
207 KeyPrefix::kInvalidId,
210 EXPECT_FALSE(s.ok());
211 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
214 invalid_low_index_id,
217 EXPECT_FALSE(s.ok());
218 s = backing_store_->GetPrimaryKeyViaIndex(
219 &transaction1, database_id, object_store_id, 0, m_key1, &new_primary_key);
220 EXPECT_FALSE(s.ok());
222 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
223 KeyPrefix::kInvalidId,
228 EXPECT_FALSE(s.ok());
229 s = backing_store_->GetPrimaryKeyViaIndex(&transaction1,
231 KeyPrefix::kInvalidId,
235 EXPECT_FALSE(s.ok());
238 TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
239 const base::string16 database_name(ASCIIToUTF16("db1"));
241 const base::string16 version(ASCIIToUTF16("old_string_version"));
242 const int64 int_version = 9;
244 const int64 object_store_id = 99;
245 const base::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 base::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 leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
258 database_name, version, int_version, &database_id);
260 EXPECT_GT(database_id, 0);
262 IndexedDBBackingStore::Transaction transaction(backing_store_);
265 s = backing_store_->CreateObjectStore(&transaction,
269 object_store_key_path,
273 s = backing_store_->CreateIndex(&transaction,
283 s = transaction.Commit();
288 IndexedDBDatabaseMetadata database;
290 leveldb::Status s = 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 s = 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