<html>
<head>
<script src="../../http/tests/inspector/inspector-test.js"></script>
<script src="../../http/tests/inspector/timeline-test.js"></script>
<script>

var scriptUrl = "timeline-network-resource.js";

function performActions() 
{
    var script = document.createElement("script");
    script.src = scriptUrl;
    document.body.appendChild(script);
}

function test()
{
    var requestId;
    var scriptUrl = "timeline-network-resource.js";

    WebInspector.showPanel("timeline");
    var model = WebInspector.panels.timeline._model;
    var presentationModel = WebInspector.panels.timeline._presentationModel;
    presentationModel.setGlueRecords(true);

    InspectorTest.startTimeline(step1);

    function step1()
    {
        InspectorTest.evaluateInPage("performActions()");
        InspectorTest.addConsoleSniffer(step2);
    }

    function step2()
    {
        InspectorTest.stopTimeline(step3);
    }

    function step3()
    {
        var lastRecordStartTime;
        function format(record)
        {
            if (record.type === WebInspector.TimelineModel.RecordType.ResourceSendRequest)
                printSend(record._record);
            else if (record.type === WebInspector.TimelineModel.RecordType.ResourceReceiveResponse)
                printReceive(record._record);
            else if (record.type === WebInspector.TimelineModel.RecordType.ResourceFinish)
                printFinish(record._record);

            if (record.parent && record.parent.type === WebInspector.TimelineModel.RecordType.Root) {
                if (lastRecordStartTime)
                    InspectorTest.assertGreaterOrEqual(record.startTime, lastRecordStartTime, "Top level records order violation");
                lastRecordStartTime = record.startTime;
            }
        }
        WebInspector.TimelinePresentationModel.forAllRecords([presentationModel.rootRecord()], format);
        InspectorTest.completeTest();
    }

    function printRecord(record)
    {
        InspectorTest.addResult("");
        InspectorTest.printTimelineRecordProperties(record);
    }

    function printSend(record)
    {
        printRecord(record);
        requestId = record.data.requestId;
        if (record.data.url === undefined) 
            InspectorTest.addResult("* No 'url' property in record");
        else if (record.data.url.indexOf(scriptUrl) === -1)
            InspectorTest.addResult("* Didn't find URL: " + scriptUrl);
    }

    function printReceive(record)
    {
        printRecord(record);
        if (requestId !== record.data.requestId)
            InspectorTest.addResult("Didn't find matching requestId: " + requestId);
        if (record.data.statusCode !== 0)
            InspectorTest.addResult("Response received status: " + record.data.statusCode);
    }

    function printFinish(record)
    {
        printRecord(record);
        if (requestId !== record.data.requestId)
            InspectorTest.addResult("Didn't find matching requestId: " + requestId);
        if (record.data.didFail)
            InspectorTest.addResult("Request failed.");
    }
}

</script>
</head>

<body onload="runTest()">
<p>
Tests the Timeline API instrumentation of a network resource load
</p>
</body>
</html>
