Skip to content

Commit

Permalink
node: add more passing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nektro committed Jan 4, 2025
1 parent d5fc928 commit 1d3cff2
Show file tree
Hide file tree
Showing 26 changed files with 1,170 additions and 0 deletions.
132 changes: 132 additions & 0 deletions test/js/node/test/parallel/test-buffer-bytelength.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const SlowBuffer = require('buffer').SlowBuffer;
const vm = require('vm');

[
[32, 'latin1'],
[NaN, 'utf8'],
[{}, 'latin1'],
[],
].forEach((args) => {
assert.throws(
() => Buffer.byteLength(...args),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "string" argument must be of type string or an instance ' +
'of Buffer or ArrayBuffer.' +
common.invalidArgTypeHelper(args[0])
}
);
});

assert(ArrayBuffer.isView(new Buffer(10)));
assert(ArrayBuffer.isView(new SlowBuffer(10)));
assert(ArrayBuffer.isView(Buffer.alloc(10)));
assert(ArrayBuffer.isView(Buffer.allocUnsafe(10)));
assert(ArrayBuffer.isView(Buffer.allocUnsafeSlow(10)));
assert(ArrayBuffer.isView(Buffer.from('')));

// buffer
const incomplete = Buffer.from([0xe4, 0xb8, 0xad, 0xe6, 0x96]);
assert.strictEqual(Buffer.byteLength(incomplete), 5);
const ascii = Buffer.from('abc');
assert.strictEqual(Buffer.byteLength(ascii), 3);

// ArrayBuffer
const buffer = new ArrayBuffer(8);
assert.strictEqual(Buffer.byteLength(buffer), 8);

// TypedArray
const int8 = new Int8Array(8);
assert.strictEqual(Buffer.byteLength(int8), 8);
const uint8 = new Uint8Array(8);
assert.strictEqual(Buffer.byteLength(uint8), 8);
const uintc8 = new Uint8ClampedArray(2);
assert.strictEqual(Buffer.byteLength(uintc8), 2);
const int16 = new Int16Array(8);
assert.strictEqual(Buffer.byteLength(int16), 16);
const uint16 = new Uint16Array(8);
assert.strictEqual(Buffer.byteLength(uint16), 16);
const int32 = new Int32Array(8);
assert.strictEqual(Buffer.byteLength(int32), 32);
const uint32 = new Uint32Array(8);
assert.strictEqual(Buffer.byteLength(uint32), 32);
const float32 = new Float32Array(8);
assert.strictEqual(Buffer.byteLength(float32), 32);
const float64 = new Float64Array(8);
assert.strictEqual(Buffer.byteLength(float64), 64);

// DataView
const dv = new DataView(new ArrayBuffer(2));
assert.strictEqual(Buffer.byteLength(dv), 2);

// Special case: zero length string
assert.strictEqual(Buffer.byteLength('', 'ascii'), 0);
assert.strictEqual(Buffer.byteLength('', 'HeX'), 0);

// utf8
assert.strictEqual(Buffer.byteLength('∑éllö wørl∂!', 'utf-8'), 19);
assert.strictEqual(Buffer.byteLength('κλμνξο', 'utf8'), 12);
assert.strictEqual(Buffer.byteLength('挵挶挷挸挹', 'utf-8'), 15);
assert.strictEqual(Buffer.byteLength('𠝹𠱓𠱸', 'UTF8'), 12);
// Without an encoding, utf8 should be assumed
assert.strictEqual(Buffer.byteLength('hey there'), 9);
assert.strictEqual(Buffer.byteLength('𠱸挶νξ#xx :)'), 17);
assert.strictEqual(Buffer.byteLength('hello world', ''), 11);
// It should also be assumed with unrecognized encoding
assert.strictEqual(Buffer.byteLength('hello world', 'abc'), 11);
assert.strictEqual(Buffer.byteLength('ßœ∑≈', 'unkn0wn enc0ding'), 10);

// base64
assert.strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ=', 'base64'), 11);
assert.strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ=', 'BASE64'), 11);
assert.strictEqual(Buffer.byteLength('bm9kZS5qcyByb2NrcyE=', 'base64'), 14);
assert.strictEqual(Buffer.byteLength('aGkk', 'base64'), 3);
assert.strictEqual(
Buffer.byteLength('bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw==', 'base64'), 25
);
// base64url
assert.strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ', 'base64url'), 11);
assert.strictEqual(Buffer.byteLength('aGVsbG8gd29ybGQ', 'BASE64URL'), 11);
assert.strictEqual(Buffer.byteLength('bm9kZS5qcyByb2NrcyE', 'base64url'), 14);
assert.strictEqual(Buffer.byteLength('aGkk', 'base64url'), 3);
assert.strictEqual(
Buffer.byteLength('bHNrZGZsa3NqZmtsc2xrZmFqc2RsZmtqcw', 'base64url'), 25
);
// special padding
assert.strictEqual(Buffer.byteLength('aaa=', 'base64'), 2);
assert.strictEqual(Buffer.byteLength('aaaa==', 'base64'), 3);
assert.strictEqual(Buffer.byteLength('aaa=', 'base64url'), 2);
assert.strictEqual(Buffer.byteLength('aaaa==', 'base64url'), 3);

assert.strictEqual(Buffer.byteLength('Il était tué'), 14);
assert.strictEqual(Buffer.byteLength('Il était tué', 'utf8'), 14);

['ascii', 'latin1', 'binary']
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
.forEach((encoding) => {
assert.strictEqual(Buffer.byteLength('Il était tué', encoding), 12);
});

['ucs2', 'ucs-2', 'utf16le', 'utf-16le']
.reduce((es, e) => es.concat(e, e.toUpperCase()), [])
.forEach((encoding) => {
assert.strictEqual(Buffer.byteLength('Il était tué', encoding), 24);
});

// Test that ArrayBuffer from a different context is detected correctly
const arrayBuf = vm.runInNewContext('new ArrayBuffer()');
assert.strictEqual(Buffer.byteLength(arrayBuf), 0);

// Verify that invalid encodings are treated as utf8
for (let i = 1; i < 10; i++) {
const encoding = String(i).repeat(i);

assert.ok(!Buffer.isEncoding(encoding));
assert.strictEqual(Buffer.byteLength('foo', encoding),
Buffer.byteLength('foo', 'utf8'));
}
11 changes: 11 additions & 0 deletions test/js/node/test/parallel/test-buffer-new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

require('../common');
const assert = require('assert');

assert.throws(() => new Buffer(42, 'utf8'), {
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError',
message: 'The "string" argument must be of type string. Received type ' +
'number (42)'
});
14 changes: 14 additions & 0 deletions test/js/node/test/parallel/test-common-gc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';
// Flags: --expose-gc
const common = require('../common');
const { onGC } = require('../common/gc');

{
onGC({}, { ongc: common.mustCall() });
global.gc();
}

{
onGC(process, { ongc: common.mustNotCall() });
global.gc();
}
23 changes: 23 additions & 0 deletions test/js/node/test/parallel/test-finalization-registry-shutdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Flags: --expose-gc
'use strict';
const common = require('../common');

// This test verifies that when a V8 FinalizationRegistryCleanupTask is queue
// at the last moment when JavaScript can be executed, the callback of a
// FinalizationRegistry will not be invoked and the process should exit
// normally.

const reg = new FinalizationRegistry(
common.mustNotCall('This FinalizationRegistry callback should never be called'));

function register() {
// Create a temporary object in a new function scope to allow it to be GC-ed.
reg.register({});
}

process.on('exit', () => {
// This is the final chance to execute JavaScript.
register();
// Queue a FinalizationRegistryCleanupTask by a testing gc request.
global.gc();
});
89 changes: 89 additions & 0 deletions test/js/node/test/parallel/test-fs-chmod-mask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict';

// This tests that the lower bits of mode > 0o777 still works in fs APIs.

const common = require('../common');
const assert = require('assert');
const fs = require('fs');

let mode;
// On Windows chmod is only able to manipulate write permission
if (common.isWindows) {
mode = 0o444; // read-only
} else {
mode = 0o777;
}

const maskToIgnore = 0o10000;

const tmpdir = require('../common/tmpdir');
tmpdir.refresh();

function test(mode, asString) {
const suffix = asString ? 'str' : 'num';
const input = asString ?
(mode | maskToIgnore).toString(8) : (mode | maskToIgnore);

{
const file = tmpdir.resolve(`chmod-async-${suffix}.txt`);
fs.writeFileSync(file, 'test', 'utf-8');

fs.chmod(file, input, common.mustSucceed(() => {
assert.strictEqual(fs.statSync(file).mode & 0o777, mode);
}));
}

{
const file = tmpdir.resolve(`chmodSync-${suffix}.txt`);
fs.writeFileSync(file, 'test', 'utf-8');

fs.chmodSync(file, input);
assert.strictEqual(fs.statSync(file).mode & 0o777, mode);
}

{
const file = tmpdir.resolve(`fchmod-async-${suffix}.txt`);
fs.writeFileSync(file, 'test', 'utf-8');
fs.open(file, 'w', common.mustSucceed((fd) => {
fs.fchmod(fd, input, common.mustSucceed(() => {
assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode);
fs.close(fd, assert.ifError);
}));
}));
}

{
const file = tmpdir.resolve(`fchmodSync-${suffix}.txt`);
fs.writeFileSync(file, 'test', 'utf-8');
const fd = fs.openSync(file, 'w');

fs.fchmodSync(fd, input);
assert.strictEqual(fs.fstatSync(fd).mode & 0o777, mode);

fs.close(fd, assert.ifError);
}

if (fs.lchmod) {
const link = tmpdir.resolve(`lchmod-src-${suffix}`);
const file = tmpdir.resolve(`lchmod-dest-${suffix}`);
fs.writeFileSync(file, 'test', 'utf-8');
fs.symlinkSync(file, link);

fs.lchmod(link, input, common.mustSucceed(() => {
assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode);
}));
}

if (fs.lchmodSync) {
const link = tmpdir.resolve(`lchmodSync-src-${suffix}`);
const file = tmpdir.resolve(`lchmodSync-dest-${suffix}`);
fs.writeFileSync(file, 'test', 'utf-8');
fs.symlinkSync(file, link);

fs.lchmodSync(link, input);
assert.strictEqual(fs.lstatSync(link).mode & 0o777, mode);
}
}

test(mode, true);
test(mode, false);
50 changes: 50 additions & 0 deletions test/js/node/test/parallel/test-fs-readfile-flags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict';

// Test of fs.readFile with different flags.
const common = require('../common');
const fs = require('fs');
const assert = require('assert');
const tmpdir = require('../common/tmpdir');

tmpdir.refresh();

{
const emptyFile = tmpdir.resolve('empty.txt');
fs.closeSync(fs.openSync(emptyFile, 'w'));

fs.readFile(
emptyFile,
// With `a+` the file is created if it does not exist
common.mustNotMutateObjectDeep({ encoding: 'utf8', flag: 'a+' }),
common.mustCall((err, data) => { assert.strictEqual(data, ''); })
);

fs.readFile(
emptyFile,
// Like `a+` but fails if the path exists.
common.mustNotMutateObjectDeep({ encoding: 'utf8', flag: 'ax+' }),
common.mustCall((err, data) => { assert.strictEqual(err.code, 'EEXIST'); })
);
}

{
const willBeCreated = tmpdir.resolve('will-be-created');

fs.readFile(
willBeCreated,
// With `a+` the file is created if it does not exist
common.mustNotMutateObjectDeep({ encoding: 'utf8', flag: 'a+' }),
common.mustCall((err, data) => { assert.strictEqual(data, ''); })
);
}

{
const willNotBeCreated = tmpdir.resolve('will-not-be-created');

fs.readFile(
willNotBeCreated,
// Default flag is `r`. An exception occurs if the file does not exist.
common.mustNotMutateObjectDeep({ encoding: 'utf8' }),
common.mustCall((err, data) => { assert.strictEqual(err.code, 'ENOENT'); })
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

'use strict';
const common = require('../common');

// Make sure the deletion event gets reported in the following scenario:
// 1. Watch a file.
// 2. The initial stat() goes okay.
// 3. Something deletes the watched file.
// 4. The second stat() fails with ENOENT.

// The second stat() translates into the first 'change' event but a logic error
// stopped it from getting emitted.
// https://github.com/nodejs/node-v0.x-archive/issues/4027

const fs = require('fs');

const tmpdir = require('../common/tmpdir');
tmpdir.refresh();

const filename = tmpdir.resolve('watched');
fs.writeFileSync(filename, 'quis custodiet ipsos custodes');

fs.watchFile(filename, { interval: 50 }, common.mustCall(function(curr, prev) {
fs.unwatchFile(filename);
}));

fs.unlinkSync(filename);
Loading

0 comments on commit 1d3cff2

Please sign in to comment.