Skip to content

Commit 09d3d3a

Browse files
committed
added batch command to run multiple wpt commands
1 parent 1d9d43c commit 09d3d3a

6 files changed

Lines changed: 136 additions & 22 deletions

File tree

bin/webpagetest

Lines changed: 121 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,28 @@ var program = require('commander'),
1010
WebPageTest = require('../lib/webpagetest'),
1111
mapping = require('../lib/mapping');
1212

13-
var command, wpt, file, ret,
13+
var command, file, ret,
1414
options = {},
1515
args = [],
16+
results = [],
1617
defaultServer = process.env.WEBPAGETEST_SERVER ||
1718
WebPageTest.defaultServer;
1819

1920
// replace default values on descriptons
2021
mapping.commands.listen.info =
2122
mapping.commands.listen.info.replace('%s', WebPageTest.defaultListenPort);
2223

23-
function output(data, exitStatus, preExit) {
24-
if (exitStatus) {
25-
process.stderr.write(data);
26-
} else {
27-
process.stdout.write(data);
28-
}
24+
var output = function(data, exitStatus, preExit) {
25+
process.stdout.write(data);
2926
if (typeof preExit === 'function') {
3027
preExit();
3128
}
3229
process.exit(exitStatus || 0);
33-
}
30+
};
3431

35-
var formatData = function (err, data, info) {
36-
var encoding = 'utf8';
32+
var formatData = function(err, data, info) {
33+
var dataStr,
34+
encoding = 'utf8';
3735

3836
if (err) {
3937
data = {error: err};
@@ -49,24 +47,26 @@ var formatData = function (err, data, info) {
4947

5048
if (!(data instanceof Buffer)) {
5149
try {
52-
data = JSON.stringify(data, null, 2);
50+
dataStr = JSON.stringify(data, null, 2);
5351
} catch (ex) {
54-
data = JSON.stringify({
52+
dataStr = JSON.stringify({
5553
data: data.toString(),
5654
error: ex.message
5755
}, null, 2);
5856
}
5957
}
6058

6159
if (file) {
62-
fs.writeFile(file, data, encoding, function writeFile(err) {
60+
fs.writeFile(file, dataStr, encoding, function writeFile(err) {
6361
if (err) {
6462
output(err.message, 1);
6563
}
6664
});
6765
} else {
68-
output(data, err ? 1 : 0);
66+
output(dataStr, err ? 1 : 0);
6967
}
68+
69+
return data;
7070
}
7171

7272
function addOptions(prg, options, nokeyList) {
@@ -135,13 +135,13 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
135135
}
136136

137137
defaultAction(decodeURIComponent(what), opts);
138-
if (options.specs) {
138+
if (options.specs && !program.batch) {
139139
options.exitOnResults = true;
140140
}
141141
},
142142
'results': function(id, opts) {
143143
defaultAction(id, opts);
144-
if (opts.specs && !program.dryrun) {
144+
if (opts.specs && !program.dryrun && !program.batch) {
145145
formatData = null;
146146
}
147147
},
@@ -158,7 +158,7 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
158158
}
159159
};
160160

161-
// command with (optional) parameter
161+
// command with (optional) parameter
162162
if (cmd.param) {
163163
if (cmd.optional) {
164164
openParam = '[';
@@ -179,10 +179,98 @@ Object.keys(mapping.commands).forEach(function eachCommand(name) {
179179
);
180180
});
181181

182-
program.parse(process.argv);
182+
function parseBatch(filename) {
183+
var lines;
183184

184-
if (command) {
185-
wpt = new WebPageTest(program.server || defaultServer);
185+
try {
186+
lines = (fs.readFileSync(filename, 'utf8') || '')
187+
.split('\n')
188+
.filter(function(line) {return line;})
189+
.map(function(line) {return line.split(' ');})
190+
.map(function(line) {
191+
var tmp = [];
192+
return line.reduce(function(prev, curr, index) {
193+
if (/^[^\\]?['"]/.test(curr)) {
194+
tmp.push(curr.slice(1));
195+
} else if (tmp.length) {
196+
if (/[^\\]['"]$/.test(curr)) {
197+
tmp.push(curr.slice(0, curr.length - 1));
198+
prev.push(tmp.join(' '));
199+
tmp = [];
200+
} else {
201+
tmp.push(curr);
202+
}
203+
} else {
204+
prev.push(curr);
205+
}
206+
return prev;
207+
}, ['', '']);
208+
});
209+
} catch (err) {
210+
output(err.message + '\n', 1);
211+
}
212+
213+
return lines;
214+
}
215+
//return console.log(parseBatch('batch.txt'));
216+
217+
function batch(file) {
218+
var accErr,
219+
count = 2,
220+
originalFormatData = formatData,
221+
originalOutput = output;
222+
223+
function checkDone() {
224+
count--;
225+
if (!count) {
226+
originalOutput(
227+
results.length ? JSON.stringify(results, null, 2) : '',
228+
accErr ? 1 : 0
229+
);
230+
}
231+
};
232+
233+
function checkError(err) {
234+
accErr = accErr || err;
235+
checkDone();
236+
}
237+
238+
function aggregate(index, err, data, info) {
239+
results[index] = originalFormatData(err, data, info);
240+
checkError(err);
241+
}
242+
243+
program.batch = true;
244+
var cmds = parseBatch(file);
245+
if (!cmds) {
246+
return;
247+
}
248+
output = function(){};
249+
250+
cmds.forEach(function(cmd, index) {
251+
program.parse(cmd);
252+
formatData = options.specs ? checkError : aggregate.bind(null, index);
253+
execCommand();
254+
cleanupProgram();
255+
});
256+
}
257+
258+
function cleanupProgram() {
259+
command = null;
260+
options = {};
261+
args = [];
262+
program.commands.forEach(function(c) {
263+
c.options.forEach(function(o) {
264+
delete c[o.long.slice(2)];
265+
});
266+
});
267+
delete program.server;
268+
delete program.dryrun;
269+
delete program.out;
270+
}
271+
272+
function execCommand() {
273+
var wpt = new WebPageTest(program.server || defaultServer);
186274

187275
// options
188276
if (options) {
@@ -198,7 +286,19 @@ if (command) {
198286
file = program.out;
199287

200288
wpt[command].apply(wpt, args);
201-
} else {
289+
}
290+
291+
program
292+
.command('batch <file>')
293+
.description(
294+
'run commands in batch, i.e. one command per line from <file> in parallel')
295+
.action(batch);
296+
297+
program.parse(process.argv);
298+
299+
if (command) {
300+
execCommand();
301+
} else if (!program.batch) {
202302
output(program.helpInformation(), 1, function defaultHelp() {
203303
program.emit('--help');
204304
});

lib/webpagetest.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ function runTest(what, options, callback) {
291291

292292
function testCallback(cb, err, data) {
293293
if (err || !(data && data.data && data.data.testId)) {
294-
callback(err || data);
294+
return callback(err || data);
295295
}
296296

297297
testId = data.data.testId;

test/command-line-test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,14 @@ describe('WebPageTest Command Line', function() {
283283
});
284284
});
285285

286+
it('gets a batch input returns the batch commands output in order', function(done) {
287+
exec(mock('batch ' + path.join(__dirname, 'fixtures/batch.txt')), function(err, data) {
288+
if (err) return done(err);
289+
data = JSON.parse(data);
290+
assert.equal(data[0].url, wptServer + 'testStatus.php?test=120816_V2_2');
291+
assert.equal(data[1].url, wptServer + 'xmlResult.php?test=120816_V2_2');
292+
done();
293+
});
294+
});
295+
286296
});

test/fixtures/batch.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
status 120816_V2_2 -s https://www.example.com:1234/foo/bar/ -d
2+
results 120816_V2_2 -s https://www.example.com:1234/foo/bar/ -d

test/fixtures/command-line/help-test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
-C, --spdy3 force SPDY version 3 (Chrome only)
4848
-J, --swrender force software rendering, disable GPU acceleration (Chrome only)
4949
-Q, --noparser disable threaded HTML parser (Chrome only)
50+
-q, --spdynossl use SPDY without SSL (Chrome only)
5051
--poll [interval] poll for results after test is scheduled at every <interval> seconds [5]
5152
--wait [hostname:port] wait for test results informed by agent once complete listening on <hostname>:<port> [hostname:first port available above 8000]
5253
--timeout <seconds> timeout for polling and waiting results [no timeout]

test/fixtures/command-line/help.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
waterfall [options] <id> get the waterfall PNG image
2121
screenshot [options] <id> get the fully loaded page screenshot in JPG format (PNG if in full resolution)
2222
listen [hostname:port] start webpagetest-api server on <hostname>:<port> [hostname:7791]
23+
batch <file> run commands in batch, i.e. one command per line from <file> in parallel
2324

2425
Options:
2526

0 commit comments

Comments
 (0)