From bcc02270897c9136f431a45797eccf8f3439e0de Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 14 Dec 2016 12:03:24 +0100 Subject: [PATCH 1/3] add infrastructure for watch tests --- test/WatchTestCases.test.js | 170 ++++++++++++++++++ .../caching-harmony/0/changing-module.js | 1 + .../parsing/caching-harmony/0/index.js | 14 ++ .../parsing/caching-harmony/0/module.js | 1 + .../caching-harmony/1/changing-module.js | 1 + .../parsing/switching-harmony/0/cc.js | 1 + .../parsing/switching-harmony/0/ch.js | 1 + .../parsing/switching-harmony/0/hc.js | 1 + .../parsing/switching-harmony/0/hh.js | 1 + .../parsing/switching-harmony/0/index.js | 23 +++ .../parsing/switching-harmony/1/cc.js | 1 + .../parsing/switching-harmony/1/ch.js | 1 + .../parsing/switching-harmony/1/hc.js | 1 + .../parsing/switching-harmony/1/hh.js | 1 + .../simple/simple/0/changing-file.js | 1 + test/watchCases/simple/simple/0/index.js | 3 + .../simple/simple/1/changing-file.js | 1 + .../simple/simple/2/changing-file.js | 1 + 18 files changed, 224 insertions(+) create mode 100644 test/WatchTestCases.test.js create mode 100644 test/watchCases/parsing/caching-harmony/0/changing-module.js create mode 100644 test/watchCases/parsing/caching-harmony/0/index.js create mode 100644 test/watchCases/parsing/caching-harmony/0/module.js create mode 100644 test/watchCases/parsing/caching-harmony/1/changing-module.js create mode 100644 test/watchCases/parsing/switching-harmony/0/cc.js create mode 100644 test/watchCases/parsing/switching-harmony/0/ch.js create mode 100644 test/watchCases/parsing/switching-harmony/0/hc.js create mode 100644 test/watchCases/parsing/switching-harmony/0/hh.js create mode 100644 test/watchCases/parsing/switching-harmony/0/index.js create mode 100644 test/watchCases/parsing/switching-harmony/1/cc.js create mode 100644 test/watchCases/parsing/switching-harmony/1/ch.js create mode 100644 test/watchCases/parsing/switching-harmony/1/hc.js create mode 100644 test/watchCases/parsing/switching-harmony/1/hh.js create mode 100644 test/watchCases/simple/simple/0/changing-file.js create mode 100644 test/watchCases/simple/simple/0/index.js create mode 100644 test/watchCases/simple/simple/1/changing-file.js create mode 100644 test/watchCases/simple/simple/2/changing-file.js diff --git a/test/WatchTestCases.test.js b/test/WatchTestCases.test.js new file mode 100644 index 000000000..ea4c77e46 --- /dev/null +++ b/test/WatchTestCases.test.js @@ -0,0 +1,170 @@ +var should = require("should"); +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var Test = require("mocha/lib/test"); +var checkArrayExpectation = require("./checkArrayExpectation"); + +var Stats = require("../lib/Stats"); +var webpack = require("../lib/webpack"); + +function copyDiff(src, dest) { + if(!fs.existsSync(dest)) + fs.mkdirSync(dest); + var files = fs.readdirSync(src); + files.forEach(function(filename) { + var srcFile = path.join(src, filename); + var destFile = path.join(dest, filename); + var directory = fs.statSync(srcFile).isDirectory(); + if(directory) { + copyDiff(srcFile, destFile); + } else { + fs.writeFileSync(destFile, fs.readFileSync(srcFile)); + } + }); +} + +function remove(src) { + if(!fs.existsSync(src)) + return; + var files = fs.readdirSync(src); + files.forEach(function(filename) { + var srcFile = path.join(src, filename); + var directory = fs.statSync(srcFile).isDirectory(); + if(directory) { + remove(srcFile); + } else { + fs.unlinkSync(srcFile); + } + }); +} + +describe("WatchTestCases", function() { + var casesPath = path.join(__dirname, "watchCases"); + var categories = fs.readdirSync(casesPath); + + categories = categories.map(function(cat) { + return { + name: cat, + tests: fs.readdirSync(path.join(casesPath, cat)).filter(function(folder) { + return folder.indexOf("_") < 0; + }).sort() + }; + }); + before(function() { + var dest = path.join(__dirname, "js"); + if(!fs.existsSync(dest)) + fs.mkdirSync(dest); + dest = path.join(__dirname, "js", "watch-src"); + if(!fs.existsSync(dest)) + fs.mkdirSync(dest); + }); + categories.forEach(function(category) { + before(function() { + var dest = path.join(__dirname, "js", "watch-src", category.name); + if(!fs.existsSync(dest)) + fs.mkdirSync(dest); + }) + describe(category.name, function() { + category.tests.forEach(function(testName) { + describe(testName, function() { + var tempDirectory = path.join(__dirname, "js", "watch-src", category.name, testName); + var testDirectory = path.join(casesPath, category.name, testName); + var runs = fs.readdirSync(testDirectory).sort().map(function(name) { + return { + name: name, + suite: describe(name, function() {}) + } + }); + before(function() { + remove(tempDirectory); + }); + it("should compile", function(done) { + this.timeout(30000); + var outputDirectory = path.join(__dirname, "js", "watch", category.name, testName); + + var options = { + context: tempDirectory, + entry: "./index.js", + output: { + path: outputDirectory, + pathinfo: true, + filename: "bundle.js" + } + }; + + var runIdx = 0; + var run = runs[runIdx]; + copyDiff(path.join(testDirectory, run.name), tempDirectory); + + var compiler = webpack(options); + compiler.watch({}, function(err, stats) { + if(run.done) return; + run.done = true; + if(err) return done(err); + var statOptions = Stats.presetToOptions("verbose"); + statOptions.colors = false; + fs.writeFileSync(path.join(outputDirectory, "stats.txt"), stats.toString(statOptions), "utf-8"); + var jsonStats = stats.toJson({ + errorDetails: true + }); + if(checkArrayExpectation(testDirectory, jsonStats, "error", "Error", done)) return; + if(checkArrayExpectation(testDirectory, jsonStats, "warning", "Warning", done)) return; + var exportedTests = 0; + + function _it(title, fn) { + var test = new Test(title, fn); + run.suite.addTest(test); + exportedTests++; + return test; + } + + function _require(currentDirectory, module) { + if(Array.isArray(module) || /^\.\.?\//.test(module)) { + var fn; + var content; + if(Array.isArray(module)) { + var p = path.join(currentDirectory, module[0]); + content = module.map(function(p) { + var p = path.join(currentDirectory, p); + return fs.readFileSync(p, "utf-8"); + }).join("\n"); + } else { + var p = path.join(currentDirectory, module); + content = fs.readFileSync(p, "utf-8"); + } + fn = vm.runInThisContext("(function(require, module, exports, __dirname, __filename, it, WATCH_STEP) {" + content + "\n})", p); + var module = { + exports: {} + }; + fn.call(module.exports, _require.bind(null, path.dirname(p)), module, module.exports, path.dirname(p), p, _it, run.name); + return module.exports; + } else if(testConfig.modules && module in testConfig.modules) { + return testConfig.modules[module]; + } else return require(module); + } + + var testConfig = {}; + try { + // try to load a test file + testConfig = require(path.join(testDirectory, "test.config.js")); + } catch(e) {} + + if(testConfig.noTests) return process.nextTick(done); + _require(outputDirectory, "./bundle.js"); + + if(exportedTests < 1) return done(new Error("No tests exported by test case")); + runIdx++; + if(runIdx < runs.length) { + run = runs[runIdx]; + copyDiff(path.join(testDirectory, run.name), tempDirectory); + } else { + process.nextTick(done); + } + }); + }); + }); + }); + }); + }); +}); diff --git a/test/watchCases/parsing/caching-harmony/0/changing-module.js b/test/watchCases/parsing/caching-harmony/0/changing-module.js new file mode 100644 index 000000000..fd1d2fbc9 --- /dev/null +++ b/test/watchCases/parsing/caching-harmony/0/changing-module.js @@ -0,0 +1 @@ +export default "original"; diff --git a/test/watchCases/parsing/caching-harmony/0/index.js b/test/watchCases/parsing/caching-harmony/0/index.js new file mode 100644 index 000000000..fab5354e7 --- /dev/null +++ b/test/watchCases/parsing/caching-harmony/0/index.js @@ -0,0 +1,14 @@ +import m from "./module"; +import cm from "./changing-module"; + +it("should flag harmony modules correctly", function() { + m.should.be.eql("module" + WATCH_STEP); + switch(WATCH_STEP) { + case 0: + cm.should.be.eql("original"); + break; + case 1: + cm.should.be.eql("change"); + break; + } +}); diff --git a/test/watchCases/parsing/caching-harmony/0/module.js b/test/watchCases/parsing/caching-harmony/0/module.js new file mode 100644 index 000000000..5a325bd96 --- /dev/null +++ b/test/watchCases/parsing/caching-harmony/0/module.js @@ -0,0 +1 @@ +export default "module" + WATCH_STEP; diff --git a/test/watchCases/parsing/caching-harmony/1/changing-module.js b/test/watchCases/parsing/caching-harmony/1/changing-module.js new file mode 100644 index 000000000..5bf38cc93 --- /dev/null +++ b/test/watchCases/parsing/caching-harmony/1/changing-module.js @@ -0,0 +1 @@ +export default "change"; diff --git a/test/watchCases/parsing/switching-harmony/0/cc.js b/test/watchCases/parsing/switching-harmony/0/cc.js new file mode 100644 index 000000000..074b70de3 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/0/cc.js @@ -0,0 +1 @@ +module.exports = "cc0"; diff --git a/test/watchCases/parsing/switching-harmony/0/ch.js b/test/watchCases/parsing/switching-harmony/0/ch.js new file mode 100644 index 000000000..3ecb85334 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/0/ch.js @@ -0,0 +1 @@ +module.exports = "ch0"; diff --git a/test/watchCases/parsing/switching-harmony/0/hc.js b/test/watchCases/parsing/switching-harmony/0/hc.js new file mode 100644 index 000000000..5c68b40b9 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/0/hc.js @@ -0,0 +1 @@ +export default "hc0"; diff --git a/test/watchCases/parsing/switching-harmony/0/hh.js b/test/watchCases/parsing/switching-harmony/0/hh.js new file mode 100644 index 000000000..e2ceb775b --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/0/hh.js @@ -0,0 +1 @@ +export default "hh0"; diff --git a/test/watchCases/parsing/switching-harmony/0/index.js b/test/watchCases/parsing/switching-harmony/0/index.js new file mode 100644 index 000000000..293405586 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/0/index.js @@ -0,0 +1,23 @@ +import hh from "./hh"; +import hc from "./hc"; +import ch from "./ch"; +import cc from "./cc"; + +it("should flag modules correctly", function() { + hh.should.be.eql("hh" + WATCH_STEP); + cc.should.be.eql("cc" + WATCH_STEP); + hc.should.be.eql("hc" + WATCH_STEP); + ch.should.be.eql("ch" + WATCH_STEP); + require("./hh").default.should.be.eql("hh" + WATCH_STEP); + require("./cc").should.be.eql("cc" + WATCH_STEP); + switch(WATCH_STEP) { + case 0: + require("./hc").default.should.be.eql("hc0"); + require("./ch").should.be.eql("ch0"); + break; + case 1: + require("./hc").should.be.eql("hc1"); + require("./ch").default.should.be.eql("ch1"); + break; + } +}); diff --git a/test/watchCases/parsing/switching-harmony/1/cc.js b/test/watchCases/parsing/switching-harmony/1/cc.js new file mode 100644 index 000000000..4d9c1c476 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/1/cc.js @@ -0,0 +1 @@ +module.exports = "cc1"; diff --git a/test/watchCases/parsing/switching-harmony/1/ch.js b/test/watchCases/parsing/switching-harmony/1/ch.js new file mode 100644 index 000000000..5fb8ff107 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/1/ch.js @@ -0,0 +1 @@ +export default "ch1"; diff --git a/test/watchCases/parsing/switching-harmony/1/hc.js b/test/watchCases/parsing/switching-harmony/1/hc.js new file mode 100644 index 000000000..4c40fce77 --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/1/hc.js @@ -0,0 +1 @@ +module.exports = "hc1"; diff --git a/test/watchCases/parsing/switching-harmony/1/hh.js b/test/watchCases/parsing/switching-harmony/1/hh.js new file mode 100644 index 000000000..7f649b4cb --- /dev/null +++ b/test/watchCases/parsing/switching-harmony/1/hh.js @@ -0,0 +1 @@ +export default "hh1"; diff --git a/test/watchCases/simple/simple/0/changing-file.js b/test/watchCases/simple/simple/0/changing-file.js new file mode 100644 index 000000000..335d3d1ad --- /dev/null +++ b/test/watchCases/simple/simple/0/changing-file.js @@ -0,0 +1 @@ +module.exports = "0"; diff --git a/test/watchCases/simple/simple/0/index.js b/test/watchCases/simple/simple/0/index.js new file mode 100644 index 000000000..3069c8ecb --- /dev/null +++ b/test/watchCases/simple/simple/0/index.js @@ -0,0 +1,3 @@ +it("should watch for changes", function() { + require("./changing-file").should.be.eql(WATCH_STEP); +}) diff --git a/test/watchCases/simple/simple/1/changing-file.js b/test/watchCases/simple/simple/1/changing-file.js new file mode 100644 index 000000000..ba0e0f3e1 --- /dev/null +++ b/test/watchCases/simple/simple/1/changing-file.js @@ -0,0 +1 @@ +module.exports = "1"; diff --git a/test/watchCases/simple/simple/2/changing-file.js b/test/watchCases/simple/simple/2/changing-file.js new file mode 100644 index 000000000..c202b8513 --- /dev/null +++ b/test/watchCases/simple/simple/2/changing-file.js @@ -0,0 +1 @@ +module.exports = "2"; From e299d600f79cd314296e2d9cf5094e43e9277ce4 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 19 Dec 2016 20:03:15 +0100 Subject: [PATCH 2/3] ignore extra compilation while testing watching --- test/WatchTestCases.test.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/WatchTestCases.test.js b/test/WatchTestCases.test.js index ea4c77e46..16ad7145f 100644 --- a/test/WatchTestCases.test.js +++ b/test/WatchTestCases.test.js @@ -95,11 +95,16 @@ describe("WatchTestCases", function() { var runIdx = 0; var run = runs[runIdx]; + var lastHash = ""; copyDiff(path.join(testDirectory, run.name), tempDirectory); var compiler = webpack(options); compiler.watch({}, function(err, stats) { - if(run.done) return; + if(stats.hash === lastHash) + return; + lastHash = stats.hash; + if(run.done) + return done(new Error("Compilation changed but no change was issued " + lastHash + " != " + stats.hash + " (run " + runIdx + ")")); run.done = true; if(err) return done(err); var statOptions = Stats.presetToOptions("verbose"); From 862478e3b4956caa10527d760baf775c2d2f79b2 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Wed, 14 Dec 2016 12:03:24 +0100 Subject: [PATCH 3/3] reset meta on recompile --- lib/NormalModule.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/NormalModule.js b/lib/NormalModule.js index 54e962e60..16b760102 100644 --- a/lib/NormalModule.js +++ b/lib/NormalModule.js @@ -178,6 +178,7 @@ NormalModule.prototype.build = function build(options, compilation, resolver, fs _this.error = null; _this.errors.length = 0; _this.warnings.length = 0; + _this.meta = {}; return _this.doBuild(options, compilation, resolver, fs, function(err) { _this.dependencies.length = 0; _this.variables.length = 0;