Update web-platform-tests to revision be5419e845d39089ba6dc338c1bd0fa279108317

This commit is contained in:
Josh Matthews 2018-01-04 13:44:24 -05:00
parent aa199307c8
commit 2b6f573eb5
3440 changed files with 109438 additions and 41750 deletions

View file

@ -31,7 +31,7 @@ promise_test(() => {
}, "* for credentialed fetches only matches literally")
promise_test(() => {
const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie)"
const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie\\,*)"
return fetch(url + sharedHeaders + headers).then(resp => {
assert_equals(resp.status, 200)
assert_equals(resp.type , "cors")

View file

@ -3,14 +3,22 @@ if (this.document === undefined) {
importScripts("../resources/utils.js");
}
function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod) {
// Creates a promise_test that fetches a URL that returns a redirect response.
//
// |opts| has additional options:
// |opts.body|: the request body as a string or blob (default is empty body)
// |opts.expectedBodyAsString|: the expected response body as a string. The
// server is expected to echo the request body. The default is the empty string
// if the request after redirection isn't POST; otherwise it's |opts.body|.
function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod, opts) {
var url = redirectUrl;
var urlParameters = "?redirect_status=" + redirectStatus;
urlParameters += "&location=" + encodeURIComponent(redirectLocation);
var requestInit = {"method": method, "redirect": "follow"};
if (method != "GET" && method != "HEAD")
requestInit.body = "this is my body";
opts = opts || {};
if (opts.body)
requestInit.body = opts.body;
promise_test(function(test) {
return fetch(url + urlParameters, requestInit).then(function(resp) {
@ -19,7 +27,10 @@ function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, met
assert_equals(resp.headers.get("x-request-method"), expectedMethod, "Request method after redirection is " + expectedMethod);
assert_true(resp.redirected);
return resp.text().then(function(text) {
assert_equals(text, expectedMethod == "POST" ? requestInit.body : "");
let expectedBody = "";
if (expectedMethod == "POST")
expectedBody = opts.expectedBodyAsString || requestInit.body;
assert_equals(text, expectedBody, "request body");
});
});
}, desc);
@ -36,20 +47,25 @@ promise_test(function(test) {
var redirUrl = RESOURCES_DIR + "redirect.py";
var locationUrl = "method.py";
const stringBody = "this is my body";
const blobBody = new Blob(["it's me the blob!", " ", "and more blob!"]);
const blobBodyAsString = "it's me the blob! and more blob!";
redirectMethod("Redirect 301 with GET", redirUrl, locationUrl, 301, "GET", "GET");
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET");
redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 301 with HEAD", redirUrl, locationUrl, 301, "HEAD", "HEAD");
redirectMethod("Redirect 302 with GET", redirUrl, locationUrl, 302, "GET", "GET");
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET");
redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 302 with HEAD", redirUrl, locationUrl, 302, "HEAD", "HEAD");
redirectMethod("Redirect 303 with GET", redirUrl, locationUrl, 303, "GET", "GET");
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET");
redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 303 with HEAD", redirUrl, locationUrl, 303, "HEAD", "HEAD");
redirectMethod("Redirect 307 with GET", redirUrl, locationUrl, 307, "GET", "GET");
redirectMethod("Redirect 307 with POST", redirUrl, locationUrl, 307, "POST", "POST");
redirectMethod("Redirect 307 with POST (string body)", redirUrl, locationUrl, 307, "POST", "POST", { body: stringBody });
redirectMethod("Redirect 307 with POST (blob body)", redirUrl, locationUrl, 307, "POST", "POST", { body: blobBody, expectedBodyAsString: blobBodyAsString });
redirectMethod("Redirect 307 with HEAD", redirUrl, locationUrl, 307, "HEAD", "HEAD");
done();

View file

@ -0,0 +1,134 @@
<!DOCTYPE html>
<title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/media.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<script>
let frame;
// Set up the service worker and the frame.
promise_test(t => {
const kScope = 'resources/empty.https.html';
const kScript = 'resources/fetch-destination-worker.js';
return service_worker_unregister_and_register(t, kScript, kScope)
.then(registration => {
add_completion_callback(() => {
registration.unregister();
});
return wait_for_state(t, registration.installing, 'activated');
})
.then(() => {
return with_iframe(kScope);
})
.then(f => {
frame = f;
add_completion_callback(() => { f.remove(); });
});
}, 'Initialize global state');
// Actual tests
// HTMLImageElement - image destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var node = frame.contentWindow.document.createElement("img");
node.onload = resolve;
node.onerror = reject;
node.src = "dummy.png?dest=image";
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLImageElement fetches with an "image" Request.destination');
// fetch() - empty string destination
promise_test(async t => {
let response = await frame.contentWindow.fetch("dummy?dest=");
assert_true(response.ok);
}, 'fetch() fetches with an empty string Request.destination');
// HTMLAudioElement - audio destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var audioURL = getAudioURI("dummy_audio");
var node = frame.contentWindow.document.createElement("audio");
node.onloadeddata = resolve;
node.onerror = reject;
node.src = audioURL + "?dest=audio";
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLAudioElement fetches with an "audio" Request.destination');
// HTMLVideoElement - video destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var videoURL = getVideoURI("dummy_video");
var node = frame.contentWindow.document.createElement("video");
node.onloadeddata = resolve;
node.onerror = reject;
node.src = videoURL + "?dest=video";
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLVideoElement fetches with a "video" Request.destination');
// HTMLScriptElement - script destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var node = frame.contentWindow.document.createElement("script");
node.onload = resolve;
node.onerror = reject;
node.src = "dummy?dest=script";
frame.contentWindow.document.body.appendChild(node);
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLScriptElement fetches with a "script" Request.destination');
// HTMLLinkElement with rel=stylesheet - script destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var node = frame.contentWindow.document.createElement("link");
node.rel = "stylesheet";
node.onload = resolve;
node.onerror = reject;
node.href = "dummy?dest=style";
frame.contentWindow.document.body.appendChild(node);
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLLinkElement with rel=stylesheet fetches with a "style" Request.destination');
// HTMLLinkElement with rel=preload and as=fetch - empty string destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var node = frame.contentWindow.document.createElement("link");
node.rel = "preload";
node.as = "fetch";
node.onload = resolve;
node.onerror = reject;
node.href = "dummy?t=2&dest=";
frame.contentWindow.document.body.appendChild(node);
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLLinkElement with rel=preload and as=fetch fetches with an empty string Request.destination');
// HTMLLinkElement with rel=preload and as=style - style destination
promise_test(async t => {
await new Promise((resolve, reject) => {
var node = frame.contentWindow.document.createElement("link");
node.rel = "preload";
node.as = "style";
node.onload = resolve;
node.onerror = reject;
node.href = "dummy?t=2&dest=style";
frame.contentWindow.document.body.appendChild(node);
}).catch(() => {
assert_unreached("Fetch errored.");
});
}, 'HTMLLinkElement with rel=preload and as=style fetches with a "style" Request.destination');
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,11 @@
self.addEventListener('fetch', function(event) {
if (event.request.url.includes('dummy')) {
let destination = new URL(event.request.url).searchParams.get("dest");
if (event.request.destination == destination) {
event.respondWith(fetch(event.request));
} else {
event.respondWith(Response.error());
}
}
});

View file

@ -15,9 +15,7 @@
typedef any JSON;
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
[NoInterfaceObject,
Exposed=(Window,Worker)]
interface Body {
interface mixin Body {
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
@ -48,7 +46,7 @@
[NewObject] Request clone();
};
Request implements Body;
Request includes Body;
dictionary RequestInit {
ByteString method;

View file

@ -12,81 +12,80 @@
</head>
<body>
<script>
"use strict";
'use strict';
// We want to ensure that our keepalive requests hang slightly before completing so we can validate
// the effects of a rolling quota. To do this we will utilize trickle.py with a 1s delay. This should
// prevent any of the Fetch's from finishing in this window.
var trickleURL = "../resources/trickle.py?count=1&ms=";
var standardDelay = 1000;
const trickleURL = '../resources/trickle.py?count=1&ms=';
const noDelay = 0;
const standardDelay = 1000;
function wait(ms) {
return new Promise(resolve => step_timeout(resolve, ms));
}
// We should expect 64KiB of rolling quota for any type of keep-alive request sent.
var expectedQuota = 65536;
const expectedQuota = 65536;
function CreateKeepAliveRequest(delay, bodySize) {
function fetchKeepAliveRequest(delay, bodySize) {
// Create a body of the specified size that's filled with *'s
var requestBody = "*".repeat(bodySize);
return new Request(trickleURL+delay, {keepalive: true, body: requestBody, method: "POST"});
const body = '*'.repeat(bodySize);
return fetch(trickleURL + delay, {keepalive: true, body, method: 'POST'}).then(res => {
return res.text();
}).then(() => {
return wait(1);
});
}
// Test 1 Byte
promise_test(function(test) {
return fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */));
}, "A Keep-Alive fetch() with a small body should succeed.");
return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
}, 'A Keep-Alive fetch() with a small body should succeed.');
// Test Quota full limit
promise_test(function(test) {
return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
}, "A Keep-Alive fetch() with a body at the Quota Limit should succeed.");
return fetchKeepAliveRequest(noDelay, expectedQuota /* bodySize */);
}, 'A Keep-Alive fetch() with a body at the Quota Limit should succeed.');
// Test Quota + 1 Byte
promise_test(function(test) {
return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota + 1)));
}, "A Keep-Alive fetch() with a body over the Quota Limit should reject.");
return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, expectedQuota + 1));
}, 'A Keep-Alive fetch() with a body over the Quota Limit should reject.');
// Test the Quota becomes available upon promise completion.
promise_test(function (test) {
// Fill our Quota then try to send a second fetch.
var firstFetch = fetch(CreateKeepAliveRequest(standardDelay, expectedQuota)).then(function(response) {
return fetchKeepAliveRequest(standardDelay, expectedQuota).then(() => {
// Now validate that we can send another Keep-Alive fetch for the full size of the quota.
return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
return fetchKeepAliveRequest(noDelay, expectedQuota);
});
return firstFetch;
}, "A Keep-Alive fetch() should return it's allocated Quota upon promise resolution.");
}, 'A Keep-Alive fetch() should return its allocated Quota upon promise resolution.');
// Ensure only the correct amount of Quota becomes available when a fetch completes.
promise_test(function(test) {
var lastFetchSucceeded = false;
// Create a fetch that uses all but 1 Byte of the Quota and runs for 2x as long as the other requests.
var firstFetch = fetch(CreateKeepAliveRequest(standardDelay * 2, expectedQuota - 1)).then(function(response) {
// This should be our last completing fetch(). We need to validate that the last fetch we sent out actually
// completed.
assert_true(lastFetchSucceeded, "Out last fetch after gaining Quota back should have succeeded.");
});
const first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
// Now create a single Byte request that will complete quicker.
fetch(CreateKeepAliveRequest(standardDelay, 1 /* bodySize */)).then(function(response) {
const second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
// We shouldn't be able to create a 2 Byte request right now as only 1 Byte should have freed up.
assert_throws(new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 2 /* bodySize */)), "Only 1 Byte of Quota should be available right now.");
return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 2 /* bodySize */));
}).then(() => {
// Now validate that we can send another Keep-Alive fetch for just 1 Byte.
fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)).then(function(response) {
// Flag we got a response from this request.
lastFetchSucceeded = true;
});
return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
});
return firstFetch;
}, "A Keep-Alive fetch() should return only it's allocated Quota upon promise resolution.");
return Promise.all([first, second]);
}, 'A Keep-Alive fetch() should return only its allocated Quota upon promise resolution.');
// Test rejecting a fetch() after the quota is used up.
promise_test(function (test) {
// Fill our Quota then try to send a second fetch.
fetch(CreateKeepAliveRequest(standardDelay, expectedQuota));
const p = fetchKeepAliveRequest(standardDelay, expectedQuota);
return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)));
}, "A Keep-Alive fetch() should not be allowed if the Quota is used up.");
const q = promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
return Promise.all([p, q]);
}, 'A Keep-Alive fetch() should not be allowed if the Quota is used up.');
</script>
</body>

View file

@ -3,6 +3,8 @@ import time
def main(request, response):
delay = float(request.GET.first("ms", 500)) / 1E3
count = int(request.GET.first("count", 50))
# Read request body
request.body
time.sleep(delay)
response.headers.set("Content-type", "text/plain")
response.write_status_headers()

View file

@ -15,9 +15,7 @@
typedef any JSON;
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
[NoInterfaceObject,
Exposed=(Window,Worker)]
interface Body {
interface mixin Body {
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
@ -45,7 +43,7 @@
[NewObject] Response clone();
};
Response implements Body;
Response includes Body;
dictionary ResponseInit {
unsigned short status = 200;