IndexedDB: Use WeakPtr for Factory-to-BackingStore reference
[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 "SharedBuffer.h"
32
33 #include <gtest/gtest.h>
34 #include <webkit/support/webkit_support.h>
35
36 #if ENABLE(INDEXED_DATABASE)
37
38 using namespace WebCore;
39
40 namespace {
41
42 class IDBBackingStoreTest : public testing::Test {
43 public:
44     IDBBackingStoreTest() { }
45     void SetUp()
46     {
47         SecurityOrigin* securityOrigin = 0;
48         // Empty pathBase means an in-memory database.
49         String pathBase;
50         String fileIdentifier;
51         m_backingStore = IDBBackingStore::open(securityOrigin, pathBase, fileIdentifier);
52
53         // useful keys and values during tests
54         const char rawValue1[] = "value1";
55         const char rawValue2[] = "value2";
56         m_value1.append(rawValue1, sizeof(rawValue1));
57         m_value2.append(rawValue2, sizeof(rawValue2));
58         m_key1 = IDBKey::createNumber(99);
59         m_key2 = IDBKey::createString("key2");
60     }
61
62 protected:
63     RefPtr<IDBBackingStore> m_backingStore;
64
65     // Sample keys and values that are consistent.
66     RefPtr<IDBKey> m_key1;
67     RefPtr<IDBKey> m_key2;
68     Vector<char> m_value1;
69     Vector<char> m_value2;
70 };
71
72 TEST_F(IDBBackingStoreTest, PutGetConsistency)
73 {
74     {
75         IDBBackingStore::Transaction transaction1(m_backingStore.get());
76         transaction1.begin();
77         IDBBackingStore::RecordIdentifier record;
78         bool ok = m_backingStore->putRecord(&transaction1, 1, 1, *m_key1.get(), SharedBuffer::create(m_value1.data(), m_value1.size()), &record);
79         EXPECT_TRUE(ok);
80         transaction1.commit();
81     }
82
83     {
84         IDBBackingStore::Transaction transaction2(m_backingStore.get());
85         transaction2.begin();
86         Vector<char> resultValue;
87         bool ok = m_backingStore->getRecord(&transaction2, 1, 1, *m_key1.get(), resultValue);
88         transaction2.commit();
89         EXPECT_TRUE(ok);
90         EXPECT_EQ(m_value1, resultValue);
91     }
92 }
93
94 // Make sure that using very high ( more than 32 bit ) values for databaseId and objectStoreId still work.
95 TEST_F(IDBBackingStoreTest, HighIds)
96 {
97     const int64_t highDatabaseId = 1ULL << 35;
98     const int64_t highObjectStoreId = 1ULL << 39;
99     {
100         IDBBackingStore::Transaction transaction1(m_backingStore.get());
101         transaction1.begin();
102         IDBBackingStore::RecordIdentifier record;
103         bool ok = m_backingStore->putRecord(&transaction1, highDatabaseId, highObjectStoreId, *m_key1.get(), SharedBuffer::create(m_value1.data(), m_value1.size()), &record);
104         EXPECT_TRUE(ok);
105         ok = transaction1.commit();
106         EXPECT_TRUE(ok);
107     }
108
109     {
110         IDBBackingStore::Transaction transaction2(m_backingStore.get());
111         transaction2.begin();
112         Vector<char> resultValue;
113         bool ok = m_backingStore->getRecord(&transaction2, highDatabaseId, highObjectStoreId, *m_key1.get(), resultValue);
114         EXPECT_TRUE(ok);
115         ok = transaction2.commit();
116         EXPECT_TRUE(ok);
117         EXPECT_EQ(m_value1, resultValue);
118     }
119 }
120
121 TEST_F(IDBBackingStoreTest, CreateDatabase)
122 {
123     const String databaseName("db1");
124     int64_t databaseId;
125     const String version("oldStringVersion");
126     const int64_t intVersion = 9;
127
128     const int64_t objectStoreId = 99;
129     const String objectStoreName("objectStore1");
130     const bool autoIncrement = true;
131     const IDBKeyPath objectStoreKeyPath("objectStoreKey");
132
133     const int64_t indexId = 999;
134     const String indexName("index1");
135     const bool unique = true;
136     const bool multiEntry = true;
137     const IDBKeyPath indexKeyPath("indexKey");
138
139     {
140         bool ok = m_backingStore->createIDBDatabaseMetaData(databaseName, version, intVersion, databaseId);
141         EXPECT_TRUE(ok);
142         EXPECT_GT(databaseId, 0);
143
144         IDBBackingStore::Transaction transaction(m_backingStore.get());
145         transaction.begin();
146
147         ok = m_backingStore->createObjectStore(&transaction, databaseId, objectStoreId, objectStoreName, objectStoreKeyPath, autoIncrement);
148         EXPECT_TRUE(ok);
149
150         ok = m_backingStore->createIndex(&transaction, databaseId, objectStoreId, indexId, indexName, indexKeyPath, unique, multiEntry);
151         EXPECT_TRUE(ok);
152
153         ok = transaction.commit();
154         EXPECT_TRUE(ok);
155     }
156
157     {
158         IDBDatabaseMetadata database;
159         bool found;
160         bool ok = m_backingStore->getIDBDatabaseMetaData(databaseName, &database, found);
161         EXPECT_TRUE(ok);
162         EXPECT_TRUE(found);
163
164         // database.name is not filled in by the implementation.
165         EXPECT_EQ(version, database.version);
166         EXPECT_EQ(intVersion, database.intVersion);
167         EXPECT_EQ(databaseId, database.id);
168
169         m_backingStore->getObjectStores(database.id, &database.objectStores);
170
171         EXPECT_EQ(1, database.objectStores.size());
172         IDBObjectStoreMetadata objectStore = database.objectStores.get(objectStoreId);
173         EXPECT_EQ(objectStoreName, objectStore.name);
174         EXPECT_EQ(objectStoreKeyPath, objectStore.keyPath);
175         EXPECT_EQ(autoIncrement, objectStore.autoIncrement);
176
177         EXPECT_EQ(1, objectStore.indexes.size());
178         IDBIndexMetadata index = objectStore.indexes.get(indexId);
179         EXPECT_EQ(indexName, index.name);
180         EXPECT_EQ(indexKeyPath, index.keyPath);
181         EXPECT_EQ(unique, index.unique);
182         EXPECT_EQ(multiEntry, index.multiEntry);
183     }
184 }
185
186 class MockIDBFactoryBackend : public IDBFactoryBackendImpl {
187 public:
188     static PassRefPtr<MockIDBFactoryBackend> create()
189     {
190         return adoptRef(new MockIDBFactoryBackend());
191     }
192
193     PassRefPtr<IDBBackingStore> testOpenBackingStore(PassRefPtr<SecurityOrigin> origin, const String& dataDirectory)
194     {
195         return openBackingStore(origin, dataDirectory);
196     }
197 };
198
199 TEST(IDBFactoryBackendTest, BackingStoreLifetime)
200 {
201     RefPtr<SecurityOrigin> origin1 = SecurityOrigin::create("http", "localhost", 81);
202     RefPtr<SecurityOrigin> origin2 = SecurityOrigin::create("http", "localhost", 82);
203
204     RefPtr<MockIDBFactoryBackend> factory = MockIDBFactoryBackend::create();
205
206     OwnPtr<webkit_support::ScopedTempDirectory> tempDirectory = adoptPtr(webkit_support::CreateScopedTempDirectory());
207     tempDirectory->CreateUniqueTempDir();
208     const String path = String::fromUTF8(tempDirectory->path().c_str());
209
210     RefPtr<IDBBackingStore> diskStore1 = factory->testOpenBackingStore(origin1, path);
211     EXPECT_TRUE(diskStore1->hasOneRef());
212
213     RefPtr<IDBBackingStore> diskStore2 = factory->testOpenBackingStore(origin1, path);
214     EXPECT_EQ(diskStore2.get(), diskStore1.get());
215     EXPECT_EQ(diskStore2->refCount(), 2);
216
217     RefPtr<IDBBackingStore> diskStore3 = factory->testOpenBackingStore(origin2, path);
218     EXPECT_TRUE(diskStore3->hasOneRef());
219     EXPECT_EQ(diskStore1->refCount(), 2);
220 }
221
222 } // namespace
223
224 #endif // ENABLE(INDEXED_DATABASE)