зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d67ed8553a
Коммит
a97c81d4d8
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче