<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
<script>
let worker1 = new Worker("resources/worker-1.js", {name: "Worker 1"});
let worker2 = new Worker("resources/worker-2.js", {name: "Worker 2"});
let worker3 = null;

function createWorker3() {
    worker3 = new Worker("resources/worker-3.js", {name: "Worker 3"});
}

function terminateWorker2FromPage() {
    worker2.terminate();
}

function terminateWorker3FromWorker() {
    worker3.postMessage("close");
}

function terminateWorker1ViaCollection() {
    worker1 = null;
}

function test()
{
    let workers = [];

    function addWorker(workerId, url) {
        workers.push({workerId, url});
        workers.sort((a, b) => a.url.localeCompare(b.url));
    }

    function removeWorker(workerId) {
        workers = workers.filter((x) => x.workerId !== workerId);
    }

    function dumpWorkers() {
        for (let {workerId, url} of workers)
            ProtocolTest.log("Worker - " + sanitizeURL(url));
        if (!workers.length)
            ProtocolTest.log("No Workers");
    }

    async function checkInternalProperties(expression, internalPropertiesToCheck) {
        let evaluateResult = await InspectorProtocol.awaitCommand({
            method: "Runtime.evaluate",
            params: {
                expression,
                objectGroup: "test",
            },
        });

        ProtocolTest.assert(evaluateResult.result.type === "object", `Evaluate result of '${expression}' should have type 'object'.`);
        ProtocolTest.assert(evaluateResult.result.className === "Worker", `Evaluate result of '${expression}' should have className 'Worker'.`);

        let {internalProperties} = await InspectorProtocol.awaitCommand({
            method: "Runtime.getProperties",
            params: {
                objectId: evaluateResult.result.objectId,
            },
        });
        ProtocolTest.assert(internalProperties.length === 2, `Worker '${expression}' should only have one internal property.`);

        function checkInternalProperty(propertyName, type) {
            let internalProperty = internalProperties.find((item) => item.name === propertyName);

            ProtocolTest.assert(internalProperty, `Worker '${expression}' should have '${propertyName}' internal property.`);
            ProtocolTest.assert(internalProperty.value.type === type, `Internal '${propertyName}' property of '${expression}' should be a boolean.`);
            ProtocolTest.assert(internalProperty.value.value === internalPropertiesToCheck[propertyName], `Internal '${propertyName}' property of '${expression}' should have value '${internalPropertiesToCheck[propertyName]}'.`);
        }
        if ("name" in internalPropertiesToCheck)
            checkInternalProperty("name", "string");
        if ("terminated" in internalPropertiesToCheck)
            checkInternalProperty("terminated", "boolean");
    }


    let triggerNextCreate;
    let triggerNextTerminate;

    function waitForWorkerCreatedEvent(callback) {
        return new Promise((resolve, reject) => {
            triggerNextCreate = resolve;
        });
    }

    function waitForWorkerTerminatedEvent(callback) {
        return new Promise((resolve, reject) => {
            triggerNextTerminate = resolve;
        });
    }

    InspectorProtocol.eventHandler["Worker.workerCreated"] = (messageObject) => {
        addWorker(messageObject.params.workerId, messageObject.params.url);
        InspectorProtocol.sendCommand("Worker.initialized", {workerId: messageObject.params.workerId});
        if (triggerNextCreate)
            triggerNextCreate();
    };

    InspectorProtocol.eventHandler["Worker.workerTerminated"] = (messageObject) => {
        removeWorker(messageObject.params.workerId);
        if (triggerNextTerminate)
            triggerNextTerminate();
    };


    let suite = ProtocolTest.createAsyncSuite("Worker.CreateAndTerminate");

    suite.addTestCase({
        name: "Worker.enable",
        description: "Worker.enable informs the frontend of the two existing Workers",
        async test() {
            await InspectorProtocol.awaitCommand({method: "Worker.enable", params: {}});

            ProtocolTest.expectEqual(workers.length, 2, "Should be informed of two existing Workers.");
            dumpWorkers();

            await Promise.all([
                checkInternalProperties(`worker1`, {name: "Worker 1", terminated: false}),
                checkInternalProperties(`worker2`, {name: "Worker 2", terminated: false}),
            ]);
        }
    });

    suite.addTestCase({
        name: "Worker.workerCreated",
        description: "Should receive a Worker.workerCreated event when creating a Worker.",
        async test() {
            await Promise.all([
                waitForWorkerCreatedEvent(),
                ProtocolTest.evaluateInPage("createWorker3()"),
            ]);

            ProtocolTest.pass("Worker.workerCreated");
            dumpWorkers();

            await Promise.all([
                checkInternalProperties(`worker1`, {name: "Worker 1", terminated: false}),
                checkInternalProperties(`worker2`, {name: "Worker 2", terminated: false}),
                checkInternalProperties(`worker3`, {name: "Worker 3", terminated: false}),
            ]);
        }
    });

    suite.addTestCase({
        name: "Worker.workerTerminated.Page",
        description: "Should receive a Worker.workerTerminated event when terminating a Worker from the Page.",
        async test() {
            await Promise.all([
                waitForWorkerTerminatedEvent(),
                ProtocolTest.evaluateInPage("terminateWorker2FromPage()"),
            ]);

            ProtocolTest.pass("Worker.workerTerminated");
            dumpWorkers();

            await Promise.all([
                checkInternalProperties(`worker1`, {name: "Worker 1", terminated: false}),
                checkInternalProperties(`worker2`, {name: "Worker 2", terminated: true}),
                checkInternalProperties(`worker3`, {name: "Worker 3", terminated: false}),
            ]);
        }
    });

    suite.addTestCase({
        name: "Worker.workerTerminated.Worker",
        description: "Should receive a Worker.workerTerminated event when terminating a Worker from the Worker.",
        async test() {
            await Promise.all([
                waitForWorkerTerminatedEvent(),
                ProtocolTest.evaluateInPage("terminateWorker3FromWorker()"),
            ]);

            ProtocolTest.pass("Worker.workerTerminated");
            dumpWorkers();

            await Promise.all([
                checkInternalProperties(`worker1`, {name: "Worker 1", terminated: false}),
                checkInternalProperties(`worker2`, {name: "Worker 2", terminated: true}),
            ]);
        }
    });

    suite.addTestCase({
        name: "Worker.workerTerminated.GC",
        description: "Should receive a Worker.workerTerminated event when terminating a Worker via Garbage Collection.",
        async test() {
            let workerTerminatedPromise = waitForWorkerTerminatedEvent();
            await ProtocolTest.evaluateInPage("terminateWorker1ViaCollection()");
            await InspectorProtocol.awaitCommand({method: "Runtime.releaseObjectGroup", params: {objectGroup: "test"}});
            await InspectorProtocol.awaitCommand({method: "Heap.gc", params: {}});
            await workerTerminatedPromise;

            ProtocolTest.pass("Worker.workerTerminated");
            dumpWorkers();

            await Promise.all([
                checkInternalProperties(`worker2`, {name: "Worker 2", terminated: true}),
            ]);
        }
    });

    suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Tests for Worker.workerCreated and Worker.workerTerminated events.</p>
</body>
</html>
