Skip to content
This repository was archived by the owner on Jul 29, 2024. It is now read-only.

Commit 816dd73

Browse files
committed
fix(launcher): allow afterLaunch to run async scripts
1 parent 54e0ccb commit 816dd73

File tree

5 files changed

+72
-40
lines changed

5 files changed

+72
-40
lines changed

Diff for: docs/referenceConf.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,7 @@ exports.config = {
184184
// A callback function called once all tests have finished running and
185185
// the WebDriver instance has been shut down. It is passed the exit code
186186
// (0 if the tests passed). This is called only once before the program
187-
// exits (after onCleanUp). The program will exit after this event loop,
188-
// so this must perform only synchronous operations.
187+
// exits (after onCleanUp).
189188
afterLaunch: function() {},
190189

191190
// The params object will be passed directly to the Protractor instance,

Diff for: lib/launcher.js

+36-16
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
var child = require('child_process'),
88
ConfigParser = require('./configParser'),
99
TaskScheduler = require('./taskScheduler'),
10-
helper = require('./util');
10+
helper = require('./util'),
11+
q = require('q');
1112

1213
var launcherPrefix = '[launcher]';
1314
var RUNNERS_FAILED_EXIT_CODE = 100;
@@ -133,13 +134,23 @@ var init = function(configFile, additionalConfig) {
133134
};
134135

135136
var cleanUpAndExit = function(exitCode) {
136-
helper.runFilenameOrFn_(config.configDir, config.afterLaunch, [exitCode]);
137-
process.exit(exitCode);
137+
return helper.runFilenameOrFn_(
138+
config.configDir, config.afterLaunch, [exitCode]).
139+
then(function(returned) {
140+
if (typeof returned === 'number') {
141+
process.exit(returned);
142+
} else {
143+
process.exit(exitCode);
144+
}
145+
}, function(err) {
146+
log_('Error:', err);
147+
process.exit(1);
148+
});
138149
};
139150

140151
helper.runFilenameOrFn_(config.configDir, config.beforeLaunch).then(function() {
141152
// Don't start new process if there is only 1 task.
142-
var totalTasks = scheduler.numTasksRemaining();
153+
var totalTasks = scheduler.numTasksOutstanding();
143154
if (totalTasks === 1) {
144155
var Runner = require('./runner');
145156
var task = scheduler.nextTask();
@@ -158,13 +169,17 @@ var init = function(configFile, additionalConfig) {
158169
throw new Error('Cannot run in debug mode with ' +
159170
'multiCapabilities, count > 1, or sharding');
160171
}
172+
var deferred = q.defer();
161173
for (var i = 0; i < scheduler.maxConcurrentTasks(); ++i) {
162174
var createNextRunnerFork = function() {
163175
var task = scheduler.nextTask();
164176
if (task) {
165177
var done = function() {
166178
task.done();
167179
createNextRunnerFork();
180+
if (scheduler.numTasksOutstanding() === 0) {
181+
deferred.fulfill();
182+
}
168183
};
169184
var runnerFork = new RunnerFork(task);
170185
runnerFork.addEventHandlers(done);
@@ -175,21 +190,26 @@ var init = function(configFile, additionalConfig) {
175190
}
176191
log_('Running ' + scheduler.countActiveTasks() + ' instances of WebDriver');
177192

193+
deferred.promise.then(function() {
194+
reporter.reportSummary();
195+
var exitCode = 0;
196+
if (runnerErrorCount > 0) {
197+
exitCode = RUNNERS_FAILED_EXIT_CODE;
198+
}
199+
return cleanUpAndExit(exitCode);
200+
});
201+
178202
process.on('exit', function(code) {
179-
if (code) {
203+
204+
if (code && code != RUNNERS_FAILED_EXIT_CODE) {
180205
log_('Process exited with error code ' + code);
181-
cleanUpAndExit(code);
182-
} else if (runnerErrorCount > 0) {
183-
reporter.reportSummary();
184-
cleanUpAndExit(RUNNERS_FAILED_EXIT_CODE);
185-
} else {
186-
if (scheduler.numTasksRemaining() > 0) {
187-
throw new Error('BUG: launcher exited with ' +
188-
scheduler.numTasksRemaining() + ' tasks remaining');
189-
}
190-
reporter.reportSummary();
191-
cleanUpAndExit(0);
206+
} else if (!code &&
207+
scheduler.numTasksOutstanding() > 0) {
208+
code = 1;
209+
log_('BUG: launcher exited with ' +
210+
scheduler.numTasksOutstanding() + ' tasks remaining');
192211
}
212+
process.exit(code);
193213
});
194214
}
195215
}).done();

Diff for: lib/runner.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,15 @@ Runner.prototype.loadDriverProvider_ = function() {
107107
* @param {int} Standard unix exit code
108108
*/
109109
Runner.prototype.exit_ = function(exitCode) {
110-
helper.runFilenameOrFn_(this.config_.configDir, this.config_.onCleanUp, [exitCode]).
111-
then(function(returned) {
112-
if (typeof returned === 'number') {
113-
return returned;
114-
} else {
115-
return exitCode;
116-
}
117-
});
110+
return helper.runFilenameOrFn_(
111+
this.config_.configDir, this.config_.onCleanUp, [exitCode]).
112+
then(function(returned) {
113+
if (typeof returned === 'number') {
114+
return returned;
115+
} else {
116+
return exitCode;
117+
}
118+
});
118119
};
119120

120121

Diff for: lib/taskScheduler.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ TaskScheduler.prototype.nextTask = function() {
130130
};
131131

132132
/**
133-
* Get the number of tasks left to run.
133+
* Get the number of tasks left to run or are currently running.
134134
*
135135
* @return {number}
136136
*/
137-
TaskScheduler.prototype.numTasksRemaining = function() {
137+
TaskScheduler.prototype.numTasksOutstanding = function() {
138138
var count = 0;
139139
this.taskQueues.forEach(function(queue) {
140-
count += (queue.specLists.length - queue.specsIndex);
140+
count += queue.numRunningInstances + (queue.specLists.length - queue.specsIndex);
141141
});
142142
return count;
143143
};

Diff for: spec/unit/taskScheduler_test.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ describe('the task scheduler', function() {
2020
expect(task.capability.browserName).toEqual('chrome');
2121
expect(task.specs.length).toEqual(2);
2222

23-
expect(scheduler.numTasksRemaining()).toEqual(0);
23+
task.done();
24+
expect(scheduler.numTasksOutstanding()).toEqual(0);
2425
});
2526

2627
it('should schedule single capability tests with sharding', function() {
@@ -46,7 +47,9 @@ describe('the task scheduler', function() {
4647
expect(task2.capability.browserName).toEqual('chrome');
4748
expect(task2.specs.length).toEqual(1);
4849

49-
expect(scheduler.numTasksRemaining()).toEqual(0);
50+
task1.done();
51+
task2.done();
52+
expect(scheduler.numTasksOutstanding()).toEqual(0);
5053
});
5154

5255
it('should schedule single capability tests with count', function() {
@@ -71,7 +74,9 @@ describe('the task scheduler', function() {
7174
expect(task2.capability.browserName).toEqual('chrome');
7275
expect(task2.specs.length).toEqual(2);
7376

74-
expect(scheduler.numTasksRemaining()).toEqual(0);
77+
task1.done();
78+
task2.done();
79+
expect(scheduler.numTasksOutstanding()).toEqual(0);
7580
});
7681

7782
it('should schedule multiCapabilities tests', function() {
@@ -97,7 +102,9 @@ describe('the task scheduler', function() {
97102
expect(task2.capability.browserName).toEqual('firefox');
98103
expect(task2.specs.length).toEqual(2);
99104

100-
expect(scheduler.numTasksRemaining()).toEqual(0);
105+
task1.done();
106+
task2.done();
107+
expect(scheduler.numTasksOutstanding()).toEqual(0);
101108
});
102109

103110
it('should obey maxInstances', function() {
@@ -121,14 +128,16 @@ describe('the task scheduler', function() {
121128

122129
var task2 = scheduler.nextTask();
123130
expect(task2).toBeNull();
124-
expect(scheduler.numTasksRemaining()).toEqual(1);
125-
131+
126132
task1.done();
133+
expect(scheduler.numTasksOutstanding()).toEqual(1);
134+
127135
var task3 = scheduler.nextTask();
128136
expect(task3.capability.browserName).toEqual('chrome');
129137
expect(task3.specs.length).toEqual(1);
130138

131-
expect(scheduler.numTasksRemaining()).toEqual(0);
139+
task3.done();
140+
expect(scheduler.numTasksOutstanding()).toEqual(0);
132141
});
133142

134143
it('should allow capability-specific specs', function() {
@@ -149,7 +158,8 @@ describe('the task scheduler', function() {
149158
expect(task.capability.browserName).toEqual('chrome');
150159
expect(task.specs.length).toEqual(3);
151160

152-
expect(scheduler.numTasksRemaining()).toEqual(0);
161+
task.done();
162+
expect(scheduler.numTasksOutstanding()).toEqual(0);
153163
});
154164

155165
it('should handle multiCapabilities with mixture of features', function() {
@@ -202,7 +212,7 @@ describe('the task scheduler', function() {
202212
expect(task6.specs.length).toEqual(1);
203213
task6.done();
204214

205-
expect(scheduler.numTasksRemaining()).toEqual(0);
215+
expect(scheduler.numTasksOutstanding()).toEqual(0);
206216
});
207217

208218
it('should default to chrome when no capability is defined', function() {
@@ -219,7 +229,8 @@ describe('the task scheduler', function() {
219229
expect(task.capability.browserName).toEqual('chrome');
220230
expect(task.specs.length).toEqual(2);
221231

222-
expect(scheduler.numTasksRemaining()).toEqual(0);
232+
task.done();
233+
expect(scheduler.numTasksOutstanding()).toEqual(0);
223234
});
224235

225236
it('should exclude capability-specific specs', function() {
@@ -240,7 +251,8 @@ describe('the task scheduler', function() {
240251
expect(task.capability.browserName).toEqual('chrome');
241252
expect(task.specs.length).toEqual(1);
242253

243-
expect(scheduler.numTasksRemaining()).toEqual(0);
254+
task.done();
255+
expect(scheduler.numTasksOutstanding()).toEqual(0);
244256
});
245257

246258
});

0 commit comments

Comments
 (0)