OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 var overallTestStartTime = Date.now(); | 5 var overallTestStartTime = Date.now(); |
6 var kUseIndex = true; | 6 var kUseIndex = true; |
7 var kDontUseIndex = false; | 7 var kDontUseIndex = false; |
8 var kReadKeysOnly = true; | 8 var kReadKeysOnly = true; |
9 var kReadDataToo = false; | 9 var kReadDataToo = false; |
10 var kWriteToo = true; | 10 var kWriteToo = true; |
11 var kDontWrite = false; | 11 var kDontWrite = false; |
| 12 var kWriteSameStore = true; |
| 13 var kWriteDifferentStore = false; |
| 14 var kPlaceholderArg = false; |
12 | 15 |
13 var tests = [ | 16 var tests = [ |
| 17 // Create a single small item in a single object store, then delete everything. |
| 18 [testCreateAndDeleteDatabase, 1, 1, 1], |
| 19 // Create a single small item in a single object store, then delete everything. |
| 20 [testCreateAndDeleteDatabase, 100, 1, 1], |
| 21 // Create a single small item in a single object store, then delete everything. |
| 22 [testCreateAndDeleteDatabase, 1, 100, 1], |
| 23 // Create a single small item in a single object store, then delete everything. |
| 24 [testCreateAndDeleteDatabase, 100, 1, 10000], |
14 // Create a single small item in a single object store. | 25 // Create a single small item in a single object store. |
15 [testCreateKeysInStores, 1, 1, 1], | 26 [testCreateKeysInStores, 1, 1, 1], |
16 // Create many small items in a single object store. | 27 // Create many small items in a single object store. |
17 [testCreateKeysInStores, 100, 1, 1], | 28 [testCreateKeysInStores, 100, 1, 1], |
18 // Create a single small item in many object stores. | 29 // Create a single small item in many object stores. |
19 [testCreateKeysInStores, 1, 100, 1], | 30 [testCreateKeysInStores, 1, 100, 1], |
20 // Create many large items in a single object store. | 31 // Create many large items in a single object store. |
21 [testCreateKeysInStores, 100, 1, 10000], | 32 [testCreateKeysInStores, 100, 1, 10000], |
22 // Read a few random items in each of many transactions. | 33 // Read a few random items in each of many transactions. |
23 [testRandomReadsAndWrites, 1000, 5, 0, 50, kDontUseIndex], | 34 [testRandomReadsAndWrites, 1000, 5, 0, 50, kDontUseIndex], |
24 // Read many random items in each of a few transactions. | 35 // Read many random items in each of a few transactions. |
25 [testRandomReadsAndWrites, 1000, 50, 0, 5, kDontUseIndex], | 36 [testRandomReadsAndWrites, 1000, 50, 0, 5, kDontUseIndex], |
26 // Read many random items in each of a few transactions, in a large store. | 37 // Read many random items in each of a few transactions, in a large store. |
27 [testRandomReadsAndWrites, 5000, 50, 0, 5, kDontUseIndex], | 38 [testRandomReadsAndWrites, 5000, 50, 0, 5, kDontUseIndex], |
28 // Read a few random items from an index, in each of many transactions. | 39 // Read a few random items from an index, in each of many transactions. |
29 [testRandomReadsAndWrites, 1000, 5, 0, 50, kUseIndex], | 40 [testRandomReadsAndWrites, 1000, 5, 0, 50, kUseIndex], |
30 // Read many random items from an index, in each of a few transactions. | 41 // Read many random items from an index, in each of a few transactions. |
31 [testRandomReadsAndWrites, 1000, 50, 0, 5, kUseIndex], | 42 [testRandomReadsAndWrites, 1000, 50, 0, 5, kUseIndex], |
32 // Read many random items from an index, in each of a few transactions, in a | 43 // Read many random items from an index, in each of a few transactions, in a |
33 // large store. | 44 // large store. |
34 [testRandomReadsAndWrites, 5000, 50, 0, 5, kUseIndex], | 45 [testRandomReadsAndWrites, 5000, 50, 0, 5, kUseIndex], |
35 // Read and write a few random items in each of many transactions. | 46 // Read and write a few random items in each of many transactions. |
36 [testRandomReadsAndWrites, 1000, 5, 5, 50, kDontUseIndex], | 47 [testRandomReadsAndWrites, 1000, 5, 5, 50, kDontUseIndex], |
37 // Read and write a few random items, reading from an index, in each of many | 48 // Read and write a few random items, reading from an index, in each of many |
38 // transactions. | 49 // transactions. |
39 [testRandomReadsAndWrites, 1000, 5, 5, 50, kUseIndex], | 50 [testRandomReadsAndWrites, 1000, 5, 5, 50, kUseIndex], |
40 // Read a long, contiguous sequence of an object store via a cursor. | 51 // Read a long, contiguous sequence of an object store via a cursor. |
41 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kDontWrite], | 52 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kDontWrite, |
| 53 kPlaceholderArg], |
42 // Read a sequence of an object store via a cursor, writing | 54 // Read a sequence of an object store via a cursor, writing |
43 // transformed values into another. | 55 // transformed values into another. |
44 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo], | 56 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo, |
| 57 kWriteDifferentStore], |
| 58 // Read a sequence of an object store via a cursor, writing |
| 59 // transformed values into another. |
| 60 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo, |
| 61 kWriteSameStore], |
45 // Read a sequence of an index into an object store via a cursor. | 62 // Read a sequence of an index into an object store via a cursor. |
46 [testCursorReadsAndRandomWrites, kReadDataToo, kUseIndex, kDontWrite], | 63 [testCursorReadsAndRandomWrites, kReadDataToo, kUseIndex, kDontWrite, |
| 64 kPlaceholderArg], |
47 // Read a sequence of an index into an object store via a key cursor. | 65 // Read a sequence of an index into an object store via a key cursor. |
48 [testCursorReadsAndRandomWrites, kReadKeysOnly, kUseIndex, kDontWrite], | 66 [testCursorReadsAndRandomWrites, kReadKeysOnly, kUseIndex, kDontWrite, |
| 67 kPlaceholderArg], |
49 // Make batches of random writes into a store, triggered by periodic setTimeout | 68 // Make batches of random writes into a store, triggered by periodic setTimeout |
50 // calls. | 69 // calls. |
51 [testSporadicWrites, 5, 0], | 70 [testSporadicWrites, 5, 0], |
52 // Make large batches of random writes into a store, triggered by periodic | 71 // Make large batches of random writes into a store, triggered by periodic |
53 // setTimeout calls. | 72 // setTimeout calls. |
54 [testSporadicWrites, 50, 0], | 73 [testSporadicWrites, 50, 0], |
55 // Make batches of random writes into a store with many indices, triggered by | 74 // Make batches of random writes into a store with many indices, triggered by |
56 // periodic setTimeout calls. | 75 // periodic setTimeout calls. |
57 [testSporadicWrites, 5, 10], | 76 [testSporadicWrites, 5, 10], |
58 // Make large batches of random writes into a store with many indices, triggered | 77 // Make large batches of random writes into a store with many indices, triggered |
(...skipping 20 matching lines...) Expand all Loading... |
79 onAllTestsComplete(); | 98 onAllTestsComplete(); |
80 } | 99 } |
81 } | 100 } |
82 | 101 |
83 function onAllTestsComplete() { | 102 function onAllTestsComplete() { |
84 var overallDuration = Date.now() - overallTestStartTime; | 103 var overallDuration = Date.now() - overallTestStartTime; |
85 automation.addResult("OverallTestDuration", overallDuration); | 104 automation.addResult("OverallTestDuration", overallDuration); |
86 automation.setDone(); | 105 automation.setDone(); |
87 } | 106 } |
88 | 107 |
| 108 // This is the only test that includes database creation and deletion in its |
| 109 // results; the others just test specific operations. To see only the |
| 110 // creation/deletion without the specific operations used to build up the data |
| 111 // in the object stores here, subtract off the results of |
| 112 // testCreateKeysInStores. |
| 113 function testCreateAndDeleteDatabase( |
| 114 numKeys, numStores, payloadLength, onTestComplete) { |
| 115 var testName = getDisplayName(arguments); |
| 116 assert(numKeys >= 0); |
| 117 assert(numStores >= 1); |
| 118 var objectStoreNames = []; |
| 119 for (var i=0; i < numStores; ++i) { |
| 120 objectStoreNames.push("store " + i); |
| 121 } |
| 122 var value = stringOfLength(payloadLength); |
| 123 function getValue() { |
| 124 return value; |
| 125 } |
| 126 |
| 127 automation.setStatus("Creating database."); |
| 128 var startTime = Date.now(); |
| 129 |
| 130 createDatabase(testName, objectStoreNames, onCreated, onError); |
| 131 |
| 132 function onCreated(db) { |
| 133 automation.setStatus("Constructing transaction."); |
| 134 var transaction = |
| 135 getTransaction(db, objectStoreNames, "readwrite", |
| 136 function() { onValuesWritten(db); }); |
| 137 putLinearValues(transaction, objectStoreNames, numKeys, null, getValue); |
| 138 } |
| 139 |
| 140 function onValuesWritten(db) { |
| 141 automation.setStatus("Deleting database."); |
| 142 db.close(); |
| 143 deleteDatabase(testName, onDeleted); |
| 144 } |
| 145 |
| 146 function onDeleted() { |
| 147 var duration = Date.now() - startTime; |
| 148 automation.addResult(testName, duration); |
| 149 automation.setStatus("Deleted database."); |
| 150 onTestComplete(); |
| 151 } |
| 152 } |
| 153 |
89 function testCreateKeysInStores( | 154 function testCreateKeysInStores( |
90 numKeys, numStores, payloadLength, onTestComplete) { | 155 numKeys, numStores, payloadLength, onTestComplete) { |
91 var testName = getDisplayName(arguments); | 156 var testName = getDisplayName(arguments); |
92 assert(numKeys >= 0); | 157 assert(numKeys >= 0); |
93 assert(numStores >= 1); | 158 assert(numStores >= 1); |
94 var objectStoreNames = []; | 159 var objectStoreNames = []; |
95 for (var i=0; i < numStores; ++i) { | 160 for (var i=0; i < numStores; ++i) { |
96 objectStoreNames.push("store " + i); | 161 objectStoreNames.push("store " + i); |
97 } | 162 } |
98 var value = stringOfLength(payloadLength); | 163 var value = stringOfLength(payloadLength); |
99 function getValue() { | 164 function getValue() { |
100 return value; | 165 return value; |
101 } | 166 } |
102 | 167 |
103 automation.setStatus("Creating database."); | 168 automation.setStatus("Creating database."); |
104 createDatabase(testName, objectStoreNames, onCreated, onError); | 169 createDatabase(testName, objectStoreNames, onCreated, onError); |
105 | 170 |
106 function onCreated(db) { | 171 function onCreated(db) { |
107 automation.setStatus("Constructing transaction."); | 172 automation.setStatus("Constructing transaction."); |
108 var completionFunc = | 173 var completionFunc = |
109 getCompletionFunc(testName, Date.now(), onTestComplete); | 174 getCompletionFunc(db, testName, Date.now(), onTestComplete); |
110 var transaction = | 175 var transaction = |
111 getTransaction(db, objectStoreNames, "readwrite", completionFunc); | 176 getTransaction(db, objectStoreNames, "readwrite", completionFunc); |
112 putLinearValues(transaction, objectStoreNames, numKeys, null, getValue); | 177 putLinearValues(transaction, objectStoreNames, numKeys, null, getValue); |
113 } | 178 } |
114 } | 179 } |
115 | 180 |
116 function testRandomReadsAndWrites( | 181 function testRandomReadsAndWrites( |
117 numKeys, numReadsPerTransaction, numWritesPerTransaction, numTransactions, | 182 numKeys, numReadsPerTransaction, numWritesPerTransaction, numTransactions, |
118 useIndexForReads, onTestComplete) { | 183 useIndexForReads, onTestComplete) { |
119 var indexName; | 184 var indexName; |
(...skipping 20 matching lines...) Expand all Loading... |
140 automation.setStatus("Setting up test database."); | 205 automation.setStatus("Setting up test database."); |
141 var transaction = getTransaction(db, objectStoreNames, "readwrite", | 206 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
142 function() { onSetupComplete(db); }); | 207 function() { onSetupComplete(db); }); |
143 putLinearValues(transaction, objectStoreNames, numKeys, null, | 208 putLinearValues(transaction, objectStoreNames, numKeys, null, |
144 function () { return "test value"; }); | 209 function () { return "test value"; }); |
145 } | 210 } |
146 | 211 |
147 var completionFunc; | 212 var completionFunc; |
148 function onSetupComplete(db) { | 213 function onSetupComplete(db) { |
149 automation.setStatus("Setup complete."); | 214 automation.setStatus("Setup complete."); |
150 completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete); | 215 completionFunc = |
| 216 getCompletionFunc(db, testName, Date.now(), onTestComplete); |
151 runOneBatch(db); | 217 runOneBatch(db); |
152 } | 218 } |
153 | 219 |
154 function runOneBatch(db) { | 220 function runOneBatch(db) { |
155 if (numTransactionsLeft <= 0) { | 221 if (numTransactionsLeft <= 0) { |
156 return; | 222 return; |
157 } | 223 } |
158 --numTransactionsLeft; | 224 --numTransactionsLeft; |
159 ++numTransactionsRunning; | 225 ++numTransactionsRunning; |
160 var mode = "readonly"; | 226 var mode = "readonly"; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 }; | 271 }; |
206 alterObjectStores(testName, objectStoreNames, f, onIndexCreated, onError); | 272 alterObjectStores(testName, objectStoreNames, f, onIndexCreated, onError); |
207 } | 273 } |
208 | 274 |
209 var completionFunc; | 275 var completionFunc; |
210 function onIndexCreated(db) { | 276 function onIndexCreated(db) { |
211 db.close(); | 277 db.close(); |
212 var indexCreationCompleteTime = Date.now(); | 278 var indexCreationCompleteTime = Date.now(); |
213 automation.addResult("testCreateIndex", | 279 automation.addResult("testCreateIndex", |
214 indexCreationCompleteTime - startTime); | 280 indexCreationCompleteTime - startTime); |
215 completionFunc = getCompletionFunc("testDeleteIndex", | 281 completionFunc = getCompletionFunc(db, "testDeleteIndex", |
216 indexCreationCompleteTime, onTestComplete); | 282 indexCreationCompleteTime, onTestComplete); |
217 var f = function(objectStore) { | 283 var f = function(objectStore) { |
218 objectStore.deleteIndex("index"); | 284 objectStore.deleteIndex("index"); |
219 }; | 285 }; |
220 automation.setStatus("Deleting index."); | 286 automation.setStatus("Deleting index."); |
221 alterObjectStores(testName, objectStoreNames, f, completionFunc, onError); | 287 alterObjectStores(testName, objectStoreNames, f, completionFunc, onError); |
222 } | 288 } |
223 } | 289 } |
224 | 290 |
225 // TODO: Add a version that writes back to the same store, to see how that | |
226 // affects cursor speed w.r.t. invalidated caches. | |
227 function testCursorReadsAndRandomWrites( | 291 function testCursorReadsAndRandomWrites( |
228 readKeysOnly, useIndexForReads, writeToAnotherStore, onTestComplete) { | 292 readKeysOnly, useIndexForReads, writeAlso, sameStoreForWrites, |
| 293 onTestComplete) { |
229 // There's no key cursor unless you're reading from an index. | 294 // There's no key cursor unless you're reading from an index. |
230 assert(useIndexForReads || !readKeysOnly); | 295 assert(useIndexForReads || !readKeysOnly); |
231 // If we're writing to another store, having an index would constrain our | 296 // If we're writing to another store, having an index would constrain our |
232 // writes, as we create both object stores with the same configurations. | 297 // writes, as we create both object stores with the same configurations. |
233 // We could do that if needed, but it's simpler not to. | 298 // We could do that if needed, but it's simpler not to. |
234 assert(!useIndexForReads || !writeToAnotherStore); | 299 assert(!useIndexForReads || !writeAlso); |
235 var numKeys = 1000; | 300 var numKeys = 1000; |
236 var numReadsPerTransaction = 100; | 301 var numReadsPerTransaction = 100; |
237 var testName = getDisplayName(arguments); | 302 var testName = getDisplayName(arguments); |
238 var objectStoreNames = ["input store"]; | 303 var objectStoreNames = ["input store"]; |
239 if (writeToAnotherStore) | 304 var outputStoreName; |
240 objectStoreNames.push("output store"); | 305 if (writeAlso) { |
| 306 if (sameStoreForWrites) { |
| 307 outputStoreName = objectStoreNames[0]; |
| 308 } else { |
| 309 outputStoreName = "output store"; |
| 310 objectStoreNames.push(outputStoreName); |
| 311 } |
| 312 } |
241 var getKeyForRead = getSimpleKey; | 313 var getKeyForRead = getSimpleKey; |
242 var indexName; | 314 var indexName; |
243 if (useIndexForReads) { | 315 if (useIndexForReads) { |
244 indexName = "index"; | 316 indexName = "index"; |
245 getKeyForRead = function(i) { | 317 getKeyForRead = function(i) { |
246 // This depends on the implementations of getValuesFromCursor and | 318 // This depends on the implementations of getValuesFromCursor and |
247 // getObjectValue. We reverse the order of the iteration here so that | 319 // getObjectValue. We reverse the order of the iteration here so that |
248 // setting up bounds from k to k+n with n>0 works. Without this reversal, | 320 // setting up bounds from k to k+n with n>0 works. Without this reversal, |
249 // the upper bound is below the lower bound. | 321 // the upper bound is below the lower bound. |
250 return getBackwardIndexKey(numKeys - i); | 322 return getBackwardIndexKey(numKeys - i); |
(...skipping 15 matching lines...) Expand all Loading... |
266 function onCreated(db) { | 338 function onCreated(db) { |
267 automation.setStatus("Setting up test database."); | 339 automation.setStatus("Setting up test database."); |
268 var transaction = getTransaction(db, objectStoreNames, "readwrite", | 340 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
269 function() { onSetupComplete(db); }); | 341 function() { onSetupComplete(db); }); |
270 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, | 342 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, |
271 getObjectValue); | 343 getObjectValue); |
272 } | 344 } |
273 function onSetupComplete(db) { | 345 function onSetupComplete(db) { |
274 automation.setStatus("Setup complete."); | 346 automation.setStatus("Setup complete."); |
275 var completionFunc = | 347 var completionFunc = |
276 getCompletionFunc(testName, Date.now(), onTestComplete); | 348 getCompletionFunc(db, testName, Date.now(), onTestComplete); |
277 var mode = "readonly"; | 349 var mode = "readonly"; |
278 if (writeToAnotherStore) | 350 if (writeAlso) |
279 mode = "readwrite"; | 351 mode = "readwrite"; |
280 var transaction = | 352 var transaction = |
281 getTransaction(db, objectStoreNames, mode, completionFunc); | 353 getTransaction(db, objectStoreNames, mode, completionFunc); |
282 | 354 |
283 getValuesFromCursor( | 355 getValuesFromCursor( |
284 transaction, objectStoreNames[0], numReadsPerTransaction, numKeys, | 356 transaction, objectStoreNames[0], numReadsPerTransaction, numKeys, |
285 indexName, getKeyForRead, readKeysOnly, objectStoreNames[1]); | 357 indexName, getKeyForRead, readKeysOnly, outputStoreName); |
286 } | 358 } |
287 } | 359 } |
288 | 360 |
289 function testSporadicWrites( | 361 function testSporadicWrites( |
290 numWritesPerTransaction, numIndices, onTestComplete) { | 362 numWritesPerTransaction, numIndices, onTestComplete) { |
291 var numKeys = 1000; | 363 var numKeys = 1000; |
292 // With 30 transactions, spaced 50ms apart, we'll need at least 1.5s. | 364 // With 30 transactions, spaced 50ms apart, we'll need at least 1.5s. |
293 var numTransactions = 30; | 365 var numTransactions = 30; |
294 var delayBetweenBatches = 50; | 366 var delayBetweenBatches = 50; |
295 var indexName; | 367 var indexName; |
(...skipping 21 matching lines...) Expand all Loading... |
317 function onCreated(db) { | 389 function onCreated(db) { |
318 automation.setStatus("Setting up test database."); | 390 automation.setStatus("Setting up test database."); |
319 var transaction = getTransaction(db, objectStoreNames, "readwrite", | 391 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
320 function() { onSetupComplete(db); }); | 392 function() { onSetupComplete(db); }); |
321 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, | 393 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, |
322 getValue); | 394 getValue); |
323 } | 395 } |
324 var completionFunc; | 396 var completionFunc; |
325 function onSetupComplete(db) { | 397 function onSetupComplete(db) { |
326 automation.setStatus("Setup complete."); | 398 automation.setStatus("Setup complete."); |
327 completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete); | 399 completionFunc = |
| 400 getCompletionFunc(db, testName, Date.now(), onTestComplete); |
328 runOneBatch(db); | 401 runOneBatch(db); |
329 } | 402 } |
330 | 403 |
331 function runOneBatch(db) { | 404 function runOneBatch(db) { |
332 assert(numTransactionsLeft); | 405 assert(numTransactionsLeft); |
333 if (--numTransactionsLeft) { | 406 if (--numTransactionsLeft) { |
334 setTimeout(function () { runOneBatch(db); }, delayBetweenBatches); | 407 setTimeout(function () { runOneBatch(db); }, delayBetweenBatches); |
335 } | 408 } |
336 ++numTransactionsRunning; | 409 ++numTransactionsRunning; |
337 | 410 |
338 function batchComplete() { | 411 function batchComplete() { |
339 assert(numTransactionsRunning); | 412 assert(numTransactionsRunning); |
340 if (!--numTransactionsRunning && !numTransactionsLeft) | 413 if (!--numTransactionsRunning && !numTransactionsLeft) |
341 completionFunc(); | 414 completionFunc(); |
342 } | 415 } |
343 | 416 |
344 var mode = "readonly"; | 417 var mode = "readonly"; |
345 if (numWritesPerTransaction) | 418 if (numWritesPerTransaction) |
346 mode = "readwrite"; | 419 mode = "readwrite"; |
347 | 420 |
348 var transaction = getTransaction(db, objectStoreNames, mode, batchComplete); | 421 var transaction = getTransaction(db, objectStoreNames, mode, batchComplete); |
349 putRandomValues(transaction, objectStoreNames, numWritesPerTransaction, | 422 putRandomValues(transaction, objectStoreNames, numWritesPerTransaction, |
350 numKeys); | 423 numKeys); |
351 } | 424 } |
352 } | 425 } |
OLD | NEW |