-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathtest.js
367 lines (353 loc) · 15.3 KB
/
test.js
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
var fs = require("fs");
var yazl = require("../");
var yauzl = require("yauzl");
var BufferList = require("./bl-minimal.js");
// Test:
// * filename canonicalization.
// * addFile, addReadStream, and addBuffer
// * extracting the zip file (via yauzl) gives the correct contents.
// * compress: false
// * specifying mode and mtime options, but not checking them.
// * verifying compression method defaults to true.
(function() {
var fileMetadata = {
mtime: new Date(),
mode: 0o100664,
};
var zipfile = new yazl.ZipFile();
zipfile.addFile(__filename, "unicōde.txt");
zipfile.addFile(__filename, "without-compression.txt", {compress: false});
zipfile.addReadStream(fs.createReadStream(__filename), "readStream.txt", fileMetadata);
var expectedContents = fs.readFileSync(__filename);
zipfile.addBuffer(expectedContents, "with/directories.txt", fileMetadata);
zipfile.addBuffer(expectedContents, "with\\windows-paths.txt", fileMetadata);
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize !== -1) throw new Error("calculatedTotalSize is impossible to know before compression");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
zipfile.on("entry", function(entry) {
var expectedCompressionMethod = entry.fileName === "without-compression.txt" ? 0 : 8;
if (entry.compressionMethod !== expectedCompressionMethod) throw new Error("expected " + entry.fileName + " compression method " + expectedCompressionMethod + ". found: " + entry.compressionMethod);
zipfile.openReadStream(entry, function(err, readStream) {
if (err) throw err;
readStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
if (!expectedContents.equals(data)) throw new Error("unexpected contents");
console.log(entry.fileName + ": pass");
}));
});
});
});
}));
});
})();
// Test:
// * specifying compressionLevel varies the output size.
// * specifying compressionLevel:0 disables compression.
(function() {
var options = {
mtime: new Date(),
mode: 0o100664,
};
var zipfile = new yazl.ZipFile();
options.compressionLevel = 1;
zipfile.addFile(__filename, "level1.txt", options);
options.compressionLevel = 9;
zipfile.addFile(__filename, "level9.txt", options);
options.compressionLevel = 0;
zipfile.addFile(__filename, "level0.txt", options);
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize !== -1) throw new Error("calculatedTotalSize is impossible to know before compression");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
var fileNameToSize = {};
zipfile.on("entry", function(entry) {
fileNameToSize[entry.fileName] = entry.compressedSize;
var expectedCompressionMethod = entry.fileName === "level0.txt" ? 0 : 8;
if (entry.compressionMethod !== expectedCompressionMethod) throw new Error("expected " + entry.fileName + " compression method " + expectedCompressionMethod + ". found: " + entry.compressionMethod);
});
zipfile.on("end", function() {
var size0 = fileNameToSize["level0.txt"];
var size1 = fileNameToSize["level1.txt"];
var size9 = fileNameToSize["level9.txt"];
// Note: undefined coerces to NaN which always results in the comparison evaluating to `false`.
if (!(size0 >= size1)) throw new Error("Compression level 1 inflated size. expected: " + size0 + " >= " + size1);
if (!(size1 >= size9)) throw new Error("Compression level 9 inflated size. expected: " + size1 + " >= " + size9);
console.log("compressionLevel (" + size0 + " >= " + size1 + " >= " + size9 + "): pass");
});
});
}));
});
})();
// Test:
// * specifying mtime outside the bounds of dos format but in bounds for unix format.
// * forceDosTimestamp, and verifying the lower clamping for dos format.
// * specifying mtime after 2038, and verifying the clamping for unix format.
(function() {
var options = {
mtime: new Date(0), // unix epoch
mode: 0o100664,
compress: false,
};
var zipfile = new yazl.ZipFile();
zipfile.addFile(__filename, "modern-1970.txt", options);
options.forceDosTimestamp = true;
zipfile.addFile(__filename, "dos-1970.txt", options);
options.forceDosTimestamp = false;
options.mtime = new Date(2080, 1, 1); // year 2080 is beyond the unix range.
zipfile.addFile(__filename, "2080.txt", options);
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize === -1) throw new Error("calculatedTotalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
if (data.length !== calculatedTotalSize) throw new Error("calculatedTotalSize prediction is wrong. " + calculatedTotalSize + " !== " + data.length);
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
zipfile.on("entry", function(entry) {
switch (entry.fileName) {
case "modern-1970.txt":
if (entry.getLastModDate().getTime() !== 0) throw new Error("expected unix epoch to be encodable. found: " + entry.getLastModDate());
break;
case "dos-1970.txt":
var year = entry.getLastModDate().getFullYear();
if (!(1979 <= year && year <= 1981)) throw new Error("expected dos format year to be clamped to 1980ish. found: " + entry.getLastModDate());
break;
case "2080.txt":
if (entry.getLastModDate().getUTCFullYear() !== 2038) throw new Error("expected timestamp clamped down to year 2038. found: " + entry.getLastModDate());
break;
default: throw new Error(entry.fileName);
}
});
zipfile.on("end", function() {
console.log("timestamp encodings: pass");
});
});
}));
});
})();
// Test:
// * forceZip64Format for various subsets of entries.
// * specifying size for addReadStream.
// * calculatedTotalSize should always be known.
// * calculatedTotalSize is correct.
(function() {
var zip64Combinations = [
[0, 0, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1],
[1, 1, 1, 1, 1],
];
zip64Combinations.forEach(function(zip64Config) {
var options = {
compress: false,
size: null,
forceZip64Format: false,
};
var zipfile = new yazl.ZipFile();
options.forceZip64Format = !!zip64Config[0];
zipfile.addFile(__filename, "asdf.txt", options);
options.forceZip64Format = !!zip64Config[1];
zipfile.addFile(__filename, "fdsa.txt", options);
options.forceZip64Format = !!zip64Config[2];
zipfile.addBuffer(bufferFrom("buffer"), "buffer.txt", options);
options.forceZip64Format = !!zip64Config[3];
var someBuffer = bufferFrom("stream");
options.size = someBuffer.length;
zipfile.addReadStream(new BufferList().append(someBuffer), "stream.txt", options);
options.size = null;
zipfile.end({forceZip64Format:!!zip64Config[4]}, function(calculatedTotalSize) {
if (calculatedTotalSize === -1) throw new Error("calculatedTotalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (data.length !== calculatedTotalSize) throw new Error("calculatedTotalSize prediction is wrong. " + calculatedTotalSize + " !== " + data.length);
console.log("calculatedTotalSize(" + zip64Config.join("") + "): pass");
}));
});
});
})();
// Test adding empty directories and verifying their names in the resulting zipfile.
(function() {
var zipfile = new yazl.ZipFile();
zipfile.addFile(__filename, "a.txt");
zipfile.addBuffer(bufferFrom("buffer"), "b.txt");
zipfile.addReadStream(new BufferList().append(bufferFrom("stream")), "c.txt");
zipfile.addEmptyDirectory("d/");
zipfile.addEmptyDirectory("e");
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize !== -1) throw new Error("calculatedTotalSize should be unknown");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
var entryNames = ["a.txt", "b.txt", "c.txt", "d/", "e/"];
zipfile.on("entry", function(entry) {
var expectedName = entryNames.shift();
if (entry.fileName !== expectedName) {
throw new Error("unexpected entry fileName: " + entry.fileName + ", expected: " + expectedName);
}
});
zipfile.on("end", function() {
if (entryNames.length === 0) console.log("optional parameters and directories: pass");
});
});
}));
});
})();
// Test:
// * just calling addBuffer() and no other add functions.
// * calculatedTotalSize should be known and correct for addBuffer with compress:false.
// * addBuffer with compress:false disables compression.
(function() {
var zipfile = new yazl.ZipFile();
zipfile.addBuffer(bufferFrom("hello"), "hello.txt", {compress: false});
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize === -1) throw new Error("calculatedTotalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
if (data.length !== calculatedTotalSize) throw new Error("calculatedTotalSize prediction is wrong. " + calculatedTotalSize + " !== " + data.length);
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
var entryNames = ["hello.txt"];
zipfile.on("entry", function(entry) {
var expectedName = entryNames.shift();
if (entry.fileName !== expectedName) {
throw new Error("unexpected entry fileName: " + entry.fileName + ", expected: " + expectedName);
}
var expectedCompressionMethod = 0;
if (entry.compressionMethod !== expectedCompressionMethod) throw new Error("expected " + entry.fileName + " compression method " + expectedCompressionMethod + ". found: " + entry.compressionMethod);
});
zipfile.on("end", function() {
if (entryNames.length === 0) console.log("justAddBuffer: pass");
});
});
}));
});
})();
// Test:
// * zipfile with no entries.
// * comment can be string or Buffer.
// * archive comment uses CP437 encoding for non-ASCII strings. (or rather that yazl and yauzl agree on the encoding.)
var weirdChars = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ';
(function() {
var testCases = [
["Hello World", "Hello World"],
[bufferFrom("Hello"), "Hello"],
[weirdChars, weirdChars],
];
testCases.forEach(function(testCase, i) {
var zipfile = new yazl.ZipFile();
zipfile.end({
comment: testCase[0],
}, function(calculatedTotalSize) {
if (calculatedTotalSize === -1) throw new Error("calculatedTotalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
if (data.length !== calculatedTotalSize) throw new Error("calculatedTotalSize prediction is wrong. " + calculatedTotalSize + " !== " + data.length);
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
if (zipfile.comment !== testCase[1]) {
throw new Error("comment is wrong. " + JSON.stringify(zipfile.comment) + " !== " + JSON.stringify(testCase[1]));
}
console.log("comment(" + i + "): pass");
});
}));
});
});
})();
// Test ensuring that archive comment cannot create an ambiguous zip file.
(function() {
var zipfile = new yazl.ZipFile();
try {
zipfile.end({
comment: bufferFrom("01234567890123456789" + "\x50\x4b\x05\x06" + "01234567890123456789")
});
} catch (e) {
if (e.toString().indexOf("comment contains end of central directory record signature") !== -1) {
console.log("block eocdr signature in comment: pass");
return;
}
}
throw new Error("expected error for including eocdr signature in comment");
})();
// Test:
// * specifying fileComment via addBuffer.
// * fileComment can be string or Buffer.
// * yauzl and yazl agree on the encoding.
// * calculatedTotalSize is known and correct with compress:false.
(function() {
var testCases = [
["Hello World!", "Hello World!"],
[bufferFrom("Hello!"), "Hello!"],
[weirdChars, weirdChars],
];
testCases.forEach(function(testCase, i) {
var zipfile = new yazl.ZipFile();
zipfile.addBuffer(bufferFrom("hello"), "hello.txt", {compress: false, fileComment: testCase[0]});
zipfile.end(function(calculatedTotalSize) {
if (calculatedTotalSize === -1) throw new Error("calculatedTotalSize should be known");
zipfile.outputStream.pipe(new BufferList(function(err, data) {
if (err) throw err;
if (data.length !== calculatedTotalSize) throw new Error("calculatedTotalSize prediction is wrong. " + calculatedTotalSize + " !== " + data.length);
yauzl.fromBuffer(data, function(err, zipfile) {
if (err) throw err;
var entryNames = ["hello.txt"];
zipfile.on("entry", function(entry) {
var expectedName = entryNames.shift();
if (entry.fileComment !== testCase[1]) {
throw new Error("fileComment is wrong. " + JSON.stringify(entry.fileComment) + " !== " + JSON.stringify(testCase[1]));
}
});
zipfile.on("end", function() {
if (entryNames.length === 0) console.log("fileComment(" + i + "): pass");
});
});
}));
});
});
})();
// Test:
// * giving an error to the addReadStreamLazy callback emits the error on the zipfile.
// * calling addReadStreamLazy with no options argument.
// * trying to add beyond end() throws an error.
(function() {
var zipfile = new yazl.ZipFile();
zipfile.on("error", function(err) {
if (err.message !== "error 1") throw new Error("expected only error 1, got: " + err.message);
});
zipfile.addReadStreamLazy("hello.txt", function(cb) {
cb(new Error("error 1"));
});
zipfile.addReadStreamLazy("hello2.txt", function(cb) {
cb(new Error("error 2"));
});
zipfile.end(function() {
throw new Error("should not call calculatedTotalSizeCallback in error conditions")
});
var gotError = false;
try {
zipfile.addBuffer(bufferFrom("a"), "a");
} catch (err) {
gotError = true;
}
if (!gotError) throw new Error("expected error for adding after calling end()");
})();
function bufferFrom(something, encoding) {
bufferFrom = modern;
try {
return bufferFrom(something, encoding);
} catch (e) {
bufferFrom = legacy;
return bufferFrom(something, encoding);
}
function modern(something, encoding) {
return Buffer.from(something, encoding);
}
function legacy(something, encoding) {
return new Buffer(something, encoding);
}
}