var steps = [ // Test single mark addition function () { ok(true, "Running mark addition test"); performance.mark("test"); var marks = performance.getEntriesByType("mark"); is(marks.length, 1, "Number of marks should be 1"); var mark = marks[0]; is(mark.name, "test", "mark name should be 'test'"); is(mark.entryType, "mark", "mark type should be 'mark'"); isnot(mark.startTime, 0, "mark start time should not be 0"); is(mark.duration, 0, "mark duration should be 0"); }, // Test multiple mark addition function () { ok(true, "Running multiple mark with same name addition test"); performance.mark("test"); performance.mark("test"); performance.mark("test"); var marks_type = performance.getEntriesByType("mark"); is(marks_type.length, 3, "Number of marks by type should be 3"); var marks_name = performance.getEntriesByName("test"); is(marks_name.length, 3, "Number of marks by name should be 3"); var mark = marks_name[0]; is(mark.name, "test", "mark name should be 'test'"); is(mark.entryType, "mark", "mark type should be 'mark'"); isnot(mark.startTime, 0, "mark start time should not be 0"); is(mark.duration, 0, "mark duration should be 0"); var times = []; // This also tests the chronological ordering specified as // required for getEntries in the performance timeline spec. marks_name.forEach(function (s) { times.forEach(function (time) { ok( s.startTime >= time.startTime, "Times should be equal or increasing between similarly named marks: " + s.startTime + " >= " + time.startTime ); }); times.push(s); }); }, // Test all marks removal function () { ok(true, "Running all mark removal test"); performance.mark("test"); performance.mark("test2"); var marks = performance.getEntriesByType("mark"); is(marks.length, 2, "number of marks before all removal"); performance.clearMarks(); marks = performance.getEntriesByType("mark"); is(marks.length, 0, "number of marks after all removal"); }, // Test single mark removal function () { ok(true, "Running removal test (0 'test' marks with other marks)"); performance.mark("test2"); var marks = performance.getEntriesByType("mark"); is(marks.length, 1, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 1, "number of marks after all removal"); }, // Test single mark removal function () { ok(true, "Running removal test (0 'test' marks with no other marks)"); var marks = performance.getEntriesByType("mark"); is(marks.length, 0, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 0, "number of marks after all removal"); }, function () { ok(true, "Running removal test (1 'test' mark with other marks)"); performance.mark("test"); performance.mark("test2"); var marks = performance.getEntriesByType("mark"); is(marks.length, 2, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 1, "number of marks after all removal"); }, function () { ok(true, "Running removal test (1 'test' mark with no other marks)"); performance.mark("test"); var marks = performance.getEntriesByType("mark"); is(marks.length, 1, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 0, "number of marks after all removal"); }, function () { ok(true, "Running removal test (2 'test' marks with other marks)"); performance.mark("test"); performance.mark("test"); performance.mark("test2"); var marks = performance.getEntriesByType("mark"); is(marks.length, 3, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 1, "number of marks after all removal"); }, function () { ok(true, "Running removal test (2 'test' marks with no other marks)"); performance.mark("test"); performance.mark("test"); var marks = performance.getEntriesByType("mark"); is(marks.length, 2, "number of marks before all removal"); performance.clearMarks("test"); marks = performance.getEntriesByType("mark"); is(marks.length, 0, "number of marks after all removal"); }, // Test mark name being same as navigation timing parameter function () { ok(true, "Running mark name collision test"); for (n in performance.timing) { try { if (n == "toJSON") { ok(true, "Skipping toJSON entry in collision test"); continue; } performance.mark(n); ok( false, "Mark name collision test failed for name " + n + ", shouldn't make it here!" ); } catch (e) { ok( e instanceof DOMException, "DOM exception thrown for mark named " + n ); is( e.code, e.SYNTAX_ERR, "DOM exception for name collision is syntax error" ); } } }, // Test measure function () { ok(true, "Running measure addition with no start/end time test"); performance.measure("test"); var measures = performance.getEntriesByType("measure"); is(measures.length, 1, "number of measures should be 1"); var measure = measures[0]; is(measure.name, "test", "measure name should be 'test'"); is(measure.entryType, "measure", "measure type should be 'measure'"); is(measure.startTime, 0, "measure start time should be zero"); ok(measure.duration >= 0, "measure duration should not be negative"); }, function () { ok(true, "Running measure addition with only start time test"); performance.mark("test1"); performance.measure("test", "test1", undefined); var measures = performance.getEntriesByName("test", "measure"); var marks = performance.getEntriesByName("test1", "mark"); var measure = measures[0]; var mark = marks[0]; is( measure.startTime, mark.startTime, "measure start time should be equal to the mark startTime" ); ok(measure.duration >= 0, "measure duration should not be negative"); }, function () { ok(true, "Running measure addition with only end time test"); performance.mark("test1"); performance.measure("test", undefined, "test1"); var measures = performance.getEntriesByName("test", "measure"); var marks = performance.getEntriesByName("test1", "mark"); var measure = measures[0]; var mark = marks[0]; ok(measure.duration >= 0, "measure duration should not be negative"); }, // Test measure picking latest version of similarly named tags function () { ok(true, "Running multiple mark with same name addition test"); performance.mark("test"); performance.mark("test"); performance.mark("test"); performance.mark("test2"); var marks_name = performance.getEntriesByName("test"); is(marks_name.length, 3, "Number of marks by name should be 3"); var marks_name2 = performance.getEntriesByName("test2"); is(marks_name2.length, 1, "Number of marks by name should be 1"); var test_mark = marks_name2[0]; performance.measure("test", "test", "test2"); var measures_type = performance.getEntriesByType("measure"); var last_mark = marks_name[marks_name.length - 1]; is(measures_type.length, 1, "Number of measures by type should be 1"); var measure = measures_type[0]; is( measure.startTime, last_mark.startTime, "Measure start time should be the start time of the latest 'test' mark" ); // Tolerance testing to avoid oranges, since we're doing double math across two different languages. ok( measure.duration - (test_mark.startTime - last_mark.startTime) < 0.00001, "Measure duration ( " + measure.duration + ") should be difference between two marks" ); }, function () { // We don't have navigationStart in workers. if ("window" in self) { ok(true, "Running measure addition with no start/end time test"); performance.measure("test", "navigationStart"); var measures = performance.getEntriesByType("measure"); is(measures.length, 1, "number of measures should be 1"); var measure = measures[0]; is(measure.name, "test", "measure name should be 'test'"); is(measure.entryType, "measure", "measure type should be 'measure'"); is(measure.startTime, 0, "measure start time should be zero"); ok(measure.duration >= 0, "measure duration should not be negative"); } }, // Test all measure removal function () { ok(true, "Running all measure removal test"); performance.measure("test"); performance.measure("test2"); var measures = performance.getEntriesByType("measure"); is(measures.length, 2, "measure entries should be length 2"); performance.clearMeasures(); measures = performance.getEntriesByType("measure"); is(measures.length, 0, "measure entries should be length 0"); }, // Test single measure removal function () { ok(true, "Running all measure removal test"); performance.measure("test"); performance.measure("test2"); var measures = performance.getEntriesByType("measure"); is(measures.length, 2, "measure entries should be length 2"); performance.clearMeasures("test"); measures = performance.getEntriesByType("measure"); is(measures.length, 1, "measure entries should be length 1"); }, // Test measure with invalid start time mark name function () { ok(true, "Running measure invalid start test"); try { performance.measure("test", "notamark"); ok(false, "invalid measure start time exception not thrown!"); } catch (e) { ok(e instanceof DOMException, "DOM exception thrown for invalid measure"); is( e.code, e.SYNTAX_ERR, "DOM exception for invalid time is syntax error" ); } }, // Test measure with invalid end time mark name function () { ok(true, "Running measure invalid end test"); try { performance.measure("test", undefined, "notamark"); ok(false, "invalid measure end time exception not thrown!"); } catch (e) { ok(e instanceof DOMException, "DOM exception thrown for invalid measure"); is( e.code, e.SYNTAX_ERR, "DOM exception for invalid time is syntax error" ); } }, // Test measure name being same as navigation timing parameter function () { ok(true, "Running measure name collision test"); for (n in performance.timing) { if (n == "toJSON") { ok(true, "Skipping toJSON entry in collision test"); continue; } performance.measure(n); ok(true, "Measure name supports name collisions: " + n); } }, // Test measure mark being a reserved name function () { ok(true, "Create measures using all reserved names"); for (n in performance.timing) { try { if (n == "toJSON") { ok(true, "Skipping toJSON entry in collision test"); continue; } performance.measure("test", n); ok(true, "Measure created from reserved name as starting time: " + n); } catch (e) { ok( [ "redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd", "secureConnectionStart", ].includes(n), "Measure created from reserved name as starting time: " + n + " and threw expected error" ); } } }, // TODO: Test measure picking latest version of similarly named tags ];