• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3
4const assert = require('assert');
5const fs = require('fs');
6const path = require('path');
7
8const tmpdir = require('../common/tmpdir');
9
10// Basic usage tests.
11assert.throws(
12  () => {
13    fs.watchFile('./some-file');
14  },
15  {
16    code: 'ERR_INVALID_ARG_TYPE',
17    name: 'TypeError'
18  });
19
20assert.throws(
21  () => {
22    fs.watchFile('./another-file', {}, 'bad listener');
23  },
24  {
25    code: 'ERR_INVALID_ARG_TYPE',
26    name: 'TypeError'
27  });
28
29assert.throws(() => {
30  fs.watchFile(new Object(), common.mustNotCall());
31}, { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError' });
32
33const enoentFile = path.join(tmpdir.path, 'non-existent-file');
34const expectedStatObject = new fs.Stats(
35  0,                                        // dev
36  0,                                        // mode
37  0,                                        // nlink
38  0,                                        // uid
39  0,                                        // gid
40  0,                                        // rdev
41  0,                                        // blksize
42  0,                                        // ino
43  0,                                        // size
44  0,                                        // blocks
45  Date.UTC(1970, 0, 1, 0, 0, 0),            // atime
46  Date.UTC(1970, 0, 1, 0, 0, 0),            // mtime
47  Date.UTC(1970, 0, 1, 0, 0, 0),            // ctime
48  Date.UTC(1970, 0, 1, 0, 0, 0)             // birthtime
49);
50
51tmpdir.refresh();
52
53// If the file initially didn't exist, and gets created at a later point of
54// time, the callback should be invoked again with proper values in stat object
55let fileExists = false;
56
57const watcher =
58  fs.watchFile(enoentFile, { interval: 0 }, common.mustCall((curr, prev) => {
59    if (!fileExists) {
60      // If the file does not exist, all the fields should be zero and the date
61      // fields should be UNIX EPOCH time
62      assert.deepStrictEqual(curr, expectedStatObject);
63      assert.deepStrictEqual(prev, expectedStatObject);
64      // Create the file now, so that the callback will be called back once the
65      // event loop notices it.
66      fs.closeSync(fs.openSync(enoentFile, 'w'));
67      fileExists = true;
68    } else {
69      // If the ino (inode) value is greater than zero, it means that the file
70      // is present in the filesystem and it has a valid inode number.
71      assert(curr.ino > 0);
72      // As the file just got created, previous ino value should be lesser than
73      // or equal to zero (non-existent file).
74      assert(prev.ino <= 0);
75      // Stop watching the file
76      fs.unwatchFile(enoentFile);
77      watcher.stop();  // Stopping a stopped watcher should be a noop
78    }
79  }, 2));
80
81// 'stop' should only be emitted once - stopping a stopped watcher should
82// not trigger a 'stop' event.
83watcher.on('stop', common.mustCall());
84
85// Watch events should callback with a filename on supported systems.
86// Omitting AIX. It works but not reliably.
87if (common.isLinux || common.isOSX || common.isWindows) {
88  const dir = path.join(tmpdir.path, 'watch');
89
90  fs.mkdir(dir, common.mustCall(function(err) {
91    if (err) assert.fail(err);
92
93    fs.watch(dir, common.mustCall(function(eventType, filename) {
94      clearInterval(interval);
95      this._handle.close();
96      assert.strictEqual(filename, 'foo.txt');
97    }));
98
99    const interval = setInterval(() => {
100      fs.writeFile(path.join(dir, 'foo.txt'), 'foo', common.mustCall((err) => {
101        if (err) assert.fail(err);
102      }));
103    }, 1);
104  }));
105}
106