gpii-universal
Version:
Cross platform, core components of the GPII personalization infrastructure.
210 lines (181 loc) • 6.93 kB
JavaScript
/*
* singleInstance Tests
*
* Copyright 2017 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The R&D leading to these results received funding from the
* Department of Education - Grant H421A150005 (GPII-APCP). However,
* these results do not necessarily represent the policy of the
* Department of Education, and you should not assume endorsement by the
* Federal Government.
*
* You may obtain a copy of the License at
* https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
;
var fluid = require("infusion"),
fs = require("fs"),
os = require("os"),
child_process = require("child_process");
var jqUnit = fluid.require("node-jqunit");
var gpii = fluid.registerNamespace("gpii");
fluid.registerNamespace("gpii.tests.singleInstance");
fluid.require("%gpii-universal");
require("singleInstance");
jqUnit.module("gpii.tests.singleInstance");
gpii.tests.singleInstance.testDefs = fluid.freezeRecursive([
{
// no pidfile
testData: null,
expected: {
checkInstance: null,
registerInstance: true,
file: "$processes.own.pid",
deregisterInstance: false
}
},
{
// junk content
testData: "not a pid",
expected: {
checkInstance: null,
registerInstance: true,
file: "$processes.own.pid",
deregisterInstance: false
}
},
{
// non-running pid
testData: "-100",
expected: {
checkInstance: null,
registerInstance: true,
file: "$processes.own.pid",
deregisterInstance: false
}
},
{
// this process
testData: "$processes.own.pid",
expected: {
checkInstance: "$processes.own.pid",
registerInstance: true,
file: "$processes.own.pid",
deregisterInstance: true
}
},
{
// another process
testData: "$processes.other.pid",
expected: {
checkInstance: "$processes.other.pid",
// If the implementation was complete, then registerInstance should succeed because the test process
// isn't another GPII instance.
registerInstance: false,
file: null,
deregisterInstance: false
}
}
]);
fluid.defaults("gpii.tests.singleInstance.testData", {
gradeNames: "fluid.modelComponent",
model: {
processes: {}
}
});
/**
* Extracts the test items from model, performing look-ups from it ("$like.this")
*
* @param {Object} model - The object to resolve from.
* @param {Object} value - The value (or values) to resolve.
* @return {Array} The test items.
*/
gpii.tests.singleInstance.resolveReferences = function (model, value) {
if (typeof(value) === "string") {
return value.charAt(0) === "$" ? fluid.get(model, value.substring(1)) : value;
} else {
return fluid.transform(value, function (obj) {
return gpii.tests.singleInstance.resolveReferences(model, obj);
});
}
};
/**
* Deletes the pid file, hiding errors if the file doesn't exist.
*
* @param {String} pidFile - The pid file.
*/
gpii.tests.singleInstance.deletePidFile = function (pidFile) {
try {
fs.unlinkSync(pidFile);
} catch (e) {
// Don't care if it failed, as long as it's gone.
if (fs.existsSync(pidFile)) {
throw e;
}
}
};
jqUnit.test("Testing checkInstance, registerGpiiInstance, and deregisterInstance", function () {
var pidFile = os.tmpdir() + "/gpii-test-pid" + Date.now();
// Start another process (a cross-platform "sleep"), to test against a live pid.
var otherProcess = child_process.exec("node -e \"setTimeout(console.log, 5000)\"");
var testData = gpii.tests.singleInstance.testData();
testData.applier.change("processes", {
own: process,
other: otherProcess
});
var tests = gpii.tests.singleInstance.resolveReferences(testData.model, gpii.tests.singleInstance.testDefs);
var funcs = [ "checkInstance", "registerInstance", "deregisterInstance" ];
try {
while (funcs.length > 0) {
var func = funcs.shift();
for (var n = 0; n < tests.length; n++) {
var test = tests[n];
var testName = func + " test " + n + ": ";
// Set the pid file.
if (test.testData === null) {
gpii.tests.singleInstance.deletePidFile(pidFile);
} else {
fs.writeFileSync(pidFile, test.testData);
}
// Call the function
var returnValue = gpii.singleInstance[func](pidFile);
jqUnit.assertEquals(testName + " return", test.expected[func], returnValue);
var exists = fs.existsSync(pidFile);
if (func === "registerInstance") {
if (test.expected.file !== null) {
jqUnit.assertTrue(testName + "pid file should exist", exists);
// Check the new pid file
var content = fs.readFileSync(pidFile, {encoding: "utf8"});
var value = parseInt(content);
jqUnit.assertEquals(testName + "pidfile content", test.expected.file, value);
}
} else if (func === "deregisterInstance") {
if (returnValue) {
jqUnit.assertTrue(testName + "pidFile should not exist after a successful deregisterInstance", !exists);
}
}
gpii.tests.singleInstance.deletePidFile(pidFile);
}
}
} finally {
gpii.tests.singleInstance.deletePidFile(pidFile);
testData.destroy();
}
});
jqUnit.test("Testing singleInstance end-to-end", function () {
var pidFile = os.tmpdir() + "/gpii-test-pid" + Date.now();
// perform an end-to-end test
var pid = gpii.singleInstance.checkInstance(pidFile);
jqUnit.assertEquals("Another instance should not be detected before registering", null, pid);
var registered = gpii.singleInstance.registerInstance(pidFile);
jqUnit.assertTrue("This instance should have been registered", registered);
pid = gpii.singleInstance.checkInstance(pidFile);
jqUnit.assertEquals("The current instance should be this one", process.pid, pid);
var deregistered = gpii.singleInstance.deregisterInstance(pidFile);
jqUnit.assertTrue("This instance should have been deregistered", deregistered);
pid = gpii.singleInstance.checkInstance(pidFile);
jqUnit.assertEquals("Another instance should not be detected after deregistering", null, pid);
});