mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
244 lines
5.9 KiB
TypeScript
244 lines
5.9 KiB
TypeScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
|
|
import { assertEquals, assertRejects } from "@std/assert";
|
|
import { toBytes } from "@std/streams/unstable-to-bytes";
|
|
import { TarStream, type TarStreamInput } from "./tar_stream.ts";
|
|
import {
|
|
type OldStyleFormat,
|
|
type PosixUstarFormat,
|
|
UntarStream,
|
|
} from "./untar_stream.ts";
|
|
|
|
Deno.test("expandTarArchiveCheckingHeaders", async () => {
|
|
const text = new TextEncoder().encode("Hello World!");
|
|
const seconds = Math.floor(Date.now() / 1000);
|
|
|
|
const readable = ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "directory",
|
|
path: "./potato",
|
|
options: {
|
|
mode: 111111,
|
|
uid: 12,
|
|
gid: 21,
|
|
mtime: seconds,
|
|
uname: "potato",
|
|
gname: "cake",
|
|
devmajor: "ice",
|
|
devminor: "scream",
|
|
},
|
|
},
|
|
{
|
|
type: "file",
|
|
path: "./text.txt",
|
|
size: text.length,
|
|
readable: ReadableStream.from([text.slice()]),
|
|
options: { mtime: seconds },
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream())
|
|
.pipeThrough(new UntarStream());
|
|
|
|
const headers: (OldStyleFormat | PosixUstarFormat)[] = [];
|
|
for await (const entry of readable) {
|
|
headers.push(entry.header);
|
|
await entry.readable?.cancel();
|
|
}
|
|
assertEquals(headers, [{
|
|
name: "./potato",
|
|
mode: 111111,
|
|
uid: 12,
|
|
gid: 21,
|
|
mtime: seconds,
|
|
uname: "potato",
|
|
gname: "cake",
|
|
devmajor: "ice",
|
|
devminor: "scream",
|
|
size: 0,
|
|
typeflag: "5",
|
|
linkname: "",
|
|
magic: "ustar\0",
|
|
version: "00",
|
|
prefix: "",
|
|
}, {
|
|
name: "./text.txt",
|
|
mode: 644,
|
|
uid: 0,
|
|
gid: 0,
|
|
mtime: seconds,
|
|
uname: "",
|
|
gname: "",
|
|
devmajor: "",
|
|
devminor: "",
|
|
size: text.length,
|
|
typeflag: "0",
|
|
linkname: "",
|
|
magic: "ustar\0",
|
|
version: "00",
|
|
prefix: "",
|
|
}]);
|
|
});
|
|
|
|
Deno.test("expandTarArchiveCheckingBodies", async () => {
|
|
const text = new TextEncoder().encode("Hello World!");
|
|
|
|
const readable = ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "directory",
|
|
path: "./potato",
|
|
},
|
|
{
|
|
type: "file",
|
|
path: "./text.txt",
|
|
size: text.length,
|
|
readable: ReadableStream.from([text.slice()]),
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream())
|
|
.pipeThrough(new UntarStream());
|
|
|
|
let buffer = new Uint8Array();
|
|
for await (const item of readable) {
|
|
if (item.readable) buffer = await toBytes(item.readable);
|
|
}
|
|
assertEquals(buffer, text);
|
|
});
|
|
|
|
Deno.test("UntarStream() with size equals to multiple of 512", async () => {
|
|
const size = 512 * 3;
|
|
const data = Uint8Array.from(
|
|
{ length: size },
|
|
() => Math.floor(Math.random() * 256),
|
|
);
|
|
|
|
const readable = ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "file",
|
|
path: "name",
|
|
size,
|
|
readable: ReadableStream.from([data.slice()]),
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream())
|
|
.pipeThrough(new UntarStream());
|
|
|
|
let buffer = new Uint8Array();
|
|
for await (const entry of readable) {
|
|
if (entry.readable) buffer = await toBytes(entry.readable);
|
|
}
|
|
assertEquals(buffer, data);
|
|
});
|
|
|
|
Deno.test("UntarStream() with invalid size", async () => {
|
|
const bytes = (await toBytes(
|
|
ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "file",
|
|
path: "newFile.txt",
|
|
size: 512,
|
|
readable: ReadableStream.from([new Uint8Array(512).fill(97)]),
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream()),
|
|
)).slice(0, -100);
|
|
|
|
const readable = ReadableStream.from([bytes])
|
|
.pipeThrough(new UntarStream());
|
|
|
|
await assertRejects(
|
|
async () => {
|
|
for await (const entry of readable) await entry.readable?.cancel();
|
|
},
|
|
RangeError,
|
|
"Cannot extract the tar archive: The tarball chunk has an unexpected number of bytes (412)",
|
|
);
|
|
});
|
|
|
|
Deno.test("UntarStream() with invalid ending", async () => {
|
|
const tarBytes = await toBytes(
|
|
ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "file",
|
|
path: "newFile.txt",
|
|
size: 512,
|
|
readable: ReadableStream.from([new Uint8Array(512).fill(97)]),
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream()),
|
|
);
|
|
tarBytes[tarBytes.length - 1] = 1;
|
|
|
|
const readable = ReadableStream.from([tarBytes])
|
|
.pipeThrough(new UntarStream());
|
|
|
|
await assertRejects(
|
|
async () => {
|
|
for await (const entry of readable) await entry.readable?.cancel();
|
|
},
|
|
TypeError,
|
|
"Cannot extract the tar archive: The tarball has invalid ending",
|
|
);
|
|
});
|
|
|
|
Deno.test("UntarStream() with too small size", async () => {
|
|
const readable = ReadableStream.from([new Uint8Array(512)])
|
|
.pipeThrough(new UntarStream());
|
|
|
|
await assertRejects(
|
|
async () => {
|
|
for await (const entry of readable) await entry.readable?.cancel();
|
|
},
|
|
RangeError,
|
|
"Cannot extract the tar archive: The tarball is too small to be valid",
|
|
);
|
|
});
|
|
|
|
Deno.test("UntarStream() with invalid checksum", async () => {
|
|
const tarBytes = await toBytes(
|
|
ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "file",
|
|
path: "newFile.txt",
|
|
size: 512,
|
|
readable: ReadableStream.from([new Uint8Array(512).fill(97)]),
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream()),
|
|
);
|
|
tarBytes[148] = 97;
|
|
|
|
const readable = ReadableStream.from([tarBytes])
|
|
.pipeThrough(new UntarStream());
|
|
|
|
await assertRejects(
|
|
async () => {
|
|
for await (const entry of readable) await entry.readable?.cancel();
|
|
},
|
|
Error,
|
|
"Cannot extract the tar archive: An archive entry has invalid header checksum",
|
|
);
|
|
});
|
|
|
|
Deno.test("UntarStream() with extra bytes", async () => {
|
|
const readable = ReadableStream.from<TarStreamInput>([
|
|
{
|
|
type: "directory",
|
|
path: "a",
|
|
},
|
|
])
|
|
.pipeThrough(new TarStream())
|
|
.pipeThrough(
|
|
new TransformStream({
|
|
flush(controller) {
|
|
controller.enqueue(new Uint8Array(512 * 2).fill(1));
|
|
},
|
|
}),
|
|
)
|
|
.pipeThrough(new UntarStream());
|
|
|
|
for await (const entry of readable) {
|
|
assertEquals(entry.path, "a");
|
|
entry.readable?.cancel();
|
|
}
|
|
});
|