Description
- Version: 8.0.0 nightly 2017 05 01
- Platform: Windows 7 x64
- Subsystem: fs, libuv?, test
This is a confusing story here, so I am sorry for possibly clumsy wording.
Prehistory
I was launching tests with own test runner, each test with various context several times, and I've found out that parallel/test-fs-chmod.js
was OK on the first run and failed on all the next ones. Moreover, this happened not on all the machines.
This turned up to be caused by some combination of a fixture file attributes.
Excursus
See this small attrib doc for context.
The test fails if both -a
and -i
flags are unset for a fixture file used in the test. This unsetting combination, strangely enough, correlates with this GUI setting:
How to reproduce
Try to run these commands with repo root as cwd (firstly, we set a combination of the -a
and -i
flags; then we check the current attributes; then we run the test twice; then we check if the attributes are the same.; --no-deprecation
key there is due to cause of #12795).
Commands :
attrib +a +i test/fixtures/a1.js
attrib test/fixtures/a1.js
node --no-deprecation test/parallel/test-fs-chmod.js
node --no-deprecation test/parallel/test-fs-chmod.js
attrib test/fixtures/a1.js
attrib +a -i test/fixtures/a1.js
attrib test/fixtures/a1.js
node --no-deprecation test/parallel/test-fs-chmod.js
node --no-deprecation test/parallel/test-fs-chmod.js
attrib test/fixtures/a1.js
attrib -a +i test/fixtures/a1.js
attrib test/fixtures/a1.js
node --no-deprecation test/parallel/test-fs-chmod.js
node --no-deprecation test/parallel/test-fs-chmod.js
attrib test/fixtures/a1.js
attrib -a -i test/fixtures/a1.js
attrib test/fixtures/a1.js
node --no-deprecation test/parallel/test-fs-chmod.js
node --no-deprecation test/parallel/test-fs-chmod.js
attrib test/fixtures/a1.js
I see this output (some path details stripped, borders added after each iteration):
Output:
/******************************************************************************/
> attrib +a +i test/fixtures/a1.js
> attrib test/fixtures/a1.js
A I fixtures/a1.js
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> attrib test/fixtures/a1.js
A I fixtures/a1.js
/******************************************************************************/
> attrib +a -i test/fixtures/a1.js
> attrib test/fixtures/a1.js
A fixtures/a1.js
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> attrib test/fixtures/a1.js
A fixtures/a1.js
/******************************************************************************/
> attrib -a +i test/fixtures/a1.js
> attrib test/fixtures/a1.js
I fixtures/a1.js
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> attrib test/fixtures/a1.js
I fixtures/a1.js
/******************************************************************************/
> attrib -a -i test/fixtures/a1.js
> attrib test/fixtures/a1.js
fixtures/a1.js
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
33060
> node --no-deprecation test/parallel/test-fs-chmod.js
33060
assert.js:557
assert.ifError = function ifError(err) { if (err) throw err; };
^
Error: EPERM: operation not permitted, open 'fixtures/a1.js'
> attrib test/fixtures/a1.js
R fixtures/a1.js
/******************************************************************************/
As you can see, in the last case the second test fails and the file mode is changed.
What is going on here?
test/parallel/test-fs-chmod.js
changes the mode of fixtures/a.js
with fs.chmod()
and the mode of fixtures/a1.js
with fs.fchmod()
twice on Windows: to read-only and back to read-write. In case of fixtures/a.js
and fs.chmod()
, all is OK even with -a
and -i
attributes unset (I've checked this). But with fixtures/a1.js
and fs.fchmod()
, the beforementioned edge case prevents fs.fchmod()
from the second change here: the fixtures/a1.js
remains read-only after the first test run and fs.open()
in append mode fails here on the second test run.
Why the test does not detect this?
This assertion before failed fs.fchmod()
call and this assertion after the failed call check the same mode number in the failed case, but as long as this number is not falsy, the second assertion does not throw. On Windows, this number is not falsy in all the cases: it just differs in normal cases and remains the same in the edge case.
What possibly should be done?
fs.fchmod()
binding should be checked for this edge case. Maybe the bug should be reported upstream forlibuv
or even for Windows.- The assertions in the test should be made stricter.
Unfortunately, I cannot be any more help in this case, as I am not good in this realm. Sorry.