327 lines
7.4 KiB
JavaScript
327 lines
7.4 KiB
JavaScript
//
|
|
// Utility functions
|
|
//
|
|
|
|
function shouldThrow(func, expected, msg) {
|
|
var err;
|
|
try {
|
|
func();
|
|
} catch (e) {
|
|
err = e;
|
|
} finally {
|
|
ok(err instanceof expected, msg);
|
|
}
|
|
}
|
|
|
|
function recursiveArrayCompare(actual, expected) {
|
|
is(
|
|
Array.isArray(actual),
|
|
Array.isArray(expected),
|
|
"Both should either be arrays, or not"
|
|
);
|
|
if (Array.isArray(actual) && Array.isArray(expected)) {
|
|
var diff = actual.length !== expected.length;
|
|
|
|
for (var i = 0, n = actual.length; !diff && i < n; ++i) {
|
|
diff = recursiveArrayCompare(actual[i], expected[i]);
|
|
}
|
|
|
|
return diff;
|
|
} else {
|
|
return actual !== expected;
|
|
}
|
|
}
|
|
|
|
function arrayEquals(actual, expected, msg) {
|
|
if (actual === expected) {
|
|
return;
|
|
}
|
|
|
|
var diff = recursiveArrayCompare(actual, expected);
|
|
|
|
ok(!diff, msg);
|
|
if (diff) {
|
|
is(actual, expected, msg);
|
|
}
|
|
}
|
|
|
|
function checkHas(headers, name, msg) {
|
|
function doCheckHas(n) {
|
|
return headers.has(n);
|
|
}
|
|
return _checkHas(doCheckHas, headers, name, msg);
|
|
}
|
|
|
|
function checkNotHas(headers, name, msg) {
|
|
function doCheckNotHas(n) {
|
|
return !headers.has(n);
|
|
}
|
|
return _checkHas(doCheckNotHas, headers, name, msg);
|
|
}
|
|
|
|
function _checkHas(func, headers, name, msg) {
|
|
ok(func(name), msg);
|
|
ok(func(name.toLowerCase()), msg);
|
|
ok(func(name.toUpperCase()), msg);
|
|
}
|
|
|
|
function checkGet(headers, name, expected, msg) {
|
|
is(headers.get(name), expected, msg);
|
|
is(headers.get(name.toLowerCase()), expected, msg);
|
|
is(headers.get(name.toUpperCase()), expected, msg);
|
|
}
|
|
|
|
//
|
|
// Test Cases
|
|
//
|
|
|
|
function TestCoreBehavior(headers, name) {
|
|
var start = headers.get(name);
|
|
|
|
headers.append(name, "bar");
|
|
|
|
checkHas(headers, name, "Has the header");
|
|
var expected = start ? start.concat(", bar") : "bar";
|
|
checkGet(headers, name, expected, "Retrieve all headers for name");
|
|
|
|
headers.append(name, "baz");
|
|
checkHas(headers, name, "Has the header");
|
|
expected = start ? start.concat(", bar, baz") : "bar, baz";
|
|
checkGet(headers, name, expected, "Retrieve all headers for name");
|
|
|
|
headers.set(name, "snafu");
|
|
checkHas(headers, name, "Has the header after set");
|
|
checkGet(headers, name, "snafu", "Retrieve all headers after set");
|
|
|
|
const value_bam = "boom";
|
|
let testHTTPWhitespace = ["\t", "\n", "\r", " "];
|
|
while (testHTTPWhitespace.length) {
|
|
headers.delete(name);
|
|
|
|
let char = testHTTPWhitespace.shift();
|
|
headers.set(name, char);
|
|
checkGet(
|
|
headers,
|
|
name,
|
|
"",
|
|
"Header value " +
|
|
char +
|
|
" should be normalized before checking and throwing"
|
|
);
|
|
headers.delete(name);
|
|
|
|
let valueFront = char + value_bam;
|
|
headers.set(name, valueFront);
|
|
checkGet(
|
|
headers,
|
|
name,
|
|
value_bam,
|
|
"Header value " +
|
|
valueFront +
|
|
" should be normalized before checking and throwing"
|
|
);
|
|
|
|
headers.delete(name);
|
|
|
|
let valueBack = value_bam + char;
|
|
headers.set(name, valueBack);
|
|
checkGet(
|
|
headers,
|
|
name,
|
|
value_bam,
|
|
"Header value " +
|
|
valueBack +
|
|
" should be normalized before checking and throwing"
|
|
);
|
|
}
|
|
|
|
headers.delete(name.toUpperCase());
|
|
checkNotHas(headers, name, "Does not have the header after delete");
|
|
checkGet(headers, name, null, "Retrieve all headers after delete");
|
|
|
|
// should be ok to delete non-existent name
|
|
headers.delete(name);
|
|
|
|
shouldThrow(
|
|
function () {
|
|
headers.append("foo,", "bam");
|
|
},
|
|
TypeError,
|
|
"Append invalid header name should throw TypeError."
|
|
);
|
|
|
|
shouldThrow(
|
|
function () {
|
|
headers.append(name, "ba\nm");
|
|
},
|
|
TypeError,
|
|
"Append invalid header value should throw TypeError."
|
|
);
|
|
|
|
shouldThrow(
|
|
function () {
|
|
headers.append(name, "ba\rm");
|
|
},
|
|
TypeError,
|
|
"Append invalid header value should throw TypeError."
|
|
);
|
|
|
|
ok(!headers.guard, "guard should be undefined in content");
|
|
}
|
|
|
|
function TestEmptyHeaders() {
|
|
is(typeof Headers, "function", "Headers global constructor exists.");
|
|
var headers = new Headers();
|
|
ok(headers, "Constructed empty Headers object");
|
|
TestCoreBehavior(headers, "foo");
|
|
}
|
|
|
|
function TestFilledHeaders() {
|
|
var source = new Headers();
|
|
var filled = new Headers(source);
|
|
ok(filled, "Fill header from empty header");
|
|
TestCoreBehavior(filled, "foo");
|
|
|
|
source = new Headers();
|
|
source.append("abc", "123");
|
|
source.append("def", "456");
|
|
source.append("def", "789");
|
|
|
|
filled = new Headers(source);
|
|
checkGet(
|
|
filled,
|
|
"abc",
|
|
source.get("abc"),
|
|
"Single value header list matches"
|
|
);
|
|
checkGet(
|
|
filled,
|
|
"def",
|
|
source.get("def"),
|
|
"Multiple value header list matches"
|
|
);
|
|
TestCoreBehavior(filled, "def");
|
|
|
|
filled = new Headers({
|
|
zxy: "987",
|
|
xwv: "654",
|
|
uts: "321",
|
|
});
|
|
checkGet(filled, "zxy", "987", "Has first object filled key");
|
|
checkGet(filled, "xwv", "654", "Has second object filled key");
|
|
checkGet(filled, "uts", "321", "Has third object filled key");
|
|
TestCoreBehavior(filled, "xwv");
|
|
|
|
filled = new Headers([
|
|
["zxy", "987"],
|
|
["xwv", "654"],
|
|
["xwv", "abc"],
|
|
["uts", "321"],
|
|
]);
|
|
checkGet(filled, "zxy", "987", "Has first sequence filled key");
|
|
checkGet(filled, "xwv", "654, abc", "Has second sequence filled key");
|
|
checkGet(filled, "uts", "321", "Has third sequence filled key");
|
|
TestCoreBehavior(filled, "xwv");
|
|
|
|
shouldThrow(
|
|
function () {
|
|
filled = new Headers([
|
|
["zxy", "987", "654"],
|
|
["uts", "321"],
|
|
]);
|
|
},
|
|
TypeError,
|
|
"Fill with non-tuple sequence should throw TypeError."
|
|
);
|
|
|
|
shouldThrow(
|
|
function () {
|
|
filled = new Headers([["zxy"], ["uts", "321"]]);
|
|
},
|
|
TypeError,
|
|
"Fill with non-tuple sequence should throw TypeError."
|
|
);
|
|
}
|
|
|
|
function iterate(iter) {
|
|
var result = [];
|
|
for (var val = iter.next(); !val.done; ) {
|
|
result.push(val.value);
|
|
val = iter.next();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function iterateForOf(iter) {
|
|
var result = [];
|
|
for (var value of iter) {
|
|
result.push(value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function byteInflate(str) {
|
|
var encoder = new TextEncoder();
|
|
var encoded = encoder.encode(str);
|
|
var result = "";
|
|
for (var i = 0; i < encoded.length; ++i) {
|
|
result += String.fromCharCode(encoded[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function TestHeadersIterator() {
|
|
var ehsanInflated = byteInflate("احسان");
|
|
var headers = new Headers();
|
|
headers.set("foo0", "bar0");
|
|
headers.append("foo", "bar");
|
|
headers.append("foo", ehsanInflated);
|
|
headers.append("Foo2", "bar2");
|
|
headers.set("Foo2", "baz2");
|
|
headers.set("foo3", "bar3");
|
|
headers.delete("foo0");
|
|
headers.delete("foo3");
|
|
|
|
var key_iter = headers.keys();
|
|
var value_iter = headers.values();
|
|
var entries_iter = headers.entries();
|
|
|
|
arrayEquals(iterate(key_iter), ["foo", "foo2"], "Correct key iterator");
|
|
arrayEquals(
|
|
iterate(value_iter),
|
|
["bar, " + ehsanInflated, "baz2"],
|
|
"Correct value iterator"
|
|
);
|
|
arrayEquals(
|
|
iterate(entries_iter),
|
|
[
|
|
["foo", "bar, " + ehsanInflated],
|
|
["foo2", "baz2"],
|
|
],
|
|
"Correct entries iterator"
|
|
);
|
|
|
|
arrayEquals(
|
|
iterateForOf(headers),
|
|
[
|
|
["foo", "bar, " + ehsanInflated],
|
|
["foo2", "baz2"],
|
|
],
|
|
"Correct entries iterator"
|
|
);
|
|
arrayEquals(
|
|
iterateForOf(new Headers(headers)),
|
|
[
|
|
["foo", "bar, " + ehsanInflated],
|
|
["foo2", "baz2"],
|
|
],
|
|
"Correct entries iterator"
|
|
);
|
|
}
|
|
|
|
function runTest() {
|
|
TestEmptyHeaders();
|
|
TestFilledHeaders();
|
|
TestHeadersIterator();
|
|
return Promise.resolve();
|
|
}
|