Skip to content

Commit

Permalink
MIME type parsing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
annevk committed Dec 7, 2017
1 parent acb307c commit b15e885
Show file tree
Hide file tree
Showing 10 changed files with 3,979 additions and 0 deletions.
1 change: 1 addition & 0 deletions mimesniff/OWNERS
@@ -0,0 +1 @@
@annevk
1 change: 1 addition & 0 deletions mimesniff/README.md
@@ -0,0 +1 @@
Tests for the [MIME Sniffing Standard](https://mimesniff.spec.whatwg.org/).
34 changes: 34 additions & 0 deletions mimesniff/mime-types/README.md
@@ -0,0 +1,34 @@
== MIME types ==

`resources/mime-types.json` and `resources/generated-mime-types.json` contain MIME type tests. The tests are encoded as a JSON array. String values in the array serve as documentation. All other values are objects with the following fields:

* `input`: The string to be parsed.
* `output`: Null if parsing resulted in failure and the MIME type record serialized as string otherwise.
* `navigable`: True if the MIME type can be used for a document to be loaded in a browsing context (i.e., does not result in a download) and omitted otherwise.
* `encoding`: The encoding that can be extracted from the MIME type or null if no encoding can be extracted, and omitted otherwise.

Note: the object description implies that there tests without `navigable` or `encoding` set.

A wrapper for these JSON MIME type tests needs to take care that not all `input` values can be tested in all entrypoints. Some entrypoints only accept bytes and some have further restrictions. A function such as the one below can be used to differentiate:

```js
function isByteCompatible(str) {
for(let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i);
// See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
// See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
if(charCode > 0xFF) {
return "incompatible";
} else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
return "header-value-incompatible";
} else if(charCode === 0x0B || charCode === 0x0C) {
return "wptserve-incompatible";
}
}
return "compatible";
}
```

`resources/generated-mime-types.json` is generated by running `resources/generated-mime-types.py`. Modify the latter to correct the former.

These tests are used by resources in this directory to test various aspects of MIME types.
57 changes: 57 additions & 0 deletions mimesniff/mime-types/charset-parameter.window.js
@@ -0,0 +1,57 @@
promise_test(() => {
// Don't load generated-mime-types.json as none of them are navigable
return fetch("resources/mime-types.json").then(res => res.json().then(runTests));
}, "Loading data…");

function isByteCompatible(str) {
for(let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i);
// See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
// See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
if(charCode > 0xFF) {
return "incompatible";
} else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
return "header-value-incompatible";
} else if(charCode === 0x0B || charCode === 0x0C) {
return "wptserve-incompatible";
}
}
return "compatible";
}

function encodeForURL(str) {
let output = "";
for(let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
if(char > 0xFF) {
throw new Error("We cannot deal with input that is not latin1");
} else {
output += "%" + char.toString(16).padStart(2, "0");
}
}
return output;
}

function runTests(tests) {
tests.forEach(val => {
if(typeof val === "string" || val.navigable === undefined || val.encoding === undefined || isByteCompatible(val.input) !== "compatible") {
return;
}
const mime = val.input;
async_test(t => {
const frame = document.createElement("iframe"),
expectedEncoding = val.encoding === null ? "UTF-8" : val.encoding;
t.add_cleanup(() => frame.remove());
frame.onload = t.step_func(() => {
if(frame.contentWindow.location.href === "about:blank") {
return;
}
// Edge fails all these tests due to not using the correct encoding label.
assert_equals(frame.contentDocument.characterSet, expectedEncoding);
t.done();
});
frame.src = "resources/mime-charset.py?type=" + encodeForURL(mime);
document.body.appendChild(frame);
}, mime);
});
}
49 changes: 49 additions & 0 deletions mimesniff/mime-types/parsing.any.js
@@ -0,0 +1,49 @@
promise_test(() => {
return Promise.all([
fetch("resources/mime-types.json"),
fetch("resources/generated-mime-types.json")
]).then(([res, res2]) => res.json().then(runTests).then(res2.json().then(runTests)));
}, "Loading data…");

function isByteCompatible(str) {
for(let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i);
// See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
// See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
if(charCode > 0xFF) {
return "incompatible";
} else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
return "header-value-incompatible";
} else if(charCode === 0x0B || charCode === 0x0C) {
return "wptserve-incompatible";
}
}
return "compatible";
}

function runTests(tests) {
tests.forEach(val => {
if(typeof val === "string") {
return;
}
const output = val.output === null ? "" : val.output
test(() => {
assert_equals(new Blob([], { type: val.input}).type, output, "Blob");
assert_equals(new File([], "noname", { type: val.input}).type, output, "File");
}, val.input + " (Blob/File)");

promise_test(() => {
const compatibleNess = isByteCompatible(val.input);
if(compatibleNess === "incompatible" || compatibleNess === "header-value-incompatible") {
assert_throws(new TypeError(), () => new Request("about:blank", { headers: [["Content-Type", val.input]] }));
assert_throws(new TypeError(), () => new Response(null, { headers: [["Content-Type", val.input]] }));
return Promise.resolve();
} else {
return Promise.all([
new Request("about:blank", { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output)),
new Response(null, { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output))
]);
}
}, val.input + " (Request/Response)");
});
}

0 comments on commit b15e885

Please sign in to comment.