WinCairo build fails to link.
[WebKit-https.git] / Source / WebKit / chromium / tests / IDBBackingStoreTest.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "IDBBackingStore.h"
29
30 #include "IDBFactoryBackendImpl.h"
31 #include "IDBLevelDBCoding.h"
32 #include "SecurityOrigin.h"
33 #include "SharedBuffer.h"
34
35 #include <gtest/gtest.h>
36 #include <webkit/support/webkit_support.h>
37
38 #if ENABLE(INDEXED_DATABASE)
39
40 using namespace WebCore;
41 using IDBLevelDBCoding::KeyPrefix;
42
43 namespace {
44
45 class IDBBackingStoreTest : public testing::Test {
46 public:
47     IDBBackingStoreTest() { }
48     void SetUp()
49     {
50         SecurityOrigin* securityOrigin = 0;
51         String fileIdentifier;
52         m_backingStore = IDBBackingStore::openInMemory(securityOrigin, fileIdentifier);
53
54         // useful keys and values during tests
55         const char rawValue1[] = "value1";
56         const char rawValue2[] = "value2";
57         const char rawValue3[] = "value3";
58         m_value1.append(rawValue1, sizeof(rawValue1));
59         m_value2.append(rawValue2, sizeof(rawValue2));
60         m_value3.append(rawValue3, sizeof(rawValue3));
61         m_key1 = IDBKey::createNumber(99);
62         m_key2 = IDBKey::createString("key2");
63         m_key3 = IDBKey::createString("key3");
64     }
65
66 protected:
67     RefPtr<IDBBackingStore> m_backingStore;
68
69     // Sample keys and values that are consistent.
70     RefPtr<IDBKey> m_key1;
71     RefPtr<IDBKey> m_key2;
72     RefPtr<IDBKey> m_key3;
73     Vector<char> m_value1;
74     Vector<char> m_value2;
75     Vector<char> m_value3;
76 };
77
78 TEST_F(IDBBackingStoreTest, PutGetConsistency)
79 {
80     {
81         IDBBackingStore::Transaction transaction1(m_backingStore.get());
82         transaction1.begin();
83         IDBBackingStore::RecordIdentifier record;
84         bool ok = m_backingStore->putRecord(&transaction1, 1, 1, *m_key1.get(), SharedBuffer::create(m_value1.data(), m_value1.size()), &record);
85         EXPECT_TRUE(ok);
86         transaction1.commit();
87     }
88
89     {
90         IDBBackingStore::Transaction transaction2(m_backingStore.get());
91         transaction2.begin();
92         Vector<char> resultValue;
93         bool ok = m_backingStore->getRecord(&transaction2, 1, 1, *m_key1.get(), resultValue);
94         transaction2.commit();
95         EXPECT_TRUE(ok);
96         EXPECT_EQ(m_value1, resultValue);
97     }
98 }
99
100 // Make sure that using very high ( more than 32 bit ) values for databaseId and objectStoreId still work.
101 TEST_F(IDBBackingStoreTest, HighIds)
102 {
103     const int64_t highDatabaseId = 1ULL << 35;
104     const int64_t highObjectStoreId = 1ULL << 39;
105     // indexIds are capped at 32 bits for storage purposes.
106     const int64_t highIndexId = 1ULL << 29;
107
108     const int64_t invalidHighIndexId = 1ULL << 37;
109
110     const RefPtr<IDBKey> indexKey = m_key2;
111     Vector<char> indexKeyRaw = IDBLevelDBCoding::encodeIDBKey(*indexKey);
112     {
113         IDBBackingStore::Transaction transaction1(m_backingStore.get());
114         transaction1.begin();
115         IDBBackingStore::RecordIdentifier record;
116         bool ok = m_backingStore->putRecord(&transaction1, highDatabaseId, highObjectStoreId, *m_key1.get(), SharedBuffer::create(m_value1.data(), m_value1.size()), &record);
117         EXPECT_TRUE(ok);
118
119         ok = m_backingStore->putIndexDataForRecord(&transaction1, highDatabaseId, highObjectStoreId, invalidHighIndexId, *indexKey, record);
120         EXPECT_FALSE(ok);
121
122         ok = m_backingStore->putIndexDataForRecord(&transaction1, highDatabaseId, highObjectStoreId, highIndexId, *indexKey, record);
123         EXPECT_TRUE(ok);
124
125         ok = transaction1.commit();
126         EXPECT_TRUE(ok);
127     }
128
129     {
130         IDBBackingStore::Transaction transaction2(m_backingStore.get());
131         transaction2.begin();
132         Vector<char> resultValue;
133         bool ok = m_backingStore->getRecord(&transaction2, highDatabaseId, highObjectStoreId, *m_key1.get(), resultValue);
134         EXPECT_TRUE(ok);
135         EXPECT_EQ(m_value1, resultValue);
136
137         RefPtr<IDBKey> newPrimaryKey;
138         ok = m_backingStore->getPrimaryKeyViaIndex(&transaction2, highDatabaseId, highObjectStoreId, invalidHighIndexId, *indexKey, newPrimaryKey);
139         EXPECT_FALSE(ok);
140
141         ok = m_backingStore->getPrimaryKeyViaIndex(&transaction2, highDatabaseId, highObjectStoreId, highIndexId, *indexKey, newPrimaryKey);
142         EXPECT_TRUE(ok);
143         EXPECT_TRUE(newPrimaryKey->isEqual(m_key1.get()));
144
145         ok = transaction2.commit();
146         EXPECT_TRUE(ok);
147     }
148 }
149
150 // Make sure that other invalid ids do not crash.
151 TEST_F(IDBBackingStoreTest, InvalidIds)
152 {
153     // valid ids for use when testing invalid ids
154     const int64_t databaseId = 1;
155     const int64_t objectStoreId = 1;
156     const int64_t indexId = IDBLevelDBCoding::MinimumIndexId;
157     const int64_t invalidLowIndexId = 19; // indexIds must be > IDBLevelDBCoding::MinimumIndexId
158
159     const RefPtr<SharedBuffer> value = SharedBuffer::create(m_value1.data(), m_value1.size());
160     Vector<char> resultValue;
161
162     IDBBackingStore::Transaction transaction1(m_backingStore.get());
163     transaction1.begin();
164
165     IDBBackingStore::RecordIdentifier record;
166     bool ok = m_backingStore->putRecord(&transaction1, databaseId, KeyPrefix::InvalidId, *m_key1.get(), value, &record);
167     EXPECT_FALSE(ok);
168     ok = m_backingStore->putRecord(&transaction1, databaseId, 0, *m_key1.get(), value, &record);
169     EXPECT_FALSE(ok);
170     ok = m_backingStore->putRecord(&transaction1, KeyPrefix::InvalidId, objectStoreId, *m_key1.get(), value, &record);
171     EXPECT_FALSE(ok);
172     ok = m_backingStore->putRecord(&transaction1, 0, objectStoreId, *m_key1.get(), value, &record);
173     EXPECT_FALSE(ok);
174
175     ok = m_backingStore->getRecord(&transaction1, databaseId, KeyPrefix::InvalidId, *m_key1.get(), resultValue);
176     EXPECT_FALSE(ok);
177     ok = m_backingStore->getRecord(&transaction1, databaseId, 0, *m_key1.get(), resultValue);
178     EXPECT_FALSE(ok);
179     ok = m_backingStore->getRecord(&transaction1, KeyPrefix::InvalidId, objectStoreId, *m_key1.get(), resultValue);
180     EXPECT_FALSE(ok);
181     ok = m_backingStore->getRecord(&transaction1, 0, objectStoreId, *m_key1.get(), resultValue);
182     EXPECT_FALSE(ok);
183
184     RefPtr<IDBKey> newPrimaryKey;
185     ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, KeyPrefix::InvalidId, *m_key1, newPrimaryKey);
186     EXPECT_FALSE(ok);
187     ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, invalidLowIndexId, *m_key1, newPrimaryKey);
188     EXPECT_FALSE(ok);
189     ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, objectStoreId, 0, *m_key1, newPrimaryKey);
190     EXPECT_FALSE(ok);
191
192     ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, KeyPrefix::InvalidId, objectStoreId, indexId, *m_key1, newPrimaryKey);
193     EXPECT_FALSE(ok);
194     ok = m_backingStore->getPrimaryKeyViaIndex(&transaction1, databaseId, KeyPrefix::InvalidId, indexId, *m_key1, newPrimaryKey);
195     EXPECT_FALSE(ok);
196 }
197
198 TEST_F(IDBBackingStoreTest, CreateDatabase)
199 {
200     const String databaseName("db1");
201     int64_t databaseId;
202     const String version("oldStringVersion");
203     const int64_t intVersion = 9;
204
205     const int64_t objectStoreId = 99;
206     const String objectStoreName("objectStore1");
207     const bool autoIncrement = true;
208     const IDBKeyPath objectStoreKeyPath("objectStoreKey");
209
210     const int64_t indexId = 999;
211     const String indexName("index1");
212     const bool unique = true;
213     const bool multiEntry = true;
214     const IDBKeyPath indexKeyPath("indexKey");
215
216     {
217         bool ok = m_backingStore->createIDBDatabaseMetaData(databaseName, version, intVersion, databaseId);
218         EXPECT_TRUE(ok);
219         EXPECT_GT(databaseId, 0);
220
221         IDBBackingStore::Transaction transaction(m_backingStore.get());
222         transaction.begin();
223
224         ok = m_backingStore->createObjectStore(&transaction, databaseId, objectStoreId, objectStoreName, objectStoreKeyPath, autoIncrement);
225         EXPECT_TRUE(ok);
226
227         ok = m_backingStore->createIndex(&transaction, databaseId, objectStoreId, indexId, indexName, indexKeyPath, unique, multiEntry);
228         EXPECT_TRUE(ok);
229
230         ok = transaction.commit();
231         EXPECT_TRUE(ok);
232     }
233
234     {
235         IDBDatabaseMetadata database;
236         bool found;
237         bool ok = m_backingStore->getIDBDatabaseMetaData(databaseName, &database, found);
238         EXPECT_TRUE(ok);
239         EXPECT_TRUE(found);
240
241         // database.name is not filled in by the implementation.
242         EXPECT_EQ(version, database.version);
243         EXPECT_EQ(intVersion, database.intVersion);
244         EXPECT_EQ(databaseId, database.id);
245
246         ok = m_backingStore->getObjectStores(database.id, &database.objectStores);
247         EXPECT_TRUE(ok);
248
249         EXPECT_EQ(1, database.objectStores.size());
250         IDBObjectStoreMetadata objectStore = database.objectStores.get(objectStoreId);
251         EXPECT_EQ(objectStoreName, objectStore.name);
252         EXPECT_EQ(objectStoreKeyPath, objectStore.keyPath);
253         EXPECT_EQ(autoIncrement, objectStore.autoIncrement);
254
255         EXPECT_EQ(1, objectStore.indexes.size());
256         IDBIndexMetadata index = objectStore.indexes.get(indexId);
257         EXPECT_EQ(indexName, index.name);
258         EXPECT_EQ(indexKeyPath, index.keyPath);
259         EXPECT_EQ(unique, index.unique);
260         EXPECT_EQ(multiEntry, index.multiEntry);
261     }
262 }
263
264 class MockIDBFactoryBackend : public IDBFactoryBackendImpl {
265 public:
266     static PassRefPtr<MockIDBFactoryBackend> create()
267     {
268         return adoptRef(new MockIDBFactoryBackend());
269     }
270
271     PassRefPtr<IDBBackingStore> testOpenBackingStore(PassRefPtr<SecurityOrigin> origin, const String& dataDirectory)
272     {
273         return openBackingStore(origin, dataDirectory);
274     }
275 };
276
277 TEST(IDBFactoryBackendTest, BackingStoreLifetime)
278 {
279     RefPtr<SecurityOrigin> origin1 = SecurityOrigin::create("http", "localhost", 81);
280     RefPtr<SecurityOrigin> origin2 = SecurityOrigin::create("http", "localhost", 82);
281
282     RefPtr<MockIDBFactoryBackend> factory = MockIDBFactoryBackend::create();
283
284     OwnPtr<webkit_support::ScopedTempDirectory> tempDirectory = adoptPtr(webkit_support::CreateScopedTempDirectory());
285     tempDirectory->CreateUniqueTempDir();
286     const String path = String::fromUTF8(tempDirectory->path().c_str());
287
288     RefPtr<IDBBackingStore> diskStore1 = factory->testOpenBackingStore(origin1, path);
289     EXPECT_TRUE(diskStore1->hasOneRef());
290
291     RefPtr<IDBBackingStore> diskStore2 = factory->testOpenBackingStore(origin1, path);
292     EXPECT_EQ(diskStore1.get(), diskStore2.get());
293     EXPECT_EQ(2, diskStore2->refCount());
294
295     RefPtr<IDBBackingStore> diskStore3 = factory->testOpenBackingStore(origin2, path);
296     EXPECT_TRUE(diskStore3->hasOneRef());
297     EXPECT_EQ(2, diskStore1->refCount());
298 }
299
300 TEST(IDBFactoryBackendTest, MemoryBackingStoreLifetime)
301 {
302     RefPtr<SecurityOrigin> origin1 = SecurityOrigin::create("http", "localhost", 81);
303     RefPtr<SecurityOrigin> origin2 = SecurityOrigin::create("http", "localhost", 82);
304
305     RefPtr<MockIDBFactoryBackend> factory = MockIDBFactoryBackend::create();
306     RefPtr<IDBBackingStore> memStore1 = factory->testOpenBackingStore(origin1, String());
307     EXPECT_EQ(2, memStore1->refCount());
308     RefPtr<IDBBackingStore> memStore2 = factory->testOpenBackingStore(origin1, String());
309     EXPECT_EQ(memStore1.get(), memStore2.get());
310     EXPECT_EQ(3, memStore2->refCount());
311
312     RefPtr<IDBBackingStore> memStore3 = factory->testOpenBackingStore(origin2, String());
313     EXPECT_EQ(2, memStore3->refCount());
314     EXPECT_EQ(3, memStore1->refCount());
315
316     factory.clear();
317     EXPECT_EQ(2, memStore1->refCount());
318     EXPECT_EQ(1, memStore3->refCount());
319 }
320
321 } // namespace
322
323 #endif // ENABLE(INDEXED_DATABASE)