Add web-platform-tests for brotli encoding

Differential Revision: https://phabricator.services.mozilla.com/D205489

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1887150
gecko-commit: f456c6be853a6307002998ad56e9014311a23349
gecko-reviewers: jgraham, necko-reviewers, kershaw
diff --git a/fetch/content-encoding/br/bad-br-body.https.any.js b/fetch/content-encoding/br/bad-br-body.https.any.js
new file mode 100644
index 0000000..43ea90a
--- /dev/null
+++ b/fetch/content-encoding/br/bad-br-body.https.any.js
@@ -0,0 +1,12 @@
+// META: global=window
+
+[
+  "arrayBuffer",
+].forEach(method => {
+  promise_test(t => {
+    return fetch("resources/bad-br-body.py").then(res => {
+      assert_equals(res.status, 200);
+      return promise_rejects_js(t, TypeError, res[method]());
+    });
+  }, "Consuming the body of a resource with bad br content with " + method + "() should reject");
+});
diff --git a/fetch/content-encoding/br/big-br-body.https.any.js b/fetch/content-encoding/br/big-br-body.https.any.js
new file mode 100644
index 0000000..1427dd7
--- /dev/null
+++ b/fetch/content-encoding/br/big-br-body.https.any.js
@@ -0,0 +1,55 @@
+// META: global=window,worker
+
+const EXPECTED_SIZE = 27000000;
+const EXPECTED_SHA256 = [
+    74,  100, 37, 243, 147, 61,  116, 60,  241, 221, 126,
+    18,  24,  71, 204, 28,  50,  62,  201, 130, 152, 225,
+    217, 183, 10, 201, 143, 214, 102, 155, 212, 248,
+  ];
+
+promise_test(async () => {
+  const response = await fetch('resources/big.text.br');
+  assert_true(response.ok);
+  const arrayBuffer = await response.arrayBuffer();
+  assert_equals(arrayBuffer.byteLength, EXPECTED_SIZE,
+               'uncompressed size should match');
+  const sha256 = await crypto.subtle.digest('SHA-256', arrayBuffer);
+  assert_array_equals(new Uint8Array(sha256), EXPECTED_SHA256,
+                      'digest should match');
+}, 'large br data should be decompressed successfully');
+
+promise_test(async () => {
+  const response = await fetch('resources/big.text.br');
+  assert_true(response.ok);
+  const reader = response.body.getReader({mode: 'byob'});
+  let offset = 0;
+  // Pre-allocate space for the output. The response body will be read
+  // chunk-by-chunk into this array.
+  let ab = new ArrayBuffer(EXPECTED_SIZE);
+  while (offset < EXPECTED_SIZE) {
+    // To stress the data pipe, we want to use a different size read each
+    // time. Unfortunately, JavaScript doesn't have a seeded random number
+    // generator, so this creates the possibility of making this test flaky if
+    // it doesn't work for some edge cases.
+    let size = Math.floor(Math.random() * 65535 + 1);
+    if (size + offset > EXPECTED_SIZE) {
+      size = EXPECTED_SIZE - offset;
+    }
+    const u8 = new Uint8Array(ab, offset, size);
+    const { value, done } = await reader.read(u8);
+    ab = value.buffer;
+    // Check that we got our original array back.
+    assert_equals(ab.byteLength, EXPECTED_SIZE,
+                  'backing array should be the same size');
+    assert_equals(offset, value.byteOffset, 'offset should match');
+    assert_less_than_equal(value.byteLength, size,
+                           'we should not have got more than we asked for');
+    offset = value.byteOffset + value.byteLength;
+    if (done) break;
+  }
+  assert_equals(offset, EXPECTED_SIZE,
+                'we should have read the whole thing');
+  const sha256 = await crypto.subtle.digest('SHA-256', new Uint8Array(ab));
+  assert_array_equals(new Uint8Array(sha256), EXPECTED_SHA256,
+                      'digest should match');
+}, 'large br data should be decompressed successfully with byte stream');
diff --git a/fetch/content-encoding/br/br-body.https.any.js b/fetch/content-encoding/br/br-body.https.any.js
new file mode 100644
index 0000000..2c2dbb5
--- /dev/null
+++ b/fetch/content-encoding/br/br-body.https.any.js
@@ -0,0 +1,15 @@
+// META: global=window,worker
+
+const expectedDecompressedSize = 10500;
+[
+    "text",
+    "octetstream"
+].forEach(contentType => {
+    promise_test(async t => {
+        let response = await fetch(`resources/foo.${contentType}.br`);
+        assert_true(response.ok);
+        let arrayBuffer = await response.arrayBuffer()
+        let u8 = new Uint8Array(arrayBuffer);
+        assert_equals(u8.length, expectedDecompressedSize);
+    }, `fetched br data with content type ${contentType} should be decompressed.`);
+});
diff --git a/fetch/content-encoding/br/resources/bad-br-body.py b/fetch/content-encoding/br/resources/bad-br-body.py
new file mode 100644
index 0000000..0710e7f
--- /dev/null
+++ b/fetch/content-encoding/br/resources/bad-br-body.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    headers = [(b"Content-Encoding", b"br")]
+    return headers, b"not actually br"
diff --git a/fetch/content-encoding/br/resources/big.text.br b/fetch/content-encoding/br/resources/big.text.br
new file mode 100644
index 0000000..b3a530d
--- /dev/null
+++ b/fetch/content-encoding/br/resources/big.text.br
Binary files differ
diff --git a/fetch/content-encoding/br/resources/big.text.br.headers b/fetch/content-encoding/br/resources/big.text.br.headers
new file mode 100644
index 0000000..aba00bd
--- /dev/null
+++ b/fetch/content-encoding/br/resources/big.text.br.headers
@@ -0,0 +1,3 @@
+Content-type: text/plain
+Content-Encoding: br
+Cache-Control: no-store
diff --git a/fetch/content-encoding/br/resources/foo.octetstream.br b/fetch/content-encoding/br/resources/foo.octetstream.br
new file mode 100644
index 0000000..30cb2f7
--- /dev/null
+++ b/fetch/content-encoding/br/resources/foo.octetstream.br
Binary files differ
diff --git a/fetch/content-encoding/br/resources/foo.octetstream.br.headers b/fetch/content-encoding/br/resources/foo.octetstream.br.headers
new file mode 100644
index 0000000..c0c19bc
--- /dev/null
+++ b/fetch/content-encoding/br/resources/foo.octetstream.br.headers
@@ -0,0 +1,2 @@
+Content-type: application/octet-stream
+Content-Encoding: br
diff --git a/fetch/content-encoding/br/resources/foo.text.br b/fetch/content-encoding/br/resources/foo.text.br
new file mode 100644
index 0000000..30cb2f7
--- /dev/null
+++ b/fetch/content-encoding/br/resources/foo.text.br
Binary files differ
diff --git a/fetch/content-encoding/br/resources/foo.text.br.headers b/fetch/content-encoding/br/resources/foo.text.br.headers
new file mode 100644
index 0000000..8c03b82
--- /dev/null
+++ b/fetch/content-encoding/br/resources/foo.text.br.headers
@@ -0,0 +1,2 @@
+Content-type: text/plain
+Content-Encoding: br