<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>window.performance User Timing mark() method is working properly</title>
        <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
        <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-mark"/>
        <script src="/resources/testharness.js"></script>
        <script src="/resources/testharnessreport.js"></script>
        <script src="resources/webperftestharness.js"></script>

    <script type="text/javascript">
        // test data
        var markTestDelay = 200;
        var testThreshold = 20;
        var marks;

        var TEST_MARKS =
        [
            {
                name:                   "mark1",
                expectedStartTime:      undefined,
                entryMatch:             undefined
            },
            {
                name:                   "mark1",
                expectedStartTime:      undefined,
                entryMatch:             undefined
            }
        ];

        setup({explicit_done: true});

        test_namespace();

        function onload_test()
        {
            // test for existance of User Timing and Performance Timeline interface
            if (!has_required_interfaces())
            {
                test_true(false,
                          "The User Timing and Performance Timeline interfaces, which are required for this test, " +
                          "are defined.");

                done();
            }
            else
            {
                // create first mark
                window.performance.mark(TEST_MARKS[0].name);

                // record the time that this mark is created; this should correspond to the mark's startTime
                TEST_MARKS[0].expectedStartTime = (new Date()) - window.performance.timing.navigationStart;

                // create the duplicate mark using the test delay; the duplicate mark's value should be equivalent to
                // the loadEventStart navigation timing attribute plus the test delay
                setTimeout(mark_test_cb, markTestDelay);
            }
        }

        function mark_test_cb()
        {
            var getByNameScenarios = new Array();

            // create second, duplicate mark
            window.performance.mark(TEST_MARKS[1].name);

            // record the time that this mark is created; this should correspond to the mark's startTime
            TEST_MARKS[1].expectedStartTime = (new Date()) - window.performance.timing.navigationStart;

            // test the test marks are returned by getEntriesByName
            entries = window.performance.getEntriesByName(TEST_MARKS[0].name);
            test_mark(entries[0],
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")[0]",
                      TEST_MARKS[0].name,
                      TEST_MARKS[0].expectedStartTime);
            TEST_MARKS[0].entryMatch = entries[0];

            test_mark(entries[1],
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")[1]",
                      TEST_MARKS[1].name,
                      TEST_MARKS[1].expectedStartTime);
            TEST_MARKS[1].entryMatch = entries[1];

            // test the test marks are returned by getEntriesByName with the entryType parameter provided
            entries = window.performance.getEntriesByName(TEST_MARKS[0].name, "mark");
            test_equals(entries[0].name, TEST_MARKS[0].name,
                        "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\", \"mark\") returns an " +
                        "object containing the \"" + TEST_MARKS[0].name + "\" mark in the correct order");

            test_equals(entries[1].name, TEST_MARKS[1].name,
                        "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\", \"mark\") returns an " +
                        "object containing the duplicate \"" + TEST_MARKS[1].name + "\" mark in the correct order");

            test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
                      "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\", \"mark\") matches the " +
                      "the \"" + TEST_MARKS[0].name + "\" mark returned by " +
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");

            test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
                      "The duplicate \"" + TEST_MARKS[1].name + "\" mark returned by " +
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\", \"mark\") matches the " +
                      "the duplicate \"" + TEST_MARKS[1].name + "\" mark returned by " +
                      "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")");

            // test the test marks are returned by getEntries
            entries = get_test_entries(window.performance.getEntries(), "mark");

            test_equals(entries[0].name, TEST_MARKS[0].name,
                        "window.performance.getEntries() returns an object containing the original \"" +
                        TEST_MARKS[0].name + "\" mark in the correct order");

            test_equals(entries[1].name, TEST_MARKS[1].name,
                        "window.performance.getEntries() returns an object containing the duplicate \"" +
                        TEST_MARKS[1].name + "\" mark in the correct order");

            test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
                      "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
                      "window.performance.getEntries() matches the the \"" + TEST_MARKS[0].name + "\" mark returned " +
                      "by window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");

            test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
                      "The \"" + TEST_MARKS[1].name + "\" mark returned by " +
                      "window.performance.getEntries() matches the the duplicate \"" + TEST_MARKS[1].name + "\" mark " +
                      "returned by window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")");

            // test the test marks are returned by getEntriesByType
            entries = window.performance.getEntriesByType("mark");

            test_equals(entries[0].name, TEST_MARKS[0].name,
                        "window.performance.getEntriesByType(\"mark\") returns an object containing the original \"" +
                        TEST_MARKS[0].name + "\" mark in the correct order");

            test_equals(entries[1].name, TEST_MARKS[1].name,
                        "window.performance.getEntriesByType(\"mark\") returns an object containing the duplicate \"" +
                        TEST_MARKS[1].name + "\" mark in the correct order");

            test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
                      "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
                      "window.performance.getEntriesByType(\"mark\") matches the the \"" + TEST_MARKS[0].name +
                      "\" mark returned by window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");

            test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
                      "The \"" + TEST_MARKS[1].name + "\" mark returned by " +
                      "window.performance.getEntriesByType(\"mark\") matches the the duplicate \"" +
                      TEST_MARKS[1].name + "\" mark returned by window.performance.getEntriesByName(\"" +
                      TEST_MARKS[1].name + "\")");

            done();
        }

        function match_entries(entry1, entry2)
        {
            var pass = true;

            // match name
            pass = pass && (entry1.name == entry2.name);

            // match startTime
            pass = pass && (entry1.startTime == entry2.startTime);

            // match entryType
            pass = pass && (entry1.entryType == entry2.entryType);

            // match duration
            pass = pass && (entry1.duration == entry2.duration);

            return pass;
        }

        function test_mark(markEntry, markEntryCommand, expectedName, expectedStartTime)
        {
            // test name
            test_equals(markEntry.name, expectedName, markEntryCommand + ".name == \"" + expectedName + "\"");

            // test startTime, allow for an acceptable threshold in the difference between the startTime and the
            // expected value for the startTime (loadEventStart + markTestDelay)
            test_true(Math.abs(markEntry.startTime - expectedStartTime) <= testThreshold,
                      markEntryCommand + ".startTime is approximately correct (up to " + testThreshold +
                      "ms difference allowed)");

            // verify entryType
            test_equals(markEntry.entryType, "mark", markEntryCommand + ".entryType == \"mark\"");

            // verify duration
            test_equals(markEntry.duration, 0, markEntryCommand + ".duration == 0");
        }

        function get_test_entries(entryList, entryType)
        {
            var testEntries = new Array();

            // filter entryList
            for (var i in entryList)
            {
                if (entryList[i].entryType == entryType)
                {
                    testEntries.push(entryList[i]);
                }
            }

            return testEntries;
        }
    </script>
    </head>
    <body onload="onload_test();">
        <h1>Description</h1>
        <p>This test validates that the performance.mark() method is working properly. This test creates the
           following marks to test this method:
            <ul>
                <li>"mark1": created using a normal mark() call</li>
                <li>"mark1": duplicate of the first mark, used to confirm names can be re-used</li>
            </ul>
           After creating each mark, the existence of these marks is validated by calling
           performance.getEntriesByName() (both with and without the entryType parameter provided),
           performance.getEntriesByType(), and performance.getEntries()
        </p>

        <div id="log"></div>
    </body>
</html>
