michael@0: /** michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: if (!this.window) { michael@0: this.runTest = function() { michael@0: todo(false, "Test disabled in xpcshell test suite for now"); michael@0: finishTest(); michael@0: } michael@0: } michael@0: michael@0: var testGenerator = testSteps(); michael@0: michael@0: function testSteps() michael@0: { michael@0: const name = this.window ? window.location.pathname : "Splendid Test"; michael@0: michael@0: // Needs to be enough to saturate the thread pool. michael@0: const SYNC_REQUEST_COUNT = 25; michael@0: michael@0: let request = indexedDB.open(name, 1); michael@0: request.onerror = errorHandler; michael@0: request.onupgradeneeded = grabEventAndContinueHandler; michael@0: request.onsuccess = grabEventAndContinueHandler; michael@0: let event = yield undefined; michael@0: michael@0: let db = event.target.result; michael@0: db.onerror = errorHandler; michael@0: michael@0: is(event.target.transaction.mode, "versionchange", "Correct mode"); michael@0: michael@0: let objectStore = db.createObjectStore("foo", { autoIncrement: true }); michael@0: michael@0: request = objectStore.add({}); michael@0: request.onerror = errorHandler; michael@0: request.onsuccess = grabEventAndContinueHandler; michael@0: event = yield undefined; michael@0: michael@0: let key = event.target.result; michael@0: ok(key, "Got a key"); michael@0: michael@0: yield undefined; michael@0: michael@0: let continueReading = true; michael@0: let readerCount = 0; michael@0: let writerCount = 0; michael@0: let callbackCount = 0; michael@0: michael@0: // Generate a bunch of reads right away without returning to the event michael@0: // loop. michael@0: info("Generating " + SYNC_REQUEST_COUNT + " readonly requests"); michael@0: michael@0: for (let i = 0; i < SYNC_REQUEST_COUNT; i++) { michael@0: readerCount++; michael@0: let request = db.transaction("foo").objectStore("foo").get(key); michael@0: request.onsuccess = function(event) { michael@0: is(event.target.transaction.mode, "readonly", "Correct mode"); michael@0: callbackCount++; michael@0: }; michael@0: } michael@0: michael@0: while (continueReading) { michael@0: readerCount++; michael@0: info("Generating additional readonly request (" + readerCount + ")"); michael@0: let request = db.transaction("foo").objectStore("foo").get(key); michael@0: request.onsuccess = function(event) { michael@0: callbackCount++; michael@0: info("Received readonly request callback (" + callbackCount + ")"); michael@0: is(event.target.transaction.mode, "readonly", "Correct mode"); michael@0: if (callbackCount == SYNC_REQUEST_COUNT) { michael@0: writerCount++; michael@0: info("Generating 1 readwrite request with " + readerCount + michael@0: " previous readonly requests"); michael@0: let request = db.transaction("foo", "readwrite") michael@0: .objectStore("foo") michael@0: .add({}, readerCount); michael@0: request.onsuccess = function(event) { michael@0: callbackCount++; michael@0: info("Received readwrite request callback (" + callbackCount + ")"); michael@0: is(event.target.transaction.mode, "readwrite", "Correct mode"); michael@0: is(event.target.result, callbackCount, michael@0: "write callback came before later reads"); michael@0: } michael@0: } michael@0: else if (callbackCount == SYNC_REQUEST_COUNT + 5) { michael@0: continueReading = false; michael@0: } michael@0: }; michael@0: michael@0: setTimeout(function() { testGenerator.next(); }, writerCount ? 1000 : 100); michael@0: yield undefined; michael@0: } michael@0: michael@0: while (callbackCount < (readerCount + writerCount)) { michael@0: executeSoon(function() { testGenerator.next(); }); michael@0: yield undefined; michael@0: } michael@0: michael@0: is(callbackCount, readerCount + writerCount, "All requests accounted for"); michael@0: michael@0: finishTest(); michael@0: yield undefined; michael@0: }