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