Skip to content

Commit ee9df35

Browse files
digitalinfinitygibfahn
authored andcommitted
test, win: fix up symlink tests
On Windows, creating a symlink requires admin privileges. There were two tests which created symlinks which were failing when run as non-admin. test-fs-symlink.js already had a check for privileges on Windows but it had a couple issues: 1. It assumed that whoami was the one that came with windows. However, whoami also ships with Win32 Unix utility ports like the distribution with git, which can cause this to get check tripped up. 2. On failure, the check would just return from the callback instead of exiting 3. whoami was executed asynchronously so the test would run regardless of privilege state. test-fs-options-immutable had no check. As part of this change, I refactored the privilege checking to a function in common, and changed both above tests to use the refactored function. Also documented this function in test\README.md PR-URL: #10477 Reviewed-By: James M Snell <[email protected]> Reviewed-By: João Reis <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]>
1 parent a6ca94a commit ee9df35

File tree

4 files changed

+40
-11
lines changed

4 files changed

+40
-11
lines changed

test/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ A stream to push an array into a REPL
163163

164164
Blocks for `time` amount of time.
165165

166+
### canCreateSymLink
167+
API to indicate whether the current running process can create
168+
symlinks. On Windows, this returns false if the process running
169+
doesn't have privileges to create symlinks (specifically
170+
[SeCreateSymbolicLinkPrivilege](https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx)).
171+
On non-Windows platforms, this currently returns true.
172+
166173
### ddCommand(filename, kilobytes)
167174
* return [&lt;Object>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
168175

test/common.js

+29
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const stream = require('stream');
99
const buffer = require('buffer');
1010
const util = require('util');
1111
const Timer = process.binding('timer_wrap').Timer;
12+
const execSync = require('child_process').execSync;
1213

1314
const testRoot = process.env.NODE_TEST_DIR ?
1415
path.resolve(process.env.NODE_TEST_DIR) : __dirname;
@@ -460,6 +461,34 @@ exports.fileExists = function(pathname) {
460461
}
461462
};
462463

464+
exports.canCreateSymLink = function() {
465+
// On Windows, creating symlinks requires admin privileges.
466+
// We'll only try to run symlink test if we have enough privileges.
467+
// On other platforms, creating symlinks shouldn't need admin privileges
468+
if (exports.isWindows) {
469+
// whoami.exe needs to be the one from System32
470+
// If unix tools are in the path, they can shadow the one we want,
471+
// so use the full path while executing whoami
472+
const whoamiPath = path.join(process.env['SystemRoot'],
473+
'System32', 'whoami.exe');
474+
475+
let err = false;
476+
let output = '';
477+
478+
try {
479+
output = execSync(whoamiPath + ' /priv', { timout: 1000 });
480+
} catch (e) {
481+
err = true;
482+
} finally {
483+
if (err || !output.includes('SeCreateSymbolicLinkPrivilege')) {
484+
return false;
485+
}
486+
}
487+
}
488+
489+
return true;
490+
};
491+
463492
function fail(msg) {
464493
assert.fail(null, null, msg);
465494
}

test/parallel/test-fs-options-immutable.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ common.refreshTmpDir();
2929
assert.doesNotThrow(() => fs.readdirSync(__dirname, options));
3030
}
3131

32-
{
32+
if (common.canCreateSymLink()) {
3333
const sourceFile = path.resolve(common.tmpDir, 'test-readlink');
3434
const linkFile = path.resolve(common.tmpDir, 'test-readlink-link');
3535

test/parallel/test-fs-symlink.js

+3-10
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,13 @@ const common = require('../common');
33
const assert = require('assert');
44
const path = require('path');
55
const fs = require('fs');
6-
const exec = require('child_process').exec;
76

87
var linkTime;
98
var fileTime;
109

11-
if (common.isWindows) {
12-
// On Windows, creating symlinks requires admin privileges.
13-
// We'll only try to run symlink test if we have enough privileges.
14-
exec('whoami /priv', function(err, o) {
15-
if (err || !o.includes('SeCreateSymbolicLinkPrivilege')) {
16-
common.skip('insufficient privileges');
17-
return;
18-
}
19-
});
10+
if (!common.canCreateSymLink()) {
11+
common.skip('insufficient privileges');
12+
return;
2013
}
2114

2215
common.refreshTmpDir();

0 commit comments

Comments
 (0)