11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ciif (common.isIBMi)
51cb0ef41Sopenharmony_ci  common.skip('IBMi does not support `fs.watch()`');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst { watch } = require('fs/promises');
81cb0ef41Sopenharmony_ciconst fs = require('fs');
91cb0ef41Sopenharmony_ciconst assert = require('assert');
101cb0ef41Sopenharmony_ciconst { join } = require('path');
111cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciclass WatchTestCase {
141cb0ef41Sopenharmony_ci  constructor(shouldInclude, dirName, fileName, field) {
151cb0ef41Sopenharmony_ci    this.dirName = dirName;
161cb0ef41Sopenharmony_ci    this.fileName = fileName;
171cb0ef41Sopenharmony_ci    this.field = field;
181cb0ef41Sopenharmony_ci    this.shouldSkip = !shouldInclude;
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci  get dirPath() { return join(tmpdir.path, this.dirName); }
211cb0ef41Sopenharmony_ci  get filePath() { return join(this.dirPath, this.fileName); }
221cb0ef41Sopenharmony_ci}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciconst kCases = [
251cb0ef41Sopenharmony_ci  // Watch on a directory should callback with a filename on supported systems
261cb0ef41Sopenharmony_ci  new WatchTestCase(
271cb0ef41Sopenharmony_ci    common.isLinux || common.isOSX || common.isWindows || common.isAIX,
281cb0ef41Sopenharmony_ci    'watch1',
291cb0ef41Sopenharmony_ci    'foo',
301cb0ef41Sopenharmony_ci    'filePath'
311cb0ef41Sopenharmony_ci  ),
321cb0ef41Sopenharmony_ci  // Watch on a file should callback with a filename on supported systems
331cb0ef41Sopenharmony_ci  new WatchTestCase(
341cb0ef41Sopenharmony_ci    common.isLinux || common.isOSX || common.isWindows,
351cb0ef41Sopenharmony_ci    'watch2',
361cb0ef41Sopenharmony_ci    'bar',
371cb0ef41Sopenharmony_ci    'dirPath'
381cb0ef41Sopenharmony_ci  ),
391cb0ef41Sopenharmony_ci];
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_citmpdir.refresh();
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cifor (const testCase of kCases) {
441cb0ef41Sopenharmony_ci  if (testCase.shouldSkip) continue;
451cb0ef41Sopenharmony_ci  fs.mkdirSync(testCase.dirPath);
461cb0ef41Sopenharmony_ci  // Long content so it's actually flushed.
471cb0ef41Sopenharmony_ci  const content1 = Date.now() + testCase.fileName.toLowerCase().repeat(1e4);
481cb0ef41Sopenharmony_ci  fs.writeFileSync(testCase.filePath, content1);
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  let interval;
511cb0ef41Sopenharmony_ci  async function test() {
521cb0ef41Sopenharmony_ci    const watcher = watch(testCase[testCase.field]);
531cb0ef41Sopenharmony_ci    for await (const { eventType, filename } of watcher) {
541cb0ef41Sopenharmony_ci      clearInterval(interval);
551cb0ef41Sopenharmony_ci      assert.strictEqual(['rename', 'change'].includes(eventType), true);
561cb0ef41Sopenharmony_ci      assert.strictEqual(filename, testCase.fileName);
571cb0ef41Sopenharmony_ci      break;
581cb0ef41Sopenharmony_ci    }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci    // Waiting on it again is a non-op
611cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars
621cb0ef41Sopenharmony_ci    for await (const p of watcher) {
631cb0ef41Sopenharmony_ci      assert.fail('should not run');
641cb0ef41Sopenharmony_ci    }
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  // Long content so it's actually flushed. toUpperCase so there's real change.
681cb0ef41Sopenharmony_ci  const content2 = Date.now() + testCase.fileName.toUpperCase().repeat(1e4);
691cb0ef41Sopenharmony_ci  interval = setInterval(() => {
701cb0ef41Sopenharmony_ci    fs.writeFileSync(testCase.filePath, '');
711cb0ef41Sopenharmony_ci    fs.writeFileSync(testCase.filePath, content2);
721cb0ef41Sopenharmony_ci  }, 100);
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  test().then(common.mustCall());
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciassert.rejects(
781cb0ef41Sopenharmony_ci  async () => {
791cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
801cb0ef41Sopenharmony_ci    for await (const _ of watch(1)) { }
811cb0ef41Sopenharmony_ci  },
821cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_TYPE' });
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ciassert.rejects(
851cb0ef41Sopenharmony_ci  async () => {
861cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
871cb0ef41Sopenharmony_ci    for await (const _ of watch(__filename, 1)) { }
881cb0ef41Sopenharmony_ci  },
891cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_TYPE' });
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ciassert.rejects(
921cb0ef41Sopenharmony_ci  async () => {
931cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
941cb0ef41Sopenharmony_ci    for await (const _ of watch('', { persistent: 1 })) { }
951cb0ef41Sopenharmony_ci  },
961cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_TYPE' });
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ciassert.rejects(
991cb0ef41Sopenharmony_ci  async () => {
1001cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
1011cb0ef41Sopenharmony_ci    for await (const _ of watch('', { recursive: 1 })) { }
1021cb0ef41Sopenharmony_ci  },
1031cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_TYPE' });
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciassert.rejects(
1061cb0ef41Sopenharmony_ci  async () => {
1071cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
1081cb0ef41Sopenharmony_ci    for await (const _ of watch('', { encoding: 1 })) { }
1091cb0ef41Sopenharmony_ci  },
1101cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_VALUE' });
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciassert.rejects(
1131cb0ef41Sopenharmony_ci  async () => {
1141cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
1151cb0ef41Sopenharmony_ci    for await (const _ of watch('', { signal: 1 })) { }
1161cb0ef41Sopenharmony_ci  },
1171cb0ef41Sopenharmony_ci  { code: 'ERR_INVALID_ARG_TYPE' });
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci(async () => {
1201cb0ef41Sopenharmony_ci  const ac = new AbortController();
1211cb0ef41Sopenharmony_ci  const { signal } = ac;
1221cb0ef41Sopenharmony_ci  setImmediate(() => ac.abort());
1231cb0ef41Sopenharmony_ci  try {
1241cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-unused-vars, no-empty
1251cb0ef41Sopenharmony_ci    for await (const _ of watch(__filename, { signal })) { }
1261cb0ef41Sopenharmony_ci  } catch (err) {
1271cb0ef41Sopenharmony_ci    assert.strictEqual(err.name, 'AbortError');
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci})().then(common.mustCall());
130