forked from bradenmacdonald/s3-lite-client
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transform-chunk-sizes.test.ts
155 lines (147 loc) · 4.38 KB
/
transform-chunk-sizes.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import { assertEquals } from "./deps-tests.ts";
import { TransformChunkSizes } from "./transform-chunk-sizes.ts";
/**
* A readable stream that generates consecutive integers.
*
* If "bytesPerChunk" is 1, it generates 1 byte at a time: 1, then 2, then 3, ...
* If "bytesPerChunk" is 2, it generates 2 bytes at a time: 1, 1, then 2, 2, then 3, 3, ...
*/
class NumberSource extends ReadableStream<Uint8Array> {
constructor(delayMs: number, chunksCount: number, bytesPerChunk = 1) {
let intervalTimer: number;
let i = 0;
super({
start(controller) {
// Enqueue a byte every 100ms
intervalTimer = setInterval(() => {
controller.enqueue(new Uint8Array(new Array(bytesPerChunk).fill(i)));
i++;
if (i === chunksCount) {
clearInterval(intervalTimer);
controller.close();
}
}, delayMs);
},
pull(_controller) {
// unused
},
cancel() {
clearInterval(intervalTimer);
},
});
}
}
/**
* A writeable stream that stores all the data chunks it receives in an array
*/
class DataSink extends WritableStream<Uint8Array> {
readonly outputData: Uint8Array[];
readonly done: Promise<void>;
constructor() {
const outputData: Uint8Array[] = [];
let markDone: () => void;
let markError: () => void;
const donePromise = new Promise<void>((resolve, reject) => {
markDone = resolve;
markError = reject;
});
super({
// deno-lint-ignore require-await
async write(chunk) {
outputData.push(new Uint8Array(chunk)); // Make a copy of chunk when we save it though
},
close() {
markDone();
},
abort(err) {
console.error("Sink error:", err);
markError();
},
});
this.outputData = outputData;
this.done = donePromise;
}
}
// Shortcut for building a single-element Uint8Array
const UA = (...number: number[]) => new Uint8Array(number);
Deno.test({
name: "Make sure our test stream classes work: Generate 4 integers (0, 1, 2, 3), 10ms apart",
fn: async () => {
const inputStream = new NumberSource(10, 4);
const outputStream = new DataSink();
inputStream.pipeTo(outputStream);
await outputStream.done;
assertEquals(
outputStream.outputData,
[UA(0), UA(1), UA(2), UA(3)],
);
},
});
Deno.test({
name: "Make sure our test stream classes work: Generate 4 integer triples (0,0,0, 1,1,1, 2,2,2, 3,3,3), 0ms apart",
fn: async () => {
const inputStream = new NumberSource(0, 4, 3);
const outputStream = new DataSink();
inputStream.pipeTo(outputStream);
await outputStream.done;
assertEquals(
outputStream.outputData,
[UA(0, 0, 0), UA(1, 1, 1), UA(2, 2, 2), UA(3, 3, 3)],
);
},
});
Deno.test({
name: "TransformChunkSizes - chunk 6 single bytes to 3x 2 bytes",
fn: async () => {
// Generate 6 integers (0, 1, 2, 3, 4, 5), 10ms apart
const inputStream = new NumberSource(10, 6);
const outputStream = new DataSink();
const transformer = new TransformChunkSizes(2);
inputStream.pipeThrough(transformer).pipeTo(outputStream);
await outputStream.done;
assertEquals(
outputStream.outputData,
[UA(0, 1), UA(2, 3), UA(4, 5)],
);
},
});
Deno.test({
name: "TransformChunkSizes - chunk 15 single bytes to 4x 4 bytes",
fn: async () => {
const inputStream = new NumberSource(0, 15);
const outputStream = new DataSink();
const transformer = new TransformChunkSizes(4);
inputStream.pipeThrough(transformer).pipeTo(outputStream);
await outputStream.done;
assertEquals(
outputStream.outputData,
[
UA(0, 1, 2, 3),
UA(4, 5, 6, 7),
UA(8, 9, 10, 11),
UA(12, 13, 14 /* last one has only three bytes */),
],
);
},
});
Deno.test({
name: "TransformChunkSizes - chunk 4x 8 bytes to chunks of 6 bytes",
fn: async () => {
const inputStream = new NumberSource(0, 4, 8);
const outputStream = new DataSink();
const transformer = new TransformChunkSizes(6);
inputStream.pipeThrough(transformer).pipeTo(outputStream);
await outputStream.done;
assertEquals(
outputStream.outputData,
[
UA(0, 0, 0, 0, 0, 0),
UA(0, 0, 1, 1, 1, 1),
UA(1, 1, 1, 1, 2, 2),
UA(2, 2, 2, 2, 2, 2),
UA(3, 3, 3, 3, 3, 3),
UA(3, 3 /* last one has only two bytes */),
],
);
},
});