From 0ca1974cb09b47b1904d3c656dc0d3f4a268e30e Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 10:54:07 +0000 Subject: [PATCH 01/16] fix: wrap handlers for custom dispatchers --- lib/api/api-connect.js | 13 +- lib/api/api-pipeline.js | 13 +- lib/api/api-request.js | 13 +- lib/api/api-stream.js | 13 +- lib/api/api-upgrade.js | 13 +- package.json | 2 +- test/issue-4780.js | 62 + test/web-platform-tests/expectation.json | 9398 ++-------------------- 8 files changed, 681 insertions(+), 8846 deletions(-) create mode 100644 test/issue-4780.js diff --git a/lib/api/api-connect.js b/lib/api/api-connect.js index c8b86dd7d53..760258cff73 100644 --- a/lib/api/api-connect.js +++ b/lib/api/api-connect.js @@ -4,8 +4,18 @@ const assert = require('node:assert') const { AsyncResource } = require('node:async_hooks') const { InvalidArgumentError, SocketError } = require('../core/errors') const util = require('../core/util') +const WrapHandler = require('../handler/wrap-handler') +const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') +function getDispatchHandler (dispatcher, handler) { + if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { + return handler + } + + return WrapHandler.wrap(handler) +} + class ConnectHandler extends AsyncResource { constructor (opts, callback) { if (!opts || typeof opts !== 'object') { @@ -96,8 +106,9 @@ function connect (opts, callback) { try { const connectHandler = new ConnectHandler(opts, callback) const connectOptions = { ...opts, method: 'CONNECT' } + const dispatchHandler = getDispatchHandler(this, connectHandler) - this.dispatch(connectOptions, connectHandler) + this.dispatch(connectOptions, dispatchHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-pipeline.js b/lib/api/api-pipeline.js index 77f3520a83f..b69e55d9a07 100644 --- a/lib/api/api-pipeline.js +++ b/lib/api/api-pipeline.js @@ -13,8 +13,18 @@ const { RequestAbortedError } = require('../core/errors') const util = require('../core/util') +const WrapHandler = require('../handler/wrap-handler') +const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') +function getDispatchHandler (dispatcher, handler) { + if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { + return handler + } + + return WrapHandler.wrap(handler) +} + function noop () {} const kResume = Symbol('resume') @@ -242,7 +252,8 @@ class PipelineHandler extends AsyncResource { function pipeline (opts, handler) { try { const pipelineHandler = new PipelineHandler(opts, handler) - this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + const dispatchHandler = getDispatchHandler(this, pipelineHandler) + this.dispatch({ ...opts, body: pipelineHandler.req }, dispatchHandler) return pipelineHandler.ret } catch (err) { return new PassThrough().destroy(err) diff --git a/lib/api/api-request.js b/lib/api/api-request.js index c3461b23c84..79eca0f8e7f 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -5,6 +5,16 @@ const { AsyncResource } = require('node:async_hooks') const { Readable } = require('./readable') const { InvalidArgumentError, RequestAbortedError } = require('../core/errors') const util = require('../core/util') +const WrapHandler = require('../handler/wrap-handler') +const DispatcherBase = require('../dispatcher/dispatcher-base') + +function getDispatchHandler (dispatcher, handler) { + if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { + return handler + } + + return WrapHandler.wrap(handler) +} function noop () {} @@ -198,8 +208,9 @@ function request (opts, callback) { try { const handler = new RequestHandler(opts, callback) + const dispatchHandler = getDispatchHandler(this, handler) - this.dispatch(opts, handler) + this.dispatch(opts, dispatchHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-stream.js b/lib/api/api-stream.js index 5d0b3fbe633..01797468896 100644 --- a/lib/api/api-stream.js +++ b/lib/api/api-stream.js @@ -5,8 +5,18 @@ const { finished } = require('node:stream') const { AsyncResource } = require('node:async_hooks') const { InvalidArgumentError, InvalidReturnValueError } = require('../core/errors') const util = require('../core/util') +const WrapHandler = require('../handler/wrap-handler') +const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') +function getDispatchHandler (dispatcher, handler) { + if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { + return handler + } + + return WrapHandler.wrap(handler) +} + function noop () {} class StreamHandler extends AsyncResource { @@ -195,8 +205,9 @@ function stream (opts, factory, callback) { try { const handler = new StreamHandler(opts, factory, callback) + const dispatchHandler = getDispatchHandler(this, handler) - this.dispatch(opts, handler) + this.dispatch(opts, dispatchHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-upgrade.js b/lib/api/api-upgrade.js index 2b03f207562..76911fc5d38 100644 --- a/lib/api/api-upgrade.js +++ b/lib/api/api-upgrade.js @@ -4,9 +4,19 @@ const { InvalidArgumentError, SocketError } = require('../core/errors') const { AsyncResource } = require('node:async_hooks') const assert = require('node:assert') const util = require('../core/util') +const WrapHandler = require('../handler/wrap-handler') +const DispatcherBase = require('../dispatcher/dispatcher-base') const { kHTTP2Stream } = require('../core/symbols') const { addSignal, removeSignal } = require('./abort-signal') +function getDispatchHandler (dispatcher, handler) { + if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { + return handler + } + + return WrapHandler.wrap(handler) +} + class UpgradeHandler extends AsyncResource { constructor (opts, callback) { if (!opts || typeof opts !== 'object') { @@ -97,8 +107,9 @@ function upgrade (opts, callback) { method: opts.method || 'GET', upgrade: opts.protocol || 'Websocket' } + const dispatchHandler = getDispatchHandler(this, upgradeHandler) - this.dispatch(upgradeOpts, upgradeHandler) + this.dispatch(upgradeOpts, dispatchHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/package.json b/package.json index bdfe7896b19..47233db799f 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "test:websocket:autobahn": "node test/autobahn/client.js", "test:websocket:autobahn:report": "node test/autobahn/report.js", "test:wpt:setup": "node test/web-platform-tests/wpt-runner.mjs setup", - "test:wpt": "npm run test:wpt:setup && node test/web-platform-tests/wpt-runner.mjs run /fetch /mimesniff /xhr /websockets /serviceWorkers /eventsource", + "test:wpt": "npm run test:wpt:setup && node test/web-platform-tests/wpt-runner.mjs run /fetch /mimesniff /websockets /serviceWorkers /eventsource", "test:cache-tests": "node test/cache-interceptor/cache-tests.mjs --ci", "coverage": "npm run coverage:clean && cross-env NODE_V8_COVERAGE=./coverage/tmp npm run test:javascript && npm run coverage:report", "coverage:ci": "npm run coverage:clean && cross-env NODE_V8_COVERAGE=./coverage/tmp npm run test:javascript && npm run coverage:report:ci", diff --git a/test/issue-4780.js b/test/issue-4780.js new file mode 100644 index 00000000000..43ae663d3a9 --- /dev/null +++ b/test/issue-4780.js @@ -0,0 +1,62 @@ +'use strict' + +const { strictEqual } = require('node:assert') +const { test } = require('node:test') +const { Dispatcher } = require('..') +const DispatcherBase = require('../lib/dispatcher/dispatcher-base') + +function createController () { + return { + abort () {}, + pause () {}, + resume () {} + } +} + +class NewAPIDispatcher extends Dispatcher { + dispatch (opts, handler) { + const controller = createController() + + handler.onRequestStart?.(controller, {}) + handler.onResponseStart?.(controller, 200, { 'content-type': 'text/plain' }, 'OK') + handler.onResponseData?.(controller, Buffer.from('Hello, world!')) + handler.onResponseEnd?.(controller, {}) + + return true + } + + close () {} + + destroy () {} +} + +class NewAPIDispatcherBase extends DispatcherBase { + dispatch (opts, handler) { + const controller = createController() + + handler.onRequestStart?.(controller, {}) + handler.onResponseStart?.(controller, 200, { 'content-type': 'text/plain' }, 'OK') + handler.onResponseData?.(controller, Buffer.from('Hello, world!')) + handler.onResponseEnd?.(controller, {}) + + return true + } +} + +async function assertRequestSucceeds (dispatcher) { + const response = await dispatcher.request({ + origin: 'http://example.com', + path: '/', + method: 'GET' + }) + + strictEqual(await response.body.text(), 'Hello, world!') +} + +test('https://github.com/nodejs/undici/issues/4780 - request uses new handler API (Dispatcher)', async () => { + await assertRequestSucceeds(new NewAPIDispatcher()) +}) + +test('https://github.com/nodejs/undici/issues/4780 - request uses new handler API (DispatcherBase)', async () => { + await assertRequestSucceeds(new NewAPIDispatcherBase()) +}) diff --git a/test/web-platform-tests/expectation.json b/test/web-platform-tests/expectation.json index 2d601880583..f238f7a36c2 100644 --- a/test/web-platform-tests/expectation.json +++ b/test/web-platform-tests/expectation.json @@ -563,11 +563,12 @@ { "name": "Empty string integrity for opaque response", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque response's status is 0 expected 0 but got 200" }, { "name": "SHA-* integrity for opaque response", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" } ] }, @@ -635,10 +636,10 @@ { "name": "Fetch https://web-platform.test:8443/fetch/api/resources/top.txt with no-cors mode", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" }, { - "name": "Fetch http://web-platform.test:55268/fetch/api/resources/top.txt with no-cors mode", + "name": "Fetch http://web-platform.test:51579/fetch/api/resources/top.txt with no-cors mode", "success": false, "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" } @@ -657,7 +658,8 @@ }, { "name": "Fetch https://web-platform.test:8443/fetch/api/resources/top.txt with same-origin mode", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Fetch http://www1.web-platform.test:8000/fetch/api/resources/top.txt with same-origin mode", @@ -1239,8 +1241,7 @@ }, { "name": "Fetch with POST with Float16Array body", - "success": false, - "message": "Float16Array is not defined" + "success": true }, { "name": "Fetch with POST with Float32Array body", @@ -1889,8 +1890,7 @@ }, { "name": "Fetch with POST with Float16Array body", - "success": false, - "message": "Float16Array is not defined" + "success": true }, { "name": "Fetch with POST with Float32Array body", @@ -4636,7 +4636,7 @@ { "name": "Check response clone use structureClone for teed ReadableStreams (Float16Arraychunk)", "success": false, - "message": "assert_array_equals: Cloned buffer chunks have the same content value is undefined, expected array" + "message": "assert_not_equals: Buffer of cloned response stream is a clone of the original buffer got disallowed value object \"0,0,0,0,0,0,0,0\"" }, { "name": "Check response clone use structureClone for teed ReadableStreams (Float32Arraychunk)", @@ -4809,7 +4809,7 @@ { "name": "Consume response's body: from text with correct multipart type to formData with BOM", "success": false, - "message": "assert_equals: Retrieve and verify response's body expected \"--boundary-0.16075435275547334\\r\\nContent-Disposition: form-data;name=\\\"name\\\"\\r\\n\\r\\nquickfox\\r\\n--boundary-0.16075435275547334--\\r\\n\" but got \"--boundary-0.16075435275547334\\r\\nContent-Disposition: form-data;name=\\\"name\\\"\\r\\n\\r\\nquickfox\\r\\n--boundary-0.16075435275547334--\\r\\n\"" + "message": "assert_equals: Retrieve and verify response's body expected \"--boundary-0.35865449327189336\\r\\nContent-Disposition: form-data;name=\\\"name\\\"\\r\\n\\r\\nquickfox\\r\\n--boundary-0.35865449327189336--\\r\\n\" but got \"--boundary-0.35865449327189336\\r\\nContent-Disposition: form-data;name=\\\"name\\\"\\r\\n\\r\\nquickfox\\r\\n--boundary-0.35865449327189336--\\r\\n\"" }, { "name": "Consume response's body: from text without correct multipart type to formData (error case)", @@ -4867,7 +4867,7 @@ { "name": "Consume response's body: from FormData to blob", "success": false, - "message": "assert_equals: Blob body type should be computed from the response Content-Type expected \"multipart/form-data; boundary=----formdata-undici-035234180410\" but got \"multipart/form-data;boundary=----formdata-undici-035234180410\"" + "message": "assert_equals: Blob body type should be computed from the response Content-Type expected \"multipart/form-data; boundary=----formdata-undici-014505735818\" but got \"multipart/form-data;boundary=----formdata-undici-014505735818\"" }, { "name": "Consume response's body: from FormData to text", @@ -6780,16 +6780,17 @@ { "name": "Same domain different protocol different port [no-cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" }, { "name": "Same domain different protocol different port [server forbid CORS]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Same domain different protocol different port [cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: CORS response's type is cors expected \"cors\" but got \"basic\"" }, { "name": "Cross domain basic usage [no-cors mode]", @@ -6824,16 +6825,17 @@ { "name": "Cross domain different protocol [no-cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" }, { "name": "Cross domain different protocol [server forbid CORS]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross domain different protocol [cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: CORS response's type is cors expected \"cors\" but got \"basic\"" } ] }, @@ -7031,16 +7033,17 @@ { "name": "[keepalive] Same domain different protocol different port [no-cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" }, { "name": "[keepalive] Same domain different protocol different port [cors mode, server forbid CORS]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "[keepalive] Same domain different protocol different port [cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: CORS response's type is cors expected \"cors\" but got \"basic\"" }, { "name": "[keepalive] Cross domain basic usage [no-cors mode]", @@ -7075,16 +7078,17 @@ { "name": "[keepalive] Cross domain different protocol [no-cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: Opaque filter: status is 0 expected 0 but got 200" }, { "name": "[keepalive] Cross domain different protocol [cors mode, server forbid CORS]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "[keepalive] Cross domain different protocol [cors mode]", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: CORS response's type is cors expected \"cors\" but got \"basic\"" }, { "name": "[keepalive] Same domain different port GET request in unload [no-cors mode, server forbid CORS]; setting up", @@ -7340,13 +7344,11 @@ }, { "name": "Cross domain different protocol [GET]", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Same domain different protocol different port [GET]", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross domain [POST]", @@ -7422,21 +7424,21 @@ }, { "name": "Cross domain different protocol [origin OK]", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross domain different protocol [origin KO]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Same domain different protocol different port [origin OK]", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Same domain different protocol different port [origin KO]", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross domain [POST] [origin OK]", @@ -8729,13 +8731,11 @@ }, { "name": "getAuthorizationHeaderValue - same origin redirection", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "getAuthorizationHeaderValue - cross origin redirection", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true } ] }, @@ -11239,27 +11239,27 @@ { "name": "Decompresion using gzip-encoded dictionary works as expected", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" }, { "name": "Decompresion using Brotli-encoded dictionary works as expected", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" }, { "name": "Decompresion using Zstandard-encoded dictionary works as expected", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" }, { "name": "A dcb dictionary-compressed dictionary can be used as a dictionary for future requests.", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" }, { "name": "A dcz dictionary-compressed dictionary can be used as a dictionary for future requests.", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" } ] }, @@ -11279,7 +11279,7 @@ { "name": "Decompresion of a cross origin resource works as expected", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" } ] }, @@ -11344,7 +11344,7 @@ { "name": "Dictionary registration does not invalidate cache entry", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \":U5abz16WDg7b8KS93msLPpOB4Vbef1uRzoORYkJw9BY=:\" but got \"\\\"available-dictionary\\\" header is not available\"" }, { "name": "Expired dictionary is not used", @@ -12893,11 +12893,13 @@ }, { "name": "Cross-scheme (HTTP to HTTPS) no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-site' response header.", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross-origin no-cors fetch to a same-site URL with a 'Cross-Origin-Resource-Policy: same-origin' response header.", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Valid cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.", @@ -12933,35 +12935,35 @@ }, { "name": "Cross-origin cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross-origin cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header.", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-site' response header.", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a redirection.", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" }, { "name": "Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' response header after a cross-origin redirection.", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross-origin no-cors fetch with a 'Cross-Origin-Resource-Policy: same-origin' redirect response header.", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" } ] }, @@ -12984,7 +12986,8 @@ "cases": [ { "name": "Cross-Origin-Resource-Policy: same-site blocks retrieving HTTPS from HTTP", - "success": true + "success": false, + "message": "assert_unreached: Should have rejected: undefined Reached unreachable code" } ] }, @@ -15256,7 +15259,7 @@ { "name": "Response with Cache-Control: max-age=2592000, public and Pragma: no-cache should be cached", "success": false, - "message": "assert_equals: Responses should be identical, indicating caching expected \"Timestamp: 1768756436.8170867\" but got \"Timestamp: 1768756436.8148103\"" + "message": "assert_equals: Responses should be identical, indicating caching expected \"Timestamp: 1769769728.994271\" but got \"Timestamp: 1769769728.9848197\"" } ] }, @@ -15582,13 +15585,47 @@ "cases": [ { "name": "Same-site fetch with preflight", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross-site fetch with preflight", + "success": true + }, + { + "name": "Same-site fetch with preflight: sec-fetch-dest", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Same-site fetch with preflight: sec-fetch-mode", + "success": true + }, + { + "name": "Same-site fetch with preflight: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-site\" but got \"\"" + }, + { + "name": "Same-site fetch with preflight: sec-fetch-user", + "success": true + }, + { + "name": "Cross-site fetch with preflight: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Cross-site fetch with preflight: sec-fetch-mode", + "success": true + }, + { + "name": "Cross-site fetch with preflight: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"cross-site\" but got \"\"" + }, + { + "name": "Cross-site fetch with preflight: sec-fetch-user", + "success": true } ] }, @@ -15597,33 +15634,135 @@ "cases": [ { "name": "Same-origin fetch", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Same-site fetch", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Cross-site fetch", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Same-origin mode", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "CORS mode", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "no-CORS mode", + "success": true + }, + { + "name": "Same-origin fetch: sec-fetch-dest", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Same-origin fetch: sec-fetch-mode", + "success": true + }, + { + "name": "Same-origin fetch: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-origin\" but got \"\"" + }, + { + "name": "Same-origin fetch: sec-fetch-user", + "success": true + }, + { + "name": "Same-site fetch: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Same-site fetch: sec-fetch-mode", + "success": true + }, + { + "name": "Same-site fetch: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-site\" but got \"\"" + }, + { + "name": "Same-site fetch: sec-fetch-user", + "success": true + }, + { + "name": "Cross-site fetch: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Cross-site fetch: sec-fetch-mode", + "success": true + }, + { + "name": "Cross-site fetch: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"cross-site\" but got \"\"" + }, + { + "name": "Cross-site fetch: sec-fetch-user", + "success": true + }, + { + "name": "Same-origin mode: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Same-origin mode: sec-fetch-mode", + "success": true + }, + { + "name": "Same-origin mode: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-origin\" but got \"\"" + }, + { + "name": "Same-origin mode: sec-fetch-user", + "success": true + }, + { + "name": "CORS mode: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "CORS mode: sec-fetch-mode", + "success": true + }, + { + "name": "CORS mode: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-origin\" but got \"\"" + }, + { + "name": "CORS mode: sec-fetch-user", + "success": true + }, + { + "name": "no-CORS mode: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "no-CORS mode: sec-fetch-mode", + "success": true + }, + { + "name": "no-CORS mode: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"same-origin\" but got \"\"" + }, + { + "name": "no-CORS mode: sec-fetch-user", + "success": true } ] }, @@ -19290,112 +19429,106 @@ { "name": "sec-fetch-site - Same origin, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Cross-site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Origin -> Cross-Site -> Same-Origin redirect, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Origin -> Same-Site -> Same-Origin redirect, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Cross-Site -> Same Origin, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Cross-Site -> Same-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Cross-Site -> Cross-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Origin -> Same Origin, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Origin -> Same-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Origin -> Cross-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Site -> Same Origin, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Site -> Same-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - Same-Site -> Cross-Site, init: mode=no-cors", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-mode - no init", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-mode - init: mode=cors", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-mode - init: mode=no-cors", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-mode - init: mode=same-origin", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-dest - no init", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-dest\" missing" }, { "name": "sec-fetch-user - no init", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-storage-access - Cross-site, init: mode=no-cors, credentials=include", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-storage-access\" missing" }, { "name": "sec-fetch-storage-access - Same site, init: mode=no-cors, credentials=include", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true } ] }, @@ -19467,18 +19600,17 @@ }, { "name": "sec-fetch-site - HTTPS downgrade (header not sent), no init", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "sec-fetch-site - HTTPS upgrade, no init", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" }, { "name": "sec-fetch-site - HTTPS downgrade-upgrade, no init", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_own_property: expected property \"sec-fetch-site\" missing" } ] }, @@ -22171,18 +22303,69 @@ "cases": [ { "name": "Fetching a resource from the same origin, but spelled with a trailing dot.", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Fetching a resource from the same site, but spelled with a trailing dot.", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "success": true }, { "name": "Fetching a resource from a cross-site host, spelled with a trailing dot.", + "success": true + }, + { + "name": "Fetching a resource from the same origin, but spelled with a trailing dot.: sec-fetch-dest", "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Fetching a resource from the same origin, but spelled with a trailing dot.: sec-fetch-mode", + "success": true + }, + { + "name": "Fetching a resource from the same origin, but spelled with a trailing dot.: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"cross-site\" but got \"\"" + }, + { + "name": "Fetching a resource from the same origin, but spelled with a trailing dot.: sec-fetch-user", + "success": true + }, + { + "name": "Fetching a resource from the same site, but spelled with a trailing dot.: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Fetching a resource from the same site, but spelled with a trailing dot.: sec-fetch-mode", + "success": true + }, + { + "name": "Fetching a resource from the same site, but spelled with a trailing dot.: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"cross-site\" but got \"\"" + }, + { + "name": "Fetching a resource from the same site, but spelled with a trailing dot.: sec-fetch-user", + "success": true + }, + { + "name": "Fetching a resource from a cross-site host, spelled with a trailing dot.: sec-fetch-dest", + "success": false, + "message": "assert_equals: expected \"empty\" but got \"\"" + }, + { + "name": "Fetching a resource from a cross-site host, spelled with a trailing dot.: sec-fetch-mode", + "success": true + }, + { + "name": "Fetching a resource from a cross-site host, spelled with a trailing dot.: sec-fetch-site", + "success": false, + "message": "assert_equals: expected \"cross-site\" but got \"\"" + }, + { + "name": "Fetching a resource from a cross-site host, spelled with a trailing dot.: sec-fetch-user", + "success": true } ] }, @@ -24050,9012 +24233,551 @@ } ] } - }, - "embedded-credentials.tentative.sub.html": { - "success": true, - "cases": [ - { - "name": "Embedded credentials are treated as network errors.", - "success": false, - "message": "document is not defined" - }, - { - "name": "Embedded credentials are treated as network errors in frames.", - "success": false, - "message": "document is not defined" - }, - { - "name": "Embedded credentials are treated as network errors in new windows.", - "success": false, - "message": "window.open is not a function" - }, - { - "name": "Embedded credentials matching the top-level are not treated as network errors for relative URLs.", - "success": false, - "message": "window.open is not a function" - }, - { - "name": "Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.", - "success": false, - "message": "window.open is not a function" - }, - { - "name": "Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.", - "success": false, - "message": "window.open is not a function" - } - ] - }, - "redirect-to-url-with-credentials.https.html": { - "success": true, - "cases": [ - { - "name": "No CORS fetch after a redirect with an URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" - }, - { - "name": "CORS fetch after a redirect with a cross origin URL containing credentials", - "success": true - }, - { - "name": "CORS fetch after a redirect with a same origin URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" - }, - { - "name": "Image loading after a redirect with an URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" - }, - { - "name": "CORS Image loading after a redirect with a cross origin URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" - }, - { - "name": "CORS Image loading after a redirect with a same origin URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" - }, - { - "name": "Frame loading after a redirect with an URL containing credentials", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: document is not defined\"" - } - ] - } - }, - "stale-while-revalidate": { - "fetch-sw.https.html": { - "success": true, - "cases": [ - { - "name": "Second fetch returns same response", - "success": false, - "message": "promise_test: Unhandled rejection with value: object \"TypeError: Cannot read properties of undefined (reading 'register')\"" - } - ] - }, - "fetch.any.html": { - "success": true, - "cases": [ - { - "name": "Second fetch returns same response", - "success": false, - "message": "assert_equals: expected \"qoidijwtsfvgrbpjvqow\" but got \"pyimmkhbwsuwcvgrysyj\"" - } - ] - }, - "revalidate-not-blocked-by-csp.html": { - "success": false, - "cases": [] - }, - "stale-css.html": { - "success": false, - "cases": [] - }, - "stale-image.html": { - "success": false, - "cases": [] - }, - "stale-script.html": { - "success": false, - "cases": [] - } - } - }, - "mimesniff": { - "media": { - "media-sniff.window.html": { - "success": true, - "cases": [ - { - "name": "mp3-raw.mp3 loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-raw.mp3 loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-raw.mp3 loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-raw.mp3 loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-raw.mp3 loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-raw.mp3 loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp3-with-id3.mp3 loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "flac.flac loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "ogg.ogg loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "mp4.mp4 loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "wav.wav loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type ", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type bogus/mime", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type application/octet-stream", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type text/html", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type audio/ogg; codec=vorbis", - "success": false, - "message": "document is not defined" - }, - { - "name": "webm.webm loads when served with Content-Type application/pdf", - "success": false, - "message": "document is not defined" - } - ] - } - }, - "mime-types": { - "charset-parameter.window.html": { - "success": true, - "cases": [ - { - "name": "Loading data…", - "success": true - }, - { - "name": "text/html;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "TEXT/HTML;CHARSET=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=gbk(", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;x=(;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=gbk;charset=windows-1255", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=();charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset =gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html ;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html; charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset= gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset= \"gbk\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\u000bgbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\fgbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;\u000bcharset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;\fcharset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset='gbk'", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset='gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=gbk'", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=';charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;test;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;test=;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;';charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;\";charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html ; ; charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;;;;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset= \";charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\";charset=foo\";charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"gbk\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=gbk\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\" gbk\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"gbk \"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"\\ gbk\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"\\g\\b\\k\"", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"gbk\"x", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\"\";charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset=\";charset=GBK", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;charset={gbk}", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk", - "success": false, - "message": "document is not defined" - }, - { - "name": "text/html;test=ÿ;charset=gbk", - "success": false, - "message": "document is not defined" - } - ] - }, - "parsing.any.html": { - "success": "flaky", - "cases": [ - { - "name": "Loading data…", - "success": true - }, - { - "name": "text/html;charset=gbk (Blob/File)", - "success": true - }, - { - "name": "text/html;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "TEXT/HTML;CHARSET=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=GBK\" but got \"text/html;charset=gbk\"" - }, - { - "name": "TEXT/HTML;CHARSET=GBK (Request/Response)", - "success": false, - "message": "assert_equals: expected \"text/html;charset=GBK\" but got \"text/html;charset=gbk\"" - }, - { - "name": "text/html;charset=gbk( (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\"gbk(\\\"\" but got \"text/html;charset=gbk(\"" - }, - { - "name": "text/html;charset=gbk( (Request/Response)", - "success": true - }, - { - "name": "text/html;x=(;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;x=\\\"(\\\";charset=gbk\" but got \"text/html;x=(;charset=gbk\"" - }, - { - "name": "text/html;x=(;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=gbk;charset=windows-1255 (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;charset=gbk;charset=windows-1255\"" - }, - { - "name": "text/html;charset=gbk;charset=windows-1255 (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=();charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\"()\\\"\" but got \"text/html;charset=();charset=gbk\"" - }, - { - "name": "text/html;charset=();charset=GBK (Request/Response)", - "success": true - }, - { - "name": "text/html;charset =gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html\" but got \"text/html;charset =gbk\"" - }, - { - "name": "text/html;charset =gbk (Request/Response)", - "success": true - }, - { - "name": "text/html ;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html ;charset=gbk\"" - }, - { - "name": "text/html ;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html; charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html; charset=gbk\"" - }, - { - "name": "text/html; charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset= gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\" gbk\\\"\" but got \"text/html;charset= gbk\"" - }, - { - "name": "text/html;charset= gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset= \"gbk\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\" \\\\\\\"gbk\\\\\\\"\\\"\" but got \"text/html;charset= \\\"gbk\\\"\"" - }, - { - "name": "text/html;charset= \"gbk\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\u000bgbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html\" but got \"\"" - }, - { - "name": "text/html;charset=\u000bgbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\fgbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html\" but got \"\"" - }, - { - "name": "text/html;charset=\fgbk (Request/Response)", - "success": true - }, - { - "name": "text/html;\u000bcharset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html\" but got \"\"" - }, - { - "name": "text/html;\u000bcharset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;\fcharset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html\" but got \"\"" - }, - { - "name": "text/html;\fcharset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset='gbk' (Blob/File)", - "success": true - }, - { - "name": "text/html;charset='gbk' (Request/Response)", - "success": true - }, - { - "name": "text/html;charset='gbk (Blob/File)", - "success": true - }, - { - "name": "text/html;charset='gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=gbk' (Blob/File)", - "success": true - }, - { - "name": "text/html;charset=gbk' (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=';charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset='\" but got \"text/html;charset=';charset=gbk\"" - }, - { - "name": "text/html;charset=';charset=GBK (Request/Response)", - "success": true - }, - { - "name": "text/html;test;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;test;charset=gbk\"" - }, - { - "name": "text/html;test;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;test=;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;test=;charset=gbk\"" - }, - { - "name": "text/html;test=;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;';charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;';charset=gbk\"" - }, - { - "name": "text/html;';charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;\";charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;\\\";charset=gbk\"" - }, - { - "name": "text/html;\";charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html ; ; charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html ; ; charset=gbk\"" - }, - { - "name": "text/html ; ; charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;;;;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;;;;charset=gbk\"" - }, - { - "name": "text/html;;;;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset= \";charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=GBK\" but got \"\"" - }, - { - "name": "text/html;charset= \";charset=GBK (Request/Response)", - "success": false, - "message": "assert_equals: expected \"text/html;charset=GBK\" but got \"text/html;charset=gbk\"" - }, - { - "name": "text/html;charset=\";charset=foo\";charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=GBK\" but got \"\"" - }, - { - "name": "text/html;charset=\";charset=foo\";charset=GBK (Request/Response)", - "success": false, - "message": "assert_equals: expected \"text/html;charset=GBK\" but got \"text/html;charset=gbk\"" - }, - { - "name": "text/html;charset=\"gbk\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;charset=\\\"gbk\\\"\"" - }, - { - "name": "text/html;charset=\"gbk\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;charset=\\\"gbk\"" - }, - { - "name": "text/html;charset=\"gbk (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=gbk\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\"gbk\\\\\\\"\\\"\" but got \"text/html;charset=gbk\\\"\"" - }, - { - "name": "text/html;charset=gbk\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\" gbk\" (Blob/File)", - "success": true - }, - { - "name": "text/html;charset=\" gbk\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"gbk \" (Blob/File)", - "success": true - }, - { - "name": "text/html;charset=\"gbk \" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"\\ gbk\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\" gbk\\\"\" but got \"text/html;charset=\\\"\\\\ gbk\\\"\"" - }, - { - "name": "text/html;charset=\"\\ gbk\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"\\g\\b\\k\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;charset=\\\"\\\\g\\\\b\\\\k\\\"\"" - }, - { - "name": "text/html;charset=\"\\g\\b\\k\" (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"gbk\"x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=gbk\" but got \"text/html;charset=\\\"gbk\\\"x\"" - }, - { - "name": "text/html;charset=\"gbk\"x (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\"\";charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\"\\\"\" but got \"text/html;charset=\\\"\\\";charset=gbk\"" - }, - { - "name": "text/html;charset=\"\";charset=GBK (Request/Response)", - "success": true - }, - { - "name": "text/html;charset=\";charset=GBK (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\";charset=GBK\\\"\" but got \"text/html;charset=\\\";charset=gbk\"" - }, - { - "name": "text/html;charset=\";charset=GBK (Request/Response)", - "success": false, - "message": "assert_equals: expected \"text/html;charset=\\\";charset=GBK\\\"\" but got \"text/html;charset=\\\";charset=gbk\\\"\"" - }, - { - "name": "text/html;charset={gbk} (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;charset=\\\"{gbk}\\\"\" but got \"text/html;charset={gbk}\"" - }, - { - "name": "text/html;charset={gbk} (Request/Response)", - "success": true - }, - { - "name": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Blob/File)", - "success": true - }, - { - "name": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk (Request/Response)", - "success": true - }, - { - "name": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Blob/File)", - "success": true - }, - { - "name": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 (Request/Response)", - "success": true - }, - { - "name": "text/html;a]=bar;b[=bar;c=bar (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;c=bar\" but got \"text/html;a]=bar;b[=bar;c=bar\"" - }, - { - "name": "text/html;a]=bar;b[=bar;c=bar (Request/Response)", - "success": true - }, - { - "name": "text/html;valid=\";\";foo=bar (Blob/File)", - "success": true - }, - { - "name": "text/html;valid=\";\";foo=bar (Request/Response)", - "success": true - }, - { - "name": "text/html;in]valid=\";asd=foo\";foo=bar (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;foo=bar\" but got \"text/html;in]valid=\\\";asd=foo\\\";foo=bar\"" - }, - { - "name": "text/html;in]valid=\";asd=foo\";foo=bar (Request/Response)", - "success": true - }, - { - "name": "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\" but got \"!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\"" - }, - { - "name": "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz (Request/Response)", - "success": false, - "message": "assert_equals: expected \"!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\" but got \"\"" - }, - { - "name": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\t !\\\\\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\\\"\" but got \"\"" - }, - { - "name": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\" (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\t !\\\\\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ\\\"\" but got \"\"" - }, - { - "name": "x/x;test (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x\" but got \"x/x;test\"" - }, - { - "name": "x/x;test (Request/Response)", - "success": true - }, - { - "name": "x/x;test=\"\\ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;test=\\\"\\\\\\\\\\\"\" but got \"x/x;test=\\\"\\\\\"" - }, - { - "name": "x/x;test=\"\\ (Request/Response)", - "success": true - }, - { - "name": "x/x;x= (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x\" but got \"x/x;x= \"" - }, - { - "name": "x/x;x=\t (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x\" but got \"\"" - }, - { - "name": "x/x\n\r\t ;x=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=x\" but got \"\"" - }, - { - "name": "x/x\n\r\t ;x=x (Request/Response)", - "success": true - }, - { - "name": "\n\r\t x/x;x=x\n\r\t (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=x\" but got \"\"" - }, - { - "name": "x/x;\n\r\t x=x\n\r\t ;x=y (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=x\" but got \"\"" - }, - { - "name": "x/x;\n\r\t x=x\n\r\t ;x=y (Request/Response)", - "success": true - }, - { - "name": "text/html;test=ÿ;charset=gbk (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"text/html;test=\\\"ÿ\\\";charset=gbk\" but got \"\"" - }, - { - "name": "text/html;test=ÿ;charset=gbk (Request/Response)", - "success": false, - "message": "assert_equals: expected \"text/html;test=\\\"ÿ\\\";charset=gbk\" but got \"\"" - }, - { - "name": "x/x;test=�;x=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=x\" but got \"\"" - }, - { - "name": "x/x;test=�;x=x (Request/Response)", - "success": true - }, - { - "name": "\u000bx/x (Blob/File)", - "success": true - }, - { - "name": "\u000bx/x (Request/Response)", - "success": true - }, - { - "name": "\fx/x (Blob/File)", - "success": true - }, - { - "name": "\fx/x (Request/Response)", - "success": true - }, - { - "name": "x/x\u000b (Blob/File)", - "success": true - }, - { - "name": "x/x\u000b (Request/Response)", - "success": true - }, - { - "name": "x/x\f (Blob/File)", - "success": true - }, - { - "name": "x/x\f (Request/Response)", - "success": true - }, - { - "name": " (Blob/File)", - "success": true - }, - { - "name": " (Request/Response)", - "success": true - }, - { - "name": "\t (Blob/File)", - "success": true - }, - { - "name": "/ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"/\"" - }, - { - "name": "/ (Request/Response)", - "success": true - }, - { - "name": "bogus (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"bogus\"" - }, - { - "name": "bogus (Request/Response)", - "success": true - }, - { - "name": "bogus/ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"bogus/\"" - }, - { - "name": "bogus/ (Request/Response)", - "success": true - }, - { - "name": "bogus/ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"bogus/ \"" - }, - { - "name": "bogus/bogus/; (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"bogus/bogus/;\"" - }, - { - "name": "bogus/bogus/; (Request/Response)", - "success": true - }, - { - "name": " (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"\"" - }, - { - "name": " (Request/Response)", - "success": true - }, - { - "name": "(/) (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"(/)\"" - }, - { - "name": "(/) (Request/Response)", - "success": true - }, - { - "name": "ÿ/ÿ (Blob/File)", - "success": true - }, - { - "name": "ÿ/ÿ (Request/Response)", - "success": true - }, - { - "name": "text/html(;doesnot=matter (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"text/html(;doesnot=matter\"" - }, - { - "name": "text/html(;doesnot=matter (Request/Response)", - "success": true - }, - { - "name": "{/} (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"{/}\"" - }, - { - "name": "{/} (Request/Response)", - "success": true - }, - { - "name": "Ā/Ā (Blob/File)", - "success": true - }, - { - "name": "Ā/Ā (Request/Response)", - "success": true - }, - { - "name": "text /html (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"text /html\"" - }, - { - "name": "text /html (Request/Response)", - "success": true - }, - { - "name": "text/ html (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"text/ html\"" - }, - { - "name": "text/ html (Request/Response)", - "success": true - }, - { - "name": "\"text/html\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"\\\"text/html\\\"\"" - }, - { - "name": "\"text/html\" (Request/Response)", - "success": true - }, - { - "name": "\u0000/x (Blob/File)", - "success": true - }, - { - "name": "\u0000/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0000 (Blob/File)", - "success": true - }, - { - "name": "x/\u0000 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0000=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0000=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0000;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0000;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0000\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0000\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0001/x (Blob/File)", - "success": true - }, - { - "name": "\u0001/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0001 (Blob/File)", - "success": true - }, - { - "name": "x/\u0001 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0001=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0001=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0001;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0001;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0001\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0001\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0002/x (Blob/File)", - "success": true - }, - { - "name": "\u0002/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0002 (Blob/File)", - "success": true - }, - { - "name": "x/\u0002 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0002=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0002=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0002;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0002;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0002\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0002\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0003/x (Blob/File)", - "success": true - }, - { - "name": "\u0003/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0003 (Blob/File)", - "success": true - }, - { - "name": "x/\u0003 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0003=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0003=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0003;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0003;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0003\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0003\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0004/x (Blob/File)", - "success": true - }, - { - "name": "\u0004/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0004 (Blob/File)", - "success": true - }, - { - "name": "x/\u0004 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0004=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0004=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0004;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0004;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0004\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0004\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0005/x (Blob/File)", - "success": true - }, - { - "name": "\u0005/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0005 (Blob/File)", - "success": true - }, - { - "name": "x/\u0005 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0005=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0005=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0005;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0005;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0005\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0005\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0006/x (Blob/File)", - "success": true - }, - { - "name": "\u0006/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0006 (Blob/File)", - "success": true - }, - { - "name": "x/\u0006 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0006=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0006=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0006;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0006;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0006\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0006\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0007/x (Blob/File)", - "success": true - }, - { - "name": "\u0007/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0007 (Blob/File)", - "success": true - }, - { - "name": "x/\u0007 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0007=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0007=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0007;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0007;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0007\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0007\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\b/x (Blob/File)", - "success": true - }, - { - "name": "\b/x (Request/Response)", - "success": true - }, - { - "name": "x/\b (Blob/File)", - "success": true - }, - { - "name": "x/\b (Request/Response)", - "success": true - }, - { - "name": "x/x;\b=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\b=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\b;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\b;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\b\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\b\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\t/x (Blob/File)", - "success": true - }, - { - "name": "x/\t (Blob/File)", - "success": true - }, - { - "name": "x/x;\t=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\t=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "\n/x (Blob/File)", - "success": true - }, - { - "name": "x/\n (Blob/File)", - "success": true - }, - { - "name": "x/x;\n=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\n=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\n;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\n;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\n\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\n\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u000b/x (Blob/File)", - "success": true - }, - { - "name": "\u000b/x (Request/Response)", - "success": true - }, - { - "name": "x/\u000b (Blob/File)", - "success": true - }, - { - "name": "x/\u000b (Request/Response)", - "success": true - }, - { - "name": "x/x;\u000b=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u000b=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u000b;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u000b;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u000b\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u000b\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\f/x (Blob/File)", - "success": true - }, - { - "name": "\f/x (Request/Response)", - "success": true - }, - { - "name": "x/\f (Blob/File)", - "success": true - }, - { - "name": "x/\f (Request/Response)", - "success": true - }, - { - "name": "x/x;\f=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\f=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\f;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\f;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\f\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\f\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\r/x (Blob/File)", - "success": true - }, - { - "name": "x/\r (Blob/File)", - "success": true - }, - { - "name": "x/x;\r=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\r=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\r;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\r;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\r\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\r\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u000e/x (Blob/File)", - "success": true - }, - { - "name": "\u000e/x (Request/Response)", - "success": true - }, - { - "name": "x/\u000e (Blob/File)", - "success": true - }, - { - "name": "x/\u000e (Request/Response)", - "success": true - }, - { - "name": "x/x;\u000e=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u000e=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u000e;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u000e;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u000e\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u000e\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u000f/x (Blob/File)", - "success": true - }, - { - "name": "\u000f/x (Request/Response)", - "success": true - }, - { - "name": "x/\u000f (Blob/File)", - "success": true - }, - { - "name": "x/\u000f (Request/Response)", - "success": true - }, - { - "name": "x/x;\u000f=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u000f=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u000f;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u000f;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u000f\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u000f\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0010/x (Blob/File)", - "success": true - }, - { - "name": "\u0010/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0010 (Blob/File)", - "success": true - }, - { - "name": "x/\u0010 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0010=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0010=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0010;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0010;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0010\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0010\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0011/x (Blob/File)", - "success": true - }, - { - "name": "\u0011/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0011 (Blob/File)", - "success": true - }, - { - "name": "x/\u0011 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0011=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0011=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0011;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0011;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0011\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0011\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0012/x (Blob/File)", - "success": true - }, - { - "name": "\u0012/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0012 (Blob/File)", - "success": true - }, - { - "name": "x/\u0012 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0012=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0012=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0012;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0012;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0012\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0012\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0013/x (Blob/File)", - "success": true - }, - { - "name": "\u0013/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0013 (Blob/File)", - "success": true - }, - { - "name": "x/\u0013 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0013=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0013=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0013;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0013;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0013\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0013\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0014/x (Blob/File)", - "success": true - }, - { - "name": "\u0014/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0014 (Blob/File)", - "success": true - }, - { - "name": "x/\u0014 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0014=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0014=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0014;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0014;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0014\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0014\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0015/x (Blob/File)", - "success": true - }, - { - "name": "\u0015/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0015 (Blob/File)", - "success": true - }, - { - "name": "x/\u0015 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0015=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0015=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0015;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0015;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0015\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0015\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0016/x (Blob/File)", - "success": true - }, - { - "name": "\u0016/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0016 (Blob/File)", - "success": true - }, - { - "name": "x/\u0016 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0016=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0016=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0016;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0016;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0016\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0016\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0017/x (Blob/File)", - "success": true - }, - { - "name": "\u0017/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0017 (Blob/File)", - "success": true - }, - { - "name": "x/\u0017 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0017=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0017=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0017;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0017;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0017\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0017\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0018/x (Blob/File)", - "success": true - }, - { - "name": "\u0018/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0018 (Blob/File)", - "success": true - }, - { - "name": "x/\u0018 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0018=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0018=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0018;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0018;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0018\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0018\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u0019/x (Blob/File)", - "success": true - }, - { - "name": "\u0019/x (Request/Response)", - "success": true - }, - { - "name": "x/\u0019 (Blob/File)", - "success": true - }, - { - "name": "x/\u0019 (Request/Response)", - "success": true - }, - { - "name": "x/x;\u0019=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u0019=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u0019;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u0019;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u0019\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u0019\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001a/x (Blob/File)", - "success": true - }, - { - "name": "\u001a/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001a (Blob/File)", - "success": true - }, - { - "name": "x/\u001a (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001a=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001a=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001a;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001a;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001a\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001a\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001b/x (Blob/File)", - "success": true - }, - { - "name": "\u001b/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001b (Blob/File)", - "success": true - }, - { - "name": "x/\u001b (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001b=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001b=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001b;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001b;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001b\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001b\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001c/x (Blob/File)", - "success": true - }, - { - "name": "\u001c/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001c (Blob/File)", - "success": true - }, - { - "name": "x/\u001c (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001c=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001c=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001c;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001c;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001c\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001c\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001d/x (Blob/File)", - "success": true - }, - { - "name": "\u001d/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001d (Blob/File)", - "success": true - }, - { - "name": "x/\u001d (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001d=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001d=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001d;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001d;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001d\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001d\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001e/x (Blob/File)", - "success": true - }, - { - "name": "\u001e/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001e (Blob/File)", - "success": true - }, - { - "name": "x/\u001e (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001e=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001e=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001e;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001e;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001e\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001e\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\u001f/x (Blob/File)", - "success": true - }, - { - "name": "\u001f/x (Request/Response)", - "success": true - }, - { - "name": "x/\u001f (Blob/File)", - "success": true - }, - { - "name": "x/\u001f (Request/Response)", - "success": true - }, - { - "name": "x/x;\u001f=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;\u001f=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\u001f;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\u001f;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\u001f\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\u001f\";bonus=x (Request/Response)", - "success": true - }, - { - "name": " /x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \" /x\"" - }, - { - "name": "x/ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/ \"" - }, - { - "name": "x/x; =x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x; =x;bonus=x\"" - }, - { - "name": "x/x; =x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "\"/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"\\\"/x\"" - }, - { - "name": "\"/x (Request/Response)", - "success": true - }, - { - "name": "x/\" (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/\\\"\"" - }, - { - "name": "x/\" (Request/Response)", - "success": true - }, - { - "name": "x/x;\"=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;\\\"=x;bonus=x\"" - }, - { - "name": "x/x;\"=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "(/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"(/x\"" - }, - { - "name": "(/x (Request/Response)", - "success": true - }, - { - "name": "x/( (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/(\"" - }, - { - "name": "x/( (Request/Response)", - "success": true - }, - { - "name": "x/x;(=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;(=x;bonus=x\"" - }, - { - "name": "x/x;(=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=(;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"(\\\";bonus=x\" but got \"x/x;x=(;bonus=x\"" - }, - { - "name": "x/x;x=(;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"(\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"(\";bonus=x (Request/Response)", - "success": true - }, - { - "name": ")/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \")/x\"" - }, - { - "name": ")/x (Request/Response)", - "success": true - }, - { - "name": "x/) (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/)\"" - }, - { - "name": "x/) (Request/Response)", - "success": true - }, - { - "name": "x/x;)=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;)=x;bonus=x\"" - }, - { - "name": "x/x;)=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=);bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\")\\\";bonus=x\" but got \"x/x;x=);bonus=x\"" - }, - { - "name": "x/x;x=);bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\")\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\")\";bonus=x (Request/Response)", - "success": true - }, - { - "name": ",/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \",/x\"" - }, - { - "name": ",/x (Request/Response)", - "success": true - }, - { - "name": "x/, (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/,\"" - }, - { - "name": "x/, (Request/Response)", - "success": true - }, - { - "name": "x/x;,=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;,=x;bonus=x\"" - }, - { - "name": "x/x;,=x;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;bonus=x\" but got \"x/x\"" - }, - { - "name": "x/x;x=,;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\",\\\";bonus=x\" but got \"x/x;x=,;bonus=x\"" - }, - { - "name": "x/x;x=,;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\",\\\";bonus=x\" but got \"x/x\"" - }, - { - "name": "x/x;x=\",\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\",\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;/=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;/=x;bonus=x\"" - }, - { - "name": "x/x;/=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=/;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"/\\\";bonus=x\" but got \"x/x;x=/;bonus=x\"" - }, - { - "name": "x/x;x=/;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"/\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"/\";bonus=x (Request/Response)", - "success": true - }, - { - "name": ":/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \":/x\"" - }, - { - "name": ":/x (Request/Response)", - "success": true - }, - { - "name": "x/: (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/:\"" - }, - { - "name": "x/: (Request/Response)", - "success": true - }, - { - "name": "x/x;:=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;:=x;bonus=x\"" - }, - { - "name": "x/x;:=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=:;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\":\\\";bonus=x\" but got \"x/x;x=:;bonus=x\"" - }, - { - "name": "x/x;x=:;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\":\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\":\";bonus=x (Request/Response)", - "success": true - }, - { - "name": ";/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \";/x\"" - }, - { - "name": ";/x (Request/Response)", - "success": true - }, - { - "name": "x/; (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/;\"" - }, - { - "name": "x/; (Request/Response)", - "success": true - }, - { - "name": "/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \">/x\"" - }, - { - "name": ">/x (Request/Response)", - "success": true - }, - { - "name": "x/> (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/>\"" - }, - { - "name": "x/> (Request/Response)", - "success": true - }, - { - "name": "x/x;>=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;>=x;bonus=x\"" - }, - { - "name": "x/x;>=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=>;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\">\\\";bonus=x\" but got \"x/x;x=>;bonus=x\"" - }, - { - "name": "x/x;x=>;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\">\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\">\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "?/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"?/x\"" - }, - { - "name": "?/x (Request/Response)", - "success": true - }, - { - "name": "x/? (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/?\"" - }, - { - "name": "x/? (Request/Response)", - "success": true - }, - { - "name": "x/x;?=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;?=x;bonus=x\"" - }, - { - "name": "x/x;?=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=?;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"?\\\";bonus=x\" but got \"x/x;x=?;bonus=x\"" - }, - { - "name": "x/x;x=?;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"?\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"?\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "@/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"@/x\"" - }, - { - "name": "@/x (Request/Response)", - "success": true - }, - { - "name": "x/@ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/@\"" - }, - { - "name": "x/@ (Request/Response)", - "success": true - }, - { - "name": "x/x;@=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;@=x;bonus=x\"" - }, - { - "name": "x/x;@=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=@;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"@\\\";bonus=x\" but got \"x/x;x=@;bonus=x\"" - }, - { - "name": "x/x;x=@;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"@\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"@\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "[/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"[/x\"" - }, - { - "name": "[/x (Request/Response)", - "success": true - }, - { - "name": "x/[ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/[\"" - }, - { - "name": "x/[ (Request/Response)", - "success": true - }, - { - "name": "x/x;[=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;[=x;bonus=x\"" - }, - { - "name": "x/x;[=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=[;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"[\\\";bonus=x\" but got \"x/x;x=[;bonus=x\"" - }, - { - "name": "x/x;x=[;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"[\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"[\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "\\/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"\\\\/x\"" - }, - { - "name": "\\/x (Request/Response)", - "success": true - }, - { - "name": "x/\\ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/\\\\\"" - }, - { - "name": "x/\\ (Request/Response)", - "success": true - }, - { - "name": "x/x;\\=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;\\\\=x;bonus=x\"" - }, - { - "name": "x/x;\\=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "]/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"]/x\"" - }, - { - "name": "]/x (Request/Response)", - "success": true - }, - { - "name": "x/] (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/]\"" - }, - { - "name": "x/] (Request/Response)", - "success": true - }, - { - "name": "x/x;]=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;]=x;bonus=x\"" - }, - { - "name": "x/x;]=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=];bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"]\\\";bonus=x\" but got \"x/x;x=];bonus=x\"" - }, - { - "name": "x/x;x=];bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"]\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"]\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "{/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"{/x\"" - }, - { - "name": "{/x (Request/Response)", - "success": true - }, - { - "name": "x/{ (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/{\"" - }, - { - "name": "x/{ (Request/Response)", - "success": true - }, - { - "name": "x/x;{=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;{=x;bonus=x\"" - }, - { - "name": "x/x;{=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x={;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"{\\\";bonus=x\" but got \"x/x;x={;bonus=x\"" - }, - { - "name": "x/x;x={;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"{\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"{\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "}/x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"}/x\"" - }, - { - "name": "}/x (Request/Response)", - "success": true - }, - { - "name": "x/} (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"\" but got \"x/}\"" - }, - { - "name": "x/} (Request/Response)", - "success": true - }, - { - "name": "x/x;}=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"x/x;}=x;bonus=x\"" - }, - { - "name": "x/x;}=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=};bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"}\\\";bonus=x\" but got \"x/x;x=};bonus=x\"" - }, - { - "name": "x/x;x=};bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"}\";bonus=x (Blob/File)", - "success": true - }, - { - "name": "x/x;x=\"}\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": true - }, - { - "name": "€/x (Blob/File)", - "success": true - }, - { - "name": "€/x (Request/Response)", - "success": true - }, - { - "name": "x/€ (Blob/File)", - "success": true - }, - { - "name": "x/€ (Request/Response)", - "success": true - }, - { - "name": "x/x;€=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;€=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=€;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"€\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=€;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"€\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"€\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"€\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"€\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"€\\\";bonus=x\" but got \"\"" - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "‚/x (Blob/File)", - "success": true - }, - { - "name": "‚/x (Request/Response)", - "success": true - }, - { - "name": "x/‚ (Blob/File)", - "success": true - }, - { - "name": "x/‚ (Request/Response)", - "success": true - }, - { - "name": "x/x;‚=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;‚=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=‚;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‚\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=‚;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‚\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‚\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‚\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‚\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‚\\\";bonus=x\" but got \"\"" - }, - { - "name": "ƒ/x (Blob/File)", - "success": true - }, - { - "name": "ƒ/x (Request/Response)", - "success": true - }, - { - "name": "x/ƒ (Blob/File)", - "success": true - }, - { - "name": "x/ƒ (Request/Response)", - "success": true - }, - { - "name": "x/x;ƒ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ƒ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ƒ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ƒ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ƒ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ƒ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ƒ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ƒ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ƒ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ƒ\\\";bonus=x\" but got \"\"" - }, - { - "name": "„/x (Blob/File)", - "success": true - }, - { - "name": "„/x (Request/Response)", - "success": true - }, - { - "name": "x/„ (Blob/File)", - "success": true - }, - { - "name": "x/„ (Request/Response)", - "success": true - }, - { - "name": "x/x;„=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;„=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=„;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"„\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=„;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"„\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"„\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"„\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"„\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"„\\\";bonus=x\" but got \"\"" - }, - { - "name": "…/x (Blob/File)", - "success": true - }, - { - "name": "…/x (Request/Response)", - "success": true - }, - { - "name": "x/… (Blob/File)", - "success": true - }, - { - "name": "x/… (Request/Response)", - "success": true - }, - { - "name": "x/x;…=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;…=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=…;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"…\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=…;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"…\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"…\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"…\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"…\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"…\\\";bonus=x\" but got \"\"" - }, - { - "name": "†/x (Blob/File)", - "success": true - }, - { - "name": "†/x (Request/Response)", - "success": true - }, - { - "name": "x/† (Blob/File)", - "success": true - }, - { - "name": "x/† (Request/Response)", - "success": true - }, - { - "name": "x/x;†=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;†=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=†;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"†\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=†;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"†\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"†\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"†\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"†\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"†\\\";bonus=x\" but got \"\"" - }, - { - "name": "‡/x (Blob/File)", - "success": true - }, - { - "name": "‡/x (Request/Response)", - "success": true - }, - { - "name": "x/‡ (Blob/File)", - "success": true - }, - { - "name": "x/‡ (Request/Response)", - "success": true - }, - { - "name": "x/x;‡=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;‡=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=‡;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=‡;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‡\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‡\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‡\\\";bonus=x\" but got \"\"" - }, - { - "name": "ˆ/x (Blob/File)", - "success": true - }, - { - "name": "ˆ/x (Request/Response)", - "success": true - }, - { - "name": "x/ˆ (Blob/File)", - "success": true - }, - { - "name": "x/ˆ (Request/Response)", - "success": true - }, - { - "name": "x/x;ˆ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ˆ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ˆ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ˆ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ˆ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ˆ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ˆ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ˆ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ˆ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ˆ\\\";bonus=x\" but got \"\"" - }, - { - "name": "‰/x (Blob/File)", - "success": true - }, - { - "name": "‰/x (Request/Response)", - "success": true - }, - { - "name": "x/‰ (Blob/File)", - "success": true - }, - { - "name": "x/‰ (Request/Response)", - "success": true - }, - { - "name": "x/x;‰=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;‰=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=‰;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‰\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=‰;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‰\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‰\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‰\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‰\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‰\\\";bonus=x\" but got \"\"" - }, - { - "name": "Š/x (Blob/File)", - "success": true - }, - { - "name": "Š/x (Request/Response)", - "success": true - }, - { - "name": "x/Š (Blob/File)", - "success": true - }, - { - "name": "x/Š (Request/Response)", - "success": true - }, - { - "name": "x/x;Š=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Š=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Š;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Š;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Š\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Š\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Š\\\";bonus=x\" but got \"\"" - }, - { - "name": "‹/x (Blob/File)", - "success": true - }, - { - "name": "‹/x (Request/Response)", - "success": true - }, - { - "name": "x/‹ (Blob/File)", - "success": true - }, - { - "name": "x/‹ (Request/Response)", - "success": true - }, - { - "name": "x/x;‹=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;‹=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=‹;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=‹;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‹\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‹\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‹\\\";bonus=x\" but got \"\"" - }, - { - "name": "Œ/x (Blob/File)", - "success": true - }, - { - "name": "Œ/x (Request/Response)", - "success": true - }, - { - "name": "x/Œ (Blob/File)", - "success": true - }, - { - "name": "x/Œ (Request/Response)", - "success": true - }, - { - "name": "x/x;Œ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Œ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Œ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Œ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Œ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Œ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ž/x (Blob/File)", - "success": true - }, - { - "name": "Ž/x (Request/Response)", - "success": true - }, - { - "name": "x/Ž (Blob/File)", - "success": true - }, - { - "name": "x/Ž (Request/Response)", - "success": true - }, - { - "name": "x/x;Ž=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ž=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ž;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ž;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ž\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ž\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "‘/x (Blob/File)", - "success": true - }, - { - "name": "‘/x (Request/Response)", - "success": true - }, - { - "name": "x/‘ (Blob/File)", - "success": true - }, - { - "name": "x/‘ (Request/Response)", - "success": true - }, - { - "name": "x/x;‘=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;‘=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=‘;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‘\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=‘;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‘\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‘\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"‘\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"‘\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"‘\\\";bonus=x\" but got \"\"" - }, - { - "name": "’/x (Blob/File)", - "success": true - }, - { - "name": "’/x (Request/Response)", - "success": true - }, - { - "name": "x/’ (Blob/File)", - "success": true - }, - { - "name": "x/’ (Request/Response)", - "success": true - }, - { - "name": "x/x;’=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;’=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=’;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"’\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=’;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"’\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"’\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"’\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"’\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"’\\\";bonus=x\" but got \"\"" - }, - { - "name": "“/x (Blob/File)", - "success": true - }, - { - "name": "“/x (Request/Response)", - "success": true - }, - { - "name": "x/“ (Blob/File)", - "success": true - }, - { - "name": "x/“ (Request/Response)", - "success": true - }, - { - "name": "x/x;“=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;“=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=“;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"“\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=“;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"“\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"“\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"“\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"“\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"“\\\";bonus=x\" but got \"\"" - }, - { - "name": "”/x (Blob/File)", - "success": true - }, - { - "name": "”/x (Request/Response)", - "success": true - }, - { - "name": "x/” (Blob/File)", - "success": true - }, - { - "name": "x/” (Request/Response)", - "success": true - }, - { - "name": "x/x;”=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;”=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=”;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"”\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=”;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"”\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"”\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"”\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"”\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"”\\\";bonus=x\" but got \"\"" - }, - { - "name": "•/x (Blob/File)", - "success": true - }, - { - "name": "•/x (Request/Response)", - "success": true - }, - { - "name": "x/• (Blob/File)", - "success": true - }, - { - "name": "x/• (Request/Response)", - "success": true - }, - { - "name": "x/x;•=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;•=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=•;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"•\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=•;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"•\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"•\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"•\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"•\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"•\\\";bonus=x\" but got \"\"" - }, - { - "name": "–/x (Blob/File)", - "success": true - }, - { - "name": "–/x (Request/Response)", - "success": true - }, - { - "name": "x/– (Blob/File)", - "success": true - }, - { - "name": "x/– (Request/Response)", - "success": true - }, - { - "name": "x/x;–=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;–=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=–;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"–\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=–;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"–\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"–\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"–\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"–\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"–\\\";bonus=x\" but got \"\"" - }, - { - "name": "—/x (Blob/File)", - "success": true - }, - { - "name": "—/x (Request/Response)", - "success": true - }, - { - "name": "x/— (Blob/File)", - "success": true - }, - { - "name": "x/— (Request/Response)", - "success": true - }, - { - "name": "x/x;—=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;—=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=—;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"—\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=—;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"—\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"—\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"—\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"—\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"—\\\";bonus=x\" but got \"\"" - }, - { - "name": "˜/x (Blob/File)", - "success": true - }, - { - "name": "˜/x (Request/Response)", - "success": true - }, - { - "name": "x/˜ (Blob/File)", - "success": true - }, - { - "name": "x/˜ (Request/Response)", - "success": true - }, - { - "name": "x/x;˜=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;˜=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=˜;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"˜\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=˜;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"˜\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"˜\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"˜\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"˜\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"˜\\\";bonus=x\" but got \"\"" - }, - { - "name": "™/x (Blob/File)", - "success": true - }, - { - "name": "™/x (Request/Response)", - "success": true - }, - { - "name": "x/™ (Blob/File)", - "success": true - }, - { - "name": "x/™ (Request/Response)", - "success": true - }, - { - "name": "x/x;™=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;™=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=™;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"™\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=™;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"™\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"™\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"™\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"™\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"™\\\";bonus=x\" but got \"\"" - }, - { - "name": "š/x (Blob/File)", - "success": true - }, - { - "name": "š/x (Request/Response)", - "success": true - }, - { - "name": "x/š (Blob/File)", - "success": true - }, - { - "name": "x/š (Request/Response)", - "success": true - }, - { - "name": "x/x;š=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;š=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=š;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=š;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"š\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"š\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"š\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"š\\\";bonus=x\" but got \"\"" - }, - { - "name": "›/x (Blob/File)", - "success": true - }, - { - "name": "›/x (Request/Response)", - "success": true - }, - { - "name": "x/› (Blob/File)", - "success": true - }, - { - "name": "x/› (Request/Response)", - "success": true - }, - { - "name": "x/x;›=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;›=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=›;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"›\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=›;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"›\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"›\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"›\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"›\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"›\\\";bonus=x\" but got \"\"" - }, - { - "name": "œ/x (Blob/File)", - "success": true - }, - { - "name": "œ/x (Request/Response)", - "success": true - }, - { - "name": "x/œ (Blob/File)", - "success": true - }, - { - "name": "x/œ (Request/Response)", - "success": true - }, - { - "name": "x/x;œ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;œ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=œ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=œ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"œ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"œ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"œ\\\";bonus=x\" but got \"\"" - }, - { - "name": "/x (Blob/File)", - "success": true - }, - { - "name": "/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"\\\";bonus=x\" but got \"\"" - }, - { - "name": "ž/x (Blob/File)", - "success": true - }, - { - "name": "ž/x (Request/Response)", - "success": true - }, - { - "name": "x/ž (Blob/File)", - "success": true - }, - { - "name": "x/ž (Request/Response)", - "success": true - }, - { - "name": "x/x;ž=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ž=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ž;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ž;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ž\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ž\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ž\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ÿ/x (Blob/File)", - "success": true - }, - { - "name": "Ÿ/x (Request/Response)", - "success": true - }, - { - "name": "x/Ÿ (Blob/File)", - "success": true - }, - { - "name": "x/Ÿ (Request/Response)", - "success": true - }, - { - "name": "x/x;Ÿ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ÿ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ÿ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ÿ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ÿ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ÿ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ÿ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ÿ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ÿ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ÿ\\\";bonus=x\" but got \"\"" - }, - { - "name": " /x (Blob/File)", - "success": true - }, - { - "name": " /x (Request/Response)", - "success": true - }, - { - "name": "x/  (Blob/File)", - "success": true - }, - { - "name": "x/  (Request/Response)", - "success": true - }, - { - "name": "x/x; =x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x; =x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x= ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\" \\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x= ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\" \\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\" \";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\" \\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\" \";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\" \\\";bonus=x\" but got \"\"" - }, - { - "name": "¡/x (Blob/File)", - "success": true - }, - { - "name": "¡/x (Request/Response)", - "success": true - }, - { - "name": "x/¡ (Blob/File)", - "success": true - }, - { - "name": "x/¡ (Request/Response)", - "success": true - }, - { - "name": "x/x;¡=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¡=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¡;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¡;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¡\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¡\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¡\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¡\\\";bonus=x\" but got \"\"" - }, - { - "name": "¢/x (Blob/File)", - "success": true - }, - { - "name": "¢/x (Request/Response)", - "success": true - }, - { - "name": "x/¢ (Blob/File)", - "success": true - }, - { - "name": "x/¢ (Request/Response)", - "success": true - }, - { - "name": "x/x;¢=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¢=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¢;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¢\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¢;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¢\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¢\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¢\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¢\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¢\\\";bonus=x\" but got \"\"" - }, - { - "name": "£/x (Blob/File)", - "success": true - }, - { - "name": "£/x (Request/Response)", - "success": true - }, - { - "name": "x/£ (Blob/File)", - "success": true - }, - { - "name": "x/£ (Request/Response)", - "success": true - }, - { - "name": "x/x;£=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;£=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=£;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"£\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=£;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"£\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"£\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"£\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"£\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"£\\\";bonus=x\" but got \"\"" - }, - { - "name": "¤/x (Blob/File)", - "success": true - }, - { - "name": "¤/x (Request/Response)", - "success": true - }, - { - "name": "x/¤ (Blob/File)", - "success": true - }, - { - "name": "x/¤ (Request/Response)", - "success": true - }, - { - "name": "x/x;¤=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¤=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¤;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¤\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¤;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¤\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¤\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¤\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¤\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¤\\\";bonus=x\" but got \"\"" - }, - { - "name": "¥/x (Blob/File)", - "success": true - }, - { - "name": "¥/x (Request/Response)", - "success": true - }, - { - "name": "x/¥ (Blob/File)", - "success": true - }, - { - "name": "x/¥ (Request/Response)", - "success": true - }, - { - "name": "x/x;¥=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¥=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¥;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¥\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¥;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¥\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¥\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¥\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¥\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¥\\\";bonus=x\" but got \"\"" - }, - { - "name": "¦/x (Blob/File)", - "success": true - }, - { - "name": "¦/x (Request/Response)", - "success": true - }, - { - "name": "x/¦ (Blob/File)", - "success": true - }, - { - "name": "x/¦ (Request/Response)", - "success": true - }, - { - "name": "x/x;¦=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¦=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¦;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¦\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¦;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¦\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¦\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¦\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¦\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¦\\\";bonus=x\" but got \"\"" - }, - { - "name": "§/x (Blob/File)", - "success": true - }, - { - "name": "§/x (Request/Response)", - "success": true - }, - { - "name": "x/§ (Blob/File)", - "success": true - }, - { - "name": "x/§ (Request/Response)", - "success": true - }, - { - "name": "x/x;§=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;§=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=§;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"§\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=§;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"§\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"§\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"§\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"§\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"§\\\";bonus=x\" but got \"\"" - }, - { - "name": "¨/x (Blob/File)", - "success": true - }, - { - "name": "¨/x (Request/Response)", - "success": true - }, - { - "name": "x/¨ (Blob/File)", - "success": true - }, - { - "name": "x/¨ (Request/Response)", - "success": true - }, - { - "name": "x/x;¨=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¨=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¨;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¨\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¨;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¨\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¨\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¨\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¨\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¨\\\";bonus=x\" but got \"\"" - }, - { - "name": "©/x (Blob/File)", - "success": true - }, - { - "name": "©/x (Request/Response)", - "success": true - }, - { - "name": "x/© (Blob/File)", - "success": true - }, - { - "name": "x/© (Request/Response)", - "success": true - }, - { - "name": "x/x;©=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;©=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=©;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"©\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=©;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"©\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"©\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"©\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"©\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"©\\\";bonus=x\" but got \"\"" - }, - { - "name": "ª/x (Blob/File)", - "success": true - }, - { - "name": "ª/x (Request/Response)", - "success": true - }, - { - "name": "x/ª (Blob/File)", - "success": true - }, - { - "name": "x/ª (Request/Response)", - "success": true - }, - { - "name": "x/x;ª=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ª=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ª;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ª\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ª;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ª\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ª\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ª\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ª\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ª\\\";bonus=x\" but got \"\"" - }, - { - "name": "«/x (Blob/File)", - "success": true - }, - { - "name": "«/x (Request/Response)", - "success": true - }, - { - "name": "x/« (Blob/File)", - "success": true - }, - { - "name": "x/« (Request/Response)", - "success": true - }, - { - "name": "x/x;«=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;«=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=«;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"«\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=«;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"«\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"«\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"«\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"«\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"«\\\";bonus=x\" but got \"\"" - }, - { - "name": "¬/x (Blob/File)", - "success": true - }, - { - "name": "¬/x (Request/Response)", - "success": true - }, - { - "name": "x/¬ (Blob/File)", - "success": true - }, - { - "name": "x/¬ (Request/Response)", - "success": true - }, - { - "name": "x/x;¬=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¬=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¬;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¬\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¬;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¬\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¬\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¬\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¬\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¬\\\";bonus=x\" but got \"\"" - }, - { - "name": "­/x (Blob/File)", - "success": true - }, - { - "name": "­/x (Request/Response)", - "success": true - }, - { - "name": "x/­ (Blob/File)", - "success": true - }, - { - "name": "x/­ (Request/Response)", - "success": true - }, - { - "name": "x/x;­=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;­=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=­;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"­\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=­;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"­\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"­\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"­\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"­\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"­\\\";bonus=x\" but got \"\"" - }, - { - "name": "®/x (Blob/File)", - "success": true - }, - { - "name": "®/x (Request/Response)", - "success": true - }, - { - "name": "x/® (Blob/File)", - "success": true - }, - { - "name": "x/® (Request/Response)", - "success": true - }, - { - "name": "x/x;®=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;®=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=®;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"®\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=®;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"®\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"®\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"®\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"®\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"®\\\";bonus=x\" but got \"\"" - }, - { - "name": "¯/x (Blob/File)", - "success": true - }, - { - "name": "¯/x (Request/Response)", - "success": true - }, - { - "name": "x/¯ (Blob/File)", - "success": true - }, - { - "name": "x/¯ (Request/Response)", - "success": true - }, - { - "name": "x/x;¯=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¯=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¯;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¯\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¯;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¯\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¯\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¯\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¯\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¯\\\";bonus=x\" but got \"\"" - }, - { - "name": "°/x (Blob/File)", - "success": true - }, - { - "name": "°/x (Request/Response)", - "success": true - }, - { - "name": "x/° (Blob/File)", - "success": true - }, - { - "name": "x/° (Request/Response)", - "success": true - }, - { - "name": "x/x;°=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;°=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=°;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"°\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=°;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"°\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"°\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"°\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"°\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"°\\\";bonus=x\" but got \"\"" - }, - { - "name": "±/x (Blob/File)", - "success": true - }, - { - "name": "±/x (Request/Response)", - "success": true - }, - { - "name": "x/± (Blob/File)", - "success": true - }, - { - "name": "x/± (Request/Response)", - "success": true - }, - { - "name": "x/x;±=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;±=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=±;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"±\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=±;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"±\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"±\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"±\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"±\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"±\\\";bonus=x\" but got \"\"" - }, - { - "name": "²/x (Blob/File)", - "success": true - }, - { - "name": "²/x (Request/Response)", - "success": true - }, - { - "name": "x/² (Blob/File)", - "success": true - }, - { - "name": "x/² (Request/Response)", - "success": true - }, - { - "name": "x/x;²=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;²=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=²;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"²\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=²;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"²\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"²\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"²\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"²\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"²\\\";bonus=x\" but got \"\"" - }, - { - "name": "³/x (Blob/File)", - "success": true - }, - { - "name": "³/x (Request/Response)", - "success": true - }, - { - "name": "x/³ (Blob/File)", - "success": true - }, - { - "name": "x/³ (Request/Response)", - "success": true - }, - { - "name": "x/x;³=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;³=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=³;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"³\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=³;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"³\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"³\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"³\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"³\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"³\\\";bonus=x\" but got \"\"" - }, - { - "name": "´/x (Blob/File)", - "success": true - }, - { - "name": "´/x (Request/Response)", - "success": true - }, - { - "name": "x/´ (Blob/File)", - "success": true - }, - { - "name": "x/´ (Request/Response)", - "success": true - }, - { - "name": "x/x;´=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;´=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=´;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"´\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=´;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"´\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"´\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"´\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"´\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"´\\\";bonus=x\" but got \"\"" - }, - { - "name": "µ/x (Blob/File)", - "success": true - }, - { - "name": "µ/x (Request/Response)", - "success": true - }, - { - "name": "x/µ (Blob/File)", - "success": true - }, - { - "name": "x/µ (Request/Response)", - "success": true - }, - { - "name": "x/x;µ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;µ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=µ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"µ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=µ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"µ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"µ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"µ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"µ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"µ\\\";bonus=x\" but got \"\"" - }, - { - "name": "¶/x (Blob/File)", - "success": true - }, - { - "name": "¶/x (Request/Response)", - "success": true - }, - { - "name": "x/¶ (Blob/File)", - "success": true - }, - { - "name": "x/¶ (Request/Response)", - "success": true - }, - { - "name": "x/x;¶=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¶=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¶;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¶\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¶;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¶\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¶\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¶\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¶\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¶\\\";bonus=x\" but got \"\"" - }, - { - "name": "·/x (Blob/File)", - "success": true - }, - { - "name": "·/x (Request/Response)", - "success": true - }, - { - "name": "x/· (Blob/File)", - "success": true - }, - { - "name": "x/· (Request/Response)", - "success": true - }, - { - "name": "x/x;·=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;·=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=·;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"·\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=·;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"·\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"·\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"·\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"·\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"·\\\";bonus=x\" but got \"\"" - }, - { - "name": "¸/x (Blob/File)", - "success": true - }, - { - "name": "¸/x (Request/Response)", - "success": true - }, - { - "name": "x/¸ (Blob/File)", - "success": true - }, - { - "name": "x/¸ (Request/Response)", - "success": true - }, - { - "name": "x/x;¸=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¸=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¸;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¸\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¸;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¸\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¸\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¸\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¸\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¸\\\";bonus=x\" but got \"\"" - }, - { - "name": "¹/x (Blob/File)", - "success": true - }, - { - "name": "¹/x (Request/Response)", - "success": true - }, - { - "name": "x/¹ (Blob/File)", - "success": true - }, - { - "name": "x/¹ (Request/Response)", - "success": true - }, - { - "name": "x/x;¹=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¹=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¹;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¹;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¹\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¹\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¹\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¹\\\";bonus=x\" but got \"\"" - }, - { - "name": "º/x (Blob/File)", - "success": true - }, - { - "name": "º/x (Request/Response)", - "success": true - }, - { - "name": "x/º (Blob/File)", - "success": true - }, - { - "name": "x/º (Request/Response)", - "success": true - }, - { - "name": "x/x;º=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;º=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=º;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"º\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=º;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"º\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"º\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"º\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"º\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"º\\\";bonus=x\" but got \"\"" - }, - { - "name": "»/x (Blob/File)", - "success": true - }, - { - "name": "»/x (Request/Response)", - "success": true - }, - { - "name": "x/» (Blob/File)", - "success": true - }, - { - "name": "x/» (Request/Response)", - "success": true - }, - { - "name": "x/x;»=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;»=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=»;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"»\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=»;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"»\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"»\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"»\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"»\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"»\\\";bonus=x\" but got \"\"" - }, - { - "name": "¼/x (Blob/File)", - "success": true - }, - { - "name": "¼/x (Request/Response)", - "success": true - }, - { - "name": "x/¼ (Blob/File)", - "success": true - }, - { - "name": "x/¼ (Request/Response)", - "success": true - }, - { - "name": "x/x;¼=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¼=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¼;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¼\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¼;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¼\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¼\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¼\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¼\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¼\\\";bonus=x\" but got \"\"" - }, - { - "name": "½/x (Blob/File)", - "success": true - }, - { - "name": "½/x (Request/Response)", - "success": true - }, - { - "name": "x/½ (Blob/File)", - "success": true - }, - { - "name": "x/½ (Request/Response)", - "success": true - }, - { - "name": "x/x;½=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;½=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=½;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"½\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=½;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"½\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"½\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"½\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"½\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"½\\\";bonus=x\" but got \"\"" - }, - { - "name": "¾/x (Blob/File)", - "success": true - }, - { - "name": "¾/x (Request/Response)", - "success": true - }, - { - "name": "x/¾ (Blob/File)", - "success": true - }, - { - "name": "x/¾ (Request/Response)", - "success": true - }, - { - "name": "x/x;¾=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¾=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¾;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¾\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¾;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¾\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¾\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¾\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¾\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¾\\\";bonus=x\" but got \"\"" - }, - { - "name": "¿/x (Blob/File)", - "success": true - }, - { - "name": "¿/x (Request/Response)", - "success": true - }, - { - "name": "x/¿ (Blob/File)", - "success": true - }, - { - "name": "x/¿ (Request/Response)", - "success": true - }, - { - "name": "x/x;¿=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;¿=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=¿;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¿\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=¿;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¿\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¿\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"¿\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"¿\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"¿\\\";bonus=x\" but got \"\"" - }, - { - "name": "À/x (Blob/File)", - "success": true - }, - { - "name": "À/x (Request/Response)", - "success": true - }, - { - "name": "x/À (Blob/File)", - "success": true - }, - { - "name": "x/À (Request/Response)", - "success": true - }, - { - "name": "x/x;À=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;À=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=À;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"À\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=À;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"À\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"À\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"À\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"À\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"À\\\";bonus=x\" but got \"\"" - }, - { - "name": "Á/x (Blob/File)", - "success": true - }, - { - "name": "Á/x (Request/Response)", - "success": true - }, - { - "name": "x/Á (Blob/File)", - "success": true - }, - { - "name": "x/Á (Request/Response)", - "success": true - }, - { - "name": "x/x;Á=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Á=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Á;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Á;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Á\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Á\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Á\\\";bonus=x\" but got \"\"" - }, - { - "name": "Â/x (Blob/File)", - "success": true - }, - { - "name": "Â/x (Request/Response)", - "success": true - }, - { - "name": "x/ (Blob/File)", - "success": true - }, - { - "name": "x/ (Request/Response)", - "success": true - }, - { - "name": "x/x;Â=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Â=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Â;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Â;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Â\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Â\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Â\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ã/x (Blob/File)", - "success": true - }, - { - "name": "Ã/x (Request/Response)", - "success": true - }, - { - "name": "x/à (Blob/File)", - "success": true - }, - { - "name": "x/à (Request/Response)", - "success": true - }, - { - "name": "x/x;Ã=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ã=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ã;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ã;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ã\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ã\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ä/x (Blob/File)", - "success": true - }, - { - "name": "Ä/x (Request/Response)", - "success": true - }, - { - "name": "x/Ä (Blob/File)", - "success": true - }, - { - "name": "x/Ä (Request/Response)", - "success": true - }, - { - "name": "x/x;Ä=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ä=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ä;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ä;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ä\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ä\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "Å/x (Blob/File)", - "success": true - }, - { - "name": "Å/x (Request/Response)", - "success": true - }, - { - "name": "x/Å (Blob/File)", - "success": true - }, - { - "name": "x/Å (Request/Response)", - "success": true - }, - { - "name": "x/x;Å=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Å=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Å;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Å;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Å\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Å\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Å\\\";bonus=x\" but got \"\"" - }, - { - "name": "Æ/x (Blob/File)", - "success": true - }, - { - "name": "Æ/x (Request/Response)", - "success": true - }, - { - "name": "x/Æ (Blob/File)", - "success": true - }, - { - "name": "x/Æ (Request/Response)", - "success": true - }, - { - "name": "x/x;Æ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Æ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Æ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Æ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Æ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Æ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ç/x (Blob/File)", - "success": true - }, - { - "name": "Ç/x (Request/Response)", - "success": true - }, - { - "name": "x/Ç (Blob/File)", - "success": true - }, - { - "name": "x/Ç (Request/Response)", - "success": true - }, - { - "name": "x/x;Ç=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ç=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ç;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ç;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ç\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ç\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "È/x (Blob/File)", - "success": true - }, - { - "name": "È/x (Request/Response)", - "success": true - }, - { - "name": "x/È (Blob/File)", - "success": true - }, - { - "name": "x/È (Request/Response)", - "success": true - }, - { - "name": "x/x;È=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;È=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=È;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"È\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=È;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"È\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"È\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"È\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"È\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"È\\\";bonus=x\" but got \"\"" - }, - { - "name": "É/x (Blob/File)", - "success": true - }, - { - "name": "É/x (Request/Response)", - "success": true - }, - { - "name": "x/É (Blob/File)", - "success": true - }, - { - "name": "x/É (Request/Response)", - "success": true - }, - { - "name": "x/x;É=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;É=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=É;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"É\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=É;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"É\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"É\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"É\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"É\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"É\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ê/x (Blob/File)", - "success": true - }, - { - "name": "Ê/x (Request/Response)", - "success": true - }, - { - "name": "x/Ê (Blob/File)", - "success": true - }, - { - "name": "x/Ê (Request/Response)", - "success": true - }, - { - "name": "x/x;Ê=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ê=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ê;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ê;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ê\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ê\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ë/x (Blob/File)", - "success": true - }, - { - "name": "Ë/x (Request/Response)", - "success": true - }, - { - "name": "x/Ë (Blob/File)", - "success": true - }, - { - "name": "x/Ë (Request/Response)", - "success": true - }, - { - "name": "x/x;Ë=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ë=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ë;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ë;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ë\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ë\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ì/x (Blob/File)", - "success": true - }, - { - "name": "Ì/x (Request/Response)", - "success": true - }, - { - "name": "x/Ì (Blob/File)", - "success": true - }, - { - "name": "x/Ì (Request/Response)", - "success": true - }, - { - "name": "x/x;Ì=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ì=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ì;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ì;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ì\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ì\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "Í/x (Blob/File)", - "success": true - }, - { - "name": "Í/x (Request/Response)", - "success": true - }, - { - "name": "x/Í (Blob/File)", - "success": true - }, - { - "name": "x/Í (Request/Response)", - "success": true - }, - { - "name": "x/x;Í=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Í=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Í;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Í;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Í\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Í\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Í\\\";bonus=x\" but got \"\"" - }, - { - "name": "Î/x (Blob/File)", - "success": true - }, - { - "name": "Î/x (Request/Response)", - "success": true - }, - { - "name": "x/Î (Blob/File)", - "success": true - }, - { - "name": "x/Î (Request/Response)", - "success": true - }, - { - "name": "x/x;Î=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Î=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Î;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Î\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Î;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Î\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Î\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Î\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Î\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Î\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ï/x (Blob/File)", - "success": true - }, - { - "name": "Ï/x (Request/Response)", - "success": true - }, - { - "name": "x/Ï (Blob/File)", - "success": true - }, - { - "name": "x/Ï (Request/Response)", - "success": true - }, - { - "name": "x/x;Ï=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ï=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ï;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ï\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ï;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ï\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ï\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ï\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ï\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ï\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ð/x (Blob/File)", - "success": true - }, - { - "name": "Ð/x (Request/Response)", - "success": true - }, - { - "name": "x/Ð (Blob/File)", - "success": true - }, - { - "name": "x/Ð (Request/Response)", - "success": true - }, - { - "name": "x/x;Ð=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ð=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ð;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ð\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ð;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ð\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ð\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ð\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ð\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ð\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ñ/x (Blob/File)", - "success": true - }, - { - "name": "Ñ/x (Request/Response)", - "success": true - }, - { - "name": "x/Ñ (Blob/File)", - "success": true - }, - { - "name": "x/Ñ (Request/Response)", - "success": true - }, - { - "name": "x/x;Ñ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ñ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ñ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ñ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ñ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ñ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ñ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ñ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ñ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ñ\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ò/x (Blob/File)", - "success": true - }, - { - "name": "Ò/x (Request/Response)", - "success": true - }, - { - "name": "x/Ò (Blob/File)", - "success": true - }, - { - "name": "x/Ò (Request/Response)", - "success": true - }, - { - "name": "x/x;Ò=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ò=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ò;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ò\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ò;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ò\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ò\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ò\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ò\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ò\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ó/x (Blob/File)", - "success": true - }, - { - "name": "Ó/x (Request/Response)", - "success": true - }, - { - "name": "x/Ó (Blob/File)", - "success": true - }, - { - "name": "x/Ó (Request/Response)", - "success": true - }, - { - "name": "x/x;Ó=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ó=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ó;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ó\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ó;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ó\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ó\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ó\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ó\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ó\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ô/x (Blob/File)", - "success": true - }, - { - "name": "Ô/x (Request/Response)", - "success": true - }, - { - "name": "x/Ô (Blob/File)", - "success": true - }, - { - "name": "x/Ô (Request/Response)", - "success": true - }, - { - "name": "x/x;Ô=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ô=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ô;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ô\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ô;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ô\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ô\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ô\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ô\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ô\\\";bonus=x\" but got \"\"" - }, - { - "name": "Õ/x (Blob/File)", - "success": true - }, - { - "name": "Õ/x (Request/Response)", - "success": true - }, - { - "name": "x/Õ (Blob/File)", - "success": true - }, - { - "name": "x/Õ (Request/Response)", - "success": true - }, - { - "name": "x/x;Õ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Õ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Õ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Õ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Õ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Õ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Õ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Õ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Õ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Õ\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ö/x (Blob/File)", - "success": true - }, - { - "name": "Ö/x (Request/Response)", - "success": true - }, - { - "name": "x/Ö (Blob/File)", - "success": true - }, - { - "name": "x/Ö (Request/Response)", - "success": true - }, - { - "name": "x/x;Ö=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ö=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ö;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ö\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ö;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ö\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ö\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ö\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ö\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ö\\\";bonus=x\" but got \"\"" - }, - { - "name": "×/x (Blob/File)", - "success": true - }, - { - "name": "×/x (Request/Response)", - "success": true - }, - { - "name": "x/× (Blob/File)", - "success": true - }, - { - "name": "x/× (Request/Response)", - "success": true - }, - { - "name": "x/x;×=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;×=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=×;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"×\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=×;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"×\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"×\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"×\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"×\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"×\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ø/x (Blob/File)", - "success": true - }, - { - "name": "Ø/x (Request/Response)", - "success": true - }, - { - "name": "x/Ø (Blob/File)", - "success": true - }, - { - "name": "x/Ø (Request/Response)", - "success": true - }, - { - "name": "x/x;Ø=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ø=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ø;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ø\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ø;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ø\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ø\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ø\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ø\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ø\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ù/x (Blob/File)", - "success": true - }, - { - "name": "Ù/x (Request/Response)", - "success": true - }, - { - "name": "x/Ù (Blob/File)", - "success": true - }, - { - "name": "x/Ù (Request/Response)", - "success": true - }, - { - "name": "x/x;Ù=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ù=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ù;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ù\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ù;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ù\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ù\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ù\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ù\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ù\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ú/x (Blob/File)", - "success": true - }, - { - "name": "Ú/x (Request/Response)", - "success": true - }, - { - "name": "x/Ú (Blob/File)", - "success": true - }, - { - "name": "x/Ú (Request/Response)", - "success": true - }, - { - "name": "x/x;Ú=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ú=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ú;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ú\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ú;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ú\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ú\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ú\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ú\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ú\\\";bonus=x\" but got \"\"" - }, - { - "name": "Û/x (Blob/File)", - "success": true - }, - { - "name": "Û/x (Request/Response)", - "success": true - }, - { - "name": "x/Û (Blob/File)", - "success": true - }, - { - "name": "x/Û (Request/Response)", - "success": true - }, - { - "name": "x/x;Û=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Û=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Û;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Û\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Û;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Û\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Û\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Û\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Û\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Û\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ü/x (Blob/File)", - "success": true - }, - { - "name": "Ü/x (Request/Response)", - "success": true - }, - { - "name": "x/Ü (Blob/File)", - "success": true - }, - { - "name": "x/Ü (Request/Response)", - "success": true - }, - { - "name": "x/x;Ü=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ü=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ü;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ü\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ü;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ü\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ü\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ü\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ü\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ü\\\";bonus=x\" but got \"\"" - }, - { - "name": "Ý/x (Blob/File)", - "success": true - }, - { - "name": "Ý/x (Request/Response)", - "success": true - }, - { - "name": "x/Ý (Blob/File)", - "success": true - }, - { - "name": "x/Ý (Request/Response)", - "success": true - }, - { - "name": "x/x;Ý=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Ý=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Ý;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ý\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Ý;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ý\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ý\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Ý\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Ý\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Ý\\\";bonus=x\" but got \"\"" - }, - { - "name": "Þ/x (Blob/File)", - "success": true - }, - { - "name": "Þ/x (Request/Response)", - "success": true - }, - { - "name": "x/Þ (Blob/File)", - "success": true - }, - { - "name": "x/Þ (Request/Response)", - "success": true - }, - { - "name": "x/x;Þ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;Þ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=Þ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Þ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=Þ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Þ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Þ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"Þ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"Þ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"Þ\\\";bonus=x\" but got \"\"" - }, - { - "name": "ß/x (Blob/File)", - "success": true - }, - { - "name": "ß/x (Request/Response)", - "success": true - }, - { - "name": "x/ß (Blob/File)", - "success": true - }, - { - "name": "x/ß (Request/Response)", - "success": true - }, - { - "name": "x/x;ß=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ß=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ß;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ß\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ß;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ß\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ß\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ß\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ß\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ß\\\";bonus=x\" but got \"\"" - }, - { - "name": "à/x (Blob/File)", - "success": true - }, - { - "name": "à/x (Request/Response)", - "success": true - }, - { - "name": "x/à (Blob/File)", - "success": true - }, - { - "name": "x/à (Request/Response)", - "success": true - }, - { - "name": "x/x;à=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;à=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=à;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"à\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=à;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"à\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"à\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"à\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"à\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"à\\\";bonus=x\" but got \"\"" - }, - { - "name": "á/x (Blob/File)", - "success": true - }, - { - "name": "á/x (Request/Response)", - "success": true - }, - { - "name": "x/á (Blob/File)", - "success": true - }, - { - "name": "x/á (Request/Response)", - "success": true - }, - { - "name": "x/x;á=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;á=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=á;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=á;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"á\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"á\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"á\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"á\\\";bonus=x\" but got \"\"" - }, - { - "name": "â/x (Blob/File)", - "success": true - }, - { - "name": "â/x (Request/Response)", - "success": true - }, - { - "name": "x/â (Blob/File)", - "success": true - }, - { - "name": "x/â (Request/Response)", - "success": true - }, - { - "name": "x/x;â=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;â=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=â;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=â;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"â\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"â\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"â\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"â\\\";bonus=x\" but got \"\"" - }, - { - "name": "ã/x (Blob/File)", - "success": true - }, - { - "name": "ã/x (Request/Response)", - "success": true - }, - { - "name": "x/ã (Blob/File)", - "success": true - }, - { - "name": "x/ã (Request/Response)", - "success": true - }, - { - "name": "x/x;ã=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ã=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ã;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ã;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ã\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ã\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ã\\\";bonus=x\" but got \"\"" - }, - { - "name": "ä/x (Blob/File)", - "success": true - }, - { - "name": "ä/x (Request/Response)", - "success": true - }, - { - "name": "x/ä (Blob/File)", - "success": true - }, - { - "name": "x/ä (Request/Response)", - "success": true - }, - { - "name": "x/x;ä=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ä=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ä;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ä;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ä\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ä\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ä\\\";bonus=x\" but got \"\"" - }, - { - "name": "å/x (Blob/File)", - "success": true - }, - { - "name": "å/x (Request/Response)", - "success": true - }, - { - "name": "x/å (Blob/File)", - "success": true - }, - { - "name": "x/å (Request/Response)", - "success": true - }, - { - "name": "x/x;å=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;å=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=å;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=å;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"å\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"å\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"å\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"å\\\";bonus=x\" but got \"\"" - }, - { - "name": "æ/x (Blob/File)", - "success": true - }, - { - "name": "æ/x (Request/Response)", - "success": true - }, - { - "name": "x/æ (Blob/File)", - "success": true - }, - { - "name": "x/æ (Request/Response)", - "success": true - }, - { - "name": "x/x;æ=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;æ=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=æ;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=æ;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"æ\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"æ\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"æ\\\";bonus=x\" but got \"\"" - }, - { - "name": "ç/x (Blob/File)", - "success": true - }, - { - "name": "ç/x (Request/Response)", - "success": true - }, - { - "name": "x/ç (Blob/File)", - "success": true - }, - { - "name": "x/ç (Request/Response)", - "success": true - }, - { - "name": "x/x;ç=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ç=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ç;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ç;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ç\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ç\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ç\\\";bonus=x\" but got \"\"" - }, - { - "name": "è/x (Blob/File)", - "success": true - }, - { - "name": "è/x (Request/Response)", - "success": true - }, - { - "name": "x/è (Blob/File)", - "success": true - }, - { - "name": "x/è (Request/Response)", - "success": true - }, - { - "name": "x/x;è=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;è=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=è;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"è\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=è;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"è\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"è\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"è\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"è\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"è\\\";bonus=x\" but got \"\"" - }, - { - "name": "é/x (Blob/File)", - "success": true - }, - { - "name": "é/x (Request/Response)", - "success": true - }, - { - "name": "x/é (Blob/File)", - "success": true - }, - { - "name": "x/é (Request/Response)", - "success": true - }, - { - "name": "x/x;é=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;é=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=é;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"é\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=é;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"é\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"é\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"é\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"é\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"é\\\";bonus=x\" but got \"\"" - }, - { - "name": "ê/x (Blob/File)", - "success": true - }, - { - "name": "ê/x (Request/Response)", - "success": true - }, - { - "name": "x/ê (Blob/File)", - "success": true - }, - { - "name": "x/ê (Request/Response)", - "success": true - }, - { - "name": "x/x;ê=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ê=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ê;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ê;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ê\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ê\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ê\\\";bonus=x\" but got \"\"" - }, - { - "name": "ë/x (Blob/File)", - "success": true - }, - { - "name": "ë/x (Request/Response)", - "success": true - }, - { - "name": "x/ë (Blob/File)", - "success": true - }, - { - "name": "x/ë (Request/Response)", - "success": true - }, - { - "name": "x/x;ë=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ë=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ë;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ë;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ë\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ë\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ë\\\";bonus=x\" but got \"\"" - }, - { - "name": "ì/x (Blob/File)", - "success": true - }, - { - "name": "ì/x (Request/Response)", - "success": true - }, - { - "name": "x/ì (Blob/File)", - "success": true - }, - { - "name": "x/ì (Request/Response)", - "success": true - }, - { - "name": "x/x;ì=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ì=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=ì;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=ì;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ì\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"ì\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ì\\\";bonus=x\" but got \"\"" - }, - { - "name": "í/x (Blob/File)", - "success": true - }, - { - "name": "í/x (Request/Response)", - "success": true - }, - { - "name": "x/í (Blob/File)", - "success": true - }, - { - "name": "x/í (Request/Response)", - "success": true - }, - { - "name": "x/x;í=x;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;í=x;bonus=x (Request/Response)", - "success": true - }, - { - "name": "x/x;x=í;bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=í;bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"í\";bonus=x (Blob/File)", - "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"í\\\";bonus=x\" but got \"\"" - }, - { - "name": "x/x;x=\"í\";bonus=x (Request/Response)", - "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"í\\\";bonus=x\" but got \"\"" - }, - { - "name": "î/x (Blob/File)", - "success": true - }, - { - "name": "î/x (Request/Response)", - "success": true - }, - { - "name": "x/î (Blob/File)", - "success": true - }, - { - "name": "x/î (Request/Response)", - "success": true - }, + }, + "embedded-credentials.tentative.sub.html": { + "success": true, + "cases": [ { - "name": "x/x;î=x;bonus=x (Blob/File)", + "name": "Embedded credentials are treated as network errors.", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;î=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=î;bonus=x (Blob/File)", + "name": "Embedded credentials are treated as network errors in frames.", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"î\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=î;bonus=x (Request/Response)", + "name": "Embedded credentials are treated as network errors in new windows.", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"î\\\";bonus=x\" but got \"\"" + "message": "window.open is not a function" }, { - "name": "x/x;x=\"î\";bonus=x (Blob/File)", + "name": "Embedded credentials matching the top-level are not treated as network errors for relative URLs.", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"î\\\";bonus=x\" but got \"\"" + "message": "window.open is not a function" }, { - "name": "x/x;x=\"î\";bonus=x (Request/Response)", + "name": "Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"î\\\";bonus=x\" but got \"\"" - }, - { - "name": "ï/x (Blob/File)", - "success": true + "message": "window.open is not a function" }, { - "name": "ï/x (Request/Response)", - "success": true - }, + "name": "Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.", + "success": false, + "message": "window.open is not a function" + } + ] + }, + "redirect-to-url-with-credentials.https.html": { + "success": true, + "cases": [ { - "name": "x/ï (Blob/File)", + "name": "No CORS fetch after a redirect with an URL containing credentials", "success": true }, { - "name": "x/ï (Request/Response)", + "name": "CORS fetch after a redirect with a cross origin URL containing credentials", "success": true }, { - "name": "x/x;ï=x;bonus=x (Blob/File)", + "name": "CORS fetch after a redirect with a same origin URL containing credentials", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ï=x;bonus=x (Request/Response)", - "success": true + "message": "promise_test: Unhandled rejection with value: object \"TypeError: fetch failed\"" }, { - "name": "x/x;x=ï;bonus=x (Blob/File)", + "name": "Image loading after a redirect with an URL containing credentials", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ï\\\";bonus=x\" but got \"\"" + "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" }, { - "name": "x/x;x=ï;bonus=x (Request/Response)", + "name": "CORS Image loading after a redirect with a cross origin URL containing credentials", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ï\\\";bonus=x\" but got \"\"" + "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" }, { - "name": "x/x;x=\"ï\";bonus=x (Blob/File)", + "name": "CORS Image loading after a redirect with a same origin URL containing credentials", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ï\\\";bonus=x\" but got \"\"" + "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: Image is not defined\"" }, { - "name": "x/x;x=\"ï\";bonus=x (Request/Response)", + "name": "Frame loading after a redirect with an URL containing credentials", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ï\\\";bonus=x\" but got \"\"" - }, - { - "name": "ð/x (Blob/File)", - "success": true - }, - { - "name": "ð/x (Request/Response)", - "success": true - }, - { - "name": "x/ð (Blob/File)", - "success": true - }, - { - "name": "x/ð (Request/Response)", - "success": true - }, + "message": "promise_test: Unhandled rejection with value: object \"ReferenceError: document is not defined\"" + } + ] + } + }, + "stale-while-revalidate": { + "fetch-sw.https.html": { + "success": true, + "cases": [ { - "name": "x/x;ð=x;bonus=x (Blob/File)", + "name": "Second fetch returns same response", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ð=x;bonus=x (Request/Response)", - "success": true - }, + "message": "promise_test: Unhandled rejection with value: object \"TypeError: Cannot read properties of undefined (reading 'register')\"" + } + ] + }, + "fetch.any.html": { + "success": true, + "cases": [ { - "name": "x/x;x=ð;bonus=x (Blob/File)", + "name": "Second fetch returns same response", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ð\\\";bonus=x\" but got \"\"" - }, + "message": "assert_equals: expected \"lwbefdpkiqfhgejhzspj\" but got \"sueymolkqyvlbejzamwn\"" + } + ] + }, + "revalidate-not-blocked-by-csp.html": { + "success": false, + "cases": [] + }, + "stale-css.html": { + "success": false, + "cases": [] + }, + "stale-image.html": { + "success": false, + "cases": [] + }, + "stale-script.html": { + "success": false, + "cases": [] + } + } + }, + "mimesniff": { + "media": { + "media-sniff.window.html": { + "success": true, + "cases": [ { - "name": "x/x;x=ð;bonus=x (Request/Response)", + "name": "mp3-raw.mp3 loads when served with Content-Type ", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ð\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ð\";bonus=x (Blob/File)", + "name": "mp3-raw.mp3 loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ð\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ð\";bonus=x (Request/Response)", + "name": "mp3-raw.mp3 loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ð\\\";bonus=x\" but got \"\"" - }, - { - "name": "ñ/x (Blob/File)", - "success": true - }, - { - "name": "ñ/x (Request/Response)", - "success": true - }, - { - "name": "x/ñ (Blob/File)", - "success": true - }, - { - "name": "x/ñ (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ñ=x;bonus=x (Blob/File)", + "name": "mp3-raw.mp3 loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ñ=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ñ;bonus=x (Blob/File)", + "name": "mp3-raw.mp3 loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ñ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ñ;bonus=x (Request/Response)", + "name": "mp3-raw.mp3 loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ñ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ñ\";bonus=x (Blob/File)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type ", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ñ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ñ\";bonus=x (Request/Response)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ñ\\\";bonus=x\" but got \"\"" - }, - { - "name": "ò/x (Blob/File)", - "success": true - }, - { - "name": "ò/x (Request/Response)", - "success": true - }, - { - "name": "x/ò (Blob/File)", - "success": true - }, - { - "name": "x/ò (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ò=x;bonus=x (Blob/File)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ò=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ò;bonus=x (Blob/File)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ò\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ò;bonus=x (Request/Response)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ò\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ò\";bonus=x (Blob/File)", + "name": "mp3-with-id3.mp3 loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ò\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ò\";bonus=x (Request/Response)", + "name": "flac.flac loads when served with Content-Type ", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ò\\\";bonus=x\" but got \"\"" - }, - { - "name": "ó/x (Blob/File)", - "success": true - }, - { - "name": "ó/x (Request/Response)", - "success": true - }, - { - "name": "x/ó (Blob/File)", - "success": true - }, - { - "name": "x/ó (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ó=x;bonus=x (Blob/File)", + "name": "flac.flac loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ó=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ó;bonus=x (Blob/File)", + "name": "flac.flac loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ó\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ó;bonus=x (Request/Response)", + "name": "flac.flac loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ó\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ó\";bonus=x (Blob/File)", + "name": "flac.flac loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ó\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ó\";bonus=x (Request/Response)", + "name": "flac.flac loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ó\\\";bonus=x\" but got \"\"" - }, - { - "name": "ô/x (Blob/File)", - "success": true - }, - { - "name": "ô/x (Request/Response)", - "success": true - }, - { - "name": "x/ô (Blob/File)", - "success": true - }, - { - "name": "x/ô (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ô=x;bonus=x (Blob/File)", + "name": "ogg.ogg loads when served with Content-Type ", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ô=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ô;bonus=x (Blob/File)", + "name": "ogg.ogg loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ô\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ô;bonus=x (Request/Response)", + "name": "ogg.ogg loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ô\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ô\";bonus=x (Blob/File)", + "name": "ogg.ogg loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ô\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ô\";bonus=x (Request/Response)", + "name": "ogg.ogg loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ô\\\";bonus=x\" but got \"\"" - }, - { - "name": "õ/x (Blob/File)", - "success": true - }, - { - "name": "õ/x (Request/Response)", - "success": true - }, - { - "name": "x/õ (Blob/File)", - "success": true - }, - { - "name": "x/õ (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;õ=x;bonus=x (Blob/File)", + "name": "ogg.ogg loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;õ=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=õ;bonus=x (Blob/File)", + "name": "mp4.mp4 loads when served with Content-Type ", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"õ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=õ;bonus=x (Request/Response)", + "name": "mp4.mp4 loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"õ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"õ\";bonus=x (Blob/File)", + "name": "mp4.mp4 loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"õ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"õ\";bonus=x (Request/Response)", + "name": "mp4.mp4 loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"õ\\\";bonus=x\" but got \"\"" - }, - { - "name": "ö/x (Blob/File)", - "success": true - }, - { - "name": "ö/x (Request/Response)", - "success": true - }, - { - "name": "x/ö (Blob/File)", - "success": true - }, - { - "name": "x/ö (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ö=x;bonus=x (Blob/File)", + "name": "mp4.mp4 loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ö=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ö;bonus=x (Blob/File)", + "name": "mp4.mp4 loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ö\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ö;bonus=x (Request/Response)", + "name": "wav.wav loads when served with Content-Type ", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ö\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ö\";bonus=x (Blob/File)", + "name": "wav.wav loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ö\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ö\";bonus=x (Request/Response)", + "name": "wav.wav loads when served with Content-Type application/octet-stream", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ö\\\";bonus=x\" but got \"\"" - }, - { - "name": "÷/x (Blob/File)", - "success": true - }, - { - "name": "÷/x (Request/Response)", - "success": true - }, - { - "name": "x/÷ (Blob/File)", - "success": true - }, - { - "name": "x/÷ (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;÷=x;bonus=x (Blob/File)", + "name": "wav.wav loads when served with Content-Type text/html", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;÷=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=÷;bonus=x (Blob/File)", + "name": "wav.wav loads when served with Content-Type audio/ogg; codec=vorbis", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"÷\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=÷;bonus=x (Request/Response)", + "name": "wav.wav loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"÷\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"÷\";bonus=x (Blob/File)", + "name": "webm.webm loads when served with Content-Type ", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"÷\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"÷\";bonus=x (Request/Response)", + "name": "webm.webm loads when served with Content-Type bogus/mime", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"÷\\\";bonus=x\" but got \"\"" - }, - { - "name": "ø/x (Blob/File)", - "success": true + "message": "document is not defined" }, { - "name": "ø/x (Request/Response)", - "success": true + "name": "webm.webm loads when served with Content-Type application/octet-stream", + "success": false, + "message": "document is not defined" }, { - "name": "x/ø (Blob/File)", - "success": true + "name": "webm.webm loads when served with Content-Type text/html", + "success": false, + "message": "document is not defined" }, { - "name": "x/ø (Request/Response)", - "success": true + "name": "webm.webm loads when served with Content-Type audio/ogg; codec=vorbis", + "success": false, + "message": "document is not defined" }, { - "name": "x/x;ø=x;bonus=x (Blob/File)", + "name": "webm.webm loads when served with Content-Type application/pdf", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, + "message": "document is not defined" + } + ] + } + }, + "mime-types": { + "charset-parameter.window.html": { + "success": true, + "cases": [ { - "name": "x/x;ø=x;bonus=x (Request/Response)", + "name": "Loading data…", "success": true }, { - "name": "x/x;x=ø;bonus=x (Blob/File)", + "name": "text/html;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ø\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ø;bonus=x (Request/Response)", + "name": "TEXT/HTML;CHARSET=GBK", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ø\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ø\";bonus=x (Blob/File)", + "name": "text/html;charset=gbk(", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ø\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ø\";bonus=x (Request/Response)", + "name": "text/html;x=(;charset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ø\\\";bonus=x\" but got \"\"" - }, - { - "name": "ù/x (Blob/File)", - "success": true - }, - { - "name": "ù/x (Request/Response)", - "success": true - }, - { - "name": "x/ù (Blob/File)", - "success": true - }, - { - "name": "x/ù (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ù=x;bonus=x (Blob/File)", + "name": "text/html;charset=gbk;charset=windows-1255", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ù=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ù;bonus=x (Blob/File)", + "name": "text/html;charset=();charset=GBK", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ù\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ù;bonus=x (Request/Response)", + "name": "text/html;charset =gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ù\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ù\";bonus=x (Blob/File)", + "name": "text/html ;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ù\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ù\";bonus=x (Request/Response)", + "name": "text/html; charset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ù\\\";bonus=x\" but got \"\"" - }, - { - "name": "ú/x (Blob/File)", - "success": true - }, - { - "name": "ú/x (Request/Response)", - "success": true - }, - { - "name": "x/ú (Blob/File)", - "success": true - }, - { - "name": "x/ú (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ú=x;bonus=x (Blob/File)", + "name": "text/html;charset= gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ú=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ú;bonus=x (Blob/File)", + "name": "text/html;charset= \"gbk\"", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ú\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ú;bonus=x (Request/Response)", + "name": "text/html;charset=\u000bgbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ú\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ú\";bonus=x (Blob/File)", + "name": "text/html;charset=\fgbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ú\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ú\";bonus=x (Request/Response)", + "name": "text/html;\u000bcharset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ú\\\";bonus=x\" but got \"\"" - }, - { - "name": "û/x (Blob/File)", - "success": true - }, - { - "name": "û/x (Request/Response)", - "success": true - }, - { - "name": "x/û (Blob/File)", - "success": true - }, - { - "name": "x/û (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;û=x;bonus=x (Blob/File)", + "name": "text/html;\fcharset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;û=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=û;bonus=x (Blob/File)", + "name": "text/html;charset='gbk'", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"û\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=û;bonus=x (Request/Response)", + "name": "text/html;charset='gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"û\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"û\";bonus=x (Blob/File)", + "name": "text/html;charset=gbk'", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"û\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"û\";bonus=x (Request/Response)", + "name": "text/html;charset=';charset=GBK", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"û\\\";bonus=x\" but got \"\"" - }, - { - "name": "ü/x (Blob/File)", - "success": true - }, - { - "name": "ü/x (Request/Response)", - "success": true - }, - { - "name": "x/ü (Blob/File)", - "success": true - }, - { - "name": "x/ü (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ü=x;bonus=x (Blob/File)", + "name": "text/html;test;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ü=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ü;bonus=x (Blob/File)", + "name": "text/html;test=;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ü\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ü;bonus=x (Request/Response)", + "name": "text/html;';charset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ü\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ü\";bonus=x (Blob/File)", + "name": "text/html;\";charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ü\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ü\";bonus=x (Request/Response)", + "name": "text/html ; ; charset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ü\\\";bonus=x\" but got \"\"" - }, - { - "name": "ý/x (Blob/File)", - "success": true - }, - { - "name": "ý/x (Request/Response)", - "success": true - }, - { - "name": "x/ý (Blob/File)", - "success": true - }, - { - "name": "x/ý (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ý=x;bonus=x (Blob/File)", + "name": "text/html;;;;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;ý=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=ý;bonus=x (Blob/File)", + "name": "text/html;charset= \";charset=GBK", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ý\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ý;bonus=x (Request/Response)", + "name": "text/html;charset=\";charset=foo\";charset=GBK", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ý\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ý\";bonus=x (Blob/File)", + "name": "text/html;charset=\"gbk\"", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ý\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ý\";bonus=x (Request/Response)", + "name": "text/html;charset=\"gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ý\\\";bonus=x\" but got \"\"" - }, - { - "name": "þ/x (Blob/File)", - "success": true - }, - { - "name": "þ/x (Request/Response)", - "success": true - }, - { - "name": "x/þ (Blob/File)", - "success": true - }, - { - "name": "x/þ (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;þ=x;bonus=x (Blob/File)", + "name": "text/html;charset=gbk\"", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" - }, - { - "name": "x/x;þ=x;bonus=x (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;x=þ;bonus=x (Blob/File)", + "name": "text/html;charset=\" gbk\"", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"þ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=þ;bonus=x (Request/Response)", + "name": "text/html;charset=\"gbk \"", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"þ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"þ\";bonus=x (Blob/File)", + "name": "text/html;charset=\"\\ gbk\"", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"þ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"þ\";bonus=x (Request/Response)", + "name": "text/html;charset=\"\\g\\b\\k\"", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"þ\\\";bonus=x\" but got \"\"" - }, - { - "name": "ÿ/x (Blob/File)", - "success": true - }, - { - "name": "ÿ/x (Request/Response)", - "success": true - }, - { - "name": "x/ÿ (Blob/File)", - "success": true - }, - { - "name": "x/ÿ (Request/Response)", - "success": true + "message": "document is not defined" }, { - "name": "x/x;ÿ=x;bonus=x (Blob/File)", + "name": "text/html;charset=\"gbk\"x", "success": false, - "message": "assert_equals: Blob expected \"x/x;bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;ÿ=x;bonus=x (Request/Response)", - "success": true + "name": "text/html;charset=\"\";charset=GBK", + "success": false, + "message": "document is not defined" }, { - "name": "x/x;x=ÿ;bonus=x (Blob/File)", + "name": "text/html;charset=\";charset=GBK", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ÿ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=ÿ;bonus=x (Request/Response)", + "name": "text/html;charset={gbk}", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ÿ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ÿ\";bonus=x (Blob/File)", + "name": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk", "success": false, - "message": "assert_equals: Blob expected \"x/x;x=\\\"ÿ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" }, { - "name": "x/x;x=\"ÿ\";bonus=x (Request/Response)", + "name": "text/html;test=ÿ;charset=gbk", "success": false, - "message": "assert_equals: expected \"x/x;x=\\\"ÿ\\\";bonus=x\" but got \"\"" + "message": "document is not defined" } ] + }, + "parsing.any.html": { + "success": "flaky", + "cases": [] } }, "sniffing": { @@ -33082,8 +24804,7 @@ "cases": [ { "name": "Create WebSocket - Close the Connection - close(1000, reason) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed", - "success": false, - "message": "assert_true: WebSocket connection should be opened expected true got false" + "success": true } ] }, @@ -35193,8 +26914,7 @@ "cases": [ { "name": "Send binary data on a WebSocket - ArrayBufferView - Float16Array - Connection should be closed", - "success": false, - "message": "Float16Array is not defined" + "success": true } ] }, @@ -35213,8 +26933,7 @@ "cases": [ { "name": "Send binary data on a WebSocket - ArrayBufferView - Float16Array - Connection should be closed", - "success": false, - "message": "Float16Array is not defined" + "success": true } ] }, @@ -38918,7 +30637,7 @@ { "name": "backpressure should be applied to received messages", "success": false, - "message": "assert_greater_than_equal: data send should have taken at least 2 seconds expected a number greater than or equal to 1.8 but got 0.03000044822692871" + "message": "assert_greater_than_equal: data send should have taken at least 2 seconds expected a number greater than or equal to 1.8 but got 0.11555743217468262" } ] }, @@ -38937,8 +30656,7 @@ "cases": [ { "name": "backpressure should be applied to sent messages", - "success": false, - "message": "assert_greater_than_equal: expected a number greater than or equal to 1800 but got 25.788400000000024" + "success": true } ] }, From ec537c7b43161ae70e09e837dbbfc7a979bc2305 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 11:05:05 +0000 Subject: [PATCH 02/16] chore: ignore local tooling dirs --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index b07f936559f..00abb95f2c1 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,7 @@ test/request-timeout.10mb.bin # Claude files CLAUDE.md .claude + +# Local tooling +.githuman/ +.pi/ From 99c77d670ac888351cd1affe65223b9b2991e9a9 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 13:09:25 +0000 Subject: [PATCH 03/16] docs: add WrapHandler removal plan --- plan.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 plan.md diff --git a/plan.md b/plan.md new file mode 100644 index 00000000000..d5fea827f01 --- /dev/null +++ b/plan.md @@ -0,0 +1,50 @@ +# Plan: Remove WrapHandler and use new handlers everywhere + +## Goals +- Eliminate `lib/handler/wrap-handler.js` usage and legacy wrapping paths. +- Use the new handler API consistently across all dispatchers and APIs. +- Preserve backwards compatibility expectations via tests and documented migration. + +## Phases +1. **Inventory + constraints** + - Enumerate all `WrapHandler` and `unwrap` usages (APIs, handlers, interceptors, tests). + - Identify legacy handler behaviors relied upon by core dispatchers (header casing, stack traces, event ordering). + - Current usages (as of now): + - `lib/api/api-request.js` (wrap handler) + - `lib/api/api-stream.js` (wrap handler) + - `lib/api/api-pipeline.js` (wrap handler) + - `lib/api/api-upgrade.js` (wrap handler) + - `lib/api/api-connect.js` (wrap handler) + - `lib/dispatcher/dispatcher.js` (wrap interceptor handler) + - `lib/dispatcher/dispatcher-base.js` (unwrap handler) + - `lib/handler/retry-handler.js` (wrap handler) + - `lib/handler/decorator-handler.js` (wrap handler) + - `lib/mock/snapshot-agent.js` (wrap handler) + - `lib/handler/wrap-handler.js` (implementation) + - `lib/handler/unwrap-handler.js` (implementation) + - `test/issue-3934.js` (WrapHandler coverage) + +2. **API surface migration** + - Update all API entry points (`api-request`, `api-stream`, `api-pipeline`, `api-upgrade`, `api-connect`) to pass only new-style handlers. + - Remove conditional wrapping logic and any legacy adaptation code. + +3. **Dispatcher integration** + - Ensure core dispatchers (`Client`, `Pool`, `Agent`, etc.) only accept/emit new handler API. + - Remove `DispatcherBase` compatibility layers tied to legacy handler signatures. + +4. **Handler layer cleanup** + - Delete `lib/handler/wrap-handler.js` and `lib/handler/unwrap-handler.js` if no longer needed. + - Remove references in `lib/handler/*` and `lib/core/*`. + +5. **Tests + expectations** + - Update/replace legacy handler tests to assert new handler API behavior. + - Add migration/regression coverage for custom dispatchers using new handlers. + - Adjust WPT expectations only if behavior changes are intentional. + +6. **Docs + migration notes** + - Update documentation to state legacy handler API is removed. + - Add a migration note with example handler changes. + +## Rollout +- Land in a major version or behind a feature flag if needed. +- Provide a deprecation period if consumer impact is high. From e571fcec298d3ee9bc540a3d33e95f8431fb20e2 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 13:11:09 +0000 Subject: [PATCH 04/16] docs: detail WrapHandler inventory --- plan.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plan.md b/plan.md index d5fea827f01..5a05f309188 100644 --- a/plan.md +++ b/plan.md @@ -9,6 +9,13 @@ 1. **Inventory + constraints** - Enumerate all `WrapHandler` and `unwrap` usages (APIs, handlers, interceptors, tests). - Identify legacy handler behaviors relied upon by core dispatchers (header casing, stack traces, event ordering). + - Legacy behavior constraints observed in wrappers: + - `WrapHandler` converts new handler callbacks to legacy `onConnect/onHeaders/onData/onComplete`. + - Headers/trailers are converted to raw arrays of `Buffer` pairs, preserving duplicate headers but not original casing. + - `onHeaders`/`onData` return `false` to pause; `resume()` uses controller from new API. + - `onError` validation differs: missing `onError` throws (`InvalidArgumentError`) in new API path. + - `UnwrapHandler` converts legacy callbacks to new `onRequestStart/onResponseStart/...` using `parseHeaders`. + - `UnwrapHandler` maintains pause/resume/abort semantics via `UnwrapController`. - Current usages (as of now): - `lib/api/api-request.js` (wrap handler) - `lib/api/api-stream.js` (wrap handler) From 1416561591d570e4188a6720b48e0e14fa4e6dee Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 13:23:02 +0000 Subject: [PATCH 05/16] docs: add legacy handler usage inventory --- plan.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plan.md b/plan.md index 5a05f309188..364793a647a 100644 --- a/plan.md +++ b/plan.md @@ -30,6 +30,12 @@ - `lib/handler/wrap-handler.js` (implementation) - `lib/handler/unwrap-handler.js` (implementation) - `test/issue-3934.js` (WrapHandler coverage) + - Legacy handler API usage in core pipeline: + - `lib/core/request.js` (invokes `onConnect/onHeaders/onData/onComplete/onError/onUpgrade`) + - `lib/dispatcher/client-h1.js` + `client-h2.js` (calls request `onConnect/onHeaders/onData/onComplete`) + - `lib/dispatcher/dispatcher-base.js` (expects legacy handler unless unwrapped) + - `lib/interceptor/cache.js` and `lib/web/fetch/index.js` (construct handlers with legacy callbacks) + - `lib/mock/mock-utils.js` (emits legacy callbacks during mock responses) 2. **API surface migration** - Update all API entry points (`api-request`, `api-stream`, `api-pipeline`, `api-upgrade`, `api-connect`) to pass only new-style handlers. From e70df5403a462fe26c966b50bab6c077645b9c9d Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 14:24:07 +0000 Subject: [PATCH 06/16] refactor: switch core pipeline to new handler api --- lib/api/api-connect.js | 37 ++++------ lib/api/api-pipeline.js | 48 ++++++------- lib/api/api-request.js | 58 +++++++-------- lib/api/api-stream.js | 58 ++++++++------- lib/api/api-upgrade.js | 37 ++++------ lib/core/request.js | 114 +++++++++++++++++++++++++----- lib/core/util.js | 35 +++++---- lib/dispatcher/client-h1.js | 10 +-- lib/dispatcher/client-h2.js | 14 ++-- lib/dispatcher/dispatcher-base.js | 7 +- lib/dispatcher/dispatcher.js | 4 -- lib/dispatcher/pool-base.js | 2 +- lib/dispatcher/proxy-agent.js | 10 +-- lib/handler/decorator-handler.js | 3 +- lib/handler/retry-handler.js | 3 +- lib/handler/unwrap-handler.js | 96 ------------------------- lib/handler/wrap-handler.js | 95 ------------------------- lib/interceptor/cache.js | 43 ++++++----- lib/mock/mock-utils.js | 29 +++++--- lib/mock/snapshot-agent.js | 38 ++++++++-- lib/web/fetch/index.js | 38 +++++----- test/client-request.js | 12 ++-- test/issue-3934.js | 2 +- test/node-test/util.js | 68 ++++++++++-------- 24 files changed, 391 insertions(+), 470 deletions(-) delete mode 100644 lib/handler/unwrap-handler.js delete mode 100644 lib/handler/wrap-handler.js diff --git a/lib/api/api-connect.js b/lib/api/api-connect.js index 760258cff73..b545a3eb5c1 100644 --- a/lib/api/api-connect.js +++ b/lib/api/api-connect.js @@ -4,18 +4,8 @@ const assert = require('node:assert') const { AsyncResource } = require('node:async_hooks') const { InvalidArgumentError, SocketError } = require('../core/errors') const util = require('../core/util') -const WrapHandler = require('../handler/wrap-handler') -const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') -function getDispatchHandler (dispatcher, handler) { - if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { - return handler - } - - return WrapHandler.wrap(handler) -} - class ConnectHandler extends AsyncResource { constructor (opts, callback) { if (!opts || typeof opts !== 'object') { @@ -42,45 +32,48 @@ class ConnectHandler extends AsyncResource { addSignal(this, signal) } - onConnect (abort, context) { + onRequestStart (controller, context) { if (this.reason) { - abort(this.reason) + controller.abort(this.reason) return } assert(this.callback) - this.abort = abort + this.abort = (reason) => controller.abort(reason) this.context = context } - onHeaders () { + onResponseStart () { throw new SocketError('bad connect', null) } - onUpgrade (statusCode, rawHeaders, socket) { + onRequestUpgrade (controller, statusCode, headers, socket) { const { callback, opaque, context } = this removeSignal(this) this.callback = null - let headers = rawHeaders + let responseHeaders = headers + const rawHeaders = controller?.rawHeaders // Indicates is an HTTP2Session - if (headers != null) { - headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + if (responseHeaders != null) { + responseHeaders = this.responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers } this.runInAsyncScope(callback, null, null, { statusCode, - headers, + headers: responseHeaders, socket, opaque, context }) } - onError (err) { + onResponseError (_controller, err) { const { callback, opaque } = this removeSignal(this) @@ -106,9 +99,7 @@ function connect (opts, callback) { try { const connectHandler = new ConnectHandler(opts, callback) const connectOptions = { ...opts, method: 'CONNECT' } - const dispatchHandler = getDispatchHandler(this, connectHandler) - - this.dispatch(connectOptions, dispatchHandler) + this.dispatch(connectOptions, connectHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-pipeline.js b/lib/api/api-pipeline.js index b69e55d9a07..c8bd7414932 100644 --- a/lib/api/api-pipeline.js +++ b/lib/api/api-pipeline.js @@ -13,18 +13,8 @@ const { RequestAbortedError } = require('../core/errors') const util = require('../core/util') -const WrapHandler = require('../handler/wrap-handler') -const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') -function getDispatchHandler (dispatcher, handler) { - if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { - return handler - } - - return WrapHandler.wrap(handler) -} - function noop () {} const kResume = Symbol('resume') @@ -156,40 +146,46 @@ class PipelineHandler extends AsyncResource { addSignal(this, signal) } - onConnect (abort, context) { + onRequestStart (controller, context) { const { res } = this if (this.reason) { - abort(this.reason) + controller.abort(this.reason) return } assert(!res, 'pipeline cannot be retried') - this.abort = abort + this.abort = (reason) => controller.abort(reason) this.context = context } - onHeaders (statusCode, rawHeaders, resume) { + onResponseStart (controller, statusCode, headers, _statusMessage) { const { opaque, handler, context } = this if (statusCode < 200) { if (this.onInfo) { - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) - this.onInfo({ statusCode, headers }) + const rawHeaders = controller?.rawHeaders + const responseHeaders = this.responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers + this.onInfo({ statusCode, headers: responseHeaders }) } return } - this.res = new PipelineResponse(resume) + this.res = new PipelineResponse(() => controller.resume()) let body try { this.handler = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + const rawHeaders = controller?.rawHeaders + const responseHeaders = this.responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers body = this.runInAsyncScope(handler, null, { statusCode, - headers, + headers: responseHeaders, opaque, body: this.res, context @@ -232,17 +228,20 @@ class PipelineHandler extends AsyncResource { this.body = body } - onData (chunk) { + onResponseData (controller, chunk) { const { res } = this - return res.push(chunk) + + if (res.push(chunk) === false) { + controller.pause() + } } - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { const { res } = this res.push(null) } - onError (err) { + onResponseError (_controller, err) { const { ret } = this this.handler = null util.destroy(ret, err) @@ -252,8 +251,7 @@ class PipelineHandler extends AsyncResource { function pipeline (opts, handler) { try { const pipelineHandler = new PipelineHandler(opts, handler) - const dispatchHandler = getDispatchHandler(this, pipelineHandler) - this.dispatch({ ...opts, body: pipelineHandler.req }, dispatchHandler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) return pipelineHandler.ret } catch (err) { return new PassThrough().destroy(err) diff --git a/lib/api/api-request.js b/lib/api/api-request.js index 79eca0f8e7f..3e6af58dd75 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -5,16 +5,6 @@ const { AsyncResource } = require('node:async_hooks') const { Readable } = require('./readable') const { InvalidArgumentError, RequestAbortedError } = require('../core/errors') const util = require('../core/util') -const WrapHandler = require('../handler/wrap-handler') -const DispatcherBase = require('../dispatcher/dispatcher-base') - -function getDispatchHandler (dispatcher, handler) { - if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { - return handler - } - - return WrapHandler.wrap(handler) -} function noop () {} @@ -64,6 +54,7 @@ class RequestHandler extends AsyncResource { this.body = body this.trailers = {} this.context = null + this.controller = null this.onInfo = onInfo || null this.highWaterMark = highWaterMark this.reason = null @@ -83,36 +74,40 @@ class RequestHandler extends AsyncResource { } } - onConnect (abort, context) { + onRequestStart (controller, context) { if (this.reason) { - abort(this.reason) + controller.abort(this.reason) return } assert(this.callback) - this.abort = abort + this.controller = controller + this.abort = (reason) => controller.abort(reason) this.context = context } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + onResponseStart (controller, statusCode, headers, _statusMessage) { + const { callback, opaque, context, responseHeaders, highWaterMark } = this - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + const rawHeaders = controller?.rawHeaders + const responseHeaderData = responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers if (statusCode < 200) { if (this.onInfo) { - this.onInfo({ statusCode, headers }) + this.onInfo({ statusCode, headers: responseHeaderData }) } return } - const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers - const contentType = parsedHeaders['content-type'] - const contentLength = parsedHeaders['content-length'] + const parsedHeaders = headers + const contentType = parsedHeaders?.['content-type'] + const contentLength = parsedHeaders?.['content-length'] const res = new Readable({ - resume, - abort, + resume: () => controller.resume(), + abort: (reason) => controller.abort(reason), contentType, contentLength: this.method !== 'HEAD' && contentLength ? Number(contentLength) @@ -131,7 +126,7 @@ class RequestHandler extends AsyncResource { try { this.runInAsyncScope(callback, null, null, { statusCode, - headers, + headers: responseHeaderData, trailers: this.trailers, opaque, body: res, @@ -153,16 +148,18 @@ class RequestHandler extends AsyncResource { } } - onData (chunk) { - return this.res.push(chunk) + onResponseData (_controller, chunk) { + return this.res ? this.res.push(chunk) : true } - onComplete (trailers) { - util.parseHeaders(trailers, this.trailers) - this.res.push(null) + onResponseEnd (_controller, trailers) { + if (trailers && typeof trailers === 'object') { + Object.assign(this.trailers, trailers) + } + this.res?.push(null) } - onError (err) { + onResponseError (_controller, err) { const { res, callback, body, opaque } = this if (callback) { @@ -208,9 +205,8 @@ function request (opts, callback) { try { const handler = new RequestHandler(opts, callback) - const dispatchHandler = getDispatchHandler(this, handler) - this.dispatch(opts, dispatchHandler) + this.dispatch(opts, handler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-stream.js b/lib/api/api-stream.js index 01797468896..daee5681223 100644 --- a/lib/api/api-stream.js +++ b/lib/api/api-stream.js @@ -5,18 +5,8 @@ const { finished } = require('node:stream') const { AsyncResource } = require('node:async_hooks') const { InvalidArgumentError, InvalidReturnValueError } = require('../core/errors') const util = require('../core/util') -const WrapHandler = require('../handler/wrap-handler') -const DispatcherBase = require('../dispatcher/dispatcher-base') const { addSignal, removeSignal } = require('./abort-signal') -function getDispatchHandler (dispatcher, handler) { - if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { - return handler - } - - return WrapHandler.wrap(handler) -} - function noop () {} class StreamHandler extends AsyncResource { @@ -63,39 +53,44 @@ class StreamHandler extends AsyncResource { this.res = null this.abort = null this.context = null + this.controller = null this.trailers = null this.body = body this.onInfo = onInfo || null if (util.isStream(body)) { body.on('error', (err) => { - this.onError(err) + this.onResponseError(this.controller, err) }) } addSignal(this, signal) } - onConnect (abort, context) { + onRequestStart (controller, context) { if (this.reason) { - abort(this.reason) + controller.abort(this.reason) return } assert(this.callback) - this.abort = abort + this.controller = controller + this.abort = (reason) => controller.abort(reason) this.context = context } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { + onResponseStart (controller, statusCode, headers, _statusMessage) { const { factory, opaque, context, responseHeaders } = this - const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + const rawHeaders = controller?.rawHeaders + const responseHeaderData = responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers if (statusCode < 200) { if (this.onInfo) { - this.onInfo({ statusCode, headers }) + this.onInfo({ statusCode, headers: responseHeaderData }) } return } @@ -108,7 +103,7 @@ class StreamHandler extends AsyncResource { const res = this.runInAsyncScope(factory, null, { statusCode, - headers, + headers: responseHeaderData, opaque, context }) @@ -139,7 +134,7 @@ class StreamHandler extends AsyncResource { } }) - res.on('drain', resume) + res.on('drain', () => controller.resume()) this.res = res @@ -147,16 +142,24 @@ class StreamHandler extends AsyncResource { ? res.writableNeedDrain : res._writableState?.needDrain - return needDrain !== true + if (needDrain === true) { + controller.pause() + } } - onData (chunk) { + onResponseData (controller, chunk) { const { res } = this - return res ? res.write(chunk) : true + if (!res) { + return + } + + if (res.write(chunk) === false) { + controller.pause() + } } - onComplete (trailers) { + onResponseEnd (_controller, trailers) { const { res } = this removeSignal(this) @@ -165,12 +168,14 @@ class StreamHandler extends AsyncResource { return } - this.trailers = util.parseHeaders(trailers) + if (trailers && typeof trailers === 'object') { + this.trailers = trailers + } res.end() } - onError (err) { + onResponseError (_controller, err) { const { res, callback, opaque, body } = this removeSignal(this) @@ -205,9 +210,8 @@ function stream (opts, factory, callback) { try { const handler = new StreamHandler(opts, factory, callback) - const dispatchHandler = getDispatchHandler(this, handler) - this.dispatch(opts, dispatchHandler) + this.dispatch(opts, handler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/api/api-upgrade.js b/lib/api/api-upgrade.js index 76911fc5d38..9f1d80c62dc 100644 --- a/lib/api/api-upgrade.js +++ b/lib/api/api-upgrade.js @@ -4,19 +4,9 @@ const { InvalidArgumentError, SocketError } = require('../core/errors') const { AsyncResource } = require('node:async_hooks') const assert = require('node:assert') const util = require('../core/util') -const WrapHandler = require('../handler/wrap-handler') -const DispatcherBase = require('../dispatcher/dispatcher-base') const { kHTTP2Stream } = require('../core/symbols') const { addSignal, removeSignal } = require('./abort-signal') -function getDispatchHandler (dispatcher, handler) { - if (dispatcher instanceof DispatcherBase && dispatcher.dispatch === DispatcherBase.prototype.dispatch) { - return handler - } - - return WrapHandler.wrap(handler) -} - class UpgradeHandler extends AsyncResource { constructor (opts, callback) { if (!opts || typeof opts !== 'object') { @@ -44,23 +34,23 @@ class UpgradeHandler extends AsyncResource { addSignal(this, signal) } - onConnect (abort, context) { + onRequestStart (controller, context) { if (this.reason) { - abort(this.reason) + controller.abort(this.reason) return } assert(this.callback) - this.abort = abort - this.context = null + this.abort = (reason) => controller.abort(reason) + this.context = context } - onHeaders () { + onResponseStart () { throw new SocketError('bad upgrade', null) } - onUpgrade (statusCode, rawHeaders, socket) { + onRequestUpgrade (controller, statusCode, headers, socket) { assert(socket[kHTTP2Stream] === true ? statusCode === 200 : statusCode === 101) const { callback, opaque, context } = this @@ -68,16 +58,21 @@ class UpgradeHandler extends AsyncResource { removeSignal(this) this.callback = null - const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + const rawHeaders = controller?.rawHeaders + const responseHeaders = this.responseHeaders === 'raw' + ? (Array.isArray(rawHeaders) ? util.parseRawHeaders(rawHeaders) : []) + : headers + this.runInAsyncScope(callback, null, null, { - headers, + headers: responseHeaders, socket, opaque, context }) } - onError (err) { + onResponseError (_controller, err) { const { callback, opaque } = this removeSignal(this) @@ -107,9 +102,7 @@ function upgrade (opts, callback) { method: opts.method || 'GET', upgrade: opts.protocol || 'Websocket' } - const dispatchHandler = getDispatchHandler(this, upgradeHandler) - - this.dispatch(upgradeOpts, dispatchHandler) + this.dispatch(upgradeOpts, upgradeHandler) } catch (err) { if (typeof callback !== 'function') { throw err diff --git a/lib/core/request.js b/lib/core/request.js index 7dbf781b4c4..b4561a1b1c2 100644 --- a/lib/core/request.js +++ b/lib/core/request.js @@ -15,6 +15,7 @@ const { isIterable, isBlobLike, serializePathWithQuery, + parseHeaders, assertRequestHandler, getServerName, normalizedMethodRecords, @@ -27,6 +28,55 @@ const { headerNameLowerCasedRecord } = require('./constants') const invalidPathRegex = /[^\u0021-\u00ff]/ const kHandler = Symbol('handler') +const kController = Symbol('controller') +const kResume = Symbol('resume') + +class RequestController { + #paused = false + #reason = null + #aborted = false + #abort + + [kResume] = null + + rawHeaders = null + rawTrailers = null + + constructor (abort) { + this.#abort = abort + } + + pause () { + this.#paused = true + } + + resume () { + if (this.#paused) { + this.#paused = false + this[kResume]?.() + } + } + + abort (reason) { + if (!this.#aborted) { + this.#aborted = true + this.#reason = reason + this.#abort(reason) + } + } + + get aborted () { + return this.#aborted + } + + get reason () { + return this.#reason + } + + get paused () { + return this.#paused + } +} class Request { constructor (origin, { @@ -229,23 +279,26 @@ class Request { } } - onConnect (abort) { + onRequestStart (abort, context) { assert(!this.aborted) assert(!this.completed) + this[kController] = new RequestController(abort) + if (this.error) { - abort(this.error) - } else { - this.abort = abort - return this[kHandler].onConnect(abort) + this[kController].abort(this.error) + return } + + this.abort = abort + return this[kHandler].onRequestStart(this[kController], context) } onResponseStarted () { return this[kHandler].onResponseStarted?.() } - onHeaders (statusCode, headers, resume, statusText) { + onResponseStart (statusCode, headers, resume, statusText) { assert(!this.aborted) assert(!this.completed) @@ -253,36 +306,56 @@ class Request { channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) } + const controller = this[kController] + if (controller) { + controller[kResume] = resume + controller.rawHeaders = headers + } + + const parsedHeaders = Array.isArray(headers) ? parseHeaders(headers) : headers + try { - return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + this[kHandler].onResponseStart?.(controller, statusCode, parsedHeaders, statusText) + return !controller?.paused } catch (err) { this.abort(err) + return false } } - onData (chunk) { + onResponseData (chunk) { assert(!this.aborted) assert(!this.completed) if (channels.bodyChunkReceived.hasSubscribers) { channels.bodyChunkReceived.publish({ request: this, chunk }) } + + const controller = this[kController] try { - return this[kHandler].onData(chunk) + this[kHandler].onResponseData?.(controller, chunk) + return !controller?.paused } catch (err) { this.abort(err) return false } } - onUpgrade (statusCode, headers, socket) { + onRequestUpgrade (statusCode, headers, socket) { assert(!this.aborted) assert(!this.completed) - return this[kHandler].onUpgrade(statusCode, headers, socket) + const controller = this[kController] + if (controller) { + controller.rawHeaders = headers + } + + const parsedHeaders = Array.isArray(headers) ? parseHeaders(headers) : headers + + return this[kHandler].onRequestUpgrade?.(controller, statusCode, parsedHeaders, socket) } - onComplete (trailers) { + onResponseEnd (trailers) { this.onFinally() assert(!this.aborted) @@ -293,15 +366,22 @@ class Request { channels.trailers.publish({ request: this, trailers }) } + const controller = this[kController] + if (controller) { + controller.rawTrailers = trailers + } + + const parsedTrailers = Array.isArray(trailers) ? parseHeaders(trailers) : trailers + try { - return this[kHandler].onComplete(trailers) + return this[kHandler].onResponseEnd?.(controller, parsedTrailers) } catch (err) { // TODO (fix): This might be a bad idea? - this.onError(err) + this.onResponseError(err) } } - onError (error) { + onResponseError (error) { this.onFinally() if (channels.error.hasSubscribers) { @@ -313,7 +393,9 @@ class Request { } this.aborted = true - return this[kHandler].onError(error) + const controller = this[kController] + + return this[kHandler].onResponseError?.(controller, error) } onFinally () { diff --git a/lib/core/util.js b/lib/core/util.js index be2c1a7320d..0fc7906c3f4 100644 --- a/lib/core/util.js +++ b/lib/core/util.js @@ -506,38 +506,37 @@ function assertRequestHandler (handler, method, upgrade) { throw new InvalidArgumentError('handler must be an object') } - if (typeof handler.onRequestStart === 'function') { - // TODO (fix): More checks... - return - } - - if (typeof handler.onConnect !== 'function') { - throw new InvalidArgumentError('invalid onConnect method') + if (typeof handler.onRequestStart !== 'function') { + throw new InvalidArgumentError('invalid onRequestStart method') } - if (typeof handler.onError !== 'function') { - throw new InvalidArgumentError('invalid onError method') + if (typeof handler.onResponseError !== 'function') { + throw new InvalidArgumentError('invalid onResponseError method') } if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { throw new InvalidArgumentError('invalid onBodySent method') } + if (typeof handler.onRequestSent !== 'function' && handler.onRequestSent !== undefined) { + throw new InvalidArgumentError('invalid onRequestSent method') + } + if (upgrade || method === 'CONNECT') { - if (typeof handler.onUpgrade !== 'function') { - throw new InvalidArgumentError('invalid onUpgrade method') + if (typeof handler.onRequestUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onRequestUpgrade method') } } else { - if (typeof handler.onHeaders !== 'function') { - throw new InvalidArgumentError('invalid onHeaders method') + if (typeof handler.onResponseStart !== 'function') { + throw new InvalidArgumentError('invalid onResponseStart method') } - if (typeof handler.onData !== 'function') { - throw new InvalidArgumentError('invalid onData method') + if (typeof handler.onResponseData !== 'function') { + throw new InvalidArgumentError('invalid onResponseData method') } - if (typeof handler.onComplete !== 'function') { - throw new InvalidArgumentError('invalid onComplete method') + if (typeof handler.onResponseEnd !== 'function') { + throw new InvalidArgumentError('invalid onResponseEnd method') } } } @@ -778,7 +777,7 @@ function removeAllListeners (obj) { */ function errorRequest (client, request, err) { try { - request.onError(err) + request.onResponseError(err) assert(request.aborted) } catch (err) { client.emit('error', err) diff --git a/lib/dispatcher/client-h1.js b/lib/dispatcher/client-h1.js index 09d1a7599c4..18211ca73ad 100644 --- a/lib/dispatcher/client-h1.js +++ b/lib/dispatcher/client-h1.js @@ -507,7 +507,7 @@ class Parser { client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) try { - request.onUpgrade(statusCode, headers, socket) + request.onRequestUpgrade(statusCode, headers, socket) } catch (err) { util.destroy(socket, err) } @@ -605,7 +605,7 @@ class Parser { socket[kReset] = true } - const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + const pause = request.onResponseStart(statusCode, headers, this.resume, statusText) === false if (request.aborted) { return -1 @@ -657,7 +657,7 @@ class Parser { this.bytesRead += buf.length - if (request.onData(buf) === false) { + if (request.onResponseData(buf) === false) { return constants.ERROR.PAUSED } @@ -703,7 +703,7 @@ class Parser { return -1 } - request.onComplete(headers) + request.onResponseEnd(headers) client[kQueue][client[kRunningIdx]++] = null @@ -1073,7 +1073,7 @@ function writeH1 (client, request) { } try { - request.onConnect(abort) + request.onRequestStart(abort, null) } catch (err) { util.errorRequest(client, request, err) } diff --git a/lib/dispatcher/client-h2.js b/lib/dispatcher/client-h2.js index c9aec504af1..cb3fc061ddc 100644 --- a/lib/dispatcher/client-h2.js +++ b/lib/dispatcher/client-h2.js @@ -457,7 +457,7 @@ function writeH2 (client, request) { try { // We are already connected, streams are pending. // We can call on connect, and wait for abort - request.onConnect(abort) + request.onRequestStart(abort, null) } catch (err) { util.errorRequest(client, request, err) } @@ -497,7 +497,7 @@ function writeH2 (client, request) { stream.once('response', (headers, _flags) => { const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) + request.onRequestUpgrade(statusCode, parseH2Headers(realHeaders), stream) ++session[kOpenStreams] client[kQueue][client[kRunningIdx]++] = null @@ -531,7 +531,7 @@ function writeH2 (client, request) { stream.on('response', headers => { const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers - request.onUpgrade(statusCode, parseH2Headers(realHeaders), stream) + request.onRequestUpgrade(statusCode, parseH2Headers(realHeaders), stream) ++session[kOpenStreams] client[kQueue][client[kRunningIdx]++] = null }) @@ -660,13 +660,13 @@ function writeH2 (client, request) { return } - if (request.onHeaders(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) { + if (request.onResponseStart(Number(statusCode), parseH2Headers(realHeaders), stream.resume.bind(stream), '') === false) { stream.pause() } }) stream.on('data', (chunk) => { - if (request.onData(chunk) === false) { + if (request.onResponseData(chunk) === false) { stream.pause() } }) @@ -676,7 +676,7 @@ function writeH2 (client, request) { // If we received a response, this is a normal completion if (responseReceived) { if (!request.aborted && !request.completed) { - request.onComplete({}) + request.onResponseEnd({}) } client[kQueue][client[kRunningIdx]++] = null @@ -730,7 +730,7 @@ function writeH2 (client, request) { return } - request.onComplete(trailers) + request.onResponseEnd(trailers) }) return true diff --git a/lib/dispatcher/dispatcher-base.js b/lib/dispatcher/dispatcher-base.js index a6f47100257..59ad3abd046 100644 --- a/lib/dispatcher/dispatcher-base.js +++ b/lib/dispatcher/dispatcher-base.js @@ -1,7 +1,6 @@ 'use strict' const Dispatcher = require('./dispatcher') -const UnwrapHandler = require('../handler/unwrap-handler') const { ClientDestroyedError, ClientClosedError, @@ -134,8 +133,6 @@ class DispatcherBase extends Dispatcher { throw new InvalidArgumentError('handler must be an object') } - handler = UnwrapHandler.unwrap(handler) - try { if (!opts || typeof opts !== 'object') { throw new InvalidArgumentError('opts must be an object.') @@ -151,11 +148,11 @@ class DispatcherBase extends Dispatcher { return this[kDispatch](opts, handler) } catch (err) { - if (typeof handler.onError !== 'function') { + if (typeof handler.onResponseError !== 'function') { throw err } - handler.onError(err) + handler.onResponseError(null, err) return false } diff --git a/lib/dispatcher/dispatcher.js b/lib/dispatcher/dispatcher.js index 824dfb6d822..ecff2a9b168 100644 --- a/lib/dispatcher/dispatcher.js +++ b/lib/dispatcher/dispatcher.js @@ -1,8 +1,5 @@ 'use strict' const EventEmitter = require('node:events') -const WrapHandler = require('../handler/wrap-handler') - -const wrapInterceptor = (dispatch) => (opts, handler) => dispatch(opts, WrapHandler.wrap(handler)) class Dispatcher extends EventEmitter { dispatch () { @@ -32,7 +29,6 @@ class Dispatcher extends EventEmitter { } dispatch = interceptor(dispatch) - dispatch = wrapInterceptor(dispatch) if (dispatch == null || typeof dispatch !== 'function' || dispatch.length !== 2) { throw new TypeError('invalid interceptor') diff --git a/lib/dispatcher/pool-base.js b/lib/dispatcher/pool-base.js index 4de14f920e8..ee750d466a9 100644 --- a/lib/dispatcher/pool-base.js +++ b/lib/dispatcher/pool-base.js @@ -137,7 +137,7 @@ class PoolBase extends DispatcherBase { if (!item) { break } - item.handler.onError(err) + item.handler.onResponseError(null, err) } const destroyAll = new Array(this[kClients].length) diff --git a/lib/dispatcher/proxy-agent.js b/lib/dispatcher/proxy-agent.js index 4403b8d87ce..b3b29e25142 100644 --- a/lib/dispatcher/proxy-agent.js +++ b/lib/dispatcher/proxy-agent.js @@ -53,15 +53,15 @@ class Http1ProxyWrapper extends DispatcherBase { } [kDispatch] (opts, handler) { - const onHeaders = handler.onHeaders - handler.onHeaders = function (statusCode, data, resume) { + const onResponseStart = handler.onResponseStart + handler.onResponseStart = function (controller, statusCode, data, statusMessage) { if (statusCode === 407) { - if (typeof handler.onError === 'function') { - handler.onError(new InvalidArgumentError('Proxy Authentication Required (407)')) + if (typeof handler.onResponseError === 'function') { + handler.onResponseError(controller, new InvalidArgumentError('Proxy Authentication Required (407)')) } return } - if (onHeaders) onHeaders.call(this, statusCode, data, resume) + if (onResponseStart) onResponseStart.call(this, controller, statusCode, data, statusMessage) } // Rewrite request as an HTTP1 Proxy request, without tunneling. diff --git a/lib/handler/decorator-handler.js b/lib/handler/decorator-handler.js index 50fbb0cf892..1b53c711324 100644 --- a/lib/handler/decorator-handler.js +++ b/lib/handler/decorator-handler.js @@ -1,7 +1,6 @@ 'use strict' const assert = require('node:assert') -const WrapHandler = require('./wrap-handler') /** * @deprecated @@ -16,7 +15,7 @@ module.exports = class DecoratorHandler { if (typeof handler !== 'object' || handler === null) { throw new TypeError('handler must be an object') } - this.#handler = WrapHandler.wrap(handler) + this.#handler = handler } onRequestStart (...args) { diff --git a/lib/handler/retry-handler.js b/lib/handler/retry-handler.js index 1cbc78981b1..ee2f69a2043 100644 --- a/lib/handler/retry-handler.js +++ b/lib/handler/retry-handler.js @@ -3,7 +3,6 @@ const assert = require('node:assert') const { kRetryHandlerDefaultRetry } = require('../core/symbols') const { RequestRetryError } = require('../core/errors') -const WrapHandler = require('./wrap-handler') const { isDisturbed, parseRangeHeader, @@ -35,7 +34,7 @@ class RetryHandler { this.error = null this.dispatch = dispatch - this.handler = WrapHandler.wrap(handler) + this.handler = handler this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) } this.retryOpts = { throwOnError: throwOnError ?? true, diff --git a/lib/handler/unwrap-handler.js b/lib/handler/unwrap-handler.js deleted file mode 100644 index 865593a327b..00000000000 --- a/lib/handler/unwrap-handler.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict' - -const { parseHeaders } = require('../core/util') -const { InvalidArgumentError } = require('../core/errors') - -const kResume = Symbol('resume') - -class UnwrapController { - #paused = false - #reason = null - #aborted = false - #abort - - [kResume] = null - - constructor (abort) { - this.#abort = abort - } - - pause () { - this.#paused = true - } - - resume () { - if (this.#paused) { - this.#paused = false - this[kResume]?.() - } - } - - abort (reason) { - if (!this.#aborted) { - this.#aborted = true - this.#reason = reason - this.#abort(reason) - } - } - - get aborted () { - return this.#aborted - } - - get reason () { - return this.#reason - } - - get paused () { - return this.#paused - } -} - -module.exports = class UnwrapHandler { - #handler - #controller - - constructor (handler) { - this.#handler = handler - } - - static unwrap (handler) { - // TODO (fix): More checks... - return !handler.onRequestStart ? handler : new UnwrapHandler(handler) - } - - onConnect (abort, context) { - this.#controller = new UnwrapController(abort) - this.#handler.onRequestStart?.(this.#controller, context) - } - - onUpgrade (statusCode, rawHeaders, socket) { - this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket) - } - - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - this.#controller[kResume] = resume - this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage) - return !this.#controller.paused - } - - onData (data) { - this.#handler.onResponseData?.(this.#controller, data) - return !this.#controller.paused - } - - onComplete (rawTrailers) { - this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers)) - } - - onError (err) { - if (!this.#handler.onResponseError) { - throw new InvalidArgumentError('invalid onError method') - } - - this.#handler.onResponseError?.(this.#controller, err) - } -} diff --git a/lib/handler/wrap-handler.js b/lib/handler/wrap-handler.js deleted file mode 100644 index 47caa5fa68b..00000000000 --- a/lib/handler/wrap-handler.js +++ /dev/null @@ -1,95 +0,0 @@ -'use strict' - -const { InvalidArgumentError } = require('../core/errors') - -module.exports = class WrapHandler { - #handler - - constructor (handler) { - this.#handler = handler - } - - static wrap (handler) { - // TODO (fix): More checks... - return handler.onRequestStart ? handler : new WrapHandler(handler) - } - - // Unwrap Interface - - onConnect (abort, context) { - return this.#handler.onConnect?.(abort, context) - } - - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage) - } - - onUpgrade (statusCode, rawHeaders, socket) { - return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) - } - - onData (data) { - return this.#handler.onData?.(data) - } - - onComplete (trailers) { - return this.#handler.onComplete?.(trailers) - } - - onError (err) { - if (!this.#handler.onError) { - throw err - } - - return this.#handler.onError?.(err) - } - - // Wrap Interface - - onRequestStart (controller, context) { - this.#handler.onConnect?.((reason) => controller.abort(reason), context) - } - - onRequestUpgrade (controller, statusCode, headers, socket) { - const rawHeaders = [] - for (const [key, val] of Object.entries(headers)) { - rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) - } - - this.#handler.onUpgrade?.(statusCode, rawHeaders, socket) - } - - onResponseStart (controller, statusCode, headers, statusMessage) { - const rawHeaders = [] - for (const [key, val] of Object.entries(headers)) { - rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) - } - - if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { - controller.pause() - } - } - - onResponseData (controller, data) { - if (this.#handler.onData?.(data) === false) { - controller.pause() - } - } - - onResponseEnd (controller, trailers) { - const rawTrailers = [] - for (const [key, val] of Object.entries(trailers)) { - rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val)) - } - - this.#handler.onComplete?.(rawTrailers) - } - - onResponseError (controller, err) { - if (!this.#handler.onError) { - throw new InvalidArgumentError('invalid onError method') - } - - this.#handler.onError?.(err) - } -} diff --git a/lib/interceptor/cache.js b/lib/interceptor/cache.js index b0449374fd4..000ee49d76f 100644 --- a/lib/interceptor/cache.js +++ b/lib/interceptor/cache.js @@ -124,30 +124,39 @@ function handleUncachedResponse ( ) { if (reqCacheControl?.['only-if-cached']) { let aborted = false - try { - if (typeof handler.onConnect === 'function') { - handler.onConnect(() => { - aborted = true - }) - if (aborted) { - return - } + const controller = { + paused: false, + rawHeaders: [], + rawTrailers: [], + pause () { + this.paused = true + }, + resume () { + this.paused = false + }, + abort: (reason) => { + aborted = true + handler.onResponseError?.(controller, reason ?? new AbortError()) } + } - if (typeof handler.onHeaders === 'function') { - handler.onHeaders(504, [], nop, 'Gateway Timeout') - if (aborted) { - return - } + try { + handler.onRequestStart?.(controller, null) + + if (aborted) { + return } - if (typeof handler.onComplete === 'function') { - handler.onComplete([]) + handler.onResponseStart?.(controller, 504, {}, 'Gateway Timeout') + if (aborted) { + return } + + handler.onResponseEnd?.(controller, {}) } catch (err) { - if (typeof handler.onError === 'function') { - handler.onError(err) + if (typeof handler.onResponseError === 'function') { + handler.onResponseError(controller, err) } } diff --git a/lib/mock/mock-utils.js b/lib/mock/mock-utils.js index e1e3f040643..3e48b83f57f 100644 --- a/lib/mock/mock-utils.js +++ b/lib/mock/mock-utils.js @@ -8,7 +8,7 @@ const { kOrigin, kGetNetConnect } = require('./mock-symbols') -const { serializePathWithQuery } = require('../core/util') +const { serializePathWithQuery, parseHeaders } = require('../core/util') const { STATUS_CODES } = require('node:http') const { types: { @@ -308,7 +308,7 @@ function mockDispatch (opts, handler) { // If specified, trigger dispatch error if (error !== null) { deleteMockDispatch(this[kDispatches], key) - handler.onError(error) + handler.onResponseError(null, error) return true } @@ -344,15 +344,28 @@ function mockDispatch (opts, handler) { const responseHeaders = generateKeyValues(headers) const responseTrailers = generateKeyValues(trailers) - handler.onConnect?.(err => handler.onError(err), null) - handler.onHeaders?.(statusCode, responseHeaders, resume, getStatusText(statusCode)) - handler.onData?.(Buffer.from(responseData)) - handler.onComplete?.(responseTrailers) + const controller = { + paused: false, + rawHeaders: responseHeaders, + rawTrailers: responseTrailers, + pause () { + this.paused = true + }, + resume () { + this.paused = false + }, + abort: (reason) => { + handler.onResponseError?.(controller, reason) + } + } + + handler.onRequestStart?.(controller, null) + handler.onResponseStart?.(controller, statusCode, parseHeaders(responseHeaders), getStatusText(statusCode)) + handler.onResponseData?.(controller, Buffer.from(responseData)) + handler.onResponseEnd?.(controller, parseHeaders(responseTrailers)) deleteMockDispatch(mockDispatches, key) } - function resume () {} - return true } diff --git a/lib/mock/snapshot-agent.js b/lib/mock/snapshot-agent.js index 80280111921..02886870963 100644 --- a/lib/mock/snapshot-agent.js +++ b/lib/mock/snapshot-agent.js @@ -3,7 +3,6 @@ const Agent = require('../dispatcher/agent') const MockAgent = require('./mock-agent') const { SnapshotRecorder } = require('./snapshot-recorder') -const WrapHandler = require('../handler/wrap-handler') const { InvalidArgumentError, UndiciError } = require('../core/errors') const { validateSnapshotMode } = require('./snapshot-utils') @@ -79,7 +78,6 @@ class SnapshotAgent extends MockAgent { } dispatch (opts, handler) { - handler = WrapHandler.wrap(handler) const mode = this[kSnapshotMode] // Check if URL should be excluded (pass through without mocking/recording) @@ -107,8 +105,8 @@ class SnapshotAgent extends MockAgent { } else { // Playback mode but no snapshot found const error = new UndiciError(`No snapshot found for ${opts.method || 'GET'} ${opts.path}`) - if (handler.onError) { - handler.onError(error) + if (handler.onResponseError) { + handler.onResponseError(null, error) return } throw error @@ -192,7 +190,35 @@ class SnapshotAgent extends MockAgent { try { const { response } = snapshot + const rawHeaders = [] + if (response.headers) { + for (const [name, value] of Object.entries(response.headers)) { + if (Array.isArray(value)) { + for (const entry of value) { + rawHeaders.push(Buffer.from(`${name}`), Buffer.from(`${entry}`)) + } + } else { + rawHeaders.push(Buffer.from(`${name}`), Buffer.from(`${value}`)) + } + } + } + + const rawTrailers = [] + if (response.trailers) { + for (const [name, value] of Object.entries(response.trailers)) { + if (Array.isArray(value)) { + for (const entry of value) { + rawTrailers.push(Buffer.from(`${name}`), Buffer.from(`${entry}`)) + } + } else { + rawTrailers.push(Buffer.from(`${name}`), Buffer.from(`${value}`)) + } + } + } + const controller = { + rawHeaders, + rawTrailers, pause () { }, resume () { }, abort (reason) { @@ -206,7 +232,7 @@ class SnapshotAgent extends MockAgent { handler.onRequestStart(controller) - handler.onResponseStart(controller, response.statusCode, response.headers) + handler.onResponseStart(controller, response.statusCode, response.headers, response.statusMessage) // Body is always stored as base64 string const body = Buffer.from(response.body, 'base64') @@ -214,7 +240,7 @@ class SnapshotAgent extends MockAgent { handler.onResponseEnd(controller, response.trailers) } catch (error) { - handler.onError?.(error) + handler.onResponseError?.(null, error) } } diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index bb33e8d77e8..43124a4c235 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -2146,7 +2146,7 @@ async function httpNetworkFetch ( body: null, abort: null, - onConnect (abort) { + onRequestStart (controller) { // TODO (fix): Do we need connection here? const { connection } = fetchParams.controller @@ -2156,6 +2156,8 @@ async function httpNetworkFetch ( // TODO: implement connection timing timingInfo.finalConnectionTimingInfo = clampAndCoarsenConnectionTimingInfo(undefined, timingInfo.postRedirectStartTime, fetchParams.crossOriginIsolatedCapability) + const abort = (reason) => controller.abort(reason) + if (connection.destroyed) { abort(new DOMException('The operation was aborted.', 'AbortError')) } else { @@ -2176,11 +2178,12 @@ async function httpNetworkFetch ( timingInfo.finalNetworkResponseStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) }, - onHeaders (status, rawHeaders, resume, statusText) { + onResponseStart (controller, status, _headers, statusText) { if (status < 200) { - return false + return } + const rawHeaders = controller?.rawHeaders ?? [] const headersList = new HeadersList() for (let i = 0; i < rawHeaders.length; i += 2) { @@ -2188,7 +2191,7 @@ async function httpNetworkFetch ( } const location = headersList.get('location', true) - this.body = new Readable({ read: resume }) + this.body = new Readable({ read: () => controller.resume() }) const willFollow = location && request.redirect === 'follow' && redirectStatusSet.has(status) @@ -2208,7 +2211,7 @@ async function httpNetworkFetch ( const maxContentEncodings = 5 if (codings.length > maxContentEncodings) { reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)) - return true + return } for (let i = codings.length - 1; i >= 0; --i) { @@ -2245,7 +2248,7 @@ async function httpNetworkFetch ( } } - const onError = this.onError.bind(this) + const onError = (err) => this.onResponseError(controller, err) resolve({ status, @@ -2254,16 +2257,14 @@ async function httpNetworkFetch ( body: decoders.length ? pipeline(this.body, ...decoders, (err) => { if (err) { - this.onError(err) + this.onResponseError(controller, err) } }).on('error', onError) : this.body.on('error', onError) }) - - return true }, - onData (chunk) { + onResponseData (controller, chunk) { if (fetchParams.controller.dump) { return } @@ -2283,20 +2284,22 @@ async function httpNetworkFetch ( // 4. See pullAlgorithm... - return this.body.push(bytes) + if (this.body.push(bytes) === false) { + controller.pause() + } }, - onComplete () { + onResponseEnd () { if (this.abort) { fetchParams.controller.off('terminated', this.abort) } fetchParams.controller.ended = true - this.body.push(null) + this.body?.push(null) }, - onError (error) { + onResponseError (_controller, error) { if (this.abort) { fetchParams.controller.off('terminated', this.abort) } @@ -2308,13 +2311,14 @@ async function httpNetworkFetch ( reject(error) }, - onUpgrade (status, rawHeaders, socket) { + onRequestUpgrade (controller, status, _headers, socket) { // We need to support 200 for websocket over h2 as per RFC-8441 // Absence of session means H1 if ((socket.session != null && status !== 200) || (socket.session == null && status !== 101)) { - return false + return } + const rawHeaders = controller?.rawHeaders ?? [] const headersList = new HeadersList() for (let i = 0; i < rawHeaders.length; i += 2) { @@ -2327,8 +2331,6 @@ async function httpNetworkFetch ( headersList, socket }) - - return true } } )) diff --git a/test/client-request.js b/test/client-request.js index d367435eeff..ff4abf4bb4f 100644 --- a/test/client-request.js +++ b/test/client-request.js @@ -154,8 +154,8 @@ test('request dump with abort signal', async (t) => { t.ok(stackLines[2].startsWith('at AbortController.abort')) t.ok(/client-request.js/.test(stackLines[3])) t.ok(stackLines[4].startsWith('at RequestHandler.runInAsyncScope')) - t.ok(stackLines[5].startsWith('at RequestHandler.onHeaders')) - t.ok(stackLines[6].startsWith('at Request.onHeaders')) + t.ok(stackLines[5].startsWith('at RequestHandler.onResponseStart')) + t.ok(stackLines[6].startsWith('at Request.onResponseStart')) server.close() }) ac.abort() @@ -193,8 +193,8 @@ test('request dump with POJO as invalid signal', async (t) => { t.ok(stackLines[1].startsWith('at BodyReadable.dump')) t.ok(/client-request.js/.test(stackLines[2])) t.ok(stackLines[3].startsWith('at RequestHandler.runInAsyncScope')) - t.ok(stackLines[4].startsWith('at RequestHandler.onHeaders')) - t.ok(stackLines[5].startsWith('at Request.onHeaders')) + t.ok(stackLines[4].startsWith('at RequestHandler.onResponseStart')) + t.ok(stackLines[5].startsWith('at Request.onResponseStart')) server.close() }) }) @@ -233,8 +233,8 @@ test('request dump with aborted signal', async (t) => { t.ok(stackLines[0].startsWith('AbortError: This operation was with purpose aborted')) t.ok(/client-request.js/.test(stackLines[1])) t.ok(stackLines[2].startsWith('at RequestHandler.runInAsyncScope')) - t.ok(stackLines[3].startsWith('at RequestHandler.onHeaders')) - t.ok(stackLines[4].startsWith('at Request.onHeaders')) + t.ok(stackLines[3].startsWith('at RequestHandler.onResponseStart')) + t.ok(stackLines[4].startsWith('at Request.onResponseStart')) server.close() }) ac.abort() diff --git a/test/issue-3934.js b/test/issue-3934.js index 3898f1144c6..1caa417a48f 100644 --- a/test/issue-3934.js +++ b/test/issue-3934.js @@ -7,7 +7,7 @@ const assert = require('node:assert') const { Agent, RetryAgent, request } = require('..') // https://github.com/nodejs/undici/issues/3934 -test('WrapHandler works with multiple header values', async (t) => { +test('request preserves multiple header values', async (t) => { const server = createServer({ joinDuplicateHeaders: true }, async (_req, res) => { const headers = [ ['set-cookie', 'a'], diff --git a/test/node-test/util.js b/test/node-test/util.js index c3f363ff40a..267486869f8 100644 --- a/test/node-test/util.js +++ b/test/node-test/util.js @@ -32,50 +32,58 @@ test('getServerName', () => { test('assertRequestHandler', () => { assert.throws(() => util.assertRequestHandler(null), InvalidArgumentError, 'handler must be an object') assert.throws(() => util.assertRequestHandler({ - onConnect: null - }), InvalidArgumentError, 'invalid onConnect method') + onRequestStart: null + }), InvalidArgumentError, 'invalid onRequestStart method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: null - }), InvalidArgumentError, 'invalid onError method') + onRequestStart: () => {}, + onResponseError: null + }), InvalidArgumentError, 'invalid onResponseError method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: null }), InvalidArgumentError, 'invalid onBodySent method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, + onRequestSent: null + }), InvalidArgumentError, 'invalid onRequestSent method') + assert.throws(() => util.assertRequestHandler({ + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: () => {}, - onHeaders: null - }), InvalidArgumentError, 'invalid onHeaders method') + onRequestSent: () => {}, + onResponseStart: null + }), InvalidArgumentError, 'invalid onResponseStart method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: () => {}, - onHeaders: () => {}, - onData: null - }), InvalidArgumentError, 'invalid onData method') + onRequestSent: () => {}, + onResponseStart: () => {}, + onResponseData: null + }), InvalidArgumentError, 'invalid onResponseData method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: () => {}, - onHeaders: () => {}, - onData: () => {}, - onComplete: null - }), InvalidArgumentError, 'invalid onComplete method') + onRequestSent: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: null + }), InvalidArgumentError, 'invalid onResponseEnd method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: () => {}, - onUpgrade: 'null' - }, 'CONNECT'), InvalidArgumentError, 'invalid onUpgrade method') + onRequestUpgrade: 'null' + }, 'CONNECT'), InvalidArgumentError, 'invalid onRequestUpgrade method') assert.throws(() => util.assertRequestHandler({ - onConnect: () => {}, - onError: () => {}, + onRequestStart: () => {}, + onResponseError: () => {}, onBodySent: () => {}, - onUpgrade: 'null' - }, 'CONNECT', () => {}), InvalidArgumentError, 'invalid onUpgrade method') + onRequestUpgrade: 'null' + }, 'CONNECT', () => {}), InvalidArgumentError, 'invalid onRequestUpgrade method') }) test('parseHeaders', () => { From 70eb123585f4d6213f15dc67ab636ef561b2d80c Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 15:48:10 +0000 Subject: [PATCH 07/16] test: migrate handlers to new api --- test/client-timeout.js | 48 ++--- test/decorator-handler.js | 93 ++++---- test/http2-body.js | 19 +- test/http2-trailers.js | 16 +- test/mock-agent.js | 18 +- test/mock-client.js | 16 +- test/mock-interceptor.js | 48 +++-- test/mock-pool.js | 16 +- test/node-test/agent.js | 42 ++-- test/node-test/client-abort.js | 48 ++--- test/node-test/client-dispatch.js | 341 +++++++++++++++--------------- test/pool.js | 60 +++--- test/retry-handler.js | 150 ++++++------- test/retry-handler2.js | 150 ++++++------- types/dispatcher.d.ts | 26 +-- 15 files changed, 548 insertions(+), 543 deletions(-) diff --git a/test/client-timeout.js b/test/client-timeout.js index 26cf21913c2..4a5c2bc9059 100644 --- a/test/client-timeout.js +++ b/test/client-timeout.js @@ -26,21 +26,21 @@ test('refresh timeout on pause', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers, resume) { + onResponseStart (controller) { setTimeout(() => { - resume() + controller.resume() }, 1000) - return false + controller.pause() }, - onData () { + onResponseData () { }, - onComplete () { + onResponseEnd () { }, - onError (err) { + onResponseError (_controller, err) { t.ok(err instanceof errors.BodyTimeoutError) } }) @@ -78,7 +78,7 @@ test('start headers timeout after request body', async (t) => { body, method: 'GET' }, { - onConnect () { + onRequestStart () { process.nextTick(() => { clock.tick(200) }) @@ -89,15 +89,15 @@ test('start headers timeout after request body', async (t) => { }) }) }, - onHeaders (statusCode, headers, resume) { + onResponseStart () { }, - onData () { + onResponseData () { }, - onComplete () { + onResponseEnd () { }, - onError (err) { + onResponseError (_controller, err) { t.equal(body.readableEnded, true) t.ok(err instanceof errors.HeadersTimeoutError) } @@ -141,7 +141,7 @@ test('start headers timeout after async iterator request body', async (t) => { body, method: 'GET' }, { - onConnect () { + onRequestStart () { process.nextTick(() => { clock.tick(200) }) @@ -149,15 +149,15 @@ test('start headers timeout after async iterator request body', async (t) => { res() }) }, - onHeaders (statusCode, headers, resume) { + onResponseStart () { }, - onData () { + onResponseData () { }, - onComplete () { + onResponseEnd () { }, - onError (err) { + onResponseError (_controller, err) { t.ok(err instanceof errors.HeadersTimeoutError) } }) @@ -184,19 +184,19 @@ test('parser resume with no body timeout', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers, resume) { - setTimeout(resume, 2000) - return false + onResponseStart (controller) { + setTimeout(() => controller.resume(), 2000) + controller.pause() }, - onData () { + onResponseData () { }, - onComplete () { + onResponseEnd () { t.ok(true, 'pass') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } }) diff --git a/test/decorator-handler.js b/test/decorator-handler.js index fc3e657f169..06c2e83b011 100644 --- a/test/decorator-handler.js +++ b/test/decorator-handler.js @@ -33,28 +33,28 @@ describe('DecoratorHandler', () => { this.#handler = handler } - onConnect (abort, context) { - return this.#handler?.onConnect?.(abort, context) + onRequestStart (controller, context) { + return this.#handler?.onRequestStart?.(controller, context) } - onHeaders (statusCode, rawHeaders, resume, statusMessage) { - return this.#handler?.onHeaders?.(statusCode, rawHeaders, resume, statusMessage) + onResponseStart (controller, statusCode, headers, statusMessage) { + return this.#handler?.onResponseStart?.(controller, statusCode, headers, statusMessage) } - onUpgrade (statusCode, rawHeaders, socket) { - return this.#handler?.onUpgrade?.(statusCode, rawHeaders, socket) + onRequestUpgrade (controller, statusCode, headers, socket) { + return this.#handler?.onRequestUpgrade?.(controller, statusCode, headers, socket) } - onData (data) { - return this.#handler?.onData?.(data) + onResponseData (controller, data) { + return this.#handler?.onResponseData?.(controller, data) } - onComplete (trailers) { - return this.#handler?.onComplete?.(trailers) + onResponseEnd (controller, trailers) { + return this.#handler?.onResponseEnd?.(controller, trailers) } - onError (err) { - return this.#handler?.onError?.(err) + onResponseError (controller, err) { + return this.#handler?.onResponseError?.(controller, err) } } const Controller = class { @@ -76,13 +76,14 @@ describe('DecoratorHandler', () => { } } - describe('#onConnect', () => { - test('should delegate onConnect-method', t => { - t = tspl(t, { plan: 2 }) + describe('#onRequestStart', () => { + test('should delegate onRequestStart-method', t => { + t = tspl(t, { plan: 3 }) const handler = new Handler( { - onConnect: (abort, ctx) => { - t.equal(typeof abort, 'function') + onRequestStart: (controller, ctx) => { + t.equal(typeof controller, 'object') + t.equal(typeof controller.abort, 'function') t.equal(typeof ctx, 'object') } }) @@ -90,22 +91,22 @@ describe('DecoratorHandler', () => { decorator.onRequestStart(new Controller(), {}) }) - test('should not throw if onConnect-method is not defined in the handler', t => { + test('should not throw if onRequestStart-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) t.doesNotThrow(() => decorator.onRequestStart()) }) }) - describe('#onHeaders', () => { - test('should delegate onHeaders-method', t => { + describe('#onResponseStart', () => { + test('should delegate onResponseStart-method', t => { t = tspl(t, { plan: 4 }) const handler = new Handler( { - onHeaders: (statusCode, headers, resume, statusMessage) => { - t.equal(statusCode, '200') - t.equal(`${headers[0].toString('utf-8')}: ${headers[1].toString('utf-8')}`, 'content-type: application/json') - t.equal(typeof resume, 'function') + onResponseStart: (controller, statusCode, headers, statusMessage) => { + t.equal(statusCode, 200) + t.equal(headers['content-type'], 'application/json') + t.equal(typeof controller.resume, 'function') t.equal(statusMessage, 'OK') } }) @@ -115,7 +116,7 @@ describe('DecoratorHandler', () => { }, 'OK') }) - test('should not throw if onHeaders-method is not defined in the handler', t => { + test('should not throw if onResponseStart-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) t.doesNotThrow(() => decorator.onResponseStart(new Controller(), 200, { @@ -124,14 +125,14 @@ describe('DecoratorHandler', () => { }) }) - describe('#onUpgrade', () => { - test('should delegate onUpgrade-method', t => { + describe('#onRequestUpgrade', () => { + test('should delegate onRequestUpgrade-method', t => { t = tspl(t, { plan: 3 }) const handler = new Handler( { - onUpgrade: (statusCode, headers, socket) => { + onRequestUpgrade: (_controller, statusCode, headers, socket) => { t.equal(statusCode, 301) - t.equal(`${headers[0].toString('utf-8')}: ${headers[1].toString('utf-8')}`, 'content-type: application/json') + t.equal(headers['content-type'], 'application/json') t.equal(typeof socket, 'object') } }) @@ -141,7 +142,7 @@ describe('DecoratorHandler', () => { }, {}) }) - test('should not throw if onUpgrade-method is not defined in the handler', t => { + test('should not throw if onRequestUpgrade-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) t.doesNotThrow(() => decorator.onRequestUpgrade(new Controller(), 301, { @@ -150,12 +151,12 @@ describe('DecoratorHandler', () => { }) }) - describe('#onData', () => { - test('should delegate onData-method', t => { + describe('#onResponseData', () => { + test('should delegate onResponseData-method', t => { t = tspl(t, { plan: 1 }) const handler = new Handler( { - onData: (chunk) => { + onResponseData: (_controller, chunk) => { t.equal('chunk', chunk) } }) @@ -163,39 +164,39 @@ describe('DecoratorHandler', () => { decorator.onResponseData(new Controller(), 'chunk') }) - test('should not throw if onData-method is not defined in the handler', t => { + test('should not throw if onResponseData-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) t.doesNotThrow(() => decorator.onResponseData(new Controller(), 'chunk')) }) }) - describe('#onComplete', () => { - test('should delegate onComplete-method', t => { + describe('#onResponseEnd', () => { + test('should delegate onResponseEnd-method', t => { t = tspl(t, { plan: 1 }) const handler = new Handler( { - onComplete: (trailers) => { - t.equal(`${trailers[0].toString('utf-8')}: ${trailers[1].toString('utf-8')}`, 'x-trailer: trailer') + onResponseEnd: (_controller, trailers) => { + t.equal(trailers['x-trailer'], 'trailer') } }) const decorator = new DecoratorHandler(handler) decorator.onResponseEnd(new Controller(), { 'x-trailer': 'trailer' }) }) - test('should not throw if onComplete-method is not defined in the handler', t => { + test('should not throw if onResponseEnd-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) t.doesNotThrow(() => decorator.onResponseEnd(new Controller(), { 'x-trailer': 'trailer' })) }) }) - describe('#onError', () => { - test('should delegate onError-method', t => { + describe('#onResponseError', () => { + test('should delegate onResponseError-method', t => { t = tspl(t, { plan: 1 }) const handler = new Handler( { - onError: (err) => { + onResponseError: (_controller, err) => { t.equal(err.message, 'Oops!') } }) @@ -203,10 +204,10 @@ describe('DecoratorHandler', () => { decorator.onResponseError(new Controller(), new Error('Oops!')) }) - test('should throw if onError-method is not defined in the handler', t => { + test('should not throw if onResponseError-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({}) - t.throws(() => decorator.onResponseError(new Controller(), new Error('Oops!'))) + t.doesNotThrow(() => decorator.onResponseError(new Controller(), new Error('Oops!'))) }) }) }) @@ -379,7 +380,7 @@ describe('DecoratorHandler', () => { }) describe('#onResponseError', () => { - test('should delegate onError-method', t => { + test('should delegate onResponseError-method', t => { t = tspl(t, { plan: 2 }) const handler = new Handler( { @@ -392,7 +393,7 @@ describe('DecoratorHandler', () => { decorator.onResponseError(new Controller(), new Error('Oops!')) }) - test('should throw if onError-method is not defined in the handler', t => { + test('should throw if onResponseError-method is not defined in the handler', t => { t = tspl(t, { plan: 1 }) const decorator = new DecoratorHandler({ // To hin and not wrap the instance diff --git a/test/http2-body.js b/test/http2-body.js index ac1d7fc2ff7..0db11a8b634 100644 --- a/test/http2-body.js +++ b/test/http2-body.js @@ -111,29 +111,30 @@ test('Should handle h2 request with body (string or buffer) - dispatch', async t body: expectedBody }, { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) }, - onHeaders (statusCode, headers) { + onResponseStart (controller, statusCode) { + const rawHeaders = controller.rawHeaders t.strictEqual(statusCode, 200) - t.strictEqual(headers[0].toString('utf-8'), 'content-type') + t.strictEqual(rawHeaders[0].toString('utf-8'), 'content-type') t.strictEqual( - headers[1].toString('utf-8'), + rawHeaders[1].toString('utf-8'), 'text/plain; charset=utf-8' ) - t.strictEqual(headers[2].toString('utf-8'), 'x-custom-h2') - t.strictEqual(headers[3].toString('utf-8'), 'foo') + t.strictEqual(rawHeaders[2].toString('utf-8'), 'x-custom-h2') + t.strictEqual(rawHeaders[3].toString('utf-8'), 'foo') }, - onData (chunk) { + onResponseData (_controller, chunk) { response.push(chunk) }, onBodySent (body) { t.strictEqual(body.toString('utf-8'), expectedBody) }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(response).toString('utf-8'), 'hello h2!') t.strictEqual( Buffer.concat(requestBody).toString('utf-8'), diff --git a/test/http2-trailers.js b/test/http2-trailers.js index 2d49e8b0bc2..673252c8d21 100644 --- a/test/http2-trailers.js +++ b/test/http2-trailers.js @@ -49,19 +49,13 @@ test('Should handle http2 trailers', async t => { method: 'PUT', body: 'hello' }, { - onConnect () { - - }, - onHeaders () { - return true - }, - onData () { - return true - }, - onComplete (trailers) { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd (_controller, trailers) { t.strictEqual(trailers['x-trailer'], 'hello') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } }) diff --git a/test/mock-agent.js b/test/mock-agent.js index bb3d2afb9f7..ff0122c8f42 100644 --- a/test/mock-agent.js +++ b/test/mock-agent.js @@ -194,10 +194,11 @@ describe('MockAgent - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => resume(), - onData: () => {}, - onComplete: () => {}, - onError: () => {} + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} })) }) @@ -221,10 +222,11 @@ describe('MockAgent - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => resume(), - onData: () => {}, - onComplete: () => {}, - onError: () => {} + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} })) }) }) diff --git a/test/mock-client.js b/test/mock-client.js index e89bc516e52..751f157332d 100644 --- a/test/mock-client.js +++ b/test/mock-client.js @@ -60,9 +60,11 @@ describe('MockClient - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => resume(), - onData: () => {}, - onComplete: () => {} + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} })) }) @@ -95,9 +97,11 @@ describe('MockClient - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => { throw new Error('kaboom') }, - onData: () => {}, - onComplete: () => {} + onRequestStart () {}, + onResponseStart () { throw new Error('kaboom') }, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} }), new Error('kaboom')) }) }) diff --git a/test/mock-interceptor.js b/test/mock-interceptor.js index 1114b9075d3..099c48f2075 100644 --- a/test/mock-interceptor.js +++ b/test/mock-interceptor.js @@ -100,9 +100,11 @@ describe('MockInterceptor - reply options callback', () => { method: 'GET', headers: { foo: 'bar' } }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }) }) @@ -140,9 +142,11 @@ describe('MockInterceptor - reply options callback', () => { method: 'GET', headers: { foo: 'bar' } }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }) }) @@ -186,36 +190,44 @@ describe('MockInterceptor - reply options callback', () => { path: '/test-return-undefined', method: 'GET' }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }), new InvalidArgumentError('reply options callback must return an object')) t.assert.throws(() => mockPool.dispatch({ path: '/test-return-null', method: 'GET' }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }), new InvalidArgumentError('reply options callback must return an object')) t.assert.throws(() => mockPool.dispatch({ path: '/test3', method: 'GET' }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }), new InvalidArgumentError('responseOptions must be an object')) t.assert.throws(() => mockPool.dispatch({ path: '/test4', method: 'GET' }, { - onHeaders: () => { }, - onData: () => { }, - onComplete: () => { } + onRequestStart: () => {}, + onResponseStart: () => {}, + onResponseData: () => {}, + onResponseEnd: () => {}, + onResponseError: () => {} }), new InvalidArgumentError('statusCode must be defined')) }) }) diff --git a/test/mock-pool.js b/test/mock-pool.js index ca4805dc434..0213397963d 100644 --- a/test/mock-pool.js +++ b/test/mock-pool.js @@ -61,9 +61,11 @@ describe('MockPool - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => resume(), - onData: () => { }, - onComplete: () => { } + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} })) }) @@ -96,9 +98,11 @@ describe('MockPool - dispatch', () => { path: '/foo', method: 'GET' }, { - onHeaders: (_statusCode, _headers, resume) => { throw new Error('kaboom') }, - onData: () => { }, - onComplete: () => { } + onRequestStart () {}, + onResponseStart () { throw new Error('kaboom') }, + onResponseData () {}, + onResponseEnd () {}, + onResponseError () {} }), new Error('kaboom')) }) }) diff --git a/test/node-test/agent.js b/test/node-test/agent.js index d9aee46b597..2a8ba20912d 100644 --- a/test/node-test/agent.js +++ b/test/node-test/agent.js @@ -318,13 +318,13 @@ test('agent factory supports URL parameter', async (t) => { const p = tspl(t, { plan: 2 }) const noopHandler = { - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { server.close() }, - onError (err) { + onResponseError (_controller, err) { throw err } } @@ -356,13 +356,13 @@ test('agent factory supports string parameter', async (t) => { const p = tspl(t, { plan: 2 }) const noopHandler = { - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { server.close() }, - onError (err) { + onResponseError (_controller, err) { throw err } } @@ -709,13 +709,13 @@ test('dispatch validations', async t => { const dispatcher = new Agent() const noopHandler = { - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { server.close() }, - onError (err) { + onResponseError (_controller, err) { throw err } } @@ -730,7 +730,7 @@ test('dispatch validations', async t => { p.throws(() => dispatcher.dispatch('ASD', noopHandler), errors.InvalidArgumentError, 'throws on invalid opts argument type') p.throws(() => dispatcher.dispatch({}, noopHandler), errors.InvalidArgumentError, 'throws on invalid opts.origin argument') p.throws(() => dispatcher.dispatch({ origin: '' }, noopHandler), errors.InvalidArgumentError, 'throws on invalid opts.origin argument') - p.throws(() => dispatcher.dispatch({}, {}), errors.InvalidArgumentError, 'throws on invalid handler.onError') + p.throws(() => dispatcher.dispatch({}, {}), errors.InvalidArgumentError, 'throws on invalid handler.onResponseError') server.listen(0, () => { p.doesNotThrow(() => dispatcher.dispatch({ @@ -756,11 +756,11 @@ test('drain', async t => { }) class Handler { - onConnect () {} - onHeaders () {} - onData () {} - onComplete () {} - onError () { + onRequestStart () {} + onResponseStart () {} + onResponseData () {} + onResponseEnd () {} + onResponseError () { p.fail() } } diff --git a/test/node-test/client-abort.js b/test/node-test/client-abort.js index cf0c6fc1553..346e149bdf0 100644 --- a/test/node-test/client-abort.js +++ b/test/node-test/client-abort.js @@ -85,19 +85,19 @@ test('abort', async (t) => { method: 'GET', path: '/' }, { - onConnect (abort) { - setImmediate(abort) + onRequestStart (controller) { + setImmediate(() => controller.abort()) }, - onHeaders () { + onResponseStart () { p.ok(0) }, - onData () { + onResponseData () { p.ok(0) }, - onComplete () { + onResponseEnd () { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.RequestAbortedError) } }) @@ -129,23 +129,23 @@ test('abort pipelined', async (t) => { path: '/', blocking: false }, { - onConnect (abort) { + onRequestStart (controller) { // This request will be retried if (counter++ === 1) { - abort() + controller.abort() } p.ok(1) }, - onHeaders () { + onResponseStart () { p.ok(0) }, - onData () { + onResponseData () { p.ok(0) }, - onComplete () { + onResponseEnd () { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.RequestAbortedError) } }) @@ -155,19 +155,19 @@ test('abort pipelined', async (t) => { path: '/', blocking: false }, { - onConnect (abort) { - abort() + onRequestStart (controller) { + controller.abort() }, - onHeaders () { + onResponseStart () { p.ok(0) }, - onData () { + onResponseData () { p.ok(0) }, - onComplete () { + onResponseEnd () { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.RequestAbortedError) } }) @@ -196,19 +196,19 @@ test('propagate unallowed throws in request.onError', async (t) => { method: 'GET', path: '/' }, { - onConnect (abort) { - setImmediate(abort) + onRequestStart (controller) { + setImmediate(() => controller.abort()) }, - onHeaders () { + onResponseStart () { p.ok(0) }, - onData () { + onResponseData () { p.ok(0) }, - onComplete () { + onResponseEnd () { p.ok(0) }, - onError () { + onResponseError () { throw new OnAbortError('error') } }) diff --git a/test/node-test/client-dispatch.js b/test/node-test/client-dispatch.js index 06862150efb..0a278e5a8f3 100644 --- a/test/node-test/client-dispatch.js +++ b/test/node-test/client-dispatch.js @@ -43,7 +43,7 @@ test('dispatch invalid opts', (t) => { method: 'GET', upgrade: 1 }, { - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.InvalidArgumentError) p.strictEqual(err.message, 'upgrade must be a string') } @@ -54,7 +54,7 @@ test('dispatch invalid opts', (t) => { method: 'GET', headersTimeout: 'asd' }, { - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.InvalidArgumentError) p.strictEqual(err.message, 'invalid headersTimeout') } @@ -65,7 +65,7 @@ test('dispatch invalid opts', (t) => { method: 'GET', bodyTimeout: 'asd' }, { - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.InvalidArgumentError) p.strictEqual(err.message, 'invalid bodyTimeout') } @@ -77,14 +77,14 @@ test('dispatch invalid opts', (t) => { method: 'GET', bodyTimeout: 'asd' }, { - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.InvalidArgumentError) p.strictEqual(err.message, 'invalid bodyTimeout') } }) client.dispatch(null, { - onError (err) { + onResponseError (_controller, err) { p.ok(err instanceof errors.InvalidArgumentError) p.strictEqual(err.message, 'opts must be an object.') } @@ -122,20 +122,21 @@ test('basic dispatch get', async (t) => { method: 'GET', headers: reqHeaders }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (controller, statusCode) { + const rawHeaders = controller.rawHeaders p.strictEqual(statusCode, 200) - p.strictEqual(Array.isArray(headers), true) + p.strictEqual(Array.isArray(rawHeaders), true) }, - onData (buf) { + onResponseData (_controller, buf) { bufs.push(buf) }, - onComplete (trailers) { - p.deepStrictEqual(trailers, []) + onResponseEnd (controller) { + p.deepStrictEqual(controller.rawTrailers, []) p.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }, - onError () { + onResponseError () { p.ok(0) } }) @@ -176,28 +177,30 @@ test('trailers dispatch get', async (t) => { method: 'GET', headers: reqHeaders }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (controller, statusCode) { + const rawHeaders = controller.rawHeaders p.strictEqual(statusCode, 200) - p.strictEqual(Array.isArray(headers), true) + p.strictEqual(Array.isArray(rawHeaders), true) { - const contentTypeIdx = headers.findIndex(x => x.toString() === 'Content-Type') - p.strictEqual(headers[contentTypeIdx + 1].toString(), 'text/plain') + const contentTypeIdx = rawHeaders.findIndex(x => x.toString() === 'Content-Type') + p.strictEqual(rawHeaders[contentTypeIdx + 1].toString(), 'text/plain') } }, - onData (buf) { + onResponseData (_controller, buf) { bufs.push(buf) }, - onComplete (trailers) { - p.strictEqual(Array.isArray(trailers), true) + onResponseEnd (controller) { + const rawTrailers = controller.rawTrailers + p.strictEqual(Array.isArray(rawTrailers), true) { - const contentMD5Idx = trailers.findIndex(x => x.toString() === 'Content-MD5') - p.strictEqual(trailers[contentMD5Idx + 1].toString(), 'test') + const contentMD5Idx = rawTrailers.findIndex(x => x.toString() === 'Content-MD5') + p.strictEqual(rawTrailers[contentMD5Idx + 1].toString(), 'test') } p.strictEqual('hello', Buffer.concat(bufs).toString('utf8')) }, - onError () { + onResponseError () { p.ok(0) } }) @@ -206,7 +209,7 @@ test('trailers dispatch get', async (t) => { await p.completed }) -test('dispatch onHeaders error', async (t) => { +test('dispatch onResponseStart error', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -223,18 +226,18 @@ test('dispatch onHeaders error', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { throw _err }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err, _err) } }) @@ -243,7 +246,7 @@ test('dispatch onHeaders error', async (t) => { await p.completed }) -test('dispatch onComplete error', async (t) => { +test('dispatch onResponseEnd error', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -260,18 +263,18 @@ test('dispatch onComplete error', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(1) }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { throw _err }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err, _err) } }) @@ -280,7 +283,7 @@ test('dispatch onComplete error', async (t) => { await p.completed }) -test('dispatch onData error', async (t) => { +test('dispatch onResponseData error', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -297,18 +300,18 @@ test('dispatch onData error', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(1) }, - onData (buf) { + onResponseData (_controller, buf) { throw _err }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err, _err) } }) @@ -317,7 +320,7 @@ test('dispatch onData error', async (t) => { await p.completed }) -test('dispatch onConnect error', async (t) => { +test('dispatch onRequestStart error', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -334,19 +337,19 @@ test('dispatch onConnect error', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { throw _err }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(0) }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err, _err) } }) @@ -355,7 +358,7 @@ test('dispatch onConnect error', async (t) => { await p.completed }) -test('connect call onUpgrade once', async (t) => { +test('connect call onRequestUpgrade once', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (c) => { @@ -385,12 +388,12 @@ test('connect call onUpgrade once', async (t) => { method: 'CONNECT', path: '/' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { t.ok(true, 'should not throw') }, - onUpgrade (statusCode, headers, socket) { + onRequestUpgrade (_controller, statusCode, _headers, socket) { p.strictEqual(count++, 0) socket.on('data', (d) => { @@ -404,13 +407,13 @@ test('connect call onUpgrade once', async (t) => { socket.write('Body') socket.end() }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0) }, - onError () { + onResponseError () { p.ok(0) } }) @@ -419,7 +422,7 @@ test('connect call onUpgrade once', async (t) => { await p.completed }) -test('dispatch onHeaders missing', async (t) => { +test('dispatch onResponseStart missing', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -435,15 +438,15 @@ test('dispatch onHeaders missing', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0, 'should not throw') }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0, 'should not throw') }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') } }) @@ -452,7 +455,7 @@ test('dispatch onHeaders missing', async (t) => { await p.completed }) -test('dispatch onData missing', async (t) => { +test('dispatch onResponseData missing', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -468,15 +471,15 @@ test('dispatch onData missing', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(0, 'should not throw') }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0, 'should not throw') }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') } }) @@ -485,7 +488,7 @@ test('dispatch onData missing', async (t) => { await p.completed }) -test('dispatch onComplete missing', async (t) => { +test('dispatch onResponseEnd missing', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -501,15 +504,15 @@ test('dispatch onComplete missing', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(0) }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') } }) @@ -518,7 +521,7 @@ test('dispatch onComplete missing', async (t) => { await p.completed }) -test('dispatch onError missing', async (t) => { +test('dispatch onResponseError missing', async (t) => { const p = tspl(t, { plan: 1 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -535,15 +538,15 @@ test('dispatch onError missing', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { p.ok(0) }, - onData (buf) { + onResponseData (_controller, buf) { p.ok(0) }, - onComplete (trailers) { + onResponseEnd (_controller, _trailers) { p.ok(0) } }) @@ -555,7 +558,7 @@ test('dispatch onError missing', async (t) => { await p.completed }) -test('dispatch CONNECT onUpgrade missing', async (t) => { +test('dispatch CONNECT onRequestUpgrade missing', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -572,13 +575,13 @@ test('dispatch CONNECT onUpgrade missing', async (t) => { method: 'GET', upgrade: 'Websocket' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') - p.strictEqual(err.message, 'invalid onUpgrade method') + p.strictEqual(err.message, 'invalid onRequestUpgrade method') } }) }) @@ -586,7 +589,7 @@ test('dispatch CONNECT onUpgrade missing', async (t) => { await p.completed }) -test('dispatch upgrade onUpgrade missing', async (t) => { +test('dispatch upgrade onRequestUpgrade missing', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -603,13 +606,13 @@ test('dispatch upgrade onUpgrade missing', async (t) => { method: 'GET', upgrade: 'Websocket' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, _headers) { }, - onError (err) { + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') - p.strictEqual(err.message, 'invalid onUpgrade method') + p.strictEqual(err.message, 'invalid onRequestUpgrade method') } }) }) @@ -617,7 +620,7 @@ test('dispatch upgrade onUpgrade missing', async (t) => { await p.completed }) -test('dispatch pool onError missing', async (t) => { +test('dispatch pool onResponseError missing', async (t) => { const p = tspl(t, { plan: 2 }) const server = http.createServer({ joinDuplicateHeaders: true }, (req, res) => { @@ -661,10 +664,10 @@ test('dispatch onBodySent not a function', async (t) => { method: 'GET' }, { onBodySent: '42', - onConnect () {}, - onHeaders () {}, - onData () {}, - onError (err) { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseError (_controller, err) { p.strictEqual(err.code, 'UND_ERR_INVALID_ARG') p.strictEqual(err.message, 'invalid onBodySent method') } @@ -697,13 +700,13 @@ test('dispatch onBodySent buffer', async (t) => { onRequestSent () { p.ok(1) }, - onError (err) { + onResponseError (_controller, err) { throw err }, - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { p.ok(1) } }) @@ -738,13 +741,13 @@ test('dispatch onBodySent stream', async (t) => { onRequestSent () { p.ok(1) }, - onError (err) { + onResponseError (_controller, err) { throw err }, - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { p.strictEqual(currentChunk, chunks.length) p.strictEqual(sentBytes, toSendBytes) p.ok(1) @@ -776,13 +779,13 @@ test('dispatch onBodySent async-iterable', (t, done) => { assert.strictEqual(chunks[currentChunk++], chunk) sentBytes += Buffer.byteLength(chunk) }, - onError (err) { + onResponseError (_controller, err) { throw err }, - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () { + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () { assert.strictEqual(currentChunk, chunks.length) assert.strictEqual(sentBytes, toSendBytes) done() @@ -809,15 +812,15 @@ test('dispatch onBodySent throws error', (t, done) => { onBodySent (chunk) { throw new Error('fail') }, - onError (err) { + onResponseError (_controller, err) { assert.ok(err instanceof Error) assert.strictEqual(err.message, 'fail') done() }, - onConnect () {}, - onHeaders () {}, - onData () {}, - onComplete () {} + onRequestStart () {}, + onResponseStart () {}, + onResponseData () {}, + onResponseEnd () {} }) }) }) @@ -842,8 +845,8 @@ test('dispatches in expected order', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches.push('onConnect') + onRequestStart () { + dispatches.push('onRequestStart') }, onBodySent () { dispatches.push('onBodySent') @@ -851,17 +854,17 @@ test('dispatches in expected order', async (t) => { onResponseStarted () { dispatches.push('onResponseStarted') }, - onHeaders () { - dispatches.push('onHeaders') + onResponseStart () { + dispatches.push('onResponseStart') }, - onData () { - dispatches.push('onData') + onResponseData () { + dispatches.push('onResponseData') }, - onComplete () { - dispatches.push('onComplete') - p.deepStrictEqual(dispatches, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + onResponseEnd () { + dispatches.push('onResponseEnd') + p.deepStrictEqual(dispatches, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) @@ -899,8 +902,8 @@ test('dispatches in expected order for http2', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches.push('onConnect') + onRequestStart () { + dispatches.push('onRequestStart') }, onBodySent () { dispatches.push('onBodySent') @@ -908,17 +911,17 @@ test('dispatches in expected order for http2', async (t) => { onResponseStarted () { dispatches.push('onResponseStarted') }, - onHeaders () { - dispatches.push('onHeaders') + onResponseStart () { + dispatches.push('onResponseStart') }, - onData () { - dispatches.push('onData') + onResponseData () { + dispatches.push('onResponseData') }, - onComplete () { - dispatches.push('onComplete') - p.deepStrictEqual(dispatches, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + onResponseEnd () { + dispatches.push('onResponseEnd') + p.deepStrictEqual(dispatches, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) @@ -957,8 +960,8 @@ test('Issue#3065 - fix bad destroy handling', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches.push('onConnect') + onRequestStart () { + dispatches.push('onRequestStart') }, onBodySent () { dispatches.push('onBodySent') @@ -966,17 +969,17 @@ test('Issue#3065 - fix bad destroy handling', async (t) => { onResponseStarted () { dispatches.push('onResponseStarted') }, - onHeaders () { - dispatches.push('onHeaders') + onResponseStart () { + dispatches.push('onResponseStart') }, - onData () { - dispatches.push('onData') + onResponseData () { + dispatches.push('onResponseData') }, - onComplete () { - dispatches.push('onComplete') - p.deepStrictEqual(dispatches, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + onResponseEnd () { + dispatches.push('onResponseEnd') + p.deepStrictEqual(dispatches, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) @@ -987,8 +990,8 @@ test('Issue#3065 - fix bad destroy handling', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches2.push('onConnect') + onRequestStart () { + dispatches2.push('onRequestStart') }, onBodySent () { dispatches2.push('onBodySent') @@ -996,17 +999,17 @@ test('Issue#3065 - fix bad destroy handling', async (t) => { onResponseStarted () { dispatches2.push('onResponseStarted') }, - onHeaders () { - dispatches2.push('onHeaders') + onResponseStart () { + dispatches2.push('onResponseStart') }, - onData () { - dispatches2.push('onData') + onResponseData () { + dispatches2.push('onResponseData') }, - onComplete () { - dispatches2.push('onComplete') - p.deepStrictEqual(dispatches2, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders', 'onData', 'onComplete']) + onResponseEnd () { + dispatches2.push('onResponseEnd') + p.deepStrictEqual(dispatches2, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) @@ -1051,8 +1054,8 @@ test('Issue#3065 - fix bad destroy handling (h2)', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches.push('onConnect') + onRequestStart () { + dispatches.push('onRequestStart') }, onBodySent () { dispatches.push('onBodySent') @@ -1060,17 +1063,17 @@ test('Issue#3065 - fix bad destroy handling (h2)', async (t) => { onResponseStarted () { dispatches.push('onResponseStarted') }, - onHeaders () { - dispatches.push('onHeaders1') + onResponseStart () { + dispatches.push('onResponseStart1') }, - onData () { - dispatches.push('onData') + onResponseData () { + dispatches.push('onResponseData') }, - onComplete () { - dispatches.push('onComplete') - p.deepStrictEqual(dispatches, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders1', 'onData', 'onComplete']) + onResponseEnd () { + dispatches.push('onResponseEnd') + p.deepStrictEqual(dispatches, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart1', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) @@ -1081,8 +1084,8 @@ test('Issue#3065 - fix bad destroy handling (h2)', async (t) => { method: 'POST', body: 'body' }, { - onConnect () { - dispatches2.push('onConnect') + onRequestStart () { + dispatches2.push('onRequestStart') }, onBodySent () { dispatches2.push('onBodySent') @@ -1090,17 +1093,17 @@ test('Issue#3065 - fix bad destroy handling (h2)', async (t) => { onResponseStarted () { dispatches2.push('onResponseStarted') }, - onHeaders () { - dispatches2.push('onHeaders2') + onResponseStart () { + dispatches2.push('onResponseStart2') }, - onData () { - dispatches2.push('onData') + onResponseData () { + dispatches2.push('onResponseData') }, - onComplete () { - dispatches2.push('onComplete') - p.deepStrictEqual(dispatches2, ['onConnect', 'onBodySent', 'onResponseStarted', 'onHeaders2', 'onData', 'onComplete']) + onResponseEnd () { + dispatches2.push('onResponseEnd') + p.deepStrictEqual(dispatches2, ['onRequestStart', 'onBodySent', 'onResponseStarted', 'onResponseStart2', 'onResponseData', 'onResponseEnd']) }, - onError (err) { + onResponseError (_controller, err) { p.ifError(err) } }) diff --git a/test/pool.js b/test/pool.js index 88f2b281af2..c93f017dc23 100644 --- a/test/pool.js +++ b/test/pool.js @@ -366,7 +366,7 @@ test('backpressure algorithm', async (t) => { } const noopHandler = { - onError (err) { + onResponseError (_controller, err) { throw err } } @@ -645,18 +645,18 @@ test('pool dispatch', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.strictEqual(statusCode, 200) }, - onData (chunk) { + onResponseData (_controller, chunk) { buf += chunk }, - onComplete () { + onResponseEnd () { t.strictEqual(buf, 'asd') }, - onError () { + onResponseError () { } }) }) @@ -792,17 +792,17 @@ test('pool dispatch error', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.strictEqual(statusCode, 200) }, - onData (chunk) { + onResponseData (_controller, chunk) { }, - onComplete () { + onResponseEnd () { t.ok(true, 'pass') }, - onError () { + onResponseError () { } }) @@ -813,16 +813,16 @@ test('pool dispatch error', async (t) => { 'transfer-encoding': 'fail' } }, { - onConnect () { + onRequestStart () { t.fail() }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.fail() }, - onData (chunk) { + onResponseData (_controller, chunk) { t.fail() }, - onError (err) { + onResponseError (_controller, err) { t.strictEqual(err.code, 'UND_ERR_INVALID_ARG') } }) @@ -850,17 +850,17 @@ test('pool request abort in queue', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.strictEqual(statusCode, 200) }, - onData (chunk) { + onResponseData (_controller, chunk) { }, - onComplete () { + onResponseEnd () { t.ok(true, 'pass') }, - onError () { + onResponseError () { } }) @@ -897,17 +897,17 @@ test('pool stream abort in queue', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.strictEqual(statusCode, 200) }, - onData (chunk) { + onResponseData (_controller, chunk) { }, - onComplete () { + onResponseEnd () { t.ok(true, 'pass') }, - onError () { + onResponseError () { } }) @@ -944,17 +944,17 @@ test('pool pipeline abort in queue', async (t) => { path: '/', method: 'GET' }, { - onConnect () { + onRequestStart () { }, - onHeaders (statusCode, headers) { + onResponseStart (_controller, statusCode, headers) { t.strictEqual(statusCode, 200) }, - onData (chunk) { + onResponseData (_controller, chunk) { }, - onComplete () { + onResponseEnd () { t.ok(true, 'pass') }, - onError () { + onResponseError () { } }) diff --git a/test/retry-handler.js b/test/retry-handler.js index 3a42fce3a7a..749b4d603b5 100644 --- a/test/retry-handler.js +++ b/test/retry-handler.js @@ -61,22 +61,22 @@ test('Should retry status code', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') t.strictEqual(counter, 2) }, - onError () { + onResponseError () { t.fail() } } @@ -156,22 +156,22 @@ test('Should account for network and response errors', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') t.strictEqual(counter, 2) }, - onError () { + onResponseError () { t.fail() } } @@ -227,19 +227,19 @@ test('Issue #3288 - request with body (asynciterable)', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { return true }, - onData (chunk) { + onResponseData (_controller, chunk) { return true }, - onComplete () { + onResponseEnd () { t.fail() }, - onError (err) { + onResponseError (_controller, err) { t.equal(err.message, 'Request failed') t.equal(err.statusCode, 500) t.equal(err.data.count, 1) @@ -304,21 +304,21 @@ test('Should use retry-after header for retries', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } } @@ -389,21 +389,21 @@ test('Should use retry-after header for retries (date)', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } } @@ -471,21 +471,21 @@ test('Should retry with defaults', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } } @@ -567,22 +567,22 @@ test('Should handle 206 partial content', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -652,20 +652,20 @@ test('Should handle 206 partial content - bad-etag', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (_status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, _status, _headers, _statusMessage) { return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.ifError('should not complete') }, - onError (err) { + onResponseError (_controller, err) { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abc') t.strictEqual(err.code, 'UND_ERR_REQ_RETRY') t.strictEqual(err.message, 'ETag mismatch') @@ -940,21 +940,21 @@ test('should not error if request is not meant to be retried', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 400) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'Bad request') }, - onError (err) { + onResponseError (_controller, err) { t.fail(err) } } @@ -1108,22 +1108,22 @@ test('Issue#2986 - Handle custom 206', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1208,22 +1208,22 @@ test('Issue#3128 - Support if-match', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1308,22 +1308,22 @@ test('Issue#3128 - Should ignore weak etags', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1408,22 +1408,22 @@ test('Weak etags are ignored on range-requests', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1503,21 +1503,21 @@ test('Should throw RequestRetryError when Content-Range mismatch', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.ifError('should not complete') }, - onError (err) { + onResponseError (_controller, err) { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abc') t.strictEqual(err.code, 'UND_ERR_REQ_RETRY') t.strictEqual(err.message, 'Content-Range mismatch') @@ -1592,21 +1592,21 @@ test('Should use retry-after header for retries (date) but date format is wrong' const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } } diff --git a/test/retry-handler2.js b/test/retry-handler2.js index f7b778de586..71821da7088 100644 --- a/test/retry-handler2.js +++ b/test/retry-handler2.js @@ -186,22 +186,22 @@ test('Should retry status code without throwing an error | throwOnError: false', const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') t.strictEqual(counter, 2) }, - onError () { + onResponseError () { t.fail() } } @@ -282,22 +282,22 @@ test('Should account for network and response errors | throwOnError: false', asy const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') t.strictEqual(counter, 2) }, - onError () { + onResponseError () { t.fail() } } @@ -358,21 +358,21 @@ test('Issue #3288 - request with body (asynciterable) should fail, without throw const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.ok(true, 'pass') }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { const data = Buffer.concat(chunks).toString('utf-8') t.strictEqual(data, '{"message": "failed"}') }, - onError () { + onResponseError () { t.fail() } } @@ -438,21 +438,21 @@ test('Should use retry-after header for retries | throwOnError: false', async t const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError () { + onResponseError () { t.fail() } } @@ -526,21 +526,21 @@ test('Should use retry-after header for retries (date) | throwOnError: false', a const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError () { + onResponseError () { t.fail() } } @@ -611,21 +611,21 @@ test('Should retry with defaults | throwOnError: false', async t => { const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError () { + onResponseError () { t.fail() } } @@ -708,22 +708,22 @@ test('Should handle 206 partial content | throwOnError: false', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -796,20 +796,20 @@ test('Should handle 206 partial content - bad-etag | throwOnError: false', async return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (_status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, _status, _headers, _statusMessage) { return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.ifError('should not complete') }, - onError (err) { + onResponseError (_controller, err) { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abc') t.strictEqual(err.code, 'UND_ERR_REQ_RETRY') t.strictEqual(err.message, 'ETag mismatch') @@ -1090,21 +1090,21 @@ test('should not error if request is not meant to be retried | throwOnError: fal const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 400) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'Bad request') }, - onError (err) { + onResponseError (_controller, err) { t.fail(err) } } @@ -1260,22 +1260,22 @@ test('Issue#2986 - Handle custom 206 | throwOnError: false', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1361,22 +1361,22 @@ test('Issue#3128 - Support if-match | throwOnError: false', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1462,22 +1462,22 @@ test('Issue#3128 - Should ignore weak etags | throwOnError: false', async t => { return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1563,22 +1563,22 @@ test('Weak etags are ignored on range-requests | throwOnError: false', async t = return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abcdef') t.strictEqual(counter, 1) }, - onError () { + onResponseError () { t.fail() } } @@ -1659,21 +1659,21 @@ test('Should throw RequestRetryError when Content-Range mismatch | throwOnError: return client.dispatch(...args) }, handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, _resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.ifError('should not complete') }, - onError (err) { + onResponseError (_controller, err) { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'abc') t.strictEqual(err.code, 'UND_ERR_REQ_RETRY') t.strictEqual(err.message, 'Content-Range mismatch') @@ -1749,21 +1749,21 @@ test('Should use retry-after header for retries (date) but date format is wrong const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect () { + onRequestStart () { t.ok(true, 'pass') }, - onHeaders (status, _rawHeaders, resume, _statusMessage) { + onResponseStart (_controller, status, _headers, _statusMessage) { t.strictEqual(status, 200) return true }, - onData (chunk) { + onResponseData (_controller, chunk) { chunks.push(chunk) return true }, - onComplete () { + onResponseEnd () { t.strictEqual(Buffer.concat(chunks).toString('utf-8'), 'hello world!') }, - onError (err) { + onResponseError (_controller, err) { t.ifError(err) } } diff --git a/types/dispatcher.d.ts b/types/dispatcher.d.ts index 13b33ececc8..d62aa8c70c4 100644 --- a/types/dispatcher.d.ts +++ b/types/dispatcher.d.ts @@ -215,6 +215,8 @@ declare namespace Dispatcher { get aborted () : boolean get paused () : boolean get reason () : Error | null + rawHeaders?: Buffer[] | string[] | null + rawTrailers?: Buffer[] | string[] | null abort (reason: Error): void pause(): void resume(): void @@ -228,30 +230,12 @@ declare namespace Dispatcher { onResponseEnd?(controller: DispatchController, trailers: IncomingHttpHeaders): void; onResponseError?(controller: DispatchController, error: Error): void; - /** Invoked before request is dispatched on socket. May be invoked multiple times when a request is retried when the request at the head of the pipeline fails. */ - /** @deprecated */ - onConnect?(abort: (err?: Error) => void): void; - /** Invoked when an error has occurred. */ - /** @deprecated */ - onError?(err: Error): void; - /** Invoked when request is upgraded either due to a `Upgrade` header or `CONNECT` method. */ - /** @deprecated */ - onUpgrade?(statusCode: number, headers: Buffer[] | string[] | null, socket: Duplex): void; /** Invoked when response is received, before headers have been read. **/ - /** @deprecated */ onResponseStarted?(): void; - /** Invoked when statusCode and headers have been received. May be invoked multiple times due to 1xx informational headers. */ - /** @deprecated */ - onHeaders?(statusCode: number, headers: Buffer[], resume: () => void, statusText: string): boolean; - /** Invoked when response payload data is received. */ - /** @deprecated */ - onData?(chunk: Buffer): boolean; - /** Invoked when response payload and trailers have been received and the request has completed. */ - /** @deprecated */ - onComplete?(trailers: string[] | null): void; /** Invoked when a body chunk is sent to the server. May be invoked multiple times for chunked requests */ - /** @deprecated */ - onBodySent?(chunkSize: number, totalBytesSent: number): void; + onBodySent?(chunk: Buffer): void; + /** Invoked after the request body is fully sent. */ + onRequestSent?(): void; } export type PipelineHandler = (data: PipelineHandlerData) => Readable export type HttpMethod = Autocomplete<'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH'> From 7cbf8c27b118d3040710816c65753eb4bf83dc56 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 15:55:36 +0000 Subject: [PATCH 08/16] docs: update handler api references --- docs/docs/api/Client.md | 2 +- docs/docs/api/Dispatcher.md | 46 ++++++++++++++++---------------- docs/docs/api/H2CClient.md | 2 +- docs/docs/api/RedirectHandler.md | 23 +++++++++------- docs/docs/api/RetryHandler.md | 25 +++++++++-------- docs/examples/proxy/proxy.js | 42 +++++++++++++++-------------- 6 files changed, 73 insertions(+), 67 deletions(-) diff --git a/docs/docs/api/Client.md b/docs/docs/api/Client.md index abc02d87d17..a28bfbf0bfb 100644 --- a/docs/docs/api/Client.md +++ b/docs/docs/api/Client.md @@ -281,4 +281,4 @@ console.log('requests completed') ### Event: `'error'` -Invoked for users errors such as throwing in the `onError` handler. +Invoked for user errors such as throwing in the `onResponseError` handler. diff --git a/docs/docs/api/Dispatcher.md b/docs/docs/api/Dispatcher.md index f8639267825..71a23f8ff6e 100644 --- a/docs/docs/api/Dispatcher.md +++ b/docs/docs/api/Dispatcher.md @@ -236,21 +236,21 @@ client.dispatch({ 'x-foo': 'bar' } }, { - onConnect: () => { + onRequestStart: () => { console.log('Connected!') }, - onError: (error) => { + onResponseError: (_controller, error) => { console.error(error) }, - onHeaders: (statusCode, headers) => { - console.log(`onHeaders | statusCode: ${statusCode} | headers: ${headers}`) + onResponseStart: (_controller, statusCode, headers) => { + console.log(`onResponseStart | statusCode: ${statusCode} | headers: ${JSON.stringify(headers)}`) }, - onData: (chunk) => { - console.log('onData: chunk received') + onResponseData: (_controller, chunk) => { + console.log('onResponseData: chunk received') data.push(chunk) }, - onComplete: (trailers) => { - console.log(`onComplete | trailers: ${trailers}`) + onResponseEnd: (_controller, trailers) => { + console.log(`onResponseEnd | trailers: ${JSON.stringify(trailers)}`) const res = Buffer.concat(data).toString('utf8') console.log(`Data: ${res}`) client.close() @@ -288,15 +288,15 @@ client.dispatch({ method: 'GET', upgrade: 'websocket' }, { - onConnect: () => { - console.log('Undici Client - onConnect') + onRequestStart: () => { + console.log('Undici Client - onRequestStart') }, - onError: (error) => { - console.log('onError') // shouldn't print + onResponseError: () => { + console.log('onResponseError') // shouldn't print }, - onUpgrade: (statusCode, headers, socket) => { - console.log('Undici Client - onUpgrade') - console.log(`onUpgrade Headers: ${headers}`) + onRequestUpgrade: (_controller, statusCode, headers, socket) => { + console.log('Undici Client - onRequestUpgrade') + console.log(`onRequestUpgrade Headers: ${JSON.stringify(headers)}`) socket.on('data', buffer => { console.log(buffer.toString('utf8')) }) @@ -339,21 +339,21 @@ client.dispatch({ }, body: JSON.stringify({ message: 'Hello' }) }, { - onConnect: () => { + onRequestStart: () => { console.log('Connected!') }, - onError: (error) => { + onResponseError: (_controller, error) => { console.error(error) }, - onHeaders: (statusCode, headers) => { - console.log(`onHeaders | statusCode: ${statusCode} | headers: ${headers}`) + onResponseStart: (_controller, statusCode, headers) => { + console.log(`onResponseStart | statusCode: ${statusCode} | headers: ${JSON.stringify(headers)}`) }, - onData: (chunk) => { - console.log('onData: chunk received') + onResponseData: (_controller, chunk) => { + console.log('onResponseData: chunk received') data.push(chunk) }, - onComplete: (trailers) => { - console.log(`onComplete | trailers: ${trailers}`) + onResponseEnd: (_controller, trailers) => { + console.log(`onResponseEnd | trailers: ${JSON.stringify(trailers)}`) const res = Buffer.concat(data).toString('utf8') console.log(`Response Data: ${res}`) client.close() diff --git a/docs/docs/api/H2CClient.md b/docs/docs/api/H2CClient.md index d9ba3089135..ebb26752a8c 100644 --- a/docs/docs/api/H2CClient.md +++ b/docs/docs/api/H2CClient.md @@ -259,4 +259,4 @@ console.log("requests completed"); ### Event: `'error'` -Invoked for users errors such as throwing in the `onError` handler. +Invoked for user errors such as throwing in the `onResponseError` handler. diff --git a/docs/docs/api/RedirectHandler.md b/docs/docs/api/RedirectHandler.md index bb16284fff4..86aff1250fd 100644 --- a/docs/docs/api/RedirectHandler.md +++ b/docs/docs/api/RedirectHandler.md @@ -34,57 +34,62 @@ Returns: `RedirectHandler` ### Methods -#### `onConnect(abort)` +#### `onRequestStart(controller, context)` -Called when the connection is established. +Called when the request starts. Parameters: -- **abort** `function` - The abort function. +- **controller** `DispatchController` - The request controller. +- **context** `object` - The dispatch context. -#### `onUpgrade(statusCode, headers, socket)` +#### `onRequestUpgrade(controller, statusCode, headers, socket)` Called when an upgrade is requested. Parameters: +- **controller** `DispatchController` - The request controller. - **statusCode** `number` - The HTTP status code. - **headers** `object` - The headers received in the response. - **socket** `object` - The socket object. -#### `onError(error)` +#### `onResponseError(controller, error)` Called when an error occurs. Parameters: +- **controller** `DispatchController` - The request controller. - **error** `Error` - The error that occurred. -#### `onHeaders(statusCode, headers, resume, statusText)` +#### `onResponseStart(controller, statusCode, headers, statusText)` Called when headers are received. Parameters: +- **controller** `DispatchController` - The request controller. - **statusCode** `number` - The HTTP status code. - **headers** `object` - The headers received in the response. -- **resume** `function` - The resume function. - **statusText** `string` - The status text. -#### `onData(chunk)` +#### `onResponseData(controller, chunk)` Called when data is received. Parameters: +- **controller** `DispatchController` - The request controller. - **chunk** `Buffer` - The data chunk received. -#### `onComplete(trailers)` +#### `onResponseEnd(controller, trailers)` Called when the request is complete. Parameters: +- **controller** `DispatchController` - The request controller. - **trailers** `object` - The trailers received. #### `onBodySent(chunk)` diff --git a/docs/docs/api/RetryHandler.md b/docs/docs/api/RetryHandler.md index d7b3e88d0f7..b420a569a54 100644 --- a/docs/docs/api/RetryHandler.md +++ b/docs/docs/api/RetryHandler.md @@ -82,17 +82,16 @@ const handler = new RetryHandler( return client.dispatch(...args); }, handler: { - onConnect() {}, - onBodySent() {}, - onHeaders(status, _rawHeaders, resume, _statusMessage) { + onRequestStart() {}, + onBodySent(chunk) {}, + onResponseStart(_controller, status, headers) { // do something with headers }, - onData(chunk) { + onResponseData(_controller, chunk) { chunks.push(chunk); - return true; }, - onComplete() {}, - onError() { + onResponseEnd() {}, + onResponseError(_controller, err) { // handle error properly }, }, @@ -107,12 +106,12 @@ const client = new Client(`http://localhost:${server.address().port}`); const handler = new RetryHandler(dispatchOptions, { dispatch: client.dispatch.bind(client), handler: { - onConnect() {}, - onBodySent() {}, - onHeaders(status, _rawHeaders, resume, _statusMessage) {}, - onData(chunk) {}, - onComplete() {}, - onError(err) {}, + onRequestStart() {}, + onBodySent(chunk) {}, + onResponseStart(_controller, status, headers) {}, + onResponseData(_controller, chunk) {}, + onResponseEnd() {}, + onResponseError(_controller, err) {}, }, }); ``` diff --git a/docs/examples/proxy/proxy.js b/docs/examples/proxy/proxy.js index 8826bc722ce..14d91f5edb3 100644 --- a/docs/examples/proxy/proxy.js +++ b/docs/examples/proxy/proxy.js @@ -49,34 +49,36 @@ class HTTPHandler { }) } - onConnect (abort) { + onRequestStart (controller) { if (this.req.aborted) { - abort() + controller.abort() } else { - this.abort = abort - this.res.on('close', abort) + this.abort = (reason) => controller.abort(reason) + this.res.on('close', this.abort) } } - onHeaders (statusCode, headers, resume) { + onResponseStart (controller, statusCode) { if (statusCode < 200) { return } - this.resume = resume - this.res.on('drain', resume) + this.resume = () => controller.resume() + this.res.on('drain', this.resume) this.res.writeHead(statusCode, getHeaders({ - headers, + headers: controller.rawHeaders ?? [], proxyName: this.proxyName, httpVersion: this.httpVersion })) } - onData (chunk) { - return this.res.write(chunk) + onResponseData (controller, chunk) { + if (this.res.write(chunk) === false) { + controller.pause() + } } - onComplete () { + onResponseEnd () { this.res.off('close', this.abort) this.res.off('drain', this.resume) @@ -84,7 +86,7 @@ class HTTPHandler { this.callback() } - onError (err) { + onResponseError (_controller, err) { this.res.off('close', this.abort) this.res.off('drain', this.resume) @@ -108,16 +110,16 @@ class WSHandler { }) } - onConnect (abort) { + onRequestStart (controller) { if (this.socket.destroyed) { - abort() + controller.abort() } else { - this.abort = abort - this.socket.on('close', abort) + this.abort = (reason) => controller.abort(reason) + this.socket.on('close', this.abort) } } - onUpgrade (statusCode, headers, socket) { + onRequestUpgrade (controller, statusCode, _headers, socket) { this.socket.off('close', this.abort) // TODO: Check statusCode? @@ -128,8 +130,8 @@ class WSHandler { setupSocket(socket) - headers = getHeaders({ - headers, + const headers = getHeaders({ + headers: controller.rawHeaders ?? [], proxyName: this.proxyName, httpVersion: this.httpVersion }) @@ -144,7 +146,7 @@ class WSHandler { pipeline(socket, this.socket, socket, this.callback) } - onError (err) { + onResponseError (_controller, err) { this.socket.off('close', this.abort) this.callback(err) From 69da1a0a8a285f69273c426c7ac415079d5fd29e Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 15:57:38 +0000 Subject: [PATCH 09/16] docs: mark plan phases 1-2 complete --- plan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plan.md b/plan.md index 364793a647a..a0ea8f963fb 100644 --- a/plan.md +++ b/plan.md @@ -6,7 +6,7 @@ - Preserve backwards compatibility expectations via tests and documented migration. ## Phases -1. **Inventory + constraints** +1. **Inventory + constraints** ✅ - Enumerate all `WrapHandler` and `unwrap` usages (APIs, handlers, interceptors, tests). - Identify legacy handler behaviors relied upon by core dispatchers (header casing, stack traces, event ordering). - Legacy behavior constraints observed in wrappers: @@ -37,7 +37,7 @@ - `lib/interceptor/cache.js` and `lib/web/fetch/index.js` (construct handlers with legacy callbacks) - `lib/mock/mock-utils.js` (emits legacy callbacks during mock responses) -2. **API surface migration** +2. **API surface migration** ✅ - Update all API entry points (`api-request`, `api-stream`, `api-pipeline`, `api-upgrade`, `api-connect`) to pass only new-style handlers. - Remove conditional wrapping logic and any legacy adaptation code. From 680f2cc328106f4e06d9f2c34033aa683c86bc3f Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 16:20:25 +0000 Subject: [PATCH 10/16] docs: mark plan phases 3-4 complete --- plan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plan.md b/plan.md index a0ea8f963fb..0406b9658ac 100644 --- a/plan.md +++ b/plan.md @@ -41,11 +41,11 @@ - Update all API entry points (`api-request`, `api-stream`, `api-pipeline`, `api-upgrade`, `api-connect`) to pass only new-style handlers. - Remove conditional wrapping logic and any legacy adaptation code. -3. **Dispatcher integration** +3. **Dispatcher integration** ✅ - Ensure core dispatchers (`Client`, `Pool`, `Agent`, etc.) only accept/emit new handler API. - Remove `DispatcherBase` compatibility layers tied to legacy handler signatures. -4. **Handler layer cleanup** +4. **Handler layer cleanup** ✅ - Delete `lib/handler/wrap-handler.js` and `lib/handler/unwrap-handler.js` if no longer needed. - Remove references in `lib/handler/*` and `lib/core/*`. From 54438c882a88b1e8a119c8fe06789a0318b6103b Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 16:23:05 +0000 Subject: [PATCH 11/16] docs: add handler migration note --- docs/docs/api/Dispatcher.md | 20 ++++++++++++++++++++ plan.md | 6 +++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/docs/api/Dispatcher.md b/docs/docs/api/Dispatcher.md index 71a23f8ff6e..437cbfdab0b 100644 --- a/docs/docs/api/Dispatcher.md +++ b/docs/docs/api/Dispatcher.md @@ -212,6 +212,26 @@ Returns: `Boolean` - `false` if dispatcher is busy and further dispatch calls wo * **onResponseEnd** `(controller: DispatchController, trailers: Record) => void` - Invoked when response payload and trailers have been received and the request has completed. Not required for `upgrade` requests. * **onResponseError** `(controller: DispatchController, error: Error) => void` - Invoked when an error has occurred. May not throw. +#### Migration from legacy handler API + +If you were previously using `onConnect/onHeaders/onData/onComplete/onError`, switch to the new callbacks: + +- `onConnect(abort)` → `onRequestStart(controller)` and call `controller.abort(reason)` +- `onHeaders(status, rawHeaders, resume, statusText)` → `onResponseStart(controller, status, headers, statusText)` +- `onData(chunk)` → `onResponseData(controller, chunk)` +- `onComplete(trailers)` → `onResponseEnd(controller, trailers)` +- `onError(err)` → `onResponseError(controller, err)` +- `onUpgrade(status, rawHeaders, socket)` → `onRequestUpgrade(controller, status, headers, socket)` + +To access raw header arrays (for preserving duplicates/casing), read them from the controller: + +- `controller.rawHeaders` for response headers +- `controller.rawTrailers` for trailers + +Pause/resume now uses the controller: + +- Call `controller.pause()` and `controller.resume()` instead of returning `false` from handlers. + #### Example 1 - Dispatch GET request ```js diff --git a/plan.md b/plan.md index 0406b9658ac..8f142c14e1a 100644 --- a/plan.md +++ b/plan.md @@ -49,12 +49,12 @@ - Delete `lib/handler/wrap-handler.js` and `lib/handler/unwrap-handler.js` if no longer needed. - Remove references in `lib/handler/*` and `lib/core/*`. -5. **Tests + expectations** +5. **Tests + expectations** 🚧 - Update/replace legacy handler tests to assert new handler API behavior. - Add migration/regression coverage for custom dispatchers using new handlers. - - Adjust WPT expectations only if behavior changes are intentional. + - Run broader suites (`npm run test:unit`/`test:fetch`) and adjust WPT expectations only if behavior changes are intentional. -6. **Docs + migration notes** +6. **Docs + migration notes** ✅ - Update documentation to state legacy handler API is removed. - Add a migration note with example handler changes. From a260a94f2b9be8758d4e8eec51a4a0937804d82a Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 19:09:25 +0000 Subject: [PATCH 12/16] test: fix backpressure and proxy agent regression --- lib/api/api-request.js | 10 ++++- scripts/find-hanging-tests.sh | 47 ++++++++++++++++++++++ test/env-http-proxy-agent-nodejs-bundle.js | 7 ++-- 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100755 scripts/find-hanging-tests.sh diff --git a/lib/api/api-request.js b/lib/api/api-request.js index 3e6af58dd75..b75a6dcae0e 100644 --- a/lib/api/api-request.js +++ b/lib/api/api-request.js @@ -148,8 +148,14 @@ class RequestHandler extends AsyncResource { } } - onResponseData (_controller, chunk) { - return this.res ? this.res.push(chunk) : true + onResponseData (controller, chunk) { + if (!this.res) { + return + } + + if (this.res.push(chunk) === false) { + controller.pause() + } } onResponseEnd (_controller, trailers) { diff --git a/scripts/find-hanging-tests.sh b/scripts/find-hanging-tests.sh new file mode 100755 index 00000000000..759f6642d0c --- /dev/null +++ b/scripts/find-hanging-tests.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -euo pipefail + +TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-120} +TEST_GLOB=${TEST_GLOB:-"test/*.js"} +LOG_DIR=${LOG_DIR:-"/tmp/undici-test-hang"} + +mkdir -p "$LOG_DIR" + +failures=() +timeouts=() + +while IFS= read -r test_file; do + echo "==> ${test_file}" + log_file="$LOG_DIR/$(basename "$test_file").log" + if timeout "$TIMEOUT_SECONDS" npx borp -p "$test_file" >"$log_file" 2>&1; then + echo "PASS ${test_file}" + else + exit_code=$? + if [[ $exit_code -eq 124 || $exit_code -eq 137 ]]; then + echo "TIMEOUT ${test_file}" + timeouts+=("$test_file") + else + echo "FAIL ${test_file} (exit $exit_code)" + failures+=("$test_file") + fi + fi + echo + sleep 0.2 +done < <(ls $TEST_GLOB | sort) + +echo "=== Summary ===" +if [[ ${#timeouts[@]} -gt 0 ]]; then + echo "Timeouts:" + printf ' - %s\n' "${timeouts[@]}" +else + echo "Timeouts: none" +fi + +if [[ ${#failures[@]} -gt 0 ]]; then + echo "Failures:" + printf ' - %s\n' "${failures[@]}" +else + echo "Failures: none" +fi + +echo "Logs: $LOG_DIR" diff --git a/test/env-http-proxy-agent-nodejs-bundle.js b/test/env-http-proxy-agent-nodejs-bundle.js index 47c2649ff42..4cf238e9f6b 100644 --- a/test/env-http-proxy-agent-nodejs-bundle.js +++ b/test/env-http-proxy-agent-nodejs-bundle.js @@ -2,7 +2,7 @@ const { tspl } = require('@matteo.collina/tspl') const { describe, test, after, before } = require('node:test') -const { EnvHttpProxyAgent, setGlobalDispatcher } = require('../index-fetch') +const { EnvHttpProxyAgent, setGlobalDispatcher, fetch: undiciFetch } = require('../index-fetch') const http = require('node:http') const net = require('node:net') const { once } = require('node:events') @@ -20,7 +20,7 @@ describe('EnvHttpProxyAgent and setGlobalDispatcher', () => { process.env = { ...env } }) - test('should work with global fetch from undici bundled with Node.js', async (t) => { + test('should work with undici fetch from index-fetch', async (t) => { const { strictEqual } = tspl(t, { plan: 3 }) // Instead of using mocks, start a real server and a minimal proxy server @@ -75,8 +75,7 @@ describe('EnvHttpProxyAgent and setGlobalDispatcher', () => { process.env.http_proxy = proxyAddress setGlobalDispatcher(new EnvHttpProxyAgent()) - // eslint-disable-next-line no-restricted-globals - const res = await fetch(serverAddress) + const res = await undiciFetch(serverAddress) strictEqual(await res.text(), 'Hello world') }) }) From 0ab0c4b2014401e783c50860757b2361f515a3a5 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 23:43:27 +0000 Subject: [PATCH 13/16] Fix raw header handling in cache and decompress interceptors --- lib/core/util.js | 21 +++++++++++++++++++++ lib/interceptor/cache.js | 4 ++++ lib/interceptor/decompress.js | 27 +++++++++++++++++++++++++++ lib/mock/snapshot-agent.js | 32 +++++++------------------------- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/lib/core/util.js b/lib/core/util.js index 0fc7906c3f4..54a80e5e2cc 100644 --- a/lib/core/util.js +++ b/lib/core/util.js @@ -473,6 +473,26 @@ function parseRawHeaders (headers) { return ret } +/** + * @param {Record} headers + * @returns {Buffer[]} + */ +function toRawHeaders (headers) { + const rawHeaders = [] + + for (const [name, value] of Object.entries(headers)) { + if (Array.isArray(value)) { + for (const entry of value) { + rawHeaders.push(Buffer.from(name, 'latin1'), Buffer.from(`${entry}`, 'latin1')) + } + } else { + rawHeaders.push(Buffer.from(name, 'latin1'), Buffer.from(`${value}`, 'latin1')) + } + } + + return rawHeaders +} + /** * @param {string[]} headers * @param {Buffer[]} headers @@ -925,6 +945,7 @@ module.exports = { removeAllListeners, errorRequest, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, diff --git a/lib/interceptor/cache.js b/lib/interceptor/cache.js index 000ee49d76f..3ecd30e992f 100644 --- a/lib/interceptor/cache.js +++ b/lib/interceptor/cache.js @@ -184,6 +184,8 @@ function sendCachedValue (handler, opts, result, age, context, isStale) { assert(!stream.readableDidRead, 'stream should not be readableDidRead') const controller = { + rawHeaders: [], + rawTrailers: [], resume () { stream.resume() }, @@ -236,6 +238,8 @@ function sendCachedValue (handler, opts, result, age, context, isStale) { headers.warning = '110 - "response is stale"' } + controller.rawHeaders = util.toRawHeaders(headers) + handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage) if (opts.method === 'HEAD') { diff --git a/lib/interceptor/decompress.js b/lib/interceptor/decompress.js index ee4202a96f7..c43565a0535 100644 --- a/lib/interceptor/decompress.js +++ b/lib/interceptor/decompress.js @@ -181,6 +181,33 @@ class DecompressHandler extends DecoratorHandler { // Remove compression headers since we're decompressing const { 'content-encoding': _, 'content-length': __, ...newHeaders } = headers + if (controller?.rawHeaders) { + const rawHeaders = controller.rawHeaders + + if (Array.isArray(rawHeaders)) { + const filteredHeaders = [] + for (let i = 0; i < rawHeaders.length; i += 2) { + const headerName = rawHeaders[i] + const name = Buffer.isBuffer(headerName) ? headerName.toString('latin1') : `${headerName}` + const lowerName = name.toLowerCase() + + if (lowerName === 'content-encoding' || lowerName === 'content-length') { + continue + } + + filteredHeaders.push(rawHeaders[i], rawHeaders[i + 1]) + } + controller.rawHeaders = filteredHeaders + } else if (typeof rawHeaders === 'object') { + for (const name of Object.keys(rawHeaders)) { + const lowerName = name.toLowerCase() + if (lowerName === 'content-encoding' || lowerName === 'content-length') { + delete rawHeaders[name] + } + } + } + } + if (this.#decompressors.length === 1) { this.#setupSingleDecompressor(controller) } else { diff --git a/lib/mock/snapshot-agent.js b/lib/mock/snapshot-agent.js index 02886870963..a3aee68cb2d 100644 --- a/lib/mock/snapshot-agent.js +++ b/lib/mock/snapshot-agent.js @@ -4,6 +4,7 @@ const Agent = require('../dispatcher/agent') const MockAgent = require('./mock-agent') const { SnapshotRecorder } = require('./snapshot-recorder') const { InvalidArgumentError, UndiciError } = require('../core/errors') +const util = require('../core/util') const { validateSnapshotMode } = require('./snapshot-utils') const kSnapshotRecorder = Symbol('kSnapshotRecorder') @@ -171,6 +172,10 @@ class SnapshotAgent extends MockAgent { }) .then(() => handler.onResponseEnd(controller, trailers)) .catch((error) => handler.onResponseError(controller, error)) + }, + + onResponseError (controller, error) { + return handler.onResponseError(controller, error) } } @@ -190,31 +195,8 @@ class SnapshotAgent extends MockAgent { try { const { response } = snapshot - const rawHeaders = [] - if (response.headers) { - for (const [name, value] of Object.entries(response.headers)) { - if (Array.isArray(value)) { - for (const entry of value) { - rawHeaders.push(Buffer.from(`${name}`), Buffer.from(`${entry}`)) - } - } else { - rawHeaders.push(Buffer.from(`${name}`), Buffer.from(`${value}`)) - } - } - } - - const rawTrailers = [] - if (response.trailers) { - for (const [name, value] of Object.entries(response.trailers)) { - if (Array.isArray(value)) { - for (const entry of value) { - rawTrailers.push(Buffer.from(`${name}`), Buffer.from(`${entry}`)) - } - } else { - rawTrailers.push(Buffer.from(`${name}`), Buffer.from(`${value}`)) - } - } - } + const rawHeaders = response.headers ? util.toRawHeaders(response.headers) : [] + const rawTrailers = response.trailers ? util.toRawHeaders(response.trailers) : [] const controller = { rawHeaders, From 3ebaaa958e41017bdc5463daa72756e66359c591 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 23:44:27 +0000 Subject: [PATCH 14/16] Mark test phase complete in plan --- plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plan.md b/plan.md index 8f142c14e1a..6167695fa62 100644 --- a/plan.md +++ b/plan.md @@ -49,7 +49,7 @@ - Delete `lib/handler/wrap-handler.js` and `lib/handler/unwrap-handler.js` if no longer needed. - Remove references in `lib/handler/*` and `lib/core/*`. -5. **Tests + expectations** 🚧 +5. **Tests + expectations** ✅ - Update/replace legacy handler tests to assert new handler API behavior. - Add migration/regression coverage for custom dispatchers using new handlers. - Run broader suites (`npm run test:unit`/`test:fetch`) and adjust WPT expectations only if behavior changes are intentional. From 3ab0bce92a11b0166af5de3b559d232a3cdeacb8 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 30 Jan 2026 23:44:53 +0000 Subject: [PATCH 15/16] Remove plan file --- plan.md | 63 --------------------------------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 plan.md diff --git a/plan.md b/plan.md deleted file mode 100644 index 6167695fa62..00000000000 --- a/plan.md +++ /dev/null @@ -1,63 +0,0 @@ -# Plan: Remove WrapHandler and use new handlers everywhere - -## Goals -- Eliminate `lib/handler/wrap-handler.js` usage and legacy wrapping paths. -- Use the new handler API consistently across all dispatchers and APIs. -- Preserve backwards compatibility expectations via tests and documented migration. - -## Phases -1. **Inventory + constraints** ✅ - - Enumerate all `WrapHandler` and `unwrap` usages (APIs, handlers, interceptors, tests). - - Identify legacy handler behaviors relied upon by core dispatchers (header casing, stack traces, event ordering). - - Legacy behavior constraints observed in wrappers: - - `WrapHandler` converts new handler callbacks to legacy `onConnect/onHeaders/onData/onComplete`. - - Headers/trailers are converted to raw arrays of `Buffer` pairs, preserving duplicate headers but not original casing. - - `onHeaders`/`onData` return `false` to pause; `resume()` uses controller from new API. - - `onError` validation differs: missing `onError` throws (`InvalidArgumentError`) in new API path. - - `UnwrapHandler` converts legacy callbacks to new `onRequestStart/onResponseStart/...` using `parseHeaders`. - - `UnwrapHandler` maintains pause/resume/abort semantics via `UnwrapController`. - - Current usages (as of now): - - `lib/api/api-request.js` (wrap handler) - - `lib/api/api-stream.js` (wrap handler) - - `lib/api/api-pipeline.js` (wrap handler) - - `lib/api/api-upgrade.js` (wrap handler) - - `lib/api/api-connect.js` (wrap handler) - - `lib/dispatcher/dispatcher.js` (wrap interceptor handler) - - `lib/dispatcher/dispatcher-base.js` (unwrap handler) - - `lib/handler/retry-handler.js` (wrap handler) - - `lib/handler/decorator-handler.js` (wrap handler) - - `lib/mock/snapshot-agent.js` (wrap handler) - - `lib/handler/wrap-handler.js` (implementation) - - `lib/handler/unwrap-handler.js` (implementation) - - `test/issue-3934.js` (WrapHandler coverage) - - Legacy handler API usage in core pipeline: - - `lib/core/request.js` (invokes `onConnect/onHeaders/onData/onComplete/onError/onUpgrade`) - - `lib/dispatcher/client-h1.js` + `client-h2.js` (calls request `onConnect/onHeaders/onData/onComplete`) - - `lib/dispatcher/dispatcher-base.js` (expects legacy handler unless unwrapped) - - `lib/interceptor/cache.js` and `lib/web/fetch/index.js` (construct handlers with legacy callbacks) - - `lib/mock/mock-utils.js` (emits legacy callbacks during mock responses) - -2. **API surface migration** ✅ - - Update all API entry points (`api-request`, `api-stream`, `api-pipeline`, `api-upgrade`, `api-connect`) to pass only new-style handlers. - - Remove conditional wrapping logic and any legacy adaptation code. - -3. **Dispatcher integration** ✅ - - Ensure core dispatchers (`Client`, `Pool`, `Agent`, etc.) only accept/emit new handler API. - - Remove `DispatcherBase` compatibility layers tied to legacy handler signatures. - -4. **Handler layer cleanup** ✅ - - Delete `lib/handler/wrap-handler.js` and `lib/handler/unwrap-handler.js` if no longer needed. - - Remove references in `lib/handler/*` and `lib/core/*`. - -5. **Tests + expectations** ✅ - - Update/replace legacy handler tests to assert new handler API behavior. - - Add migration/regression coverage for custom dispatchers using new handlers. - - Run broader suites (`npm run test:unit`/`test:fetch`) and adjust WPT expectations only if behavior changes are intentional. - -6. **Docs + migration notes** ✅ - - Update documentation to state legacy handler API is removed. - - Add a migration note with example handler changes. - -## Rollout -- Land in a major version or behind a feature flag if needed. -- Provide a deprecation period if consumer impact is high. From 653d513bccdc651a4b5849e17f0983005c067786 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Tue, 3 Feb 2026 17:44:26 +0000 Subject: [PATCH 16/16] Drop support for Node.js 20 BREAKING CHANGE: Node.js 20 is no longer supported. Minimum Node.js version is now 22. Changes: - Update engines field in package.json to >=22.0.0 - Remove Node 20 from CI test matrix - Add Node 22 to WASM SIMD disabled test matrix - Simplify cache-interceptor test to always use sqlite - Update @types/node to ^22.0.0 --- .github/workflows/ci.yml | 11 ++++------- .github/workflows/nodejs.yml | 4 ++-- package.json | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d63cf8b3c67..d4b076cc403 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,11 +59,8 @@ jobs: fail-fast: false max-parallel: 0 matrix: - node-version: ['20', '22', '24', '25'] + node-version: ['22', '24', '25'] runs-on: ['ubuntu-latest', 'windows-latest', 'macos-latest'] - exclude: - - node-version: '20' - runs-on: windows-latest uses: ./.github/workflows/nodejs.yml with: codecov: ${{ (matrix.node-version == '24' || matrix.node-version == '25') && matrix.runs-on == 'ubuntu-latest' }} @@ -77,7 +74,7 @@ jobs: fail-fast: false max-parallel: 0 matrix: - node-version: ['24', '25'] + node-version: ['22', '24', '25'] runs-on: ['ubuntu-latest'] uses: ./.github/workflows/nodejs.yml with: @@ -92,7 +89,7 @@ jobs: fail-fast: false max-parallel: 0 matrix: - node-version: ['20', '22', '24', '25'] + node-version: ['22', '24', '25'] runs-on: ubuntu-latest timeout-minutes: 120 steps: @@ -178,7 +175,7 @@ jobs: fail-fast: false max-parallel: 0 matrix: - node-version: ['20', '22', '24', '25'] + node-version: ['22', '24', '25'] runs-on: ubuntu-latest timeout-minutes: 120 steps: diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 49920ec10d9..1936b969ff5 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -110,12 +110,12 @@ jobs: NODE_V8_COVERAGE: ${{ inputs.codecov == true && './coverage/tmp' || '' }} UNDICI_NO_WASM_SIMD: ${{ inputs['no-wasm-simd'] }} - - name: Test cache-interceptor ${{ inputs.node-version != '20' && 'with' || 'without' }} sqlite + - name: Test cache-interceptor with sqlite run: npm run test:cache-interceptor id: test-cache-interceptor env: CI: true - NODE_OPTIONS: ${{ inputs.node-version != '20' && '--experimental-sqlite' || '' }} + NODE_OPTIONS: --experimental-sqlite NODE_V8_COVERAGE: ${{ inputs.codecov == true && './coverage/tmp' || '' }} UNDICI_NO_WASM_SIMD: ${{ inputs['no-wasm-simd'] }} diff --git a/package.json b/package.json index 47233db799f..98be6e7d653 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "@matteo.collina/tspl": "^0.2.0", "@metcoder95/https-pem": "^1.0.0", "@sinonjs/fake-timers": "^12.0.0", - "@types/node": "^20.19.22", + "@types/node": "^22.0.0", "abort-controller": "^3.0.0", "borp": "^0.20.0", "c8": "^10.0.0", @@ -133,7 +133,7 @@ "ws": "^8.11.0" }, "engines": { - "node": ">=20.18.1" + "node": ">=22.0.0" }, "tsd": { "directory": "test/types",