UNPKG

core-worker

Version:
263 lines (210 loc) 8.94 kB
/* * This file is part of CoreWorker. * * CoreWorker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CoreWorker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with CoreWorker. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2016 TeeAge-Beatz UG (haftungsbeschränkt) */ import sinon from "sinon"; import assert from "assert"; import Process from "../Process"; import NodeProcess from "../NodeProcess"; import { assign } from "lodash"; import TimeoutError from "../TimeoutError"; import { Writable } from "stream"; const test = (function() { const parameters = { promises: [], resolve: null, spies: { kill: sinon.spy(), stdin: sinon.spy(), stdout: sinon.spy() } }; return { all: () => parameters, spies: () => parameters.spies, set: params => assign(parameters, params) }; }()); const write = chunk => test.spies().stdin(chunk); const run = function() { assign(this.instance, { isRunning: true }); const promises = test.all().promises; setTimeout(function() { const resolvedValue = test.all().resolve; promises.forEach(resolve => resolve(resolvedValue)); assign(this.instance, { isRunning: false, fulfilled: true, lastMatch: resolvedValue }); test.set({ promises: [] }); }.bind(this), 3); }; const runTimingout = function() { assign(this.instance, { isRunning: true }); setTimeout(function() { this.emitter.emit("timeout"); }.bind(this), 2); }; const runWithConsoleOutput = function() { assign(this.instance, { isRunning: true }); this.emitter.on("data", data => this.store(data.toString())); this.emitter.on("data", data => this.validate(data.toString())); this.emitter.emit("data", "Foo"); this.emitter.emit("data", "Bar"); setTimeout(function() { this.emitter.emit("timeout"); }.bind(this), 2); }; const onReady = function(resolve) { test.set({ promises: test.all().promises.concat(resolve) }); }; const onDeath = function(deferred) { test.set({ promises: test.all().promises.concat(deferred.resolve) }); }; const kill = function(reason) { test.spies().kill(reason); }; const restoreAndSet = function(toRestore, toSet, functionName, stubFunction) { toRestore.restore(); sinon.stub(toSet, functionName).callsFake(stubFunction); }; describe("Process", function() { before(function() { sinon.stub(NodeProcess.prototype, "run").callsFake(run); sinon.stub(NodeProcess.prototype, "write").callsFake(write); sinon.stub(NodeProcess.prototype, "onReady").callsFake(onReady); sinon.stub(NodeProcess.prototype, "onDeath").callsFake(onDeath); sinon.stub(NodeProcess.prototype, "kill").callsFake(kill); this.clock = sinon.useFakeTimers(); }); after(function() { NodeProcess.prototype.run.restore(); NodeProcess.prototype.onReady.restore(); NodeProcess.prototype.onDeath.restore(); NodeProcess.prototype.kill.restore(); NodeProcess.prototype.write.restore(); this.clock.restore(); }); it("creates a new Instance", function() { const process = Process.create("node Test.js", "TestString"); assert(process.instance instanceof NodeProcess, "Instance should be instanceof NodeProcess"); assert(!process.instance.isRunning(), "Instance shouldn't run after create"); assert(!process.instance.isReady(), "Instanc shouldn't be ready after create"); }); it("runs a new Instance and waits until it is ready", function(done) { test.set({ resolve: "TestString" }); const instance = Process.create("node Test.js", "TestString"); instance.ready(10).then(function(match) { assert.equal(match, "TestString", "TestString should be resolved"); done(); }).catch(done); this.clock.tick(3); }); it("runs a new Instance and waits until it is ready exceeding given timeout", function(done) { restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", runTimingout); const instance = Process.create("node Test.js", "TestString"); instance.ready(3).then(function() { done(new Error("Promise shouldn't get resolved")); }).catch(function(err) { assert(TimeoutError.is(err), "Error is not an instance of TimeoutError"); assert.equal(err.message, "Timeout exceeded."); done(); }); this.clock.tick(2); restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", run); }); it("runs a new Instance, waits until it is ready exceeding given timeout and checks last process output in error", function(done) { restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", runWithConsoleOutput); const instance = Process.create("node Test.js", "TestString"); instance.ready(3).then(function() { done(new Error("Promise shouldn't get resolved")); }).catch(function(err) { assert(TimeoutError.is(err), "Error is not an instance of TimeoutError"); assert.equal(err.message, "Timeout exceeded. Last process output is: Bar"); done(); }); this.clock.tick(2); restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", run); }); it("runs a new Instance and waits until death", function(done) { test.set({ resolve: { data: "TestString" } }); const instance = Process.create("node Test.js", "TestString"); instance.death().then(function(data) { assert.deepStrictEqual(data, { data: "TestString" }, `TestString should be resolved: \n ${JSON.stringify(data)}`); done(); }).catch(done); this.clock.tick(3); }); it("runs a new Instance and waits until death exceeding given timeout", function(done) { restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", runTimingout); const instance = Process.create("node Test.js", "TestString"); instance.death(1).then(function() { done(new Error("Promise shouldn't get resolved.")); }).catch(function(err) { assert(TimeoutError.is(err), "Error is not an instance of TimeoutError"); assert.equal(err.message, "Timeout exceeded."); done(); }); this.clock.tick(2); restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", run); }); it("runs a new Instance, waits until death exceeding given timeout and checks last process output in error", function(done) { restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", runWithConsoleOutput); const instance = Process.create("node Test.js", "TestString"); instance.death(1).then(function() { done(new Error("Promise shouldn't get resolved.")); }).catch(function(err) { assert(TimeoutError.is(err), "Error is not an instance of TimeoutError"); assert.equal(err.message, "Timeout exceeded. Last process output is: Bar"); done(); }); this.clock.tick(2); restoreAndSet(NodeProcess.prototype.run, NodeProcess.prototype, "run", run); }); it("runs a new Instance and returns a stream", function() { // eslint-disable-line test.set({ resolve: "TestString" }); const process = Process.create("node Test.js", "TestString"); const stream = process.stream(); const pipeSpy = sinon.spy(); const streamSpy = new Writable({ // eslint-disable-line write(data, enc, next) { pipeSpy(data); next(); } }); stream.pipe(streamSpy); stream.write("Test"); assert(test.spies().stdin.calledWith(new Buffer("Test")), `stdinSpy was called with wrong args: \n ${test.spies().stdin.lastCall.args}`); process.instance.emitter.emit("data", "Test2"); assert(pipeSpy.calledWith(new Buffer("Test2")), `pipeSpy was called with wrong args: \n ${pipeSpy.lastCall.args}`); assert.throws(process.stream, "It should only run one instance"); }); });