blob: 73c76315b45ed6a792b263ddb07b327fb29c4573 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script src="../debugger/resources/log-pause-location.js"></script>
<script>
let worker1, worker2;
let testVariable = "main thread";
function triggerStartWorkers() {
worker1 = new Worker("resources/worker-debugger-thread-1.js");
worker2 = new Worker("resources/worker-debugger-thread-2.js");
}
function triggerWork() {
worker1.postMessage("doWork");
worker2.postMessage("doWork");
setTimeout(workOnMainThread, 250);
}
function workOnMainThread() {
TestPage.dispatchEventToFrontend("MainThreadDidWork");
Date.now();
}
function test()
{
let mainTarget = WI.mainTarget;
let workerTarget1;
let workerTarget2;
function areAllTargetsPaused() {
for (let target of WI.targets) {
let targetData = WI.debuggerManager.dataForTarget(target);
if (!targetData.paused)
return false;
}
return true;
}
function areAllTargetsUnpaused() {
for (let target of WI.targets) {
let targetData = WI.debuggerManager.dataForTarget(target);
if (targetData.paused)
return false;
}
return true;
}
function dumpCallFrames() {
InspectorTest.log("");
for (let target of WI.targets) {
InspectorTest.log(`TARGET: ${target.displayName}`);
let targetData = WI.debuggerManager.dataForTarget(target);
let callFrames = targetData.callFrames;
for (let i = 0; i < callFrames.length; ++i) {
let callFrame = callFrames[i];
let active = callFrame === WI.debuggerManager.activeCallFrame;
InspectorTest.log(` ${active ? "*" : " "} CALL FRAME #${i + 1}: ${callFrame.functionName}`);
}
}
}
let okayToReceiveMainThreadEvent = false;
InspectorTest.singleFireEventListener("MainThreadDidWork", (event) => {
if (!okayToReceiveMainThreadEvent) {
InspectorTest.fail("Main Thread's work fired before it could pause. Failing early.");
InspectorTest.completeTest();
}
});
let suite = InspectorTest.createAsyncSuite("Worker.Debugger.Threads");
suite.addTestCase({
name: "Worker.Debugger.Threads.CreateThreads",
description: "Spawn multiple targets.",
test(resolve, reject) {
InspectorTest.evaluateInPage(`triggerStartWorkers()`);
WI.targetManager.singleFireEventListener(WI.TargetManager.Event.TargetAdded, (event) => {
InspectorTest.pass("Created Worker 1");
workerTarget1 = event.data.target;
WI.targetManager.singleFireEventListener(WI.TargetManager.Event.TargetAdded, (event) => {
InspectorTest.pass("Created Worker 2");
workerTarget2 = event.data.target;
resolve();
});
});
}
});
suite.addTestCase({
name: "Worker.Debugger.Threads.Pause",
description: "Should be able to pause in multiple targets.",
test(resolve, reject) {
InspectorTest.evaluateInPage(`triggerWork()`);
let receivedCallFramesDidChange = false;
let receivedPauseBeforeCallFramesDidChange = false;
let otherTargetsPausing = false;
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
receivedPauseBeforeCallFramesDidChange = !receivedCallFramesDidChange;
otherTargetsPausing = WI.debuggerManager.dataForTarget(mainTarget).pausing && WI.debuggerManager.dataForTarget(workerTarget2).pausing;
});
let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
receivedCallFramesDidChange = true;
if (!areAllTargetsPaused())
return;
WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.CallFramesDidChange, listener);
let activeCallFrame = WI.debuggerManager.activeCallFrame;
InspectorTest.assert(activeCallFrame.target === workerTarget1);
InspectorTest.expectThat(receivedPauseBeforeCallFramesDidChange, "Paused event should happen before CallFramesDidChange event.");
InspectorTest.expectThat(otherTargetsPausing, "In Paused event all other Targets should be pausing.");
InspectorTest.expectEqual(activeCallFrame.target.displayName, "worker-debugger-thread-1.js", "Worker 1 should be the first to pause.");
InspectorTest.pass("All Targets should eventually pause.");
dumpCallFrames();
resolve();
});
}
});
function addEvaluateTestCase({name, targetResolver, expected}) {
suite.addTestCase({
name, description: "Should be able to evaluate in different threads while paused.",
test(resolve, reject) {
let target = targetResolver();
let targetData = WI.debuggerManager.dataForTarget(target);
WI.debuggerManager.activeCallFrame = targetData.callFrames[0];
WI.runtimeManager.evaluateInInspectedWindow("testVariable", {objectGroup: "test", includeCommandLineAPI: true}, (remoteObject) => {
InspectorTest.expectEqual(remoteObject.description, expected, `Evaluated result in ${target.displayName} should be ${JSON.stringify(expected)}.`)
resolve();
});
}
});
}
addEvaluateTestCase({
name: "Worker.Debugger.Threads.Paused.Worker1Evaluate",
targetResolver: () => workerTarget1,
expected: "worker thread 1",
});
addEvaluateTestCase({
name: "Worker.Debugger.Threads.Paused.Worker2Evaluate",
targetResolver: () => workerTarget2,
expected: "worker thread 2",
});
addEvaluateTestCase({
name: "Worker.Debugger.Threads.Paused.MainEvaluate",
targetResolver: () => mainTarget,
expected: "main thread",
});
suite.addTestCase({
name: "Worker.Debugger.Threads.Paused.Worker1.StepOut",
description: "Should be able to step in individual threads and not affect the others.",
test(resolve, reject) {
let targetData = WI.debuggerManager.dataForTarget(workerTarget1);
WI.debuggerManager.activeCallFrame = targetData.callFrames[0];
WI.debuggerManager.stepOut();
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
InspectorTest.expectEqual(event.data.target, workerTarget1, "Should receive CallFramesDidChange for Worker 1.");
dumpCallFrames();
resolve();
});
}
});
suite.addTestCase({
name: "Worker.Debugger.Threads.Paused.Worker2.ResumeThread",
description: "Should be able to resume an individual thread and not affect the others.",
test(resolve, reject) {
let targetData = WI.debuggerManager.dataForTarget(workerTarget2);
WI.debuggerManager.continueUntilNextRunLoop(workerTarget2);
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
InspectorTest.expectEqual(event.data.target, workerTarget2, "Should Receive CallFramesDidChange for Worker 2.");
InspectorTest.expectThat(targetData.pausing, "Worker 2 should be pausing.");
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
InspectorTest.expectEqual(event.data.target, workerTarget2, "Should Receive CallFramesDidChange for Worker 2.");
InspectorTest.expectThat(targetData.paused, "Worker 2 should be paused.");
dumpCallFrames();
resolve();
});
});
}
});
suite.addTestCase({
name: "Worker.Debugger.Threads.Complete",
description: "Resume all threads for the test to complete.",
test(resolve, reject) {
okayToReceiveMainThreadEvent = true;
WI.debuggerManager.resume();
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Resumed, () => {
InspectorTest.pass("Received Resume event.");
InspectorTest.expectThat(areAllTargetsUnpaused(), "All Targets should be unpaused.");
resolve();
});
}
});
suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Ensure we can pause in multiple targets and evaluate in each.</p>
</body>
</html>