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");
27 IndexedDBBackingStore::OpenInMemory(origin
, NULL
/* task_runner */);
29 // useful keys and values during tests
30 m_value1
= IndexedDBValue("value1", std::vector
<IndexedDBBlobInfo
>());
31 m_value2
= IndexedDBValue("value2", std::vector
<IndexedDBBlobInfo
>());
33 m_key1
= IndexedDBKey(99, blink::WebIDBKeyTypeNumber
);
34 m_key2
= IndexedDBKey(ASCIIToUTF16("key2"));
38 scoped_refptr
<IndexedDBBackingStore
> backing_store_
;
40 // Sample keys and values that are consistent.
43 IndexedDBValue m_value1
;
44 IndexedDBValue m_value2
;
47 DISALLOW_COPY_AND_ASSIGN(IndexedDBBackingStoreTest
);
50 TEST_F(IndexedDBBackingStoreTest
, PutGetConsistency
) {
52 IndexedDBBackingStore::Transaction
transaction1(backing_store_
);
54 ScopedVector
<webkit_blob::BlobDataHandle
> handles
;
55 IndexedDBBackingStore::RecordIdentifier record
;
56 leveldb::Status s
= backing_store_
->PutRecord(
57 &transaction1
, 1, 1, m_key1
, m_value1
, &handles
, &record
);
59 transaction1
.Commit();
63 IndexedDBBackingStore::Transaction
transaction2(backing_store_
);
65 IndexedDBValue result_value
;
67 backing_store_
->GetRecord(&transaction2
, 1, 1, m_key1
, &result_value
);
68 transaction2
.Commit();
70 EXPECT_EQ(m_value1
.bits
, result_value
.bits
);
74 // Make sure that using very high ( more than 32 bit ) values for database_id
75 // and object_store_id still work.
76 TEST_F(IndexedDBBackingStoreTest
, HighIds
) {
77 const int64 high_database_id
= 1ULL << 35;
78 const int64 high_object_store_id
= 1ULL << 39;
79 // index_ids are capped at 32 bits for storage purposes.
80 const int64 high_index_id
= 1ULL << 29;
82 const int64 invalid_high_index_id
= 1ULL << 37;
84 const IndexedDBKey
& index_key
= m_key2
;
85 std::string index_key_raw
;
86 EncodeIDBKey(index_key
, &index_key_raw
);
88 IndexedDBBackingStore::Transaction
transaction1(backing_store_
);
90 ScopedVector
<webkit_blob::BlobDataHandle
> handles
;
91 IndexedDBBackingStore::RecordIdentifier record
;
92 leveldb::Status s
= backing_store_
->PutRecord(&transaction1
,
101 s
= backing_store_
->PutIndexDataForRecord(&transaction1
,
103 high_object_store_id
,
104 invalid_high_index_id
,
107 EXPECT_FALSE(s
.ok());
109 s
= backing_store_
->PutIndexDataForRecord(&transaction1
,
111 high_object_store_id
,
117 s
= transaction1
.Commit();
122 IndexedDBBackingStore::Transaction
transaction2(backing_store_
);
123 transaction2
.Begin();
124 IndexedDBValue result_value
;
125 leveldb::Status s
= backing_store_
->GetRecord(&transaction2
,
127 high_object_store_id
,
131 EXPECT_EQ(m_value1
.bits
, result_value
.bits
);
133 scoped_ptr
<IndexedDBKey
> new_primary_key
;
134 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction2
,
136 high_object_store_id
,
137 invalid_high_index_id
,
140 EXPECT_FALSE(s
.ok());
142 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction2
,
144 high_object_store_id
,
149 EXPECT_TRUE(new_primary_key
->Equals(m_key1
));
151 s
= transaction2
.Commit();
156 // Make sure that other invalid ids do not crash.
157 TEST_F(IndexedDBBackingStoreTest
, InvalidIds
) {
158 // valid ids for use when testing invalid ids
159 const int64 database_id
= 1;
160 const int64 object_store_id
= 1;
161 const int64 index_id
= kMinimumIndexId
;
162 const int64 invalid_low_index_id
= 19; // index_ids must be > kMinimumIndexId
164 IndexedDBValue result_value
;
166 IndexedDBBackingStore::Transaction
transaction1(backing_store_
);
167 transaction1
.Begin();
169 ScopedVector
<webkit_blob::BlobDataHandle
> handles
;
170 IndexedDBBackingStore::RecordIdentifier record
;
171 leveldb::Status s
= backing_store_
->PutRecord(&transaction1
,
173 KeyPrefix::kInvalidId
,
178 EXPECT_FALSE(s
.ok());
179 s
= backing_store_
->PutRecord(
180 &transaction1
, database_id
, 0, m_key1
, m_value1
, &handles
, &record
);
181 EXPECT_FALSE(s
.ok());
182 s
= backing_store_
->PutRecord(&transaction1
,
183 KeyPrefix::kInvalidId
,
189 EXPECT_FALSE(s
.ok());
190 s
= backing_store_
->PutRecord(
191 &transaction1
, 0, object_store_id
, m_key1
, m_value1
, &handles
, &record
);
192 EXPECT_FALSE(s
.ok());
194 s
= backing_store_
->GetRecord(
195 &transaction1
, database_id
, KeyPrefix::kInvalidId
, m_key1
, &result_value
);
196 EXPECT_FALSE(s
.ok());
197 s
= backing_store_
->GetRecord(
198 &transaction1
, database_id
, 0, m_key1
, &result_value
);
199 EXPECT_FALSE(s
.ok());
200 s
= backing_store_
->GetRecord(&transaction1
,
201 KeyPrefix::kInvalidId
,
205 EXPECT_FALSE(s
.ok());
206 s
= backing_store_
->GetRecord(
207 &transaction1
, 0, object_store_id
, m_key1
, &result_value
);
208 EXPECT_FALSE(s
.ok());
210 scoped_ptr
<IndexedDBKey
> new_primary_key
;
211 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction1
,
214 KeyPrefix::kInvalidId
,
217 EXPECT_FALSE(s
.ok());
218 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction1
,
221 invalid_low_index_id
,
224 EXPECT_FALSE(s
.ok());
225 s
= backing_store_
->GetPrimaryKeyViaIndex(
226 &transaction1
, database_id
, object_store_id
, 0, m_key1
, &new_primary_key
);
227 EXPECT_FALSE(s
.ok());
229 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction1
,
230 KeyPrefix::kInvalidId
,
235 EXPECT_FALSE(s
.ok());
236 s
= backing_store_
->GetPrimaryKeyViaIndex(&transaction1
,
238 KeyPrefix::kInvalidId
,
242 EXPECT_FALSE(s
.ok());
245 TEST_F(IndexedDBBackingStoreTest
, CreateDatabase
) {
246 const base::string16
database_name(ASCIIToUTF16("db1"));
248 const base::string16
version(ASCIIToUTF16("old_string_version"));
249 const int64 int_version
= 9;
251 const int64 object_store_id
= 99;
252 const base::string16
object_store_name(ASCIIToUTF16("object_store1"));
253 const bool auto_increment
= true;
254 const IndexedDBKeyPath
object_store_key_path(
255 ASCIIToUTF16("object_store_key"));
257 const int64 index_id
= 999;
258 const base::string16
index_name(ASCIIToUTF16("index1"));
259 const bool unique
= true;
260 const bool multi_entry
= true;
261 const IndexedDBKeyPath
index_key_path(ASCIIToUTF16("index_key"));
264 leveldb::Status s
= backing_store_
->CreateIDBDatabaseMetaData(
265 database_name
, version
, int_version
, &database_id
);
267 EXPECT_GT(database_id
, 0);
269 IndexedDBBackingStore::Transaction
transaction(backing_store_
);
272 s
= backing_store_
->CreateObjectStore(&transaction
,
276 object_store_key_path
,
280 s
= backing_store_
->CreateIndex(&transaction
,
290 s
= transaction
.Commit();
295 IndexedDBDatabaseMetadata database
;
297 leveldb::Status s
= backing_store_
->GetIDBDatabaseMetaData(
298 database_name
, &database
, &found
);
302 // database.name is not filled in by the implementation.
303 EXPECT_EQ(version
, database
.version
);
304 EXPECT_EQ(int_version
, database
.int_version
);
305 EXPECT_EQ(database_id
, database
.id
);
307 s
= backing_store_
->GetObjectStores(database
.id
, &database
.object_stores
);
310 EXPECT_EQ(1UL, database
.object_stores
.size());
311 IndexedDBObjectStoreMetadata object_store
=
312 database
.object_stores
[object_store_id
];
313 EXPECT_EQ(object_store_name
, object_store
.name
);
314 EXPECT_EQ(object_store_key_path
, object_store
.key_path
);
315 EXPECT_EQ(auto_increment
, object_store
.auto_increment
);
317 EXPECT_EQ(1UL, object_store
.indexes
.size());
318 IndexedDBIndexMetadata index
= object_store
.indexes
[index_id
];
319 EXPECT_EQ(index_name
, index
.name
);
320 EXPECT_EQ(index_key_path
, index
.key_path
);
321 EXPECT_EQ(unique
, index
.unique
);
322 EXPECT_EQ(multi_entry
, index
.multi_entry
);
328 } // namespace content