Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/test/common/buffer.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import { timeout } from '../../common/async.js';
8
import { bufferedStreamToBuffer, bufferToReadable, bufferToStream, decodeBase64, decodeHex, encodeBase64, encodeHex, newWriteableBufferStream, readableToBuffer, streamToBuffer, VSBuffer } from '../../common/buffer.js';
9
import { peekStream } from '../../common/stream.js';
10
import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';
11
12
suite('Buffer', () => {
13
14
ensureNoDisposablesAreLeakedInTestSuite();
15
16
test('issue #71993 - VSBuffer#toString returns numbers', () => {
17
const data = new Uint8Array([1, 2, 3, 'h'.charCodeAt(0), 'i'.charCodeAt(0), 4, 5]).buffer;
18
const buffer = VSBuffer.wrap(new Uint8Array(data, 3, 2));
19
assert.deepStrictEqual(buffer.toString(), 'hi');
20
});
21
22
test('bufferToReadable / readableToBuffer', () => {
23
const content = 'Hello World';
24
const readable = bufferToReadable(VSBuffer.fromString(content));
25
26
assert.strictEqual(readableToBuffer(readable).toString(), content);
27
});
28
29
test('bufferToStream / streamToBuffer', async () => {
30
const content = 'Hello World';
31
const stream = bufferToStream(VSBuffer.fromString(content));
32
33
assert.strictEqual((await streamToBuffer(stream)).toString(), content);
34
});
35
36
test('bufferedStreamToBuffer', async () => {
37
const content = 'Hello World';
38
const stream = await peekStream(bufferToStream(VSBuffer.fromString(content)), 1);
39
40
assert.strictEqual((await bufferedStreamToBuffer(stream)).toString(), content);
41
});
42
43
test('bufferWriteableStream - basics (no error)', async () => {
44
const stream = newWriteableBufferStream();
45
46
const chunks: VSBuffer[] = [];
47
stream.on('data', data => {
48
chunks.push(data);
49
});
50
51
let ended = false;
52
stream.on('end', () => {
53
ended = true;
54
});
55
56
const errors: Error[] = [];
57
stream.on('error', error => {
58
errors.push(error);
59
});
60
61
await timeout(0);
62
stream.write(VSBuffer.fromString('Hello'));
63
await timeout(0);
64
stream.end(VSBuffer.fromString('World'));
65
66
assert.strictEqual(chunks.length, 2);
67
assert.strictEqual(chunks[0].toString(), 'Hello');
68
assert.strictEqual(chunks[1].toString(), 'World');
69
assert.strictEqual(ended, true);
70
assert.strictEqual(errors.length, 0);
71
});
72
73
test('bufferWriteableStream - basics (error)', async () => {
74
const stream = newWriteableBufferStream();
75
76
const chunks: VSBuffer[] = [];
77
stream.on('data', data => {
78
chunks.push(data);
79
});
80
81
let ended = false;
82
stream.on('end', () => {
83
ended = true;
84
});
85
86
const errors: Error[] = [];
87
stream.on('error', error => {
88
errors.push(error);
89
});
90
91
await timeout(0);
92
stream.write(VSBuffer.fromString('Hello'));
93
await timeout(0);
94
stream.error(new Error());
95
stream.end();
96
97
assert.strictEqual(chunks.length, 1);
98
assert.strictEqual(chunks[0].toString(), 'Hello');
99
assert.strictEqual(ended, true);
100
assert.strictEqual(errors.length, 1);
101
});
102
103
test('bufferWriteableStream - buffers data when no listener', async () => {
104
const stream = newWriteableBufferStream();
105
106
await timeout(0);
107
stream.write(VSBuffer.fromString('Hello'));
108
await timeout(0);
109
stream.end(VSBuffer.fromString('World'));
110
111
const chunks: VSBuffer[] = [];
112
stream.on('data', data => {
113
chunks.push(data);
114
});
115
116
let ended = false;
117
stream.on('end', () => {
118
ended = true;
119
});
120
121
const errors: Error[] = [];
122
stream.on('error', error => {
123
errors.push(error);
124
});
125
126
assert.strictEqual(chunks.length, 1);
127
assert.strictEqual(chunks[0].toString(), 'HelloWorld');
128
assert.strictEqual(ended, true);
129
assert.strictEqual(errors.length, 0);
130
});
131
132
test('bufferWriteableStream - buffers errors when no listener', async () => {
133
const stream = newWriteableBufferStream();
134
135
await timeout(0);
136
stream.write(VSBuffer.fromString('Hello'));
137
await timeout(0);
138
stream.error(new Error());
139
140
const chunks: VSBuffer[] = [];
141
stream.on('data', data => {
142
chunks.push(data);
143
});
144
145
const errors: Error[] = [];
146
stream.on('error', error => {
147
errors.push(error);
148
});
149
150
let ended = false;
151
stream.on('end', () => {
152
ended = true;
153
});
154
155
stream.end();
156
157
assert.strictEqual(chunks.length, 1);
158
assert.strictEqual(chunks[0].toString(), 'Hello');
159
assert.strictEqual(ended, true);
160
assert.strictEqual(errors.length, 1);
161
});
162
163
test('bufferWriteableStream - buffers end when no listener', async () => {
164
const stream = newWriteableBufferStream();
165
166
await timeout(0);
167
stream.write(VSBuffer.fromString('Hello'));
168
await timeout(0);
169
stream.end(VSBuffer.fromString('World'));
170
171
let ended = false;
172
stream.on('end', () => {
173
ended = true;
174
});
175
176
const chunks: VSBuffer[] = [];
177
stream.on('data', data => {
178
chunks.push(data);
179
});
180
181
const errors: Error[] = [];
182
stream.on('error', error => {
183
errors.push(error);
184
});
185
186
assert.strictEqual(chunks.length, 1);
187
assert.strictEqual(chunks[0].toString(), 'HelloWorld');
188
assert.strictEqual(ended, true);
189
assert.strictEqual(errors.length, 0);
190
});
191
192
test('bufferWriteableStream - nothing happens after end()', async () => {
193
const stream = newWriteableBufferStream();
194
195
const chunks: VSBuffer[] = [];
196
stream.on('data', data => {
197
chunks.push(data);
198
});
199
200
await timeout(0);
201
stream.write(VSBuffer.fromString('Hello'));
202
await timeout(0);
203
stream.end(VSBuffer.fromString('World'));
204
205
let dataCalledAfterEnd = false;
206
stream.on('data', data => {
207
dataCalledAfterEnd = true;
208
});
209
210
let errorCalledAfterEnd = false;
211
stream.on('error', error => {
212
errorCalledAfterEnd = true;
213
});
214
215
let endCalledAfterEnd = false;
216
stream.on('end', () => {
217
endCalledAfterEnd = true;
218
});
219
220
await timeout(0);
221
stream.write(VSBuffer.fromString('Hello'));
222
await timeout(0);
223
stream.error(new Error());
224
await timeout(0);
225
stream.end(VSBuffer.fromString('World'));
226
227
assert.strictEqual(dataCalledAfterEnd, false);
228
assert.strictEqual(errorCalledAfterEnd, false);
229
assert.strictEqual(endCalledAfterEnd, false);
230
231
assert.strictEqual(chunks.length, 2);
232
assert.strictEqual(chunks[0].toString(), 'Hello');
233
assert.strictEqual(chunks[1].toString(), 'World');
234
});
235
236
test('bufferWriteableStream - pause/resume (simple)', async () => {
237
const stream = newWriteableBufferStream();
238
239
const chunks: VSBuffer[] = [];
240
stream.on('data', data => {
241
chunks.push(data);
242
});
243
244
let ended = false;
245
stream.on('end', () => {
246
ended = true;
247
});
248
249
const errors: Error[] = [];
250
stream.on('error', error => {
251
errors.push(error);
252
});
253
254
stream.pause();
255
256
await timeout(0);
257
stream.write(VSBuffer.fromString('Hello'));
258
await timeout(0);
259
stream.end(VSBuffer.fromString('World'));
260
261
assert.strictEqual(chunks.length, 0);
262
assert.strictEqual(errors.length, 0);
263
assert.strictEqual(ended, false);
264
265
stream.resume();
266
267
assert.strictEqual(chunks.length, 1);
268
assert.strictEqual(chunks[0].toString(), 'HelloWorld');
269
assert.strictEqual(ended, true);
270
assert.strictEqual(errors.length, 0);
271
});
272
273
test('bufferWriteableStream - pause/resume (pause after first write)', async () => {
274
const stream = newWriteableBufferStream();
275
276
const chunks: VSBuffer[] = [];
277
stream.on('data', data => {
278
chunks.push(data);
279
});
280
281
let ended = false;
282
stream.on('end', () => {
283
ended = true;
284
});
285
286
const errors: Error[] = [];
287
stream.on('error', error => {
288
errors.push(error);
289
});
290
291
await timeout(0);
292
stream.write(VSBuffer.fromString('Hello'));
293
294
stream.pause();
295
296
await timeout(0);
297
stream.end(VSBuffer.fromString('World'));
298
299
assert.strictEqual(chunks.length, 1);
300
assert.strictEqual(chunks[0].toString(), 'Hello');
301
assert.strictEqual(errors.length, 0);
302
assert.strictEqual(ended, false);
303
304
stream.resume();
305
306
assert.strictEqual(chunks.length, 2);
307
assert.strictEqual(chunks[0].toString(), 'Hello');
308
assert.strictEqual(chunks[1].toString(), 'World');
309
assert.strictEqual(ended, true);
310
assert.strictEqual(errors.length, 0);
311
});
312
313
test('bufferWriteableStream - pause/resume (error)', async () => {
314
const stream = newWriteableBufferStream();
315
316
const chunks: VSBuffer[] = [];
317
stream.on('data', data => {
318
chunks.push(data);
319
});
320
321
let ended = false;
322
stream.on('end', () => {
323
ended = true;
324
});
325
326
const errors: Error[] = [];
327
stream.on('error', error => {
328
errors.push(error);
329
});
330
331
stream.pause();
332
333
await timeout(0);
334
stream.write(VSBuffer.fromString('Hello'));
335
await timeout(0);
336
stream.error(new Error());
337
stream.end();
338
339
assert.strictEqual(chunks.length, 0);
340
assert.strictEqual(ended, false);
341
assert.strictEqual(errors.length, 0);
342
343
stream.resume();
344
345
assert.strictEqual(chunks.length, 1);
346
assert.strictEqual(chunks[0].toString(), 'Hello');
347
assert.strictEqual(ended, true);
348
assert.strictEqual(errors.length, 1);
349
});
350
351
test('bufferWriteableStream - destroy', async () => {
352
const stream = newWriteableBufferStream();
353
354
const chunks: VSBuffer[] = [];
355
stream.on('data', data => {
356
chunks.push(data);
357
});
358
359
let ended = false;
360
stream.on('end', () => {
361
ended = true;
362
});
363
364
const errors: Error[] = [];
365
stream.on('error', error => {
366
errors.push(error);
367
});
368
369
stream.destroy();
370
371
await timeout(0);
372
stream.write(VSBuffer.fromString('Hello'));
373
await timeout(0);
374
stream.end(VSBuffer.fromString('World'));
375
376
assert.strictEqual(chunks.length, 0);
377
assert.strictEqual(ended, false);
378
assert.strictEqual(errors.length, 0);
379
});
380
381
test('Performance issue with VSBuffer#slice #76076', function () { // TODO@alexdima this test seems to fail in web (https://github.com/microsoft/vscode/issues/114042)
382
// Buffer#slice creates a view
383
if (typeof Buffer !== 'undefined') {
384
const buff = Buffer.from([10, 20, 30, 40]);
385
const b2 = buff.slice(1, 3);
386
assert.strictEqual(buff[1], 20);
387
assert.strictEqual(b2[0], 20);
388
389
buff[1] = 17; // modify buff AND b2
390
assert.strictEqual(buff[1], 17);
391
assert.strictEqual(b2[0], 17);
392
}
393
394
// TypedArray#slice creates a copy
395
{
396
const unit = new Uint8Array([10, 20, 30, 40]);
397
const u2 = unit.slice(1, 3);
398
assert.strictEqual(unit[1], 20);
399
assert.strictEqual(u2[0], 20);
400
401
unit[1] = 17; // modify unit, NOT b2
402
assert.strictEqual(unit[1], 17);
403
assert.strictEqual(u2[0], 20);
404
}
405
406
// TypedArray#subarray creates a view
407
{
408
const unit = new Uint8Array([10, 20, 30, 40]);
409
const u2 = unit.subarray(1, 3);
410
assert.strictEqual(unit[1], 20);
411
assert.strictEqual(u2[0], 20);
412
413
unit[1] = 17; // modify unit AND b2
414
assert.strictEqual(unit[1], 17);
415
assert.strictEqual(u2[0], 17);
416
}
417
});
418
419
test('indexOf', () => {
420
const haystack = VSBuffer.fromString('abcaabbccaaabbbccc');
421
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('')), 0);
422
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('a'.repeat(100))), -1);
423
424
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('a')), 0);
425
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('c')), 2);
426
427
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('abcaa')), 0);
428
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('caaab')), 8);
429
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('ccc')), 15);
430
431
assert.strictEqual(haystack.indexOf(VSBuffer.fromString('cccb')), -1);
432
});
433
434
test('wrap', () => {
435
const actual = new Uint8Array([1, 2, 3]);
436
const wrapped = VSBuffer.wrap(actual);
437
assert.strictEqual(wrapped.byteLength, 3);
438
assert.deepStrictEqual(Array.from(wrapped.buffer), [1, 2, 3]);
439
});
440
441
test('fromString', () => {
442
const value = 'Hello World';
443
const buff = VSBuffer.fromString(value);
444
assert.strictEqual(buff.toString(), value);
445
});
446
447
test('fromByteArray', () => {
448
const array = [1, 2, 3, 4, 5];
449
const buff = VSBuffer.fromByteArray(array);
450
assert.strictEqual(buff.byteLength, array.length);
451
assert.deepStrictEqual(Array.from(buff.buffer), array);
452
});
453
454
test('concat', () => {
455
const chunks = [
456
VSBuffer.fromString('abc'),
457
VSBuffer.fromString('def'),
458
VSBuffer.fromString('ghi')
459
];
460
461
// Test without total length
462
const result1 = VSBuffer.concat(chunks);
463
assert.strictEqual(result1.toString(), 'abcdefghi');
464
465
// Test with total length
466
const result2 = VSBuffer.concat(chunks, 9);
467
assert.strictEqual(result2.toString(), 'abcdefghi');
468
});
469
470
test('clone', () => {
471
const original = VSBuffer.fromString('test');
472
const clone = original.clone();
473
474
assert.notStrictEqual(original.buffer, clone.buffer);
475
assert.deepStrictEqual(Array.from(original.buffer), Array.from(clone.buffer));
476
});
477
478
test('slice', () => {
479
const buff = VSBuffer.fromString('Hello World');
480
481
const slice1 = buff.slice(0, 5);
482
assert.strictEqual(slice1.toString(), 'Hello');
483
484
const slice2 = buff.slice(6);
485
assert.strictEqual(slice2.toString(), 'World');
486
});
487
488
test('set', () => {
489
const buff = VSBuffer.alloc(5);
490
491
// Test setting from VSBuffer
492
buff.set(VSBuffer.fromString('ab'), 0);
493
assert.strictEqual(buff.toString().substring(0, 2), 'ab');
494
495
// Test setting from Uint8Array
496
buff.set(new Uint8Array([99, 100]), 2); // 'cd'
497
assert.strictEqual(buff.toString().substring(2, 4), 'cd');
498
499
// Test invalid input
500
assert.throws(() => {
501
buff.set({} as any);
502
});
503
});
504
505
test('equals', () => {
506
const buff1 = VSBuffer.fromString('test');
507
const buff2 = VSBuffer.fromString('test');
508
const buff3 = VSBuffer.fromString('different');
509
const buff4 = VSBuffer.fromString('tes1');
510
511
assert.strictEqual(buff1.equals(buff1), true);
512
assert.strictEqual(buff1.equals(buff2), true);
513
assert.strictEqual(buff1.equals(buff3), false);
514
assert.strictEqual(buff1.equals(buff4), false);
515
});
516
517
test('read/write methods', () => {
518
const buff = VSBuffer.alloc(8);
519
520
// Test UInt32BE
521
buff.writeUInt32BE(0x12345678, 0);
522
assert.strictEqual(buff.readUInt32BE(0), 0x12345678);
523
524
// Test UInt32LE
525
buff.writeUInt32LE(0x12345678, 4);
526
assert.strictEqual(buff.readUInt32LE(4), 0x12345678);
527
528
// Test UInt8
529
const buff2 = VSBuffer.alloc(1);
530
buff2.writeUInt8(123, 0);
531
assert.strictEqual(buff2.readUInt8(0), 123);
532
});
533
534
suite('encoding', () => {
535
/*
536
Generated with:
537
538
const crypto = require('crypto');
539
540
for (let i = 0; i < 16; i++) {
541
const buf = crypto.randomBytes(i);
542
console.log(`[new Uint8Array([${Array.from(buf).join(', ')}]), '${buf.toString('base64')}'],`)
543
}
544
545
*/
546
547
const testCases: [Uint8Array, base64: string, hex: string][] = [
548
[new Uint8Array([]), '', ''],
549
[new Uint8Array([77]), 'TQ==', '4d'],
550
[new Uint8Array([230, 138]), '5oo=', 'e68a'],
551
[new Uint8Array([104, 98, 82]), 'aGJS', '686252'],
552
[new Uint8Array([92, 114, 57, 209]), 'XHI50Q==', '5c7239d1'],
553
[new Uint8Array([238, 51, 1, 240, 124]), '7jMB8Hw=', 'ee3301f07c'],
554
[new Uint8Array([96, 54, 130, 79, 47, 179]), 'YDaCTy+z', '6036824f2fb3'],
555
[new Uint8Array([91, 22, 68, 217, 68, 117, 116]), 'WxZE2UR1dA==', '5b1644d9447574'],
556
[new Uint8Array([184, 227, 214, 171, 244, 175, 141, 53]), 'uOPWq/SvjTU=', 'b8e3d6abf4af8d35'],
557
[new Uint8Array([53, 98, 93, 130, 71, 117, 191, 137, 156]), 'NWJdgkd1v4mc', '35625d824775bf899c'],
558
[new Uint8Array([154, 156, 60, 102, 232, 197, 92, 25, 124, 98]), 'mpw8ZujFXBl8Yg==', '9a9c3c66e8c55c197c62'],
559
[new Uint8Array([152, 131, 106, 234, 17, 183, 164, 245, 252, 67, 26]), 'mINq6hG3pPX8Qxo=', '98836aea11b7a4f5fc431a'],
560
[new Uint8Array([232, 254, 194, 234, 16, 42, 86, 135, 117, 61, 179, 4]), '6P7C6hAqVod1PbME', 'e8fec2ea102a5687753db304'],
561
[new Uint8Array([4, 199, 85, 172, 125, 171, 172, 219, 61, 47, 78, 155, 127]), 'BMdVrH2rrNs9L06bfw==', '04c755ac7dabacdb3d2f4e9b7f'],
562
[new Uint8Array([189, 67, 62, 189, 87, 171, 27, 164, 87, 142, 126, 113, 23, 182]), 'vUM+vVerG6RXjn5xF7Y=', 'bd433ebd57ab1ba4578e7e7117b6'],
563
[new Uint8Array([153, 156, 145, 240, 228, 200, 199, 158, 40, 167, 97, 52, 217, 148, 43]), 'mZyR8OTIx54op2E02ZQr', '999c91f0e4c8c79e28a76134d9942b'],
564
];
565
566
test('encodes base64', () => {
567
for (const [bytes, expected] of testCases) {
568
assert.strictEqual(encodeBase64(VSBuffer.wrap(bytes)), expected);
569
}
570
});
571
572
test('decodes, base64', () => {
573
for (const [expected, encoded] of testCases) {
574
assert.deepStrictEqual(new Uint8Array(decodeBase64(encoded).buffer), expected);
575
}
576
});
577
578
test('encodes hex', () => {
579
for (const [bytes, , expected] of testCases) {
580
assert.strictEqual(encodeHex(VSBuffer.wrap(bytes)), expected);
581
}
582
});
583
584
test('decodes, hex', () => {
585
for (const [expected, , encoded] of testCases) {
586
assert.deepStrictEqual(new Uint8Array(decodeHex(encoded).buffer), expected);
587
}
588
});
589
590
test('throws error on invalid encoding', () => {
591
assert.throws(() => decodeBase64('invalid!'));
592
assert.throws(() => decodeHex('invalid!'));
593
});
594
});
595
});
596
597