tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_resource_timing.js (9464B)


      1 var TEST_ALLOWED_TIMING_DELTA = 20;
      2 
      3 var waitTimer;
      4 var expectedEntries = {};
      5 
      6 var initiatorTypes = ["iframe", "img", "link", "script", "xmlhttprequest"];
      7 
      8 var tests = {};
      9 setup(function() {
     10    for (var i in initiatorTypes) {
     11        var type = initiatorTypes[i];
     12        tests[type] = {
     13            "entry": async_test("window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (" + type + ")"),
     14            "simple_attrs": async_test("PerformanceEntry has correct name, initiatorType, startTime, and duration (" + type + ")"),
     15            "timing_attrs": async_test("PerformanceEntry has correct order of timing attributes (" + type + ")"),
     16            "network_attrs": async_test("PerformanceEntry has correct network transfer attributes (" + type + ")"),
     17            "protocol": async_test("PerformanceEntry has correct protocol attribute (" + type + ")")
     18        };
     19    }
     20 });
     21 
     22 function resolve(path) {
     23    var a = document.createElement("a");
     24    a.href = path;
     25    return a.href;
     26 }
     27 
     28 onload = function()
     29 {
     30    // check that the Performance Timeline API exists
     31    test(function() {
     32        assert_idl_attribute(window.performance, "getEntriesByName",
     33                             "window.performance.getEntriesByName() is defined");
     34    });
     35    test(function() {
     36        assert_idl_attribute(window.performance, "getEntriesByType",
     37                             "window.performance.getEntriesByType() is defined");
     38    });
     39    test(function() {
     40        assert_idl_attribute(window.performance, "getEntries",
     41                             "window.performance.getEntries() is defined");
     42    });
     43 
     44    var expected_entry;
     45    var url;
     46    var type;
     47    var startTime;
     48    var element;
     49    var encodedBodySize;
     50    var decodedBodySize;
     51    for (var i in initiatorTypes) {
     52        startTime = window.performance.now();
     53        type = initiatorTypes[i];
     54        if (type != "xmlhttprequest") {
     55            element = document.createElement(type);
     56        } else {
     57            element = null;
     58        }
     59        switch (type) {
     60        case "iframe":
     61            url = resolve("resources/resource_timing_test0.html");
     62            element.src = url;
     63            encodedBodySize = 215;
     64            decodedBodySize = 215;
     65            break;
     66        case "img":
     67            url = resolve("resources/resource_timing_test0.png");
     68            element.src = url;
     69            encodedBodySize = 249;
     70            decodedBodySize = 249;
     71            break;
     72        case "link":
     73            element.rel = "stylesheet";
     74            url = resolve("resources/resource_timing_test0.css");
     75            element.href = url;
     76            encodedBodySize = 44;
     77            decodedBodySize = 44;
     78            break;
     79        case "script":
     80            element.type = "text/javascript";
     81            url = resolve("resources/resource_timing_test0.js");
     82            element.src = url;
     83            encodedBodySize = 133;
     84            decodedBodySize = 133;
     85            break;
     86        case "xmlhttprequest":
     87            var xmlhttp = new XMLHttpRequest();
     88            url = resolve("resources/gzip_xml.py");
     89            xmlhttp.open('GET', url, true);
     90            xmlhttp.send();
     91            encodedBodySize = 112;
     92            decodedBodySize = 125;
     93            break;
     94        }
     95 
     96        expected_entry = {name:url,
     97                          startTime: startTime,
     98                          initiatorType: type,
     99                          encodedBodySize: encodedBodySize,
    100                          decodedBodySize: decodedBodySize
    101                         };
    102 
    103        switch (type) {
    104        case "link":
    105            poll_for_stylesheet_load(expected_entry);
    106            document.body.appendChild(element);
    107            break;
    108        case "xmlhttprequest":
    109            xmlhttp.onload = (function(entry) {
    110                return function (event) {
    111                    resource_load(entry);
    112                };
    113            })(expected_entry);
    114            break;
    115        default:
    116            element.onload = (function(entry) {
    117                return function (event) {
    118                    resource_load(entry);
    119                };
    120            })(expected_entry);
    121            document.body.appendChild(element);
    122        }
    123 
    124    }
    125 };
    126 
    127 function poll_for_stylesheet_load(expected_entry) {
    128    var t = tests[expected_entry.initiatorType];
    129 
    130    function inner() {
    131        for(var i=0; i<document.styleSheets.length; i++) {
    132            var sheet = document.styleSheets[i];
    133            if (sheet.href === expected_entry.name) {
    134                try {
    135                    // try/catch avoids throwing if sheet object exists before it is loaded,
    136                    // which is a bug, but not what we are trying to test here.
    137                    var hasRules = sheet.cssRules.length > 0;
    138                } catch(e) {
    139                    hasRules = false;
    140                }
    141                if (hasRules) {
    142                    t["entry"].step_timeout(function() {
    143                        resource_load(expected_entry);
    144                    }, 200);
    145                    return;
    146                }
    147            }
    148        }
    149        t["entry"].step_timeout(inner, 100);
    150    }
    151    inner();
    152 }
    153 
    154 function resource_load(expected)
    155 {
    156    var t = tests[expected.initiatorType];
    157 
    158    t["entry"].step(function() {
    159        var entries_by_name = window.performance.getEntriesByName(expected.name);
    160        assert_equals(entries_by_name.length, 1, "should have a single entry for each resource (without type)");
    161        var entries_by_name_type = window.performance.getEntriesByName(expected.name, "resource");
    162        assert_equals(entries_by_name_type.length, 1, "should have a single entry for each resource (with type)");
    163        assert_not_equals(entries_by_name, entries_by_name_type, "values should be copies");
    164        for (p in entries_by_name[0]) {
    165            var assertMethod = assert_equals
    166            if (Array.isArray(entries_by_name[0][p]) && Array.isArray(entries_by_name_type[0][p])) {
    167              assertMethod = assert_array_equals
    168            }
    169            assertMethod(entries_by_name[0][p], entries_by_name_type[0][p], "Property " + p + " should match");
    170        }
    171        this.done();
    172    });
    173 
    174    t["simple_attrs"].step(function() {
    175        var actual = window.performance.getEntriesByName(expected.name)[0];
    176        var expected_type = expected.initiatorType;
    177        assert_equals(actual.name, expected.name);
    178        assert_equals(actual.initiatorType, expected_type);
    179        assert_equals(actual.entryType, "resource");
    180        assert_greater_than_equal(actual.startTime, expected.startTime, "startTime is after the script to initiate the load ran");
    181        assert_equals(actual.duration, (actual.responseEnd - actual.startTime));
    182        this.done();
    183    });
    184 
    185    t["timing_attrs"].step(function test() {
    186        const entries = window.performance.getEntriesByName(expected.name);
    187        assert_equals(entries.length, 1, 'There should be a single matching entry');
    188        const actual = entries[0];
    189        if (window.location.protocol == "http:") {
    190            assert_equals(actual.secureConnectionStart, 0, 'secureConnectionStart should be 0 in http');
    191        } else {
    192            assert_greater_than(actual.secureConnectionStart, 0, 'secureConnectionStart should not be 0 in https');
    193        }
    194 
    195        assert_equals(actual.redirectStart, 0, 'redirectStart should be 0');
    196        assert_equals(actual.redirectEnd, 0, 'redirectEnd should be 0');
    197        assert_equals(actual.fetchStart, actual.startTime, 'fetchStart is equal to startTime');
    198        assert_greater_than_equal(actual.domainLookupStart, actual.fetchStart, 'domainLookupStart after fetchStart');
    199        assert_greater_than_equal(actual.domainLookupEnd, actual.domainLookupStart, 'domainLookupEnd after domainLookupStart');
    200        assert_greater_than_equal(actual.connectStart, actual.domainLookupEnd, 'connectStart after domainLookupEnd');
    201        assert_greater_than_equal(actual.connectEnd, actual.connectStart, 'connectEnd after connectStart');
    202        assert_true(actual.secureConnectionStart == 0 || actual.secureConnectionStart <= actual.requestStart,
    203            "secureConnectionStart should be either 0 or smaller than/equals to requestStart")
    204        assert_greater_than_equal(actual.requestStart, actual.connectEnd, 'requestStart after connectEnd');
    205        assert_greater_than_equal(actual.responseStart, actual.requestStart, 'responseStart after requestStart');
    206        assert_greater_than_equal(actual.responseEnd, actual.responseStart, 'responseEnd after responseStart');
    207        this.done();
    208    });
    209 
    210    t["network_attrs"].step(function test() {
    211        var actual = window.performance.getEntriesByName(expected.name)[0];
    212        assert_equals(actual.encodedBodySize, expected.encodedBodySize, "encodedBodySize size");
    213        assert_equals(actual.decodedBodySize, expected.decodedBodySize, "decodedBodySize size");
    214 
    215        // Transfer size will vary from browser to browser based on default headers, etc. This
    216        // test verifies that transferSize for uncached resources is greater than on-the-wire
    217        // body size.
    218        assert_greater_than(actual.transferSize, actual.encodedBodySize, "transferSize size");
    219        this.done();
    220    });
    221 
    222    t["protocol"].step(function() {
    223        var actual = window.performance.getEntriesByName(expected.name)[0];
    224        assert_equals(actual.nextHopProtocol, "http/1.1", "expected protocol");
    225        this.done();
    226    });
    227 
    228 }