Skip to content

Commit

Permalink
Referrer-Policy: Debug/Release mode for test templates and sanity che…
Browse files Browse the repository at this point in the history
…cks.
  • Loading branch information
kristijanburnik authored and kburnik committed May 23, 2015
1 parent 7a40d6f commit 56b0ccf
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 102 deletions.
23 changes: 21 additions & 2 deletions referrer-policy/README.md
Expand Up @@ -27,12 +27,16 @@ The ```spec.src.json``` defines all the test scenarios for the referrer policy.

Invoking ```./generic/tools/generate.py``` will parse the spec JSON and determine which tests to generate (or skip) while using templates.


The spec can be validated by running ```./generic/tools/spec_validator.py```. This is specially important when you're making changes to ```spec.src.json```. Make sure it's a valid JSON (no comments or trailing commas). The validator should be informative and very specific on any issues.

For details about the spec JSON, see **Overview of the spec JSON** below.


## Generating the tests
## Generating and running the tests

The repository already contains generated tests, so if you're making changes,
see the **Removing all generated tests** section below, on how to remove them before you start generating tests which include your changes.

Start from the command line:

Expand All @@ -58,6 +62,18 @@ Run tests under path: ```/referrer-policy```.

Click start.


## Options for generating tests

The generator script ```./generic/tools/generate.py``` has two targets: ```release``` and ```debug```.

* Using **release** for the target will produce tests using a template for optimizing size and performance. The release template is intended for the official web-platform-tests and possibly other test suites. No sanity checking is done in release mode. Use this option whenever you're checking into web-platform-tests.

* When generating for ```debug```, the produced tests will contain more verbosity and sanity checks. Use this target to identify problems with the test suite when making changes locally. Make sure you don't check in tests generated with the debug target.

Note that **release** is the default target when invoking ```generate.py```.


## Removing all generated tests

```bash
Expand All @@ -77,6 +93,7 @@ git add * && git commit -m "Remove generated tests"
**Important:**
The ```./generic/tools/clean.py``` utility will only work if there is a valid ```spec.src.json``` and previously generated directories match the specification requirement names. So make sure you run ```clean.py``` before you alter the specification section of the spec JSON.


## Updating the tests

The main test logic lives in ```./generic/referrer-policy-test-case.js``` with helper functions defined in ```./generic/common.js``` so you should probably start there.
Expand Down Expand Up @@ -124,6 +141,7 @@ git add * && git commit -m "Update generated tests"

```


## Overview of the spec JSON

**Main sections:**
Expand Down Expand Up @@ -152,6 +170,7 @@ git add * && git commit -m "Update generated tests"
A 1:1 mapping of a **subresource type** to the URL path of the sub-resource.
When adding a new sub-resource, a path to an existing file for it also must be specified.


### Test Expansion Patterns

Each field in a test expansion can be in one of the following formats:
Expand Down Expand Up @@ -206,6 +225,7 @@ var scenario = {
"source_protocol": "http",
"target_protocol": "http",
"subresource": "iframe-tag",
"subresource_path": "/referrer-policy/generic/subresource/document.py",
"referrer_url": "origin"
};
```
Expand All @@ -219,4 +239,3 @@ Taking the spec JSON, the generator follows this algorithm:

* For each specification requirement: Expand the ```test_expansion``` pattern into selections and check each against the blacklist, if not marked as suppresed, generate the test resources for the selection


40 changes: 20 additions & 20 deletions referrer-policy/generic/common.js
Expand Up @@ -38,25 +38,25 @@ function loadImage(src, callback) {
}

function decodeImageData(rgba) {
// Remove alpha component.
var data = new Uint8ClampedArray(rgba.length);
var x = 0;
for (var i in rgba) {
if (i > 0 && i%4 == 3 || rgba[i] == 0)
var rgb = new Uint8ClampedArray(rgba.length);

// RGBA -> RGB.
var rgb_length = 0;
for (var i = 0; i < rgba.length; ++i) {
// Skip alpha component.
if (i % 4 == 3)
continue;

data[x++] = rgba[i];
}
// Zero is the string terminator.
if (rgba[i] == 0)
break;

// Remove trailing nulls from data.
var length = rgba.length;

for (var i = rgba.length - 1; data[i] == 0 && i > 0; i--) {
length--;
rgb[rgb_length++] = rgba[i];
}

data = data.subarray(0, length);
var string_data = (new TextDecoder("ascii")).decode(data);
// Remove trailing nulls from data.
rgb = rgb.subarray(0, rgb_length);
var string_data = (new TextDecoder("ascii")).decode(rgb);

return JSON.parse(string_data);
}
Expand All @@ -74,6 +74,7 @@ function decodeImage(url, callback) {
function normalizePort(targetPort) {
var defaultPorts = [80, 443];
var isDefaultPortForProtocol = (defaultPorts.indexOf(targetPort) >= 0);

return (targetPort == "" || isDefaultPortForProtocol) ?
"" : ":" + targetPort;
}
Expand Down Expand Up @@ -109,15 +110,12 @@ function queryImage(url, callback) {
function queryXhr(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
console.log(url);

xhr.onreadystatechange = function(e) {
if (this.readyState == 4 && this.status == 200) {
var headers = JSON.parse(this.responseText);
callback(wrapResult(url, headers));
}
};

xhr.send();
}

Expand Down Expand Up @@ -175,9 +173,6 @@ function queryLink(url, callback, referrer_policy) {

function queryAreaLink(url, callback, referrer_policy) {
var area = document.createElement("area");
area.shape="rect"
area.coords="0,0,10,10"

// TODO(kristijanburnik): Append to map and add image.
document.body.appendChild(area);
queryNavigable(area, url, callback, referrer_policy)
Expand All @@ -196,3 +191,8 @@ function queryScript(url, callback) {

document.body.appendChild(script);
}

// SanityChecker does nothing in release mode.
function SanityChecker() {}
SanityChecker.prototype.checkScenario = function() {};
SanityChecker.prototype.checkSubresourceResult = function() {};
51 changes: 8 additions & 43 deletions referrer-policy/generic/referrer-policy-test-case.js
@@ -1,4 +1,4 @@
var ReferrerPolicyTestCase = function(scenario, testDescription) {
function ReferrerPolicyTestCase(scenario, testDescription, sanityChecker) {
// Pass and skip rest of the test if browser does not support fetch.
if (scenario.subresource == "fetch-request" && !window.fetch) {
// TODO(kristijanburnik): This should be refactored.
Expand All @@ -10,28 +10,8 @@ var ReferrerPolicyTestCase = function(scenario, testDescription) {
};
}

// Check if scenario is valid.
// TODO(kristijanburnik): Move to a sanity-checks.js for debug mode only.
test(function() {

// We extend the exsiting test_expansion_schema not to kill performance by
// copying.
var expectedFields = SPEC_JSON["test_expansion_schema"];
expectedFields["referrer_policy"] = SPEC_JSON["referrer_policy_schema"];

for (var field in expectedFields) {
assert_own_property(scenario, field,
"The scenario contains field " + field)
assert_in_array(scenario[field], expectedFields[field],
"Scenario's " + field + " is one of: " +
expectedFields[field].join(", ")) + "."
}

// Check if the protocol is matched.
assert_equals(scenario["source_protocol"] + ":", location.protocol,
"Protocol of the test page should match the scenario.")

}, "[ReferrerPolicyTestCase] The test scenario is valid.");
// This check is A NOOP in release.
sanityChecker.checkScenario(scenario);

var subresourceInvoker = {
"a-tag": queryLink,
Expand All @@ -44,8 +24,6 @@ var ReferrerPolicyTestCase = function(scenario, testDescription) {
"xhr-request": queryXhr
};

var pathForSubresource = SPEC_JSON["subresource_path"];

var referrerUrlResolver = {
"omitted": function() {
return undefined;
Expand Down Expand Up @@ -85,7 +63,7 @@ var ReferrerPolicyTestCase = function(scenario, testDescription) {
t._subresourceUrl = t._scenario.target_protocol + "://" +
domainForOrigin[t._scenario.origin] +
normalizePort(targetPort) +
pathForSubresource[t._scenario.subresource];
t._scenario["subresource_path"];
},

_constructExpectedReferrerUrl: function() {
Expand Down Expand Up @@ -121,29 +99,16 @@ var ReferrerPolicyTestCase = function(scenario, testDescription) {
var test = async_test(t._testDescription);

t._invokeSubresource(function(result) {
// Check if the result is in valid format.
test.step(function() {
assert_equals(Object.keys(result).length, 3);
assert_own_property(result, "location");
assert_own_property(result, "referrer");
assert_own_property(result, "headers");

// Skip location check for scripts.
if (t._scenario.subresource == "script-tag")
return;

// Sanity check: location of sub-resource matches reported location.
assert_equals(result.location, t._subresourceUrl,
"Subresource reported location.");
}, "Running a valid test scenario.");
// Check if the result is in valid format. NOOP in release.
sanityChecker.checkSubresourceResult(
test, t._scenario, t._subresourceUrl, result);

// Check the reported URL.
test.step(function() {
assert_equals(result.referrer,
t._expectedReferrerUrl,
"Reported Referrer URL is '" +
t._scenario.referrer_url +
"'.");
t._scenario.referrer_url + "'.");
assert_equals(result.headers.referer,
t._expectedReferrerUrl,
"Reported Referrer URL from HTTP header is '" +
Expand Down
52 changes: 52 additions & 0 deletions referrer-policy/generic/sanity-checker.js
@@ -0,0 +1,52 @@
// The SanityChecker is used in debug mode to identify problems with the
// structure of the testsuite. In release mode it is mocked out to do nothing.

function SanityChecker() {}

SanityChecker.prototype.checkScenario = function(scenario) {
// Check if scenario is valid.
// TODO(kristijanburnik): Move to a sanity-checks.js for debug mode only.
test(function() {

// We extend the exsiting test_expansion_schema not to kill performance by
// copying.
var expectedFields = SPEC_JSON["test_expansion_schema"];
expectedFields["referrer_policy"] = SPEC_JSON["referrer_policy_schema"];

assert_own_property(scenario, "subresource_path",
"Scenario has the path to the subresource.");

for (var field in expectedFields) {
assert_own_property(scenario, field,
"The scenario contains field " + field)
assert_in_array(scenario[field], expectedFields[field],
"Scenario's " + field + " is one of: " +
expectedFields[field].join(", ")) + "."
}

// Check if the protocol is matched.
assert_equals(scenario["source_protocol"] + ":", location.protocol,
"Protocol of the test page should match the scenario.")

}, "[ReferrerPolicyTestCase] The test scenario is valid.");
}

SanityChecker.prototype.checkSubresourceResult = function(test,
scenario,
subresourceUrl,
result) {
test.step(function() {
assert_equals(Object.keys(result).length, 3);
assert_own_property(result, "location");
assert_own_property(result, "referrer");
assert_own_property(result, "headers");

// Skip location check for scripts.
if (scenario.subresource == "script-tag")
return;

// Sanity check: location of sub-resource matches reported location.
assert_equals(result.location, subresourceUrl,
"Subresource reported location.");
}, "Running a valid test scenario.");
};
6 changes: 0 additions & 6 deletions referrer-policy/generic/template/document.html.template
Expand Up @@ -2,13 +2,8 @@
<html>
<head>
<title>This page reports back it's request details to the parent frame</title>
<!-- Common global functions for referrer-policy tests. -->
<script src="/referrer-policy/generic/common.js"></script>
</head>
<body>
<h2>This page reports back it's request details to the parent frame</h2>
<pre>%(headers)s</pre>

<script>
var SERVER_REQUEST_HEADERS = %(headers)s;
var result = {
Expand All @@ -18,6 +13,5 @@
};
parent.postMessage(result, "*");
</script>

</body>
</html>
1 change: 0 additions & 1 deletion referrer-policy/generic/template/script.js.template
@@ -1,3 +1,2 @@
var SERVER_REQUEST_HEADERS = %(headers)s;

postMessage(SERVER_REQUEST_HEADERS, '*');
@@ -1,29 +1,34 @@
<!DOCTYPE html>
%(generated_disclaimer)s
<!-- TODO(kristijanburnik): Create a template for automated tests:
http://testthewebforward.org/docs/test-templates.html#script-test-with-metadata
-->
<html>
<head>
<title>Referrer-Policy: %(spec_title)s</title>
<meta name="description" content="%(spec_description)s">%(meta_delivery_method)s
<title>Referrer-Policy: %(spec_title)s</title>%(meta_delivery_method)s
<meta name="description" content="%(spec_description)s">
<meta name="assert" content="The referrer URL is %(referrer_url)s when a
document served over %(source_protocol)s requires an %(target_protocol)s
sub-resource via %(subresource)s using the %(delivery_method)s
delivery method and when the target request is %(origin)s.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<!-- Common global functions for referrer-policy tests. -->
<script src="/referrer-policy/generic/common.js"></script>
<!-- The original specification JSON for validating the scenario. -->
<script src="/referrer-policy/spec_json.js"></script>
<!-- Internal checking of the tests -->
<script src="/referrer-policy/generic/sanity-checker.js"></script>
<!-- Simple wrapper API for all referrer-policy test cases. -->
<script src="/referrer-policy/generic/referrer-policy-test-case.js?pipe=sub"></script>
</head>
<body>
<h1>%(spec_title)s</h1>
<h2>%(spec_description)s</h2>

<p id="description">The referrer URL is %(referrer_url)s when a document
served over %(source_protocol)s requires an %(target_protocol)s
sub-resource via %(subresource)s using the %(delivery_method)s delivery
method and when the target request is %(origin)s.</p>
<p>
<script>
// Show the detailed assertion description of the test.
document.write(document.querySelector("meta[name=assert]").content);
</script>
</p>

<p>See <a href="%(spec_specification_url)s" target="_blank">specification</a>
details for this test.</p>
Expand Down Expand Up @@ -53,19 +58,7 @@ http://testthewebforward.org/docs/test-templates.html#script-test-with-metadata
<tbody>
</table>

<script>
var scenario = {
"referrer_policy": %(referrer_policy_json)s,
"delivery_method": "%(delivery_method)s",
"origin": "%(origin)s",
"source_protocol": "%(source_protocol)s",
"target_protocol": "%(target_protocol)s",
"subresource": "%(subresource)s",
"referrer_url": "%(referrer_url)s"
};
var description = document.getElementById("description").innerHTML;
ReferrerPolicyTestCase(scenario, description).start();
</script>
<script>%(test_js)s</script>

<div id="log"></div>
</body>
Expand Down

0 comments on commit 56b0ccf

Please sign in to comment.