test_writer_starvation.js (3347B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 6 7 if (!this.window) { 8 this.runTest = function () { 9 todo(false, "Test disabled in xpcshell test suite for now"); 10 finishTest(); 11 }; 12 } 13 14 var testGenerator = testSteps(); 15 16 function* testSteps() { 17 const name = this.window ? window.location.pathname : "Splendid Test"; 18 19 // Needs to be enough to saturate the thread pool. 20 const SYNC_REQUEST_COUNT = 25; 21 22 let request = indexedDB.open(name, 1); 23 request.onerror = errorHandler; 24 request.onupgradeneeded = grabEventAndContinueHandler; 25 request.onsuccess = grabEventAndContinueHandler; 26 let event = yield undefined; 27 28 let db = event.target.result; 29 db.onerror = errorHandler; 30 31 is(event.target.transaction.mode, "versionchange", "Correct mode"); 32 33 let objectStore = db.createObjectStore("foo", { autoIncrement: true }); 34 35 request = objectStore.add({}); 36 request.onerror = errorHandler; 37 request.onsuccess = grabEventAndContinueHandler; 38 event = yield undefined; 39 40 let key = event.target.result; 41 ok(key, "Got a key"); 42 43 yield undefined; 44 45 let continueReading = true; 46 let readerCount = 0; 47 let writerCount = 0; 48 let callbackCount = 0; 49 50 // Generate a bunch of reads right away without returning to the event 51 // loop. 52 info("Generating " + SYNC_REQUEST_COUNT + " readonly requests"); 53 54 for (let i = 0; i < SYNC_REQUEST_COUNT; i++) { 55 readerCount++; 56 let request = db.transaction("foo").objectStore("foo").get(key); 57 request.onsuccess = function (event) { 58 is(event.target.transaction.mode, "readonly", "Correct mode"); 59 callbackCount++; 60 }; 61 } 62 63 while (continueReading) { 64 readerCount++; 65 info("Generating additional readonly request (" + readerCount + ")"); 66 let request = db.transaction("foo").objectStore("foo").get(key); 67 request.onsuccess = function (event) { 68 callbackCount++; 69 info("Received readonly request callback (" + callbackCount + ")"); 70 is(event.target.transaction.mode, "readonly", "Correct mode"); 71 if (callbackCount == SYNC_REQUEST_COUNT) { 72 writerCount++; 73 info( 74 "Generating 1 readwrite request with " + 75 readerCount + 76 " previous readonly requests" 77 ); 78 let request = db 79 .transaction("foo", "readwrite") 80 .objectStore("foo") 81 .add({}, readerCount); 82 request.onsuccess = function (event) { 83 callbackCount++; 84 info("Received readwrite request callback (" + callbackCount + ")"); 85 is(event.target.transaction.mode, "readwrite", "Correct mode"); 86 is( 87 event.target.result, 88 callbackCount, 89 "write callback came before later reads" 90 ); 91 }; 92 } else if (callbackCount == SYNC_REQUEST_COUNT + 5) { 93 continueReading = false; 94 } 95 }; 96 97 setTimeout( 98 function () { 99 testGenerator.next(); 100 }, 101 writerCount ? 1000 : 100 102 ); 103 yield undefined; 104 } 105 106 while (callbackCount < readerCount + writerCount) { 107 executeSoon(function () { 108 testGenerator.next(); 109 }); 110 yield undefined; 111 } 112 113 is(callbackCount, readerCount + writerCount, "All requests accounted for"); 114 115 finishTest(); 116 yield undefined; 117 }