| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 |
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
7×
7×
7×
7×
7×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
2×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
1×
| /*
* Windows Kill Process Unit Tests
*
* Copyright 2015 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The research leading to these results has received funding from the European Union's
* Seventh Framework Programme (FP7/2007-2013)
* under grant agreement no. 289016.
*
* You may obtain a copy of the License at
* https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
"use strict";
var fluid = require("universal");
var jqUnit = fluid.require("node-jqunit");
var gpii = fluid.registerNamespace("gpii");
var shelljs = require("shelljs");
var path = require("path");
var child_process = require("child_process");
require("../processHandling.js");
fluid.registerNamespace("gpii.tests.windows.processHandling");
var waitExe = "gpii-process-handling-test.exe";
var waitExePath = null;
jqUnit.module("gpii.tests.windows.processHandling", {
setup: function () {
// Take a copy of the built-in "waitfor" command, to ensure a unique process name.
// This command is a glorified "sleep" that is also able to be terminated "nicely".
waitExePath = path.join(process.env.TEMP, waitExe);
shelljs.cp(path.join(process.env.SystemRoot, "/System32/waitfor.exe"), waitExePath);
},
teardown: function () {
Eif (waitExePath !== null) {
gpii.windows.killProcessByName(waitExe);
shelljs.rm(waitExePath);
}
}
});
jqUnit.test("Testing findProcessByName", function () {
// Find a process that isn't running.
var pid = gpii.windows.findProcessByName("a non-matching process.exe");
jqUnit.assertEquals("Process should not have been found running", null, pid);
// Find a process that is running.
pid = gpii.windows.findProcessByName("node.exe");
jqUnit.assertNotEquals("Process should have been found running", null, pid);
// Find multiple processes. There's always more than one svchost.exe running on Windows.
var pids = gpii.windows.findProcessByName("svchost.exe", true);
jqUnit.assertTrue("Should have found several matching process.", pids.length > 1);
});
jqUnit.asyncTest("Testing timeout waiting for processes start", function () {
jqUnit.expect(1);
var exe = "a non-matching process.exe";
gpii.windows.waitForProcessStart(exe, { timeout: 100 })
.then(function () {
jqUnit.fail("The process '" + exe + "' should not be running");
}, function () {
jqUnit.assert("Should have timed out");
jqUnit.start();
});
});
jqUnit.asyncTest("Testing timeout waiting for processes termination", function () {
jqUnit.expect(1);
var exe = "node.exe";
gpii.windows.waitForProcessTermination(exe, { timeout: 100 })
.then(function () {
jqUnit.fail("The process '" + exe + "' should not have terminated");
}, function () {
jqUnit.assert("Should have timed out");
jqUnit.start();
});
});
jqUnit.asyncTest("Testing waiting for processes start and end", function () {
jqUnit.expect(3);
var pid = gpii.windows.findProcessByName(waitExe);
jqUnit.assertEquals("The process should not already be running.", null, pid);
// Timeout waiting for the process start/end after 10 seconds.
var options = { timeout: 10000 };
// Wait for it to start.
gpii.windows.waitForProcessStart(waitExe, options)
.then(function () {
jqUnit.assert("We just started the new process.");
// Wait for it to die
gpii.windows.waitForProcessTermination(waitExe, options)
.then(function () {
jqUnit.assert("Child process terminated.");
jqUnit.start();
}, function () {
jqUnit.fail("Failed to detect process termination.");
});
// Tell the process to stop now.
child_process.execSync("waitfor /SI waitForProcessTerminationTest");
}, function () {
jqUnit.fail("Failed to detect process start.");
});
// Create the process, with a 5 second timeout
child_process.exec(waitExePath + " waitForProcessTerminationTest /T 5 > nul");
});
jqUnit.asyncTest("Testing Killing Processes", function () {
jqUnit.expect(3);
var pid = gpii.windows.findProcessByName(waitExe);
jqUnit.assertEquals("The process should not already be running.", null, pid);
// On the call below, async is true because if it is false shelljs will
// wait around until it is manually killed before continuing with the
// rest of the tests.
var command = waitExePath + " killProcessByNameTest /T 30";
fluid.log("Executing " + command);
child_process.exec(command, function (error, stdout, stderr) {
fluid.log("Exit code:", error.code);
jqUnit.assertEquals("Process should have terminated with code SIGKILL", 9, error.code);
fluid.log("Program output:", stdout);
fluid.log("Program stderr:", stderr);
jqUnit.start();
});
// Kill the process when it starts
gpii.windows.waitForProcessStart(waitExe)
.then(function () {
jqUnit.assert("The process has started");
gpii.windows.killProcessByName(waitExe);
});
});
jqUnit.asyncTest("Testing closeProcessByName", function () {
jqUnit.expect(3);
var exitCode = 5;
// Start a process that creates a window.
var exeName = "test-window.exe";
var exePath = path.join(__dirname, exeName);
var command = exePath + " -window";
fluid.log("Executing " + command);
var child = child_process.exec(command, function (error) {
fluid.log("Exit code:", error.code);
jqUnit.assertEquals("Exit code", exitCode, error.code);
});
child.stdout.on("data", function (data) {
// Wait for the window to be created
if (data.match("Window created")) {
jqUnit.assert("Window is created");
gpii.windows.closeProcessByName(exeName, {cleanOnly: true, timeout: 1000, exitCode: exitCode})
.then(function (clean) {
jqUnit.assertTrue("Should have closed cleanly", clean);
jqUnit.start();
}, function (e) {
fluid.log(e.message);
jqUnit.fail("Process should have closed.");
gpii.windows.killProcessByName(exeName);
});
}
});
});
jqUnit.asyncTest("Testing closeProcessByName (window-less process)", function () {
jqUnit.expect(3);
// Start a process that does not have a window.
gpii.windows.waitForProcessStart(waitExe)
.then(function () {
jqUnit.assert("Process started");
// The process doesn't have any windows, so this should fail to terminate it.
gpii.windows.closeProcessByName(waitExe, {cleanOnly: true})
.then(function () {
jqUnit.fail("Process should not have closed.");
}, function (e) {
jqUnit.assert("Process not closed");
fluid.log(e.message);
// Retry with force
gpii.windows.closeProcessByName(waitExe, {cleanOnly: false})
.then(function () {
jqUnit.assert("Process terminated");
jqUnit.start();
});
});
});
var command = waitExePath + " closeProcessByNameTest /T 30";
fluid.log("Executing " + command);
child_process.exec(command);
});
|