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 | 6 |
7 function testCreateKeysInStores( | 7 function testCreateKeysInStores( |
8 numKeys, numStores, payloadLength, onTestComplete) { | 8 numKeys, numStores, payloadLength, onTestComplete) { |
9 var testName = getDisplayName(arguments); | 9 var testName = getDisplayName(arguments); |
10 assert(numKeys >= 0); | 10 assert(numKeys >= 0); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 function onCreated(db) { | 44 function onCreated(db) { |
45 automation.setStatus("Setting up test database."); | 45 automation.setStatus("Setting up test database."); |
46 var transaction = getTransaction(db, objectStoreNames, "readwrite", | 46 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
47 function() { onSetupComplete(db); }); | 47 function() { onSetupComplete(db); }); |
48 putLinearValues(transaction, objectStoreNames, numKeys, null, | 48 putLinearValues(transaction, objectStoreNames, numKeys, null, |
49 function () { return "test value"; }); | 49 function () { return "test value"; }); |
50 } | 50 } |
51 var completionFunc; | 51 var completionFunc; |
52 function onSetupComplete(db) { | 52 function onSetupComplete(db) { |
53 automation.setStatus("Setup complete."); | 53 automation.setStatus("Setup complete."); |
| 54 completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete); |
54 runOneBatch(db); | 55 runOneBatch(db); |
55 completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete); | |
56 } | 56 } |
57 | 57 |
58 function runOneBatch(db) { | 58 function runOneBatch(db) { |
59 if (numTransactionsLeft <= 0) { | 59 if (numTransactionsLeft <= 0) { |
60 return; | 60 return; |
61 } | 61 } |
62 --numTransactionsLeft; | 62 --numTransactionsLeft; |
63 ++numTransactionsRunning; | 63 ++numTransactionsRunning; |
64 var mode = "readonly"; | 64 var mode = "readonly"; |
65 if (numWritesPerTransaction) | 65 if (numWritesPerTransaction) |
66 mode = "readwrite"; | 66 mode = "readwrite"; |
67 var transaction = getTransaction(db, objectStoreNames, mode, | 67 var transaction = getTransaction(db, objectStoreNames, mode, |
68 function() { | 68 function() { |
69 assert(!--numTransactionsRunning); | 69 assert(!--numTransactionsRunning); |
70 if (numTransactionsLeft <= 0) { | 70 if (numTransactionsLeft <= 0) { |
71 completionFunc(); | 71 completionFunc(); |
72 } else { | 72 } else { |
73 runOneBatch(db); | 73 runOneBatch(db); |
74 } | 74 } |
75 }); | 75 }); |
76 | 76 |
77 getRandomValues(transaction, objectStoreNames, numReadsPerTransaction, | 77 getRandomValues(transaction, objectStoreNames, numReadsPerTransaction, |
78 numKeys, indexName); | 78 numKeys, indexName); |
79 putRandomValues(transaction, objectStoreNames, numWritesPerTransaction, | 79 putRandomValues(transaction, objectStoreNames, numWritesPerTransaction, |
80 numKeys); | 80 numKeys); |
81 } | 81 } |
82 | 82 |
83 automation.setStatus("Creating database."); | 83 automation.setStatus("Creating database."); |
84 var options = {}; | 84 var options; |
85 if (useIndexForReads) { | 85 if (useIndexForReads) { |
86 options.indexName = indexName; | 86 options = [{ |
87 options.indexKeyPath = ""; | 87 indexName: indexName, |
88 options.indexIsUnique = false; | 88 indexKeyPath: "", |
89 options.indexIsMultiEntry = false; | 89 indexIsUnique: false, |
| 90 indexIsMultiEntry: false, |
| 91 }]; |
90 } | 92 } |
91 createDatabase(testName, objectStoreNames, onCreated, onError, options); | 93 createDatabase(testName, objectStoreNames, onCreated, onError, options); |
92 } | 94 } |
93 | 95 |
94 function testCreateAndDeleteIndex(numKeys, onTestComplete) { | 96 function testCreateAndDeleteIndex(numKeys, onTestComplete) { |
95 var testName = getDisplayName(arguments); | 97 var testName = getDisplayName(arguments); |
96 var objectStoreNames = ["store"]; | 98 var objectStoreNames = ["store"]; |
97 function getValue(i) { | 99 function getValue(i) { |
98 return { firstName: i + " first name", lastName: i + " last name" }; | 100 return { firstName: i + " first name", lastName: i + " last name" }; |
99 } | 101 } |
(...skipping 28 matching lines...) Expand all Loading... |
128 objectStore.deleteIndex("index"); | 130 objectStore.deleteIndex("index"); |
129 }; | 131 }; |
130 automation.setStatus("Deleting index."); | 132 automation.setStatus("Deleting index."); |
131 alterObjectStores(testName, objectStoreNames, f, completionFunc, onError); | 133 alterObjectStores(testName, objectStoreNames, f, completionFunc, onError); |
132 } | 134 } |
133 | 135 |
134 automation.setStatus("Creating database."); | 136 automation.setStatus("Creating database."); |
135 createDatabase(testName, objectStoreNames, onCreated, onError); | 137 createDatabase(testName, objectStoreNames, onCreated, onError); |
136 } | 138 } |
137 | 139 |
| 140 // TODO: Add a version that writes back to the same store, to see how that |
| 141 // affects cursor speed w.r.t. invalidated caches. |
| 142 function testCursorReadsAndRandomWrites( |
| 143 readKeysOnly, useIndexForReads, writeToAnotherStore, onTestComplete) { |
| 144 // There's no key cursor unless you're reading from an index. |
| 145 assert(useIndexForReads || !readKeysOnly); |
| 146 // If we're writing to another store, having an index would constrain our |
| 147 // writes, as we create both object stores with the same configurations. |
| 148 // We could do that if needed, but it's simpler not to. |
| 149 assert(!useIndexForReads || !writeToAnotherStore); |
| 150 var numKeys = 1000; |
| 151 var numReadsPerTransaction = 100; |
| 152 var testName = getDisplayName(arguments); |
| 153 var objectStoreNames = ["input store"]; |
| 154 if (writeToAnotherStore) |
| 155 objectStoreNames.push("output store"); |
| 156 var getKeyForRead = getSimpleKey; |
| 157 var indexName; |
| 158 if (useIndexForReads) { |
| 159 indexName = "index"; |
| 160 getKeyForRead = function(i) { |
| 161 // This depends on the implementations of getValuesFromCursor and |
| 162 // getObjectValue. We reverse the order of the iteration here so that |
| 163 // setting up bounds from k to k+n with n>0 works. Without this reversal, |
| 164 // the upper bound is below the lower bound. |
| 165 return getBackwardIndexKey(numKeys - i); |
| 166 } |
| 167 } |
| 168 |
| 169 function onCreated(db) { |
| 170 automation.setStatus("Setting up test database."); |
| 171 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
| 172 function() { onSetupComplete(db); }); |
| 173 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, |
| 174 getObjectValue); |
| 175 } |
| 176 function onSetupComplete(db) { |
| 177 automation.setStatus("Setup complete."); |
| 178 var completionFunc = |
| 179 getCompletionFunc(testName, Date.now(), onTestComplete); |
| 180 var mode = "readonly"; |
| 181 if (writeToAnotherStore) |
| 182 mode = "readwrite"; |
| 183 var transaction = |
| 184 getTransaction(db, objectStoreNames, mode, completionFunc); |
| 185 |
| 186 getValuesFromCursor( |
| 187 transaction, objectStoreNames[0], numReadsPerTransaction, numKeys, |
| 188 indexName, getKeyForRead, readKeysOnly, objectStoreNames[1]); |
| 189 } |
| 190 |
| 191 automation.setStatus("Creating database."); |
| 192 var options; |
| 193 if (useIndexForReads) { |
| 194 options = [{ |
| 195 indexName: indexName, |
| 196 indexKeyPath: "lastName", // depends on getBackwardIndexKey() |
| 197 indexIsUnique: true, |
| 198 indexIsMultiEntry: false, |
| 199 }]; |
| 200 } |
| 201 createDatabase(testName, objectStoreNames, onCreated, onError, options); |
| 202 } |
| 203 |
| 204 function testSporadicWrites( |
| 205 numWritesPerTransaction, numIndices, onTestComplete) { |
| 206 var numKeys = 1000; |
| 207 // With 30 transactions, spaced 50ms apart, we'll need at least 1.5s. |
| 208 var numTransactions = 30; |
| 209 var delayBetweenBatches = 50; |
| 210 var indexName; |
| 211 var testName = getDisplayName(arguments); |
| 212 var numTransactionsLeft = numTransactions; |
| 213 var objectStoreNames = ["store"]; |
| 214 var numTransactionsRunning = 0; |
| 215 |
| 216 var getValue = getSimpleValue; |
| 217 if (numIndices) |
| 218 getValue = function (i) { return getNFieldObjectValue(i, numIndices); }; |
| 219 |
| 220 function onCreated(db) { |
| 221 automation.setStatus("Setting up test database."); |
| 222 var transaction = getTransaction(db, objectStoreNames, "readwrite", |
| 223 function() { onSetupComplete(db); }); |
| 224 putLinearValues(transaction, objectStoreNames, numKeys, getSimpleKey, |
| 225 getValue); |
| 226 } |
| 227 var completionFunc; |
| 228 function onSetupComplete(db) { |
| 229 automation.setStatus("Setup complete."); |
| 230 completionFunc = getCompletionFunc(testName, Date.now(), onTestComplete); |
| 231 runOneBatch(db); |
| 232 } |
| 233 |
| 234 function runOneBatch(db) { |
| 235 assert(numTransactionsLeft); |
| 236 if (--numTransactionsLeft) { |
| 237 setTimeout(function () { runOneBatch(db); }, delayBetweenBatches); |
| 238 } |
| 239 ++numTransactionsRunning; |
| 240 |
| 241 function batchComplete() { |
| 242 assert(numTransactionsRunning); |
| 243 if (!--numTransactionsRunning && !numTransactionsLeft) |
| 244 completionFunc(); |
| 245 } |
| 246 |
| 247 var mode = "readonly"; |
| 248 if (numWritesPerTransaction) |
| 249 mode = "readwrite"; |
| 250 |
| 251 var transaction = getTransaction(db, objectStoreNames, mode, batchComplete); |
| 252 putRandomValues(transaction, objectStoreNames, numWritesPerTransaction, |
| 253 numKeys); |
| 254 } |
| 255 |
| 256 automation.setStatus("Creating database."); |
| 257 var options = []; |
| 258 for (var i=0; i < numIndices; ++i) { |
| 259 var o = {}; |
| 260 o.indexName = "index " + i; |
| 261 o.indexKeyPath = getNFieldName(i); |
| 262 o.indexIsUnique = false; |
| 263 o.indexIsMultiEntry = false; |
| 264 options.push(o); |
| 265 } |
| 266 createDatabase(testName, objectStoreNames, onCreated, onError, options); |
| 267 } |
| 268 |
138 var kUseIndex = true; | 269 var kUseIndex = true; |
139 var kDontUseIndex = false; | 270 var kDontUseIndex = false; |
| 271 var kReadKeysOnly = true; |
| 272 var kReadDataToo = false; |
| 273 var kWriteToo = true; |
| 274 var kDontWrite = false; |
| 275 |
140 var tests = [ | 276 var tests = [ |
| 277 // Create a single small item in a single object store. |
141 [testCreateKeysInStores, 1, 1, 1], | 278 [testCreateKeysInStores, 1, 1, 1], |
| 279 // Create many small items in a single object store. |
142 [testCreateKeysInStores, 100, 1, 1], | 280 [testCreateKeysInStores, 100, 1, 1], |
| 281 // Create a single small item in many object stores. |
143 [testCreateKeysInStores, 1, 100, 1], | 282 [testCreateKeysInStores, 1, 100, 1], |
| 283 // Create many large items in a single object store. |
144 [testCreateKeysInStores, 100, 1, 10000], | 284 [testCreateKeysInStores, 100, 1, 10000], |
| 285 // Read a few random items in each of many transactions. |
145 [testRandomReadsAndWrites, 1000, 5, 0, 50, kDontUseIndex], | 286 [testRandomReadsAndWrites, 1000, 5, 0, 50, kDontUseIndex], |
| 287 // Read many random items in each of a few transactions. |
146 [testRandomReadsAndWrites, 1000, 50, 0, 5, kDontUseIndex], | 288 [testRandomReadsAndWrites, 1000, 50, 0, 5, kDontUseIndex], |
| 289 // Read many random items in each of a few transactions, in a large store. |
147 [testRandomReadsAndWrites, 5000, 50, 0, 5, kDontUseIndex], | 290 [testRandomReadsAndWrites, 5000, 50, 0, 5, kDontUseIndex], |
| 291 // Read a few random items from an index, in each of many transactions. |
148 [testRandomReadsAndWrites, 1000, 5, 0, 50, kUseIndex], | 292 [testRandomReadsAndWrites, 1000, 5, 0, 50, kUseIndex], |
| 293 // Read many random items from an index, in each of a few transactions. |
149 [testRandomReadsAndWrites, 1000, 50, 0, 5, kUseIndex], | 294 [testRandomReadsAndWrites, 1000, 50, 0, 5, kUseIndex], |
| 295 // Read many random items from an index, in each of a few transactions, in a |
| 296 // large store. |
150 [testRandomReadsAndWrites, 5000, 50, 0, 5, kUseIndex], | 297 [testRandomReadsAndWrites, 5000, 50, 0, 5, kUseIndex], |
| 298 // Read and write a few random items in each of many transactions. |
151 [testRandomReadsAndWrites, 1000, 5, 5, 50, kDontUseIndex], | 299 [testRandomReadsAndWrites, 1000, 5, 5, 50, kDontUseIndex], |
| 300 // Read and write a few random items, reading from an index, in each of many |
| 301 // transactions. |
152 [testRandomReadsAndWrites, 1000, 5, 5, 50, kUseIndex], | 302 [testRandomReadsAndWrites, 1000, 5, 5, 50, kUseIndex], |
| 303 // Read a long, contiguous sequence of an object store via a cursor. |
| 304 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kDontWrite], |
| 305 // Read a sequence of an object store via a cursor, writing |
| 306 // transformed values into another. |
| 307 [testCursorReadsAndRandomWrites, kReadDataToo, kDontUseIndex, kWriteToo], |
| 308 // Read a sequence of an index into an object store via a cursor. |
| 309 [testCursorReadsAndRandomWrites, kReadDataToo, kUseIndex, kDontWrite], |
| 310 // Read a sequence of an index into an object store via a key cursor. |
| 311 [testCursorReadsAndRandomWrites, kReadKeysOnly, kUseIndex, kDontWrite], |
| 312 // Make batches of random writes into a store, triggered by periodic setTimeout |
| 313 // calls. |
| 314 [testSporadicWrites, 5, 0], |
| 315 // Make large batches of random writes into a store, triggered by periodic |
| 316 // setTimeout calls. |
| 317 [testSporadicWrites, 50, 0], |
| 318 // Make batches of random writes into a store with many indices, triggered by |
| 319 // periodic setTimeout calls. |
| 320 [testSporadicWrites, 5, 10], |
| 321 // Make large batches of random writes into a store with many indices, triggered |
| 322 // by periodic setTimeout calls. |
| 323 [testSporadicWrites, 50, 10], |
| 324 // Create and delete an index on a store that already contains data [produces |
| 325 // a timing result for each of creation and deletion]. |
153 [testCreateAndDeleteIndex, 1000] | 326 [testCreateAndDeleteIndex, 1000] |
154 ]; | 327 ]; |
155 | 328 |
156 var currentTest = 0; | 329 var currentTest = 0; |
157 | 330 |
158 function runNextTest() { | 331 function runNextTest() { |
159 if (currentTest < tests.length) { | 332 if (currentTest < tests.length) { |
160 var test = tests[currentTest++].slice(); | 333 var test = tests[currentTest++].slice(); |
161 var f = test.shift(); | 334 var f = test.shift(); |
162 test.push(runNextTest); | 335 test.push(runNextTest); |
163 f.apply(null, test); | 336 f.apply(null, test); |
164 } else { | 337 } else { |
165 onAllTestsComplete(); | 338 onAllTestsComplete(); |
166 } | 339 } |
167 } | 340 } |
168 | 341 |
169 function onAllTestsComplete() { | 342 function onAllTestsComplete() { |
170 var overallDuration = Date.now() - overallTestStartTime; | 343 var overallDuration = Date.now() - overallTestStartTime; |
171 automation.addResult("OverallTestDuration", overallDuration); | 344 automation.addResult("OverallTestDuration", overallDuration); |
172 automation.setDone(); | 345 automation.setDone(); |
173 } | 346 } |
174 | 347 |
175 function test() { | 348 function test() { |
176 runNextTest(); | 349 runNextTest(); |
177 } | 350 } |
OLD | NEW |