mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-30 09:16:07 -04:00
update tests
This commit is contained in:
@@ -274,6 +274,7 @@
|
||||
const src = new FormData();
|
||||
src.append('username', 'alice');
|
||||
src.append('note', 'two\r\nlines');
|
||||
src.append('a\tb', 'tabbed');
|
||||
src.append('username', 'bob');
|
||||
const req2 = new Request('https://example.com', { method: 'POST', body: src });
|
||||
const fd2 = await req2.formData();
|
||||
@@ -340,6 +341,7 @@
|
||||
testing.expectEqual('alice', fd2.getAll('username')[0]);
|
||||
testing.expectEqual('bob', fd2.getAll('username')[1]);
|
||||
testing.expectEqual('two\r\nlines', fd2.get('note'));
|
||||
testing.expectEqual('tabbed', fd2.get('a\tb'));
|
||||
|
||||
testing.expectEqual('y z', fd3.get('x'));
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
const src = new FormData();
|
||||
src.append('username', 'alice');
|
||||
src.append('note', 'two\r\nlines');
|
||||
src.append('a\tb', 'tabbed');
|
||||
src.append('username', 'bob');
|
||||
const res2 = new Response(src);
|
||||
const fd2 = await res2.formData();
|
||||
@@ -123,6 +124,28 @@
|
||||
const promised6 = p6 instanceof Promise;
|
||||
try { await p6; } catch (e) { rejected6 = e instanceof TypeError; }
|
||||
|
||||
// A null body with a form Content-Type acts as an empty byte sequence and
|
||||
// resolves with an empty FormData.
|
||||
const res7 = new Response(null, {
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
});
|
||||
const fd7 = await res7.formData();
|
||||
|
||||
// A multipart Content-Type without a boundary rejects with a TypeError.
|
||||
let rejected8 = false;
|
||||
const res8 = new Response('x', {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
try { await res8.formData(); } catch (e) { rejected8 = e instanceof TypeError; }
|
||||
|
||||
// A part with an unquoted RFC 5987 filename* parameter — which real
|
||||
// servers emit — parses; the parameter itself is skipped.
|
||||
const res9 = new Response(
|
||||
'--B\r\nContent-Disposition: form-data; filename*=UTF-8\'\'a.jpg; name="n"\r\n\r\nv\r\n--B--\r\n',
|
||||
{ headers: { 'Content-Type': 'multipart/form-data; boundary=B' } },
|
||||
);
|
||||
const fd9 = await res9.formData();
|
||||
|
||||
state.resolve();
|
||||
await state.done(() => {
|
||||
testing.expectEqual(true, fd1 instanceof FormData);
|
||||
@@ -136,6 +159,7 @@
|
||||
testing.expectEqual('alice', fd2.getAll('username')[0]);
|
||||
testing.expectEqual('bob', fd2.getAll('username')[1]);
|
||||
testing.expectEqual('two\r\nlines', fd2.get('note'));
|
||||
testing.expectEqual('tabbed', fd2.get('a\tb'));
|
||||
|
||||
testing.expectEqual('y z', fd3.get('x'));
|
||||
|
||||
@@ -144,6 +168,11 @@
|
||||
|
||||
testing.expectEqual(true, promised6);
|
||||
testing.expectEqual(true, rejected6);
|
||||
|
||||
testing.expectEqual(true, fd7 instanceof FormData);
|
||||
testing.expectEqual(0, [...fd7].length);
|
||||
testing.expectEqual(true, rejected8);
|
||||
testing.expectEqual('v', fd9.get('n'));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1314,6 +1314,9 @@ test "FormData: multipart round-trip" {
|
||||
try src.appendText("username", "alice");
|
||||
try src.appendText("username", "bob");
|
||||
try src.appendText("a\"b\r\nc", "quoted \"value\"");
|
||||
// HTAB in a name survives the trip: the encoder writes it raw into the
|
||||
// Content-Disposition value and the parser accepts it (RFC 9110).
|
||||
try src.appendText("a\tb", "tabbed");
|
||||
|
||||
var buf = std.Io.Writer.Allocating.init(allocator);
|
||||
try src.write(.{
|
||||
@@ -1328,10 +1331,11 @@ test "FormData: multipart round-trip" {
|
||||
};
|
||||
try fd.parseMultipart(frame._page, buf.written(), "BOUNDARY");
|
||||
|
||||
try testing.expectEqual(3, fd._entries.items.len);
|
||||
try testing.expectEqual(4, fd._entries.items.len);
|
||||
try testing.expectString("username", fd._entries.items[0].name.str());
|
||||
try testing.expectString("alice", fd._entries.items[0].value.asString());
|
||||
try testing.expectString("username", fd._entries.items[1].name.str());
|
||||
try testing.expectString("bob", fd._entries.items[1].value.asString());
|
||||
try testing.expectString("quoted \"value\"", fd.get(.wrap("a\"b\r\nc")).?);
|
||||
try testing.expectString("tabbed", fd.get(.wrap("a\tb")).?);
|
||||
}
|
||||
|
||||
@@ -390,16 +390,22 @@ test "header_parser: parse HTTP header" {
|
||||
try testing.expectString("def", header.value);
|
||||
try testing.expectEqual(true, cursor.reachedEnd());
|
||||
|
||||
// Leading whitespaces of the value are skipped, trailing ones are kept.
|
||||
cursor = initCursor("Key: value \r\n");
|
||||
// Leading whitespaces of the value — spaces and HTABs — are skipped,
|
||||
// trailing ones are kept.
|
||||
cursor = initCursor("Key: \t value \t\r\n");
|
||||
try header.parse(&cursor);
|
||||
try testing.expectString("value ", header.value);
|
||||
try testing.expectString("value \t", header.value);
|
||||
|
||||
// 0 length values are fine.
|
||||
cursor = initCursor("Key:\r\n");
|
||||
try header.parse(&cursor);
|
||||
try testing.expectString("Key", header.key);
|
||||
try testing.expectString("", header.value);
|
||||
|
||||
// HTAB is legal field content, including next to spaces.
|
||||
cursor = initCursor("Key: a\tb\t c\r\n");
|
||||
try header.parse(&cursor);
|
||||
try testing.expectString("a\tb\t c", header.value);
|
||||
}
|
||||
|
||||
test "header_parser: parse HTTP header incomplete" {
|
||||
@@ -490,8 +496,8 @@ test "header_parser: cursor" {
|
||||
try testing.expectEqual(true, cursor.reachedEnd());
|
||||
try testing.expectString("", cursor.remaining());
|
||||
|
||||
// Skipping spaces stops at the end of the buffer.
|
||||
cursor = initCursor(" ");
|
||||
// Skipping spaces covers HTABs too and stops at the end of the buffer.
|
||||
cursor = initCursor(" \t \t");
|
||||
cursor.skipSpaces();
|
||||
try testing.expectEqual(true, cursor.reachedEnd());
|
||||
}
|
||||
@@ -525,6 +531,20 @@ test "header_parser: match functions against scalar reference" {
|
||||
}
|
||||
}
|
||||
|
||||
// HTAB is the one valid byte below space; pair it with every byte at
|
||||
// every position to prove it never disturbs its neighbor's verdict
|
||||
// (a cross-lane borrow in the SWAR path would).
|
||||
for (2..buf.len + 1) |len| {
|
||||
for (0..len - 1) |pos| {
|
||||
for (0..256) |c| {
|
||||
@memset(buf[0..len], 'a');
|
||||
buf[pos] = '\t';
|
||||
buf[pos + 1] = @intCast(c);
|
||||
try expectMatchesReference(buf[0..len]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Randomized: fully random buffers to exercise multiple invalid bytes per
|
||||
// chunk at once.
|
||||
var prng = std.Random.DefaultPrng.init(0x5eed);
|
||||
|
||||
Reference in New Issue
Block a user