shelljs/test/chmod.js
Nate Fischer 1a31356343 refactor: use require instead of import
No change to logic. This swaps over tests to use require() since
everything is currently designed for the commonjs module system.
2025-04-07 22:44:24 -07:00

360 lines
10 KiB
JavaScript

const fs = require('fs');
const test = require('ava');
const shell = require('..');
const common = require('../src/common');
const utils = require('./utils/utils');
let TMP;
const BITMASK = parseInt('777', 8);
test.before(() => {
TMP = utils.getTempDir();
shell.cp('-r', 'test/resources', TMP);
shell.config.silent = true;
});
test.after(() => {
shell.rm('-rf', TMP);
});
//
// Invalids
//
test('invalid permissions', t => {
let result = shell.chmod('blah');
t.truthy(shell.error());
t.is(result.code, 1);
result = shell.chmod('893', `${TMP}/chmod`); // invalid permissions - mode must be in octal
t.truthy(shell.error());
t.is(result.code, 1);
});
test('Basic usage with octal codes', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('755', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('755', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('644', 8)
);
});
});
test('symbolic mode', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('o+x', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('007', 8),
parseInt('005', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('symbolic mode, without group', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('+x', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('755', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('Test setuid', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('u+s', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('4000', 8),
parseInt('4000', 8)
);
result = shell.chmod('u-s', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('644', 8)
);
// according to POSIX standards at http://linux.die.net/man/1/chmod,
// setuid is never cleared from a directory unless explicitly asked for.
result = shell.chmod('u+s', `${TMP}/chmod/c`);
t.is(result.code, 0);
result = shell.chmod('755', `${TMP}/chmod/c`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/c`).mode & parseInt('4000', 8),
parseInt('4000', 8)
);
result = shell.chmod('u-s', `${TMP}/chmod/c`);
t.is(result.code, 0);
});
});
test('Test setgid', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('g+s', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('2000', 8),
parseInt('2000', 8)
);
result = shell.chmod('g-s', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('644', 8)
);
});
});
test('Test sticky bit', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('+t', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('1000', 8),
parseInt('1000', 8)
);
result = shell.chmod('-t', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & BITMASK,
parseInt('644', 8)
);
t.is(common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('1000', 8), 0);
});
});
test('Test directories', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('a-w', `${TMP}/chmod/b/a/b`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/b/a/b`).mode & BITMASK,
parseInt('555', 8)
);
result = shell.chmod('755', `${TMP}/chmod/b/a/b`);
t.is(result.code, 0);
});
});
test('Test recursion', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('-R', 'a+w', `${TMP}/chmod/b`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/b/a/b`).mode & BITMASK,
BITMASK
);
result = shell.chmod('-R', '755', `${TMP}/chmod/b`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/b/a/b`).mode & BITMASK,
parseInt('755', 8)
);
});
});
test('Test symbolic links w/ recursion - WARNING: *nix only', t => {
utils.skipOnWin(t, () => {
fs.symlinkSync(`${TMP}/chmod/b/a`, `${TMP}/chmod/a/b/c/link`, 'dir');
let result = shell.chmod('-R', 'u-w', `${TMP}/chmod/a/b`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/a/b/c`).mode & parseInt('700', 8),
parseInt('500', 8)
);
t.is(
common.statFollowLinks(`${TMP}/chmod/b/a`).mode & parseInt('700', 8),
parseInt('700', 8)
);
result = shell.chmod('-R', 'u+w', `${TMP}/chmod/a/b`);
t.is(result.code, 0);
fs.unlinkSync(`${TMP}/chmod/a/b/c/link`);
});
});
test('Test combinations', t => {
let result = shell.chmod('a-rwx', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('000', 8),
parseInt('000', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('multiple symbolic modes', t => {
let result = shell.chmod('a-rwx,u+r', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('400', 8),
parseInt('400', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('multiple symbolic modes #2', t => {
let result = shell.chmod('a-rwx,u+rw', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('600', 8),
parseInt('600', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('multiple symbolic modes #3', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('a-rwx,u+rwx', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('700', 8),
parseInt('700', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('u+rw', t => {
let result = shell.chmod('000', `${TMP}/chmod/file1`);
t.is(result.code, 0);
result = shell.chmod('u+rw', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('600', 8),
parseInt('600', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('u+wx', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('000', `${TMP}/chmod/file1`);
t.is(result.code, 0);
result = shell.chmod('u+wx', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('300', 8),
parseInt('300', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('Multiple symbolic modes at once', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('000', `${TMP}/chmod/file1`);
t.is(result.code, 0);
result = shell.chmod('u+r,g+w,o+x', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('421', 8),
parseInt('421', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('u+rw,g+wx', t => {
utils.skipOnWin(t, () => {
let result = shell.chmod('000', `${TMP}/chmod/file1`);
t.is(result.code, 0);
result = shell.chmod('u+rw,g+wx', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('630', 8),
parseInt('630', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
});
test('u-x,g+rw', t => {
let result = shell.chmod('700', `${TMP}/chmod/file1`);
t.is(result.code, 0);
result = shell.chmod('u-x,g+rw', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('660', 8),
parseInt('660', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('a-rwx,u+rw', t => {
let result = shell.chmod('a-rwx,u+rw', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('600', 8),
parseInt('600', 8)
);
result = shell.chmod('a-rwx,u+rw', `${TMP}/chmod/file1`);
t.is(result.code, 0);
t.is(
common.statFollowLinks(`${TMP}/chmod/file1`).mode & parseInt('600', 8),
parseInt('600', 8)
);
result = shell.chmod('644', `${TMP}/chmod/file1`);
t.is(result.code, 0);
});
test('Numeric modes', t => {
let result = shell.chmod('744', `${TMP}/chmod/xdir`);
t.is(result.code, 0);
result = shell.chmod('644', `${TMP}/chmod/xdir/file`);
t.is(result.code, 0);
result = shell.chmod('744', `${TMP}/chmod/xdir/deep`);
t.is(result.code, 0);
result = shell.chmod('644', `${TMP}/chmod/xdir/deep/file`);
t.is(result.code, 0);
result = shell.chmod('-R', 'a+X', `${TMP}/chmod/xdir`);
t.is(result.code, 0);
});
test('Make sure chmod succeeds for a variety of octal codes', t => {
utils.skipOnWin(t, () => {
t.is(
common.statFollowLinks(`${TMP}/chmod/xdir`).mode & parseInt('755', 8),
parseInt('755', 8)
);
t.is(
common.statFollowLinks(`${TMP}/chmod/xdir/file`).mode & parseInt('644', 8),
parseInt('644', 8)
);
t.is(
common.statFollowLinks(`${TMP}/chmod/xdir/deep`).mode & parseInt('755', 8),
parseInt('755', 8)
);
t.is(
common.statFollowLinks(`${TMP}/chmod/xdir/deep/file`).mode & parseInt('644', 8),
parseInt('644', 8)
);
});
});