test: parallelize test-repl-persistent-history
authorJeremiah Senkpiel <fishrock123@rocketmail.com>
Fri, 11 Dec 2015 22:45:53 +0000 (17:45 -0500)
committerMyles Borins <mborins@us.ibm.com>
Tue, 19 Jan 2016 19:52:23 +0000 (11:52 -0800)
Refs: https://github.com/nodejs/node/pull/2224#issuecomment-127356413
PR-URL: https://github.com/nodejs/node/pull/4247
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
test/parallel/test-repl-persistent-history.js [new file with mode: 0644]
test/sequential/test-repl-persistent-history.js [deleted file]

diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js
new file mode 100644 (file)
index 0000000..10e0ded
--- /dev/null
@@ -0,0 +1,274 @@
+'use strict';
+
+// Flags: --expose-internals
+
+const common = require('../common');
+const stream = require('stream');
+const REPL = require('internal/repl');
+const assert = require('assert');
+const fs = require('fs');
+const util = require('util');
+const path = require('path');
+const os = require('os');
+
+common.refreshTmpDir();
+
+// Mock os.homedir()
+os.homedir = function() {
+  return common.tmpDir;
+};
+
+// Create an input stream specialized for testing an array of actions
+class ActionStream extends stream.Stream {
+  run(data) {
+    const _iter = data[Symbol.iterator]();
+    const self = this;
+
+    function doAction() {
+      const next = _iter.next();
+      if (next.done) {
+        // Close the repl. Note that it must have a clean prompt to do so.
+        setImmediate(function() {
+          self.emit('keypress', '', { ctrl: true, name: 'd' });
+        });
+        return;
+      }
+      const action = next.value;
+
+      if (typeof action === 'object') {
+        self.emit('keypress', '', action);
+      } else {
+        self.emit('data', action + '\n');
+      }
+      setImmediate(doAction);
+    }
+    setImmediate(doAction);
+  }
+  resume() {}
+  pause() {}
+}
+ActionStream.prototype.readable = true;
+
+
+// Mock keys
+const UP = { name: 'up' };
+const ENTER = { name: 'enter' };
+const CLEAR = { ctrl: true, name: 'u' };
+// Common message bits
+const prompt = '> ';
+const replDisabled = '\nPersistent history support disabled. Set the ' +
+                     'NODE_REPL_HISTORY environment\nvariable to a valid, ' +
+                     'user-writable path to enable.\n';
+const convertMsg = '\nConverting old JSON repl history to line-separated ' +
+                   'history.\nThe new repl history file can be found at ' +
+                   path.join(common.tmpDir, '.node_repl_history') + '.\n';
+const homedirErr = '\nError: Could not get the home directory.\n' +
+                   'REPL session history will not be persisted.\n';
+const replFailedRead = '\nError: Could not open history file.\n' +
+                       'REPL session history will not be persisted.\n';
+// File paths
+const fixtures = path.join(common.testDir, 'fixtures');
+const historyFixturePath = path.join(fixtures, '.node_repl_history');
+const historyPath = path.join(common.tmpDir, '.fixture_copy_repl_history');
+const historyPathFail = path.join(common.tmpDir, '.node_repl\u0000_history');
+const oldHistoryPath = path.join(fixtures, 'old-repl-history-file.json');
+const enoentHistoryPath = path.join(fixtures, 'enoent-repl-history-file.json');
+const defaultHistoryPath = path.join(common.tmpDir, '.node_repl_history');
+
+
+const tests = [{
+  env: { NODE_REPL_HISTORY: '' },
+  test: [UP],
+  expected: [prompt, replDisabled, prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: '',
+         NODE_REPL_HISTORY_FILE: enoentHistoryPath },
+  test: [UP],
+  expected: [prompt, replDisabled, prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: '',
+         NODE_REPL_HISTORY_FILE: oldHistoryPath },
+  test: [UP],
+  expected: [prompt, replDisabled, prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: historyPath },
+  test: [UP, CLEAR],
+  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: historyPath,
+         NODE_REPL_HISTORY_FILE: oldHistoryPath },
+  test: [UP, CLEAR],
+  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: historyPath,
+         NODE_REPL_HISTORY_FILE: '' },
+  test: [UP, CLEAR],
+  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
+},
+{
+  env: {},
+  test: [UP],
+  expected: [prompt]
+},
+{
+  env: { NODE_REPL_HISTORY_FILE: oldHistoryPath },
+  test: [UP, CLEAR, '\'42\'', ENTER],
+  expected: [prompt, convertMsg, prompt, prompt + '\'=^.^=\'', prompt, '\'',
+             '4', '2', '\'', '\'42\'\n', prompt, prompt],
+  after: function ensureHistoryFixture() {
+    // XXX(Fishrock123) Make sure nothing weird happened to our fixture
+    //  or it's temporary copy.
+    // Sometimes this test used to erase the fixture and I'm not sure why.
+    const history = fs.readFileSync(historyFixturePath, 'utf8');
+    assert.strictEqual(history,
+                       '\'you look fabulous today\'\n\'Stay Fresh~\'\n');
+    const historyCopy = fs.readFileSync(historyPath, 'utf8');
+    assert.strictEqual(historyCopy, '\'you look fabulous today\'' + os.EOL +
+                                    '\'Stay Fresh~\'' + os.EOL);
+  }
+},
+{ // Requires the above testcase
+  env: {},
+  test: [UP, UP, ENTER],
+  expected: [prompt, prompt + '\'42\'', prompt + '\'=^.^=\'', '\'=^.^=\'\n',
+             prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: historyPath,
+         NODE_REPL_HISTORY_SIZE: 1 },
+  test: [UP, UP, CLEAR],
+  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
+},
+{
+  env: { NODE_REPL_HISTORY_FILE: oldHistoryPath,
+         NODE_REPL_HISTORY_SIZE: 1 },
+  test: [UP, UP, UP, CLEAR],
+  expected: [prompt, convertMsg, prompt, prompt + '\'=^.^=\'', prompt]
+},
+{
+  env: { NODE_REPL_HISTORY: historyPathFail,
+         NODE_REPL_HISTORY_SIZE: 1 },
+  test: [UP],
+  expected: [prompt, replFailedRead, prompt, replDisabled, prompt]
+},
+{ // Make sure this is always the last test, since we change os.homedir()
+  before: function mockHomedirFailure() {
+    // Mock os.homedir() failure
+    os.homedir = function() {
+      throw new Error('os.homedir() failure');
+    };
+  },
+  env: {},
+  test: [UP],
+  expected: [prompt, homedirErr, prompt, replDisabled, prompt]
+}];
+const numtests = tests.length;
+
+
+var testsNotRan = tests.length;
+
+process.on('beforeExit', () =>
+  assert.strictEqual(testsNotRan, 0)
+);
+
+function cleanupTmpFile() {
+  try {
+    // Write over the file, clearing any history
+    fs.writeFileSync(defaultHistoryPath, '');
+  } catch (err) {
+    if (err.code === 'ENOENT') return true;
+    throw err;
+  }
+  return true;
+}
+
+// Copy our fixture to the tmp directory
+fs.createReadStream(historyFixturePath)
+  .pipe(fs.createWriteStream(historyPath)).on('unpipe', () => runTest());
+
+function runTest(assertCleaned) {
+  const opts = tests.shift();
+  if (!opts) return; // All done
+
+  if (assertCleaned) {
+    try {
+      assert.strictEqual(fs.readFileSync(defaultHistoryPath, 'utf8'), '');
+    } catch (e) {
+      if (e.code !== 'ENOENT') {
+        console.error(`Failed test # ${numtests - tests.length}`);
+        throw e;
+      }
+    }
+  }
+
+  const env = opts.env;
+  const test = opts.test;
+  const expected = opts.expected;
+  const after = opts.after;
+  const before = opts.before;
+
+  if (before) before();
+
+  REPL.createInternalRepl(env, {
+    input: new ActionStream(),
+    output: new stream.Writable({
+      write(chunk, _, next) {
+        const output = chunk.toString();
+
+        // Ignore escapes and blank lines
+        if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output))
+          return next();
+
+        try {
+          assert.strictEqual(output, expected.shift());
+        } catch (err) {
+          console.error(`Failed test # ${numtests - tests.length}`);
+          throw err;
+        }
+        next();
+      }
+    }),
+    prompt: prompt,
+    useColors: false,
+    terminal: true
+  }, function(err, repl) {
+    if (err) {
+      console.error(`Failed test # ${numtests - tests.length}`);
+      throw err;
+    }
+
+    repl.once('close', () => {
+      if (repl._flushing) {
+        repl.once('flushHistory', onClose);
+        return;
+      }
+
+      onClose();
+    });
+
+    function onClose() {
+      if (after) {
+        var cleaned = after();
+      } else {
+        var cleaned = cleanupTmpFile();
+      }
+
+      try {
+        // Ensure everything that we expected was output
+        assert.strictEqual(expected.length, 0);
+        testsNotRan--;
+        setImmediate(runTest, cleaned);
+      } catch (err) {
+        console.error(`Failed test # ${numtests - tests.length}`);
+        throw err;
+      }
+    }
+
+    repl.inputStream.run(test);
+  });
+}
diff --git a/test/sequential/test-repl-persistent-history.js b/test/sequential/test-repl-persistent-history.js
deleted file mode 100644 (file)
index 10e0ded..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-'use strict';
-
-// Flags: --expose-internals
-
-const common = require('../common');
-const stream = require('stream');
-const REPL = require('internal/repl');
-const assert = require('assert');
-const fs = require('fs');
-const util = require('util');
-const path = require('path');
-const os = require('os');
-
-common.refreshTmpDir();
-
-// Mock os.homedir()
-os.homedir = function() {
-  return common.tmpDir;
-};
-
-// Create an input stream specialized for testing an array of actions
-class ActionStream extends stream.Stream {
-  run(data) {
-    const _iter = data[Symbol.iterator]();
-    const self = this;
-
-    function doAction() {
-      const next = _iter.next();
-      if (next.done) {
-        // Close the repl. Note that it must have a clean prompt to do so.
-        setImmediate(function() {
-          self.emit('keypress', '', { ctrl: true, name: 'd' });
-        });
-        return;
-      }
-      const action = next.value;
-
-      if (typeof action === 'object') {
-        self.emit('keypress', '', action);
-      } else {
-        self.emit('data', action + '\n');
-      }
-      setImmediate(doAction);
-    }
-    setImmediate(doAction);
-  }
-  resume() {}
-  pause() {}
-}
-ActionStream.prototype.readable = true;
-
-
-// Mock keys
-const UP = { name: 'up' };
-const ENTER = { name: 'enter' };
-const CLEAR = { ctrl: true, name: 'u' };
-// Common message bits
-const prompt = '> ';
-const replDisabled = '\nPersistent history support disabled. Set the ' +
-                     'NODE_REPL_HISTORY environment\nvariable to a valid, ' +
-                     'user-writable path to enable.\n';
-const convertMsg = '\nConverting old JSON repl history to line-separated ' +
-                   'history.\nThe new repl history file can be found at ' +
-                   path.join(common.tmpDir, '.node_repl_history') + '.\n';
-const homedirErr = '\nError: Could not get the home directory.\n' +
-                   'REPL session history will not be persisted.\n';
-const replFailedRead = '\nError: Could not open history file.\n' +
-                       'REPL session history will not be persisted.\n';
-// File paths
-const fixtures = path.join(common.testDir, 'fixtures');
-const historyFixturePath = path.join(fixtures, '.node_repl_history');
-const historyPath = path.join(common.tmpDir, '.fixture_copy_repl_history');
-const historyPathFail = path.join(common.tmpDir, '.node_repl\u0000_history');
-const oldHistoryPath = path.join(fixtures, 'old-repl-history-file.json');
-const enoentHistoryPath = path.join(fixtures, 'enoent-repl-history-file.json');
-const defaultHistoryPath = path.join(common.tmpDir, '.node_repl_history');
-
-
-const tests = [{
-  env: { NODE_REPL_HISTORY: '' },
-  test: [UP],
-  expected: [prompt, replDisabled, prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: '',
-         NODE_REPL_HISTORY_FILE: enoentHistoryPath },
-  test: [UP],
-  expected: [prompt, replDisabled, prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: '',
-         NODE_REPL_HISTORY_FILE: oldHistoryPath },
-  test: [UP],
-  expected: [prompt, replDisabled, prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: historyPath },
-  test: [UP, CLEAR],
-  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: historyPath,
-         NODE_REPL_HISTORY_FILE: oldHistoryPath },
-  test: [UP, CLEAR],
-  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: historyPath,
-         NODE_REPL_HISTORY_FILE: '' },
-  test: [UP, CLEAR],
-  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
-},
-{
-  env: {},
-  test: [UP],
-  expected: [prompt]
-},
-{
-  env: { NODE_REPL_HISTORY_FILE: oldHistoryPath },
-  test: [UP, CLEAR, '\'42\'', ENTER],
-  expected: [prompt, convertMsg, prompt, prompt + '\'=^.^=\'', prompt, '\'',
-             '4', '2', '\'', '\'42\'\n', prompt, prompt],
-  after: function ensureHistoryFixture() {
-    // XXX(Fishrock123) Make sure nothing weird happened to our fixture
-    //  or it's temporary copy.
-    // Sometimes this test used to erase the fixture and I'm not sure why.
-    const history = fs.readFileSync(historyFixturePath, 'utf8');
-    assert.strictEqual(history,
-                       '\'you look fabulous today\'\n\'Stay Fresh~\'\n');
-    const historyCopy = fs.readFileSync(historyPath, 'utf8');
-    assert.strictEqual(historyCopy, '\'you look fabulous today\'' + os.EOL +
-                                    '\'Stay Fresh~\'' + os.EOL);
-  }
-},
-{ // Requires the above testcase
-  env: {},
-  test: [UP, UP, ENTER],
-  expected: [prompt, prompt + '\'42\'', prompt + '\'=^.^=\'', '\'=^.^=\'\n',
-             prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: historyPath,
-         NODE_REPL_HISTORY_SIZE: 1 },
-  test: [UP, UP, CLEAR],
-  expected: [prompt, prompt + '\'you look fabulous today\'', prompt]
-},
-{
-  env: { NODE_REPL_HISTORY_FILE: oldHistoryPath,
-         NODE_REPL_HISTORY_SIZE: 1 },
-  test: [UP, UP, UP, CLEAR],
-  expected: [prompt, convertMsg, prompt, prompt + '\'=^.^=\'', prompt]
-},
-{
-  env: { NODE_REPL_HISTORY: historyPathFail,
-         NODE_REPL_HISTORY_SIZE: 1 },
-  test: [UP],
-  expected: [prompt, replFailedRead, prompt, replDisabled, prompt]
-},
-{ // Make sure this is always the last test, since we change os.homedir()
-  before: function mockHomedirFailure() {
-    // Mock os.homedir() failure
-    os.homedir = function() {
-      throw new Error('os.homedir() failure');
-    };
-  },
-  env: {},
-  test: [UP],
-  expected: [prompt, homedirErr, prompt, replDisabled, prompt]
-}];
-const numtests = tests.length;
-
-
-var testsNotRan = tests.length;
-
-process.on('beforeExit', () =>
-  assert.strictEqual(testsNotRan, 0)
-);
-
-function cleanupTmpFile() {
-  try {
-    // Write over the file, clearing any history
-    fs.writeFileSync(defaultHistoryPath, '');
-  } catch (err) {
-    if (err.code === 'ENOENT') return true;
-    throw err;
-  }
-  return true;
-}
-
-// Copy our fixture to the tmp directory
-fs.createReadStream(historyFixturePath)
-  .pipe(fs.createWriteStream(historyPath)).on('unpipe', () => runTest());
-
-function runTest(assertCleaned) {
-  const opts = tests.shift();
-  if (!opts) return; // All done
-
-  if (assertCleaned) {
-    try {
-      assert.strictEqual(fs.readFileSync(defaultHistoryPath, 'utf8'), '');
-    } catch (e) {
-      if (e.code !== 'ENOENT') {
-        console.error(`Failed test # ${numtests - tests.length}`);
-        throw e;
-      }
-    }
-  }
-
-  const env = opts.env;
-  const test = opts.test;
-  const expected = opts.expected;
-  const after = opts.after;
-  const before = opts.before;
-
-  if (before) before();
-
-  REPL.createInternalRepl(env, {
-    input: new ActionStream(),
-    output: new stream.Writable({
-      write(chunk, _, next) {
-        const output = chunk.toString();
-
-        // Ignore escapes and blank lines
-        if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output))
-          return next();
-
-        try {
-          assert.strictEqual(output, expected.shift());
-        } catch (err) {
-          console.error(`Failed test # ${numtests - tests.length}`);
-          throw err;
-        }
-        next();
-      }
-    }),
-    prompt: prompt,
-    useColors: false,
-    terminal: true
-  }, function(err, repl) {
-    if (err) {
-      console.error(`Failed test # ${numtests - tests.length}`);
-      throw err;
-    }
-
-    repl.once('close', () => {
-      if (repl._flushing) {
-        repl.once('flushHistory', onClose);
-        return;
-      }
-
-      onClose();
-    });
-
-    function onClose() {
-      if (after) {
-        var cleaned = after();
-      } else {
-        var cleaned = cleanupTmpFile();
-      }
-
-      try {
-        // Ensure everything that we expected was output
-        assert.strictEqual(expected.length, 0);
-        testsNotRan--;
-        setImmediate(runTest, cleaned);
-      } catch (err) {
-        console.error(`Failed test # ${numtests - tests.length}`);
-        throw err;
-      }
-    }
-
-    repl.inputStream.run(test);
-  });
-}