Bug 1150253 - Part 3: Migrate onGarbageCollection tests; r=sfink

--HG--
rename : js/src/jit-test/tests/debug/Memory-onGarbageCollection-04.js => js/xpconnect/tests/unit/test_onGarbageCollection-04.js
This commit is contained in:
Nick Fitzgerald 2015-04-22 09:43:02 -07:00
Родитель d67ed8553a
Коммит a97c81d4d8
11 изменённых файлов: 311 добавлений и 161 удалений

Просмотреть файл

@ -1,57 +0,0 @@
// Test basic usage of onGarbageCollection
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
const NUM_SLICES = root.NUM_SLICES = 10;
let fired = false;
let slicesFound = 0;
dbg.memory.onGarbageCollection = data => {
fired = true;
print("Got onGarbageCollection: " + JSON.stringify(data, null, 2));
assertEq(typeof data.reason, "string");
assertEq(typeof data.nonincrementalReason == "string" || data.nonincrementalReason === null,
true);
let lastStartTimestamp = 0;
for (let i = 0; i < data.collections.length; i++) {
let slice = data.collections[i];
assertEq(slice.startTimestamp >= lastStartTimestamp, true);
assertEq(slice.startTimestamp <= slice.endTimestamp, true);
lastStartTimestamp = slice.startTimestamp;
}
assertEq(data.collections.length >= 1, true);
slicesFound += data.collections.length;
}
root.eval(
`
this.allocs = [];
// GC slices
for (var i = 0; i < NUM_SLICES; i++) {
this.allocs.push({});
gcslice();
}
// Full GC
this.allocs.push({});
gc();
`
);
// The hook should have been fired at least once.
assertEq(fired, true);
// NUM_SLICES + 1 full gc + however many were triggered naturally (due to
// whatever zealousness setting).
print("Found " + slicesFound + " slices");
assertEq(slicesFound >= NUM_SLICES + 1, true);

Просмотреть файл

@ -1,69 +0,0 @@
// Test multiple debuggers, GCs, and zones interacting with each other.
gczeal(0);
const root1 = newGlobal();
const dbg1 = new Debugger();
dbg1.addDebuggee(root1)
const root2 = newGlobal();
const dbg2 = new Debugger();
dbg2.addDebuggee(root2)
let fired1 = false;
let fired2 = false;
dbg1.memory.onGarbageCollection = _ => fired1 = true;
dbg2.memory.onGarbageCollection = _ => fired2 = true;
function reset() {
fired1 = false;
fired2 = false;
}
// GC 1 only
root1.eval(`gc(this)`);
assertEq(fired1, true);
assertEq(fired2, false);
// GC 2 only
reset();
root2.eval(`gc(this)`);
assertEq(fired1, false);
assertEq(fired2, true);
// Full GC
reset();
gc();
assertEq(fired1, true);
assertEq(fired2, true);
// Full GC with no debuggees
reset();
dbg1.removeAllDebuggees();
dbg2.removeAllDebuggees();
gc();
assertEq(fired1, false);
assertEq(fired2, false);
// One debugger with multiple debuggees in different zones.
dbg1.addDebuggee(root1);
dbg1.addDebuggee(root2);
// Just debuggee 1
reset();
root1.eval(`gc(this)`);
assertEq(fired1, true);
assertEq(fired2, false);
// Just debuggee 2
reset();
root2.eval(`gc(this)`);
assertEq(fired1, true);
assertEq(fired2, false);
// All debuggees
reset();
gc();
assertEq(fired1, true);
assertEq(fired2, false);

Просмотреть файл

@ -1,18 +0,0 @@
// Test that the onGarbageCollection hook is not reentrant.
gczeal(0);
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
let timesFired = 0;
dbg.memory.onGarbageCollection = _ => {
timesFired++;
root.eval(`gc()`);
}
root.eval(`gc()`);
assertEq(timesFired, 1);

Просмотреть файл

@ -92,6 +92,7 @@ skip-if = buildapp == 'mulet'
[test_localstorage_with_nsEp.xul]
[test_matches.xul]
[test_nodelists.xul]
[test_onGarbageCollection.html]
[test_paris_weakmap_keys.xul]
[test_precisegc.xul]
[test_sandboxImport.xul]

Просмотреть файл

@ -0,0 +1,35 @@
<!doctype html>
<html>
<head>
<title>Bug 1150253 - Sanity test for the SpiderMonkey Debugger API's onGarbageCollection hook</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js">
</script>
</head>
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1150253"
target="_blank">Mozilla Bug 1150253</a>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
const Cu = Components.utils;
Cu.import("resource://gre/modules/devtools/Loader.jsm");
const require = devtools.require;
const { gc } = Cu.getJSTestingFunctions();
const Debugger = require("Debugger");
const dbg = new Debugger(this);
dbg.memory.onGarbageCollection = function (data) {
// Don't keep calling this hook after we finish.
dbg.enabled = false;
ok(data, "The onGarbageCollection hook was fired.");
SimpleTest.finish();
};
gc();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,41 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/jsdebugger.jsm");
const testingFunctions = Cu.getJSTestingFunctions();
const systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
function addTestingFunctionsToGlobal(global) {
for (let k in testingFunctions) {
global[k] = testingFunctions[k];
}
global.print = do_print;
global.newGlobal = newGlobal;
addDebuggerToGlobal(global);
}
function newGlobal() {
const global = new Cu.Sandbox(systemPrincipal, { freshZone: true });
addTestingFunctionsToGlobal(global);
return global;
}
addTestingFunctionsToGlobal(this);
function executeSoon(f) {
Services.tm.mainThread.dispatch({ run: f },
Ci.nsIThread.DISPATCH_NORMAL);
}
// The onGarbageCollection tests don't play well gczeal settings and lead to
// intermittents.
if (typeof gczeal == "function") {
gczeal(0);
}
// Make sure to GC before we start the test, so that no zones are scheduled for
// GC before we start testing onGarbageCollection hooks.
gc();

Просмотреть файл

@ -0,0 +1,64 @@
// Test basic usage of onGarbageCollection
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
const NUM_SLICES = root.NUM_SLICES = 10;
let fired = false;
let slicesFound = 0;
dbg.memory.onGarbageCollection = data => {
fired = true;
print("Got onGarbageCollection: " + JSON.stringify(data, null, 2));
equal(typeof data.reason, "string");
equal(typeof data.nonincrementalReason == "string" || data.nonincrementalReason === null,
true);
let lastStartTimestamp = 0;
for (let i = 0; i < data.collections.length; i++) {
let slice = data.collections[i];
equal(slice.startTimestamp >= lastStartTimestamp, true);
equal(slice.startTimestamp <= slice.endTimestamp, true);
lastStartTimestamp = slice.startTimestamp;
}
equal(data.collections.length >= 1, true);
slicesFound += data.collections.length;
}
function run_test() {
do_test_pending();
root.eval(
`
this.allocs = [];
// GC slices
for (var i = 0; i < NUM_SLICES; i++) {
this.allocs.push({});
gcslice();
}
// Full GC
this.allocs.push({});
gc();
`
);
executeSoon(() => {
equal(fired, true, "The GC hook should have fired at least once");
// NUM_SLICES + 1 full gc + however many were triggered naturally (due to
// whatever zealousness setting).
print("Found " + slicesFound + " slices");
equal(slicesFound >= NUM_SLICES + 1, true);
do_test_finished();
});
}

Просмотреть файл

@ -0,0 +1,94 @@
// Test multiple debuggers, GCs, and zones interacting with each other.
//
// Note: when observing both globals, but GC'ing in only one, we don't test that
// we *didn't* GC in the other zone because GCs are finicky and unreliable. That
// used to work when this was a jit-test, but in the process of migrating to
// xpcshell, we lost some amount of reliability and determinism.
const root1 = newGlobal();
const dbg1 = new Debugger();
dbg1.addDebuggee(root1)
const root2 = newGlobal();
const dbg2 = new Debugger();
dbg2.addDebuggee(root2)
let fired1 = false;
let fired2 = false;
dbg1.memory.onGarbageCollection = _ => fired1 = true;
dbg2.memory.onGarbageCollection = _ => fired2 = true;
function reset() {
fired1 = false;
fired2 = false;
}
function run_test() {
do_test_pending();
gc();
executeSoon(() => {
reset();
// GC 1 only
root1.eval(`gc(this)`);
executeSoon(() => {
equal(fired1, true);
// GC 2 only
reset();
root2.eval(`gc(this)`);
executeSoon(() => {
equal(fired2, true);
// Full GC
reset();
gc();
executeSoon(() => {
equal(fired1, true);
equal(fired2, true);
// Full GC with no debuggees
reset();
dbg1.removeAllDebuggees();
dbg2.removeAllDebuggees();
gc();
executeSoon(() => {
equal(fired1, false);
equal(fired2, false);
// One debugger with multiple debuggees in different zones.
dbg1.addDebuggee(root1);
dbg1.addDebuggee(root2);
// Just debuggee 1
reset();
root1.eval(`gc(this)`);
executeSoon(() => {
equal(fired1, true);
equal(fired2, false);
// Just debuggee 2
reset();
root2.eval(`gc(this)`);
executeSoon(() => {
equal(fired1, true);
equal(fired2, false);
// All debuggees
reset();
gc();
executeSoon(() => {
equal(fired1, true);
equal(fired2, false);
do_test_finished();
});
});
});
});
});
});
});
});
}

Просмотреть файл

@ -0,0 +1,35 @@
// Test that the onGarbageCollection hook is not reentrant.
function run_test() {
do_test_pending();
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
let fired = true;
let depth = 0;
dbg.memory.onGarbageCollection = _ => {
fired = true;
equal(depth, 0);
depth++;
try {
root.eval(`gc()`);
} finally {
equal(depth, 1);
depth--;
}
}
root.eval(`gc()`);
executeSoon(() => {
ok(fired);
equal(depth, 0);
dbg.memory.onGarbageCollection = undefined;
do_test_finished();
});
}

Просмотреть файл

@ -23,29 +23,45 @@
// same time that we are preventing reentrancy into debuggeree's
// onGarbageCollection hook.
gczeal(0);
function run_test() {
do_test_pending();
const debuggeree = newGlobal();
const debuggee = debuggeree.debuggee = newGlobal();
const debuggeree = newGlobal();
const debuggee = debuggeree.debuggee = newGlobal();
debuggeree.eval(
`
const dbg = new Debugger(this.debuggee);
debuggeree.eval(
`
const dbg = new Debugger(this.debuggee);
let fired = 0;
dbg.memory.onGarbageCollection = _ => {
fired++;
gc(this);
};
`
);
const dbg = new Debugger(debuggeree);
let fired = 0;
dbg.memory.onGarbageCollection = _ => {
fired++;
gc(this);
};
`
);
const dbg = new Debugger(debuggeree);
let fired = 0;
dbg.memory.onGarbageCollection = _ => {
fired++;
};
debuggee.eval(`gc(this)`);
debuggee.eval(`gc(this)`);
// Let first onGarbageCollection runnable get run.
executeSoon(() => {
assertEq(debuggeree.fired, 1);
assertEq(fired, 1);
// Let second onGarbageCollection runnable get run.
executeSoon(() => {
// Even though we request GC'ing a single zone, we can't rely on that
// behavior and both zones could have been scheduled for gc for both
// gc(this) calls.
ok(debuggeree.fired >= 1);
ok(fired >= 1);
debuggeree.dbg.enabled = dbg.enabled = false;
do_test_finished();
});
});
}

Просмотреть файл

@ -66,6 +66,14 @@ support-files =
[test_interposition.js]
[test_isModuleLoaded.js]
[test_js_weak_references.js]
[test_onGarbageCollection-01.js]
head = head_ongc.js
[test_onGarbageCollection-02.js]
head = head_ongc.js
[test_onGarbageCollection-03.js]
head = head_ongc.js
[test_onGarbageCollection-04.js]
head = head_ongc.js
[test_reflect_parse.js]
[test_localeCompare.js]
# Bug 676965: test fails consistently on Android