blob: 88014efc89128646bb9f77d673bf5da0b163422c [file] [log] [blame]
// Asserts that the given attributes are present in 'entry' and hold equal
// values.
const assert_all_equal_ = (entry, attributes) => {
let first = attributes[0];
attributes.slice(1).forEach(other => {
assert_equals(entry[first], entry[other],
`${first} should be equal to ${other}`);
});
}
// Asserts that the given attributes are present in 'entry' and hold values
// that are sorted in the same order as given in 'attributes'.
const assert_ordered_ = (entry, attributes) => {
let before = attributes[0];
attributes.slice(1).forEach(after => {
assert_greater_than_equal(entry[after], entry[before],
`${after} should be greater than ${before}`);
before = after;
});
}
// Asserts that the given attributes are present in 'entry' and hold a value of
// 0.
const assert_zeroed_ = (entry, attributes) => {
attributes.forEach(attribute => {
assert_equals(entry[attribute], 0, `${attribute} should be 0`);
});
}
// Asserts that the given attributes are present in 'entry' and hold a value of
// 0 or more.
const assert_not_negative_ = (entry, attributes) => {
attributes.forEach(attribute => {
assert_greater_than_equal(entry[attribute], 0,
`${attribute} should be greater than or equal to 0`);
});
}
// Asserts that the given attributes are present in 'entry' and hold a value
// greater than 0.
const assert_positive_ = (entry, attributes) => {
attributes.forEach(attribute => {
assert_greater_than(entry[attribute], 0,
`${attribute} should be greater than 0`);
});
}
const invariants = {
// Asserts that attributes of the given PerformanceResourceTiming entry match
// what the spec dictates for any resource fetched over HTTP without
// redirects but passing the Timing-Allow-Origin checks.
assert_tao_pass_no_redirect_http: entry => {
assert_ordered_(entry, [
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"connectEnd",
"requestStart",
"responseStart",
"responseEnd",
]);
assert_zeroed_(entry, [
"workerStart",
"secureConnectionStart",
"redirectStart",
"redirectEnd",
]);
assert_not_negative_(entry, [
"duration",
]);
assert_positive_(entry, [
"fetchStart",
"transferSize",
"encodedBodySize",
"decodedBodySize",
]);
},
// Like assert_tao_pass_no_redirect_http but for resources fetched over HTTPS
assert_tao_pass_no_redirect_https: entry => {
assert_ordered_(entry, [
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"secureConnectionStart",
"connectStart",
"connectEnd",
"requestStart",
"responseStart",
"responseEnd",
]);
assert_zeroed_(entry, [
"workerStart",
"redirectStart",
"redirectEnd",
]);
assert_not_negative_(entry, [
"duration",
]);
assert_positive_(entry, [
"fetchStart",
"transferSize",
"encodedBodySize",
"decodedBodySize",
]);
},
// Like assert_tao_pass_no_redirect_http but, since the resource's bytes
// won't be retransmitted, the encoded and decoded sizes must be zero.
assert_tao_pass_304_not_modified_http: entry => {
assert_ordered_(entry, [
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"connectEnd",
"requestStart",
"responseStart",
"responseEnd",
]);
assert_zeroed_(entry, [
"workerStart",
"secureConnectionStart",
"redirectStart",
"redirectEnd",
"encodedBodySize",
"decodedBodySize",
]);
assert_not_negative_(entry, [
"duration",
]);
assert_positive_(entry, [
"fetchStart",
"transferSize",
]);
},
// Like assert_tao_pass_304_not_modified_http but for resources fetched over
// HTTPS.
assert_tao_pass_304_not_modified_https: entry => {
assert_ordered_(entry, [
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"secureConnectionStart",
"connectStart",
"connectEnd",
"requestStart",
"responseStart",
"responseEnd",
]);
assert_zeroed_(entry, [
"workerStart",
"redirectStart",
"redirectEnd",
"encodedBodySize",
"decodedBodySize",
]);
assert_not_negative_(entry, [
"duration",
]);
assert_positive_(entry, [
"fetchStart",
"transferSize",
]);
},
// Asserts that attributes of the given PerformanceResourceTiming entry match
// what the spec dictates for any resource subsequently fetched over a
// persistent connection. When this happens, we expect that certain
// attributes describing transport layer behaviour will be equal.
assert_connection_reused: entry => {
assert_all_equal_(entry, [
"fetchStart",
"connectStart",
"connectEnd",
"domainLookupStart",
"domainLookupEnd",
]);
},
// Asserts that attributes of the given PerformanceResourceTiming entry match
// what the spec dictates for any resource fetched over HTTP through an HTTP
// redirect.
assert_same_origin_redirected_resource: entry => {
assert_positive_(entry, [
"redirectStart",
]);
assert_equals(entry.redirectStart, entry.startTime,
"redirectStart should be equal to startTime");
assert_ordered_(entry, [
"redirectStart",
"redirectEnd",
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
]);
},
// Asserts that attributes of the given PerformanceResourceTiming entry match
// what the spec dictates for any resource fetched over HTTPS through a
// cross-origin redirect.
// (e.g. GET http://remote.com/foo => 302 Location: https://remote.com/foo)
assert_cross_origin_redirected_resource: entry => {
assert_zeroed_(entry, [
"redirectStart",
"redirectEnd",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"connectEnd",
"secureConnectionStart",
"requestStart",
"responseStart",
]);
assert_positive_(entry, [
"fetchStart",
"responseEnd",
]);
assert_ordered_(entry, [
"fetchStart",
"responseEnd",
]);
},
// Asserts that attributes of the given PerformanceResourceTiming entry match
// what the spec dictates for a resource fetched over HTTPS through a
// TAO enabled cross-origin redirect.
assert_tao_enabled_cross_origin_redirected_resource: entry => {
assert_positive_(entry, [
"redirectStart",
]);
assert_ordered_(entry, [
"redirectStart",
"redirectEnd",
"fetchStart",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"secureConnectionStart",
"connectEnd",
"requestStart",
"responseStart",
"responseEnd",
]);
},
assert_same_origin_redirected_from_cross_origin_resource: entry => {
assert_zeroed_(entry, [
"workerStart",
"redirectStart",
"redirectEnd",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"connectEnd",
"secureConnectionStart",
"requestStart",
"responseStart",
"transferSize",
"encodedBodySize",
"decodedBodySize",
]);
assert_ordered_(entry, [
"fetchStart",
"responseEnd",
]);
assert_equals(entry.fetchStart, entry.startTime,
"fetchStart must equal startTime");
},
assert_tao_failure_resource: entry => {
assert_equals(entry.entryType, "resource", "entryType must always be 'resource'");
assert_positive_(entry, [
"startTime",
"duration",
]);
assert_zeroed_(entry, [
"redirectStart",
"redirectEnd",
"domainLookupStart",
"domainLookupEnd",
"connectStart",
"connectEnd",
"secureConnectionStart",
"requestStart",
"responseStart",
"transferSize",
"encodedBodySize",
"decodedBodySize",
]);
}
};
const attribute_test_internal = (loader, path, validator, run_test, test_label) => {
promise_test(
async () => {
let loaded_entry = new Promise((resolve, reject) => {
new PerformanceObserver((entry_list, self) => {
try {
const name_matches = entry_list.getEntries().forEach(entry => {
if (entry.name.includes(path)) {
resolve(entry);
}
});
} catch(e) {
// By surfacing exceptions through the Promise interface, tests can
// fail fast with a useful message instead of timing out.
reject(e);
}
}).observe({"type": "resource"});
});
await loader(path, validator);
const entry = await(loaded_entry);
run_test(entry);
}, test_label);
};
// Given a resource-loader, a path (a relative path or absolute URL), and a
// PerformanceResourceTiming test, applies the loader to the resource path
// and tests the resulting PerformanceResourceTiming entry.
const attribute_test = (loader, path, run_test, test_label) => {
attribute_test_internal(loader, path, () => {}, run_test, test_label);
};
// Similar to attribute test, but on top of that, validates the added element,
// to ensure the test does what it intends to do.
const attribute_test_with_validator = (loader, path, validator, run_test, test_label) => {
attribute_test_internal(loader, path, validator, run_test, test_label);
};