test-runner.html   [plain text]


<html>
<script src="jsdifflib.js"></script>
<script src="utilities.js"></script>
<script src="DOMExtension.js"></script>
<script src="treeoutline.js"></script>

<link rel="stylesheet" type="text/css" href="inspector.css">
<style>
:focus {
    outline: none;
}

.failed {
    color: red;
}

.timeout {
    color: brown;
}

iframe {
    width: 0;
    height: 0;
    opacity: 0;
}

</style>

<script>

var layoutTestsServer = "http://localhost:8002/";
var scannerServer = "http://localhost:8002/";
var remoteDebuggingServer = "http://localhost:9222/";

var tests = [];
var skipList = [
    // HALT
    "inspector/console/console-api-on-call-frame.html",

    // FAILED
    "inspector/console/console-dir-global.html",
    "inspector/console/console-log-toString-object.html",
    "inspector/console/console-uncaught-exception-in-eval.html",
    "inspector/elements/edit-dom-actions.html",
    "inspector/elements/highlight-node-scaled.html",
    "inspector/elements/highlight-node-scroll.html",
    "inspector/elements/highlight-node.html",
    "inspector/elements/highlight-svg-root.html",
    "inspector/network-status-non-http.html",
    "inspector/storage-panel-dom-storage-update.html",
    "inspector/styles/inject-stylesheet.html",
    "inspector/styles/protocol-css-regions-commands.html",
    "inspector/styles/region-style-crash.html",
    "inspector/styles/styles-disable-then-enable-overriden-ua.html",
    "inspector/styles/styles-url-linkify.html",
    "inspector/styles/vendor-prefixes.html",
    "inspector/timeline/timeline-event-dispatch.html",
    "inspector/timeline/timeline-frames.html",
    "inspector/timeline/timeline-network-resource.html",
    "inspector/timeline/timeline-paint.html",
    "inspector/timeline/timeline-receive-response-event.html",

    // TIMEOUT
    "inspector/profiler/cpu-profiler-profiling-without-inspector.html",
    "inspector/profiler/heap-snapshot-inspect-dom-wrapper.html",
    "inspector/timeline/timeline-network-received-data.html",
];
var treeOutline = null;

function run(debug)
{
    if (window.runner && debug) {
        window.runner.continueDebugging();
        return;
    }

    if (window.testScannerIframe) 
        document.body.removeChild(window.testScannerIframe);

    if (window.runner)
        window.runner.cleanup();

    window.testScannerIframe = document.createElement("iframe");
    window.testScannerIframe.src = scannerServer + "LayoutTests/http/tests/inspector/resources/test-scanner.html";
    document.body.appendChild(window.testScannerIframe);
    window.debug = debug;
}

function runTests()
{
    document.getElementById("outline").removeChildren();
    treeOutline = new TreeOutline(document.getElementById("outline"));

    document.getElementById("pass").textContent = 0;
    document.getElementById("skip").textContent = 0;
    document.getElementById("fail").textContent = 0;
    document.getElementById("timeout").textContent = 0;
    document.getElementById("remaining").textContent = tests.length;

    runNextTest();
}

function interrupt()
{
    tests = [];
}

function runNextTest(lastResult)
{
    if (lastResult) {
        var element = document.getElementById(lastResult);
        element.textContent = parseInt(element.textContent) + 1;

        element = document.getElementById("remaining");
        element.textContent = parseInt(element.textContent) - 1;
        if (window.debug) {
            document.getElementById("debug").textContent = "Debug";
            return;
        }
    }

    var test;
    var filter = document.getElementById("filter").value;
    while (test = tests.shift()) {
        if (!filter || test[0].match(filter)) {
            new StandaloneTestRunner(layoutTestsServer + test[0], test[1], runNextTest.bind(null));
            return;
        }
    }
}

function StandaloneTestRunner(testPath, expected, next)
{
    this._testPath = testPath;
    this._next = next;
    this._expected = expected;
    this._pendingMessages = [];

    this._treeElement = new TreeElement(testPath);
    treeOutline.appendChild(this._treeElement);

    for (var i = 0; !window.debug && i < skipList.length; ++i) {
        if (testPath.indexOf(skipList[i]) !== -1) {
            this._treeElement.title = testPath + ": SKIPPED";
            this._next("skip");
            return;
        }
    }
    window.runner = this;
    this._testPage = window.open("about:blank", "inspected", "width=800,height=600");

    window.remoteDebuggingHandshake = this._remoteDebuggingHandshake.bind(this);
    var script = document.createElement("script");
    script.src = remoteDebuggingServer + "json?jsonp=remoteDebuggingHandshake";
    document.head.appendChild(script);
}

StandaloneTestRunner.FrontendLocation = "inspector.html";

StandaloneTestRunner.prototype = {
    _remoteDebuggingHandshake: function(data)
    {
        for (var i = 0; i < data.length; ++i) {
            if (data[i].url !== "about:blank")
                continue;
            this._debuggerURL = data[i].webSocketDebuggerUrl.replace("://", "=");
            this._navigateTestPage();
            break;
        }
    },

    _navigateTestPage: function()
    {
        this._testPage.location.href = this._testPath;
        var width = localStorage.getItem('inspectorWidth') || 600;
        var height = localStorage.getItem('inspectorHeight') || 400;
        var features = "width=" + Math.max(width , 600) + ",height=" + Math.max(height, 400);
        this._inspectorWindowLoading = window.open(StandaloneTestRunner.FrontendLocation + "?" + this._debuggerURL, "inspector", features);
        this._inspectorWindowLoading.dispatchStandaloneTestRunnerMessages = true;
        
        window.addEventListener('unload', this.cleanup.bind(this));

        if (!window.debug)
            this._watchDog = setTimeout(this._timeout.bind(this), 10000);
    },

    loadCompleted: function()
    {
        if (!window.debug) {
            this._loadCompleted(this);
            return;
        }
        document.getElementById("debug").textContent = "Continue";
    },

    continueDebugging: function()
    {
        this._loadCompleted();
    },

    _loadCompleted: function()
    {
        this._inspectorWindow = this._inspectorWindowLoading;
        for (var i = 0; i < this._pendingMessages.length; ++i)
            this._inspectorWindow.postMessage(this._pendingMessages[i], "*");
        this._pendingMessages = [];
    },

    closeWebInspector: function()
    {
        if (!window.debug)
            this._inspectorWindow.close();
    },

    notifyDone: function(actual)
    {
        if (this._done)
            return;
        this._done = true;

        if (!window.debug) 
            this.cleanup()

        clearTimeout(this._watchDog);

        this._treeElement.onselect = this.onTreeElementSelect.bind(this);

        // TODO pavel  is the  RHS || condition wanted?
        if (actual === this._expected || actual === this._expected + "\n") {
            this._treeElement.title = this._testPath + ": SUCCESS";
            this._next("pass");
            return;
        }

        this._treeElement.title = this._testPath + ": FAILED";
        this._treeElement.listItemElement.addStyleClass("failed");

        var baseLines = difflib.stringAsLines(this._expected);
        var newLines = difflib.stringAsLines(actual);
        var sm = new difflib.SequenceMatcher(baseLines, newLines);
        var opcodes = sm.get_opcodes();
        var lastWasSeparator = false;

        for (var idx = 0; idx < opcodes.length; idx++) {
            var code = opcodes[idx];
            var change = code[0];
            var b = code[1];
            var be = code[2];
            var n = code[3];
            var ne = code[4];
            var rowCount = Math.max(be - b, ne - n);
            var topRows = [];
            var bottomRows = [];
            for (var i = 0; i < rowCount; i++) {
                if (change === "delete" || (change === "replace" && b < be)) {
                    var lineNumber = b++;
                    this._treeElement.appendChild(new TreeElement("- [" + lineNumber + "] " + baseLines[lineNumber]));
                }

                if (change === "insert" || (change === "replace" && n < ne)) {
                    var lineNumber = n++;
                    this._treeElement.appendChild(new TreeElement("+ [" + lineNumber + "] " + newLines[lineNumber]));
                }

                if (change === "equal") {
                    b++;
                    n++;
                }
            }
        }

        this._next("fail");
    },

    evaluateInWebInspector: function(callId, script)
    {
        if (this._inspectorWindow)
            this._inspectorWindow.postMessage(["evaluateForTest", callId, script], "*");
        else
            this._pendingMessages.push(["evaluateForTest", callId, script]);
    },

    _timeout: function()
    {
        this._treeElement.title = this._testPath + ": TIMEOUT";
        this._treeElement.listItemElement.addStyleClass("timeout");
        this._done = true;
        this.cleanup();
        this._next("timeout");
    },

    cleanup: function ()
    {
        localStorage.setItem('inspectorWidth', this._inspectorWindowLoading.outerWidth);
        localStorage.setItem('inspectorHeight', this._inspectorWindowLoading.outerHeight);
        this._inspectorWindowLoading.close();
        this._testPage.close();
        delete window.runner;
    },

    onTreeElementSelect: function () 
    {
        var baseEndSentinel = '/inspector/';
        var baseChars = this._testPath.indexOf(baseEndSentinel) + baseEndSentinel.length;
        if (baseChars > 0) 
            document.getElementById("filter").value = this._testPath.substr(baseChars);
    },

    display: function() { }
}

function onMessageFromTestPage(event)
{
    var signature = event.data;
    var method = signature.shift();
    if (method === "tests") {
        tests = signature[0];
        runTests();
        return;
    }

    if (window.runner)
        window.runner[method].apply(window.runner, signature);
}

function onload()
{
    var queryParamsObject = {};
    var queryParams = window.location.search;
    if (!queryParams)
        return;
    var params = queryParams.substring(1).split("&");
    for (var i = 0; i < params.length; ++i) {
        var pair = params[i].split("=");
        queryParamsObject[pair[0]] = pair[1];
    }
    if ("filter" in queryParamsObject)
        document.getElementById("filter").value = queryParamsObject["filter"];
}

window.addEventListener("message", onMessageFromTestPage, true);

</script>
<body onload="onload()">
This is a standalone test suite for inspector front-end. Here is how you run it:
<ul>
<li>Check out WebKit source tree: git clone http://git.chromium.org/external/Webkit.git</li>
<li>Run "Tools/Scripts/new-run-webkit-httpd --root=. --port=8002 --server=start"</li>
<li>Run Chrome Canary (ToT Chromium) with following flags: "--remote-debugging-port=9222 --user-data-dir=testProfile http://localhost:8002/Source/WebCore/inspector/front-end/test-runner.html"</li>
</ul>

<button onclick="run()">Run</button>
<button id="debug" onclick="run(true)">Debug</button>
<button onclick="interrupt()">Interrupt</button>
Filter: <input id="filter" type="text" size="40"></input><small><i>Click on results to load filter</i></small><br>

<span>Passed: <span id="pass">0</span></span>
<span>Failed: <span id="fail">0</span></span>
<span>Timeout: <span id="timeout">0</span></span>
<span>Skipped: <span id="skip">0</span></span>
<span>Remaining: <span id="remaining">0</span><br>

<ol id="outline" style="font-size: 12px !important" class="source-code outline-disclosure"></ol>

</body>
</html>