UNPKG

mesos-framework

Version:

A wrapper around the Mesos HTTP APIs for Schedulers and Executors. Write your Mesos framework in pure JavaScript!

1,206 lines (1,179 loc) 88.7 kB
"use strict"; // Global var http = require("http"); var util = require("util"); var EventEmitter = require("events").EventEmitter; // Project require var lib = require("requirefrom")("lib"); var Scheduler = require("../index").Scheduler; var helpers = lib("helpers"); var TaskHelper = lib("taskHelper"); var mesos = lib("mesos")().getMesos(); var Builder = lib("builder"); // Lib require for stubs var zookeeper = require("node-zookeeper-client"); // Testing require var expect = require("chai").expect; var sinon = require("sinon"); var MockReq = require("mock-req"); var MockRes = require("mock-res"); describe("Scheduler constructor", function() { var sandbox; var clock; it("Check mesos access function", function () { (require("../lib/mesos"))().getProtoBuf(); }); it("Create the Scheduler with default options", function () { var scheduler = Scheduler({}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(0); expect(scheduler.requestTemplate.path).to.equal("/api/v1/scheduler"); expect(scheduler.requestTemplate.host).to.equal(scheduler.options.masterUrl); expect(scheduler.requestTemplate.port).to.equal(scheduler.options.port); }); it("Create the Scheduler with custom log file", function () { var scheduler = Scheduler({logging:{path:"logs", fileName:"tests.log"}}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); }); it("Create the Scheduler with a task", function () { var scheduler = Scheduler({tasks: {task1:{}}}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(1); }); it.skip("Create the Scheduler with a submitted task", function () { var scheduler = Scheduler({tasks: {task1:{isSubmitted:true}}}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(1); expect(scheduler.pendingTasks).to.have.lengthOf(0); }); it("Create the Scheduler with 2 submitted tasks (sort test)", function () { var scheduler = Scheduler({tasks: { task1:{isSubmitted:true}, task2:{isSubmitted:true} }, "staticPorts": true, "serialNumberedTasks": false}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(2); }); it("Create the Scheduler with 3 submitted tasks with priority (sort test)", function () { var scheduler = Scheduler({tasks: { task1:{isSubmitted:true, priority:1}, task2:{isSubmitted:true, priority:2}, task3:{isSubmitted:true, priority:1} }}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(3); }); it("Create the Scheduler with 3 submitted tasks with priority and multiple instances (sort test)", function () { var scheduler = Scheduler({tasks: { task1:{isSubmitted:true, priority:1}, task2:{isSubmitted:true, priority:2}, task3:{isSubmitted:true, priority:1, instances:2} }}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(4); }); describe("Create scheduler with an already submitted task", function () { before(function () { sandbox = sinon.sandbox.create(); sandbox.stub(helpers, "sortTasksByPriority", function(tasks) { return [{name:"task1", isSubmitted:true}, {name:"task2", isSubmitted:true, instances:3}]; }); }); after(function (done) { sandbox.restore(); done(); }); it("The actual test", function () { var scheduler = Scheduler({tasks: { task1:{isSubmitted:true} }}); expect(scheduler).to.be.instanceOf(Scheduler); expect(scheduler.tasks).to.be.an("array"); expect(scheduler.tasks).to.have.lengthOf(2); expect(scheduler.pendingTasks).to.have.lengthOf(0); }); }); describe("Create scheduler with ZK", function () { var zkClient = zookeeper.createClient("127.0.0.1"); var logger = helpers.getLogger(null, null, "debug"); var taskHelper = new TaskHelper({"zkClient": zkClient, "logger": logger, "pendingTasks":[], "launchedTasks":[], scheduler:{}}); beforeEach(function () { sandbox = sinon.sandbox.create(); clock = sinon.useFakeTimers(); sandbox.stub(zkClient, "connect", function() { this.emit("connected"); }); sandbox.stub(zkClient, "getData", function(path,watch,cb) { cb(null, "434e8173-45ea-435e-905e-d577b260898c-1021", 1); }); sandbox.stub(taskHelper, "loadTasks", function() { var self = this; setTimeout(function() { self.scheduler.emit("ready"); }, 100); }); }); afterEach(function (done) { sandbox.restore(); clock.restore(); done(); }); it("Success path", function (done) { var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} }, useZk: true, logging: {level: "debug"}, zkClient: zkClient, taskHelper: taskHelper}); scheduler.on("ready", function() { done(); }); clock.tick(100); }); it("Read no node error path", function (done) { zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { setTimeout(function() { cb(zookeeper.Exception.create(zookeeper.Exception.NO_NODE), null, 1); }, 100); }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient, taskHelper: taskHelper}); scheduler.on("ready", function() { done(); }); clock.tick(100); clock.tick(100); }); it("Read other error path", function (done) { var isReady = false; zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { setTimeout(function() { cb(zookeeper.Exception.create(zookeeper.Exception.CONNECTION_LOSS), null, 1); //cb(null, "434e8173-45ea-435e-905e-d577b260898c-2021", 1); }, 100); }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient, taskHelper: taskHelper}); scheduler.on("ready", function() { isReady = true; console.log("got to ready"); expect(true).to.be.false; }); setTimeout(function () { expect(isReady).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("Read zk OOB error", function (done) { var isReady = false; zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { var self = this; setTimeout(function() { var err = zookeeper.Exception.create(zookeeper.Exception.CONNECTION_LOSS); self.emit("error", err); cb(err, null, 1); }, 100); }); var scheduler = Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient, taskHelper: taskHelper}); scheduler.on("ready", function() { isReady = true; console.log("got to ready"); expect(true).to.be.false; }); setTimeout(function () { expect(isReady).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("Read null data", function (done) { var isReady = false; zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { setTimeout(function() { cb(null, null, 1); }, 100); }); var scheduler = Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient, taskHelper: taskHelper}); scheduler.on("ready", function() { isReady = true; console.log("got to ready"); done(); }); setTimeout(function () { expect(isReady).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("Read null data without helper", function (done) { var isReady = false; zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { setTimeout(function() { cb(null, null, 1); }, 100); }); var scheduler = Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient}); scheduler.on("ready", function() { isReady = true; console.log("got to ready"); done(); }); setTimeout(function () { expect(isReady).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("Connect fail", function (done) { var isReady = false; zkClient.getData.restore(); sandbox.stub(zkClient, "getData", function(path,watch,cb) { setTimeout(function() { cb(zookeeper.Exception.create(zookeeper.Exception.CONNECTION_LOSS), null, 1); }, 100); }); var scheduler = Scheduler({tasks: { task1:{isSubmitted:true} },useZk: true, logging: {level: "debug"}, zkClient: zkClient}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { isReady = true; console.log("got to ready"); }); setTimeout(function () { expect(isReady).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("Custom handler - no case mixing", function (done) { var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}, handlers: {"SUBSCRIBED": function (type) {}}}); scheduler.on("ready", function() { console.log("Function length: " + (function (type) {}).length.toString()); expect(Object.keys(scheduler.customEventHandlers)).not.to.have.lengthOf(0); done(); }); clock.tick(100); }); it("Custom handler - case mixing", function (done) { var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}, handlers: {"subSCRIBED": function (type) {}}}); scheduler.on("ready", function() { console.log("Function length: " + (function (type) {}).length.toString()); expect(Object.keys(scheduler.customEventHandlers)).not.to.have.lengthOf(0); done(); }); clock.tick(100); }); it("Custom bad handlers (ignored)", function (done) { var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}, handlers: {"test":"test"}}); scheduler.on("ready", function() { expect(Object.keys(scheduler.customEventHandlers)).to.have.lengthOf(0); done(); }); clock.tick(100); }); }); describe("Request functions", function() { beforeEach(function() { sandbox = sinon.sandbox.create(); this.request = sandbox.stub(helpers, "doRequest"); clock = sinon.useFakeTimers(); }); afterEach(function() { helpers.doRequest.restore(); sandbox.restore(); clock.restore(); }); it("kill Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.kill("1234","12345"); }); var sent = false; scheduler.on("sent_kill", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("kill Fail", function(done) { var self = this; var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { self.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); scheduler.kill("1234","12345"); }); var sent = false; scheduler.on("sent_kill", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("shutdown Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.shutdown("1234","12345"); }); var sent = false; scheduler.on("sent_shutdown", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("shutdown fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.shutdown("1234","12345"); }); var sent = false; scheduler.on("sent_shutdown", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("reconcile Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.reconcile("1234","12345"); }); var sent = false; scheduler.on("sent_reconcile", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("reconcile fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.reconcile("1234","12345"); }); var sent = false; scheduler.on("sent_reconcile", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("revive Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.revive(); }); var sent = false; scheduler.on("sent_revive", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("revive fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.revive(); }); var sent = false; scheduler.on("sent_revive", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("sync Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.killTasks = [{taskId: "1234", runtimeInfo:{agentId:"12345"}}, {taskId: "12354", runtimeInfo:{agentId:"123455"}}]; scheduler.launchedTasks = [{taskId: "12s364", runtimeInfo:{agentId:"12346w5"}}, {taskId: "1237q54", runtimeInfo:{}}]; scheduler.reconcileTasks = [{taskId: "12345", runtimeInfo:{agentId:"123456"}}, {taskId: "12364", runtimeInfo:{agentId:"123465"}}, {taskId: "123754", runtimeInfo:{}}]; scheduler.sync(); }); var sent = 0; scheduler.on("sent_reconcile", function() { sent++; expect(sent).to.be.above(0); }); scheduler.on("sent_kill", function() { sent++; expect(sent).to.be.above(0); }); setTimeout(function () { expect(sent).to.equal(5); expect(scheduler.killTasks).to.have.length.of(0); expect(scheduler.reconcileTasks).to.have.length.of(0); done(); }, 400); clock.tick(100); clock.tick(400); }); it("sync Success with zk and bad task", function(done) { this.request.callsArgWith(1, null); var taskHelper = new TaskHelper({"zkClient": {}, "logger": {}, "pendingTasks":[], "launchedTasks":[], scheduler:{}}); sandbox.stub(taskHelper, "deleteTask"); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.killTasks = [{taskId: "1234", runtimeInfo:{agentId:"12345"}}, {taskId: "12354", runtimeInfo:{agentId:"123455"}}]; scheduler.reconcileTasks = [{taskId: "12345", runtimeInfo:{agentId:"123456"}}, {taskId: "12364", runtimeInfo:{agentId:"123465"}}, {taskId: "123754", runtimeInfo:{}}]; scheduler.options.useZk = true; scheduler.taskHelper = taskHelper; scheduler.sync(); }); var sentRec = 0; var sentKill = 0; scheduler.on("sent_reconcile", function() { sentRec++; expect(sentRec).to.be.above(0); }); scheduler.on("sent_kill", function() { sentKill++; expect(sentKill).to.be.above(0); }); setTimeout(function () { expect(sentRec).to.equal(3); expect(sentKill).to.equal(2); expect(scheduler.killTasks).to.have.length.of(0); expect(scheduler.reconcileTasks).to.have.length.of(0); done(); }, 400); clock.tick(100); clock.tick(400); }); it("teardown Success", function(done) { this.request.callsArgWith(1, null); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("ready", function() { scheduler.teardown(); }); var sent = false; scheduler.on("sent_teardown", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("teardown fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.teardown(); }); var sent = false; scheduler.on("sent_teardown", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("acknowledge success", function(done) { this.request.callsArgWith(1, null); // { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.acknowledge({status:{agent_id:"1234", task_id:"123456",uuid:"1232153212"}}); }); var sent = false; scheduler.on("sent_acknowledge", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("acknowledge no uuid", function(done) { this.request.callsArgWith(1, null); // { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.acknowledge({status:{agent_id:"1234", task_id:"123456"}}); }); var sent = false; scheduler.on("sent_acknowledge", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("acknowledge fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.acknowledge({status:{agent_id:"1234", task_id:"123456", uuid:"12312451251"}}); }); var sent = false; scheduler.on("sent_acknowledge", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("accept success", function(done) { this.request.callsArgWith(1, null);//{ message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; var toLaunch = []; var demandedResources = [ helpers.fixEnums(new mesos.Resource(null, "cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), helpers.fixEnums(new mesos.Resource(null, "mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) ]; scheduler.frameworkId = "123445547452563"; toLaunch.push( new mesos.TaskInfo( "312312", // Task name new mesos.TaskID("23242"), // TaskID {value:"321312"}, // AgentID demandedResources, // Resources null, // ExecutorInfo null, // CommandInfo null, // ContainerInfo null, // HealthCheck null, // KillPolicy null, // Data null, // Labels null // DiscoveryInfo ) ); var Operations = new Builder("mesos.Offer.Operation") .setType(mesos.Offer.Operation.Type.LAUNCH) .setLaunch(new mesos.Offer.Operation.Launch(toLaunch)); scheduler.on("ready", function() { scheduler.accept([{value:"12312312"}], Operations, null); }); scheduler.on("sent_accept", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("accept error", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; var toLaunch = []; var demandedResources = [ helpers.fixEnums(new mesos.Resource(null, "cpus", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(1))), helpers.fixEnums(new mesos.Resource(null, "mem", mesos.Value.Type.SCALAR, new mesos.Value.Scalar(128))) ]; scheduler.frameworkId = "123445547452563"; toLaunch.push( new mesos.TaskInfo( "312312", // Task name new mesos.TaskID("23242"), // TaskID {value:"321312"}, // AgentID demandedResources, // Resources null, // ExecutorInfo null, // CommandInfo null, // ContainerInfo null, // HealthCheck null, // KillPolicy null, // Data null, // Labels null // DiscoveryInfo ) ); var Operations = new Builder("mesos.Offer.Operation") .setType(mesos.Offer.Operation.Type.LAUNCH) .setLaunch(new mesos.Offer.Operation.Launch(toLaunch)); scheduler.on("ready", function() { scheduler.accept([{value:"12312312"}], Operations, null); }); scheduler.on("sent_accept", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("decline success", function(done) { this.request.callsArgWith(1, null);//{ message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { scheduler.decline([{value:"12312312"}], {}); }); scheduler.on("sent_decline", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("decline error", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { scheduler.decline([{value:"12312312"}], {}); }); scheduler.on("sent_decline", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("message success", function(done) { this.request.callsArgWith(1, null);//{ message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { scheduler.message("12312312", "dasfasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"); }); scheduler.on("sent_message", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("message fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { scheduler.message("12312312", "dasfasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"); }); scheduler.on("sent_message", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("request success", function(done) { this.request.callsArgWith(1, null);//{ message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { //scheduler.request(["12312312","fasfafas", "sdfasfasfgasgloewy2398y423r5fqwncas"]); scheduler.request(new Builder("mesos.Request") .setAgentId(new Builder("mesos.AgentID").setValue("12312312")) .setResources([ new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(1.1)) ]) ); }); scheduler.on("sent_request", function() { sent = true; expect(sent).to.be.true; }); setTimeout(function () { expect(sent).to.be.true; done(); }, 400); clock.tick(100); clock.tick(400); }); it("request fail", function(done) { this.request.callsArgWith(1, { message: "Request was not accepted properly. Reponse status code was '400'. Body was 'malformed request'." }); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); var sent = false; scheduler.frameworkId = "123445547452563"; scheduler.on("ready", function() { scheduler.request(new Builder("mesos.Request") .setAgentId(new Builder("mesos.AgentID").setValue("12312312")) .setResources([ new Builder("mesos.Resource").setName("cpus").setType(mesos.Value.Type.SCALAR).setScalar(new mesos.Value.Scalar(1.1)) ]) ); }); scheduler.on("sent_request", function() { sent = true; expect(sent).to.be.false; }); setTimeout(function () { expect(sent).to.be.false; done(); }, 400); clock.tick(100); clock.tick(400); }); it("getRunningTasks", function(done) { var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true} },useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); }); scheduler.on("ready", function() { scheduler.runtimeInfo = {"one": {"runningInstances": {"task1":"12124521", "task2":"2343541"}}}; var tasks = scheduler.getRunningTasks(); expect(tasks).to.be.an("array"); expect(tasks.length).to.equal(2); done(); }); clock.tick(100); }); }); describe("Subscribe flow", function() { beforeEach(function() { this.request = sinon.stub(http, "request"); clock = sinon.useFakeTimers(); }); afterEach(function() { http.request.restore(); clock.restore(); delete process.env.PORT0; delete process.env.HOST; }); it("error http status (fail)", function(done) { var data = "OK"; var res = new MockRes(); res.writeHead(500); res.write(data); res.headers = {}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); done(); }); scheduler.on("ready", function () { scheduler.subscribe(); }); clock.tick(100); }); it("http redirect status no location (fail)", function(done) { var data = "OK"; var res = new MockRes(); res.writeHead(307); res.write(data); res.headers = {}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); done(); }); scheduler.on("ready", function () { scheduler.subscribe(); }); clock.tick(100); }); it("http redirect status with location (fail)", function(done) { var data = "OK"; var res = new MockRes(); var errors = 0; //clock.restore(); res.writeHead(307); res.write(data); res.headers = {"location":"http://1.2.3.4:5030/fgs/fgdsg"}; res.end(); var req = new MockReq({ method: "POST" }); this.request.onFirstCall().callsArgWith(1, res).returns(req); var res2 = new MockRes(); res2.writeHead(500); res2.write(data); res2.headers = {}; res2.end(); this.request.onSecondCall().callsArgWith(1, res2).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); errors++; clock.tick(1); }); scheduler.on("ready", function () { scheduler.subscribe(); clock.tick(97); }); setTimeout(function (){ expect(scheduler.options.masterUrl).to.equal("1.2.3.4"); expect(scheduler.options.port).to.equal("5030"); expect(errors).to.equal(3); done(); }, 200); clock.tick(100); }); it("http redirect status with location without scheme and path (fail)", function(done) { var data = "OK"; var res = new MockRes(); var errors = 0; res.writeHead(307); res.write(data); res.headers = {"location":"1.2.3.4:5030"}; res.end(); var req = new MockReq({ method: "POST" }); this.request.onFirstCall().callsArgWith(1, res).returns(req); var res2 = new MockRes(); res2.writeHead(500); res2.write(data); res2.headers = {}; res2.end(); this.request.onSecondCall().callsArgWith(1, res2).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); errors++; clock.tick(1); }); scheduler.on("ready", function () { scheduler.subscribe(); clock.tick(97); }); setTimeout(function (){ expect(errors).to.equal(3); expect(scheduler.options.masterUrl).to.equal("1.2.3.4"); expect(scheduler.options.port).to.equal("5030"); done(); }, 200); clock.tick(100); }); it("error http status no message (fail)", function(done) { var data = ""; var res = new MockRes(); res.writeHead(500); res.headers = {}; var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); done(); }); setTimeout(function () { res.write(data); res.emit("data", ""); res.end(); }, 100); scheduler.on("ready", function () { scheduler.subscribe(); }); clock.tick(100); clock.tick(100); }); it("OK http status - no stream id (fail)", function(done) { var data = "OK"; var res = new MockRes(); res.writeHead(200); res.write(data); res.headers = {}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); done(); }); scheduler.on("ready", function () { scheduler.subscribe(); }); clock.tick(100); }); it("OK http status - with stream id, really short response (fail)", function(done) { var data = "OK"; var res = new MockRes(); var errorSet = false; res.writeHead(200); res.write(data); res.headers = {"mesos-stream-id":"123412412"}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); errorSet = true; clock.tick(1); }); scheduler.on("ready", function () { scheduler.subscribe(); clock.tick(299); }); setTimeout(function () { expect(errorSet).to.be.true; done(); }, 400); clock.tick(100); }); it("OK http status - with stream id, invalid JSON response (fail)", function(done) { var data = "2\nOK"; var res = new MockRes(); var errorSet = false; res.writeHead(200); res.write(data); res.headers = {"mesos-stream-id":"123412412"}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); errorSet = true; clock.tick(1); }); scheduler.on("ready", function () { scheduler.subscribe(); clock.tick(299); }); setTimeout(function () { expect(errorSet).to.be.true; done(); }, 400); clock.tick(100); }); it("OK http status - with stream id, too many line ends (fail)", function(done) { var data = "2\nOK\n"; var res = new MockRes(); var errorSet = false; res.writeHead(200); res.write(data); res.headers = {"mesos-stream-id":"123412412"}; res.end(); var req = new MockReq({ method: "POST" }); this.request.callsArgWith(1, res).returns(req); var scheduler = new Scheduler({tasks: { task1:{isSubmitted:true}},useZk: false, logging: {level: "debug"}}); scheduler.on("error", function(error) { console.log(JSON.stringify(error)); errorSet = true; clock.tick(1); }); scheduler.on("ready", function () { scheduler.subscribe(); clock.tick(299); }); setTimeout(function () { expect(errorSet).to.be.true; done(); },