Improve rtcbot to load all test files at start and allow them to registerTests

via: registerBotTest. After loading all tests main.js starts running the
requested one on the command arguments.

R=houssainy@google.com

Review URL: https://webrtc-codereview.appspot.com/29779004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7461 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
andresp@webrtc.org 2014-10-16 07:36:37 +00:00
parent 9aed002090
commit 458c2c3b06
6 changed files with 139 additions and 58 deletions

View File

@ -17,7 +17,10 @@ access its exposed API. Details are in botmanager.js.
== How to run the test ==
$ cd trunk/webrtc/tool/rtcbot
$ npm install express browserify ws websocket-stream dnode
$ node test.js <test_file_path>
$ node main.js "<test_name>"
== How can I see the list of available tests? ==
$ node main.js
== Example on how to install nodejs ==
$ cd /work/tools/
@ -30,7 +33,7 @@ access its exposed API. Details are in botmanager.js.
- "chrome": chrome on host machine.
- "android-chrome": chrome on android device. Details in "Android" Section.
* Bot type is specified for each spawned bot in the test file.
* Bot type is specified directly by the test.
== Android ==
Before running test with Android one MUST forward the device port 8080 to the

102
webrtc/tools/rtcbot/main.js Normal file
View File

@ -0,0 +1,102 @@
// Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// This script loads all the test/* files into a very small context that
// only exposes a minimal set of functions that allows to register tests.
//
// Once all files are loaded it runs the specific test on the command line.
// If no arguments are given it lists all the registered tests.
//
// Note: the small context where the scripts are loaded is intended to keep
// nodejs-isms away from the test code and isolate implementation details away
// from them.
var fs = require('fs');
var vm = require('vm');
var Test = require('./test.js');
var testSuites = {};
function registerTest(name, func) {
testSuites[name] = func;
}
function registerBotTest(name, func, bots) {
registerTest(name, bootstrap);
function bootstrap(test) {
var callbacks = [];
for (var i = 0; i != bots.length; ++i)
callbacks.push(test.spawnBot.bind(test, "", bots[i]));
test.wait(callbacks, func.bind(test, test));
}
}
function loadTestFile(filename, doneCallback) {
var loadTestContext = {
setTimeout: setTimeout,
registerTest: registerTest,
registerBotTest: registerBotTest
};
var script = vm.createScript(fs.readFileSync(filename), filename);
script.runInNewContext(loadTestContext);
doneCallback();
}
function iterateOverTestFiles(foreachCallback, doneCallback) {
fs.readdir('test', function (error, list) {
function iterateNextFile() {
if (list.length === 0) {
doneCallback();
} else {
var filename = list.pop();
if (filename[0] === '.' || filename.slice(-3) !== '.js') {
// Skip hidden and non .js files on that directory.
iterateNextFile();
} else {
foreachCallback('test/' + filename, iterateNextFile);
}
}
}
if (error !== null) {
throw error;
}
iterateNextFile();
});
}
function runTest(testname) {
if (testname in testSuites) {
console.log("Running test: " + testname);
var test = new Test();
testSuites[testname](test);
} else {
console.log("Unknown test: " + testname);
}
}
function printUsage() {
console.log('Run as:\n $ '
+ process.argv[0] + ' ' + process.argv[1]
+ ' <testname>');
console.log('These are the existent ones:');
for (var testname in testSuites)
console.log(' ' + testname);
}
function main() {
// TODO(andresp): support multiple tests.
var testList = process.argv.slice(2);
if (testList.length === 1)
runTest(testList[0]);
else
printUsage();
}
iterateOverTestFiles(loadTestFile, main);

View File

@ -6,14 +6,9 @@
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
// This script loads the test file in the virtual machine and runs it in a
// context that only exposes a test variable with methods for testing and to
// spawn bots.
//
// Note: an important part of this script is to keep nodejs-isms away from test
// code and isolate it from implementation details.
// Provides a Test class that exposes api to the tests.
// Read test.prototype to see what methods are exposed.
var fs = require('fs');
var vm = require('vm');
var BotManager = require('./botmanager.js');
function Test() {
@ -134,13 +129,6 @@ StatisticsReport.prototype = {
doneCallback);
}
},
}
};
function runTest(testfile) {
console.log("Running test: " + testfile);
var script = vm.createScript(fs.readFileSync(testfile), testfile);
script.runInNewContext({ test: new Test(), setInterval: setInterval,
setTimeout: setTimeout });
}
runTest(process.argv[2]);
module.exports = Test;

View File

@ -6,8 +6,9 @@
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
//
function testPingPong(bot) {
test.log('bot:alice > Sending Ping to bot');
function testPingPong(test, bot) {
test.assert(typeof bot.ping === 'function', 'Bot does not exposes ping.');
bot.ping(gotAnswer);
function gotAnswer(answer) {
@ -16,4 +17,4 @@ function testPingPong(bot) {
}
}
test.spawnBot("alice", "chrome", testPingPong);
registerBotTest('testPingPong/chrome', testPingPong, ['chrome']);

View File

@ -10,17 +10,12 @@
//
// Note: This test does not performs ice candidate exchange and
// does not verifies that media can flow between the peers.
function testOfferAnswer(peer1, peer2) {
test.wait([
createPeerConnection.bind(peer1),
createPeerConnection.bind(peer2) ],
establishCall);
function testOfferAnswer(test, bot1, bot2) {
test.wait( [ bot1.createPeerConnection.bind(bot1, null),
bot2.createPeerConnection.bind(bot2, null) ],
run);
function createPeerConnection(done) {
this.createPeerConnection(null, done, test.fail);
}
function establishCall(pc1, pc2) {
function run(pc1, pc2) {
test.log("Establishing call.");
pc1.createOffer(gotOffer);
@ -38,17 +33,16 @@ function testOfferAnswer(peer1, peer2) {
pc2.setLocalDescription(answer, expectedCall, test.fail);
pc1.setRemoteDescription(answer, expectedCall, test.fail);
}
// TODO(andresp): Implement utilities in test to write expectations
// that certain methods must be called.
var expectedCalls = 0;
function expectedCall() {
if (++expectedCalls == 6)
test.done();
}
}
}
// TODO(andresp): Implement utilities in test to write expectations that certain
// methods must be called.
var expectedCalls = 0;
function expectedCall() {
if (++expectedCalls == 6)
test.done();
}
test.wait( [ test.spawnBot.bind(test, "alice", "chrome"),
test.spawnBot.bind(test, "bob", "chrome") ],
testOfferAnswer);
registerBotTest('testOfferAnswer/chrome=>chrome',
testOfferAnswer, ['chrome', 'chrome']);

View File

@ -11,11 +11,7 @@
// and then write these stats to a file.
//
// Note: the source of the video and audio stream is getUserMedia().
//
function testVideoStreaming(bot1, bot2) {
var pc1 = null;
var pc2 = null;
function testOneWayVideo(test, bot1, bot2) {
var report = test.createStatisticsReport("webrtc_video_streaming");
test.wait([
@ -29,10 +25,8 @@ function testVideoStreaming(bot1, bot2) {
}.bind(this), test.fail);
}
function onPeerConnectionCreated(peer1, peer2) {
function onPeerConnectionCreated(pc1, pc2) {
test.log("RTC Peers created.");
pc1 = peer1;
pc2 = peer2;
pc1.addEventListener('addstream', test.fail);
pc2.addEventListener('addstream', onAddStream);
pc1.addEventListener('icecandidate', onIceCandidate.bind(pc2));
@ -45,7 +39,7 @@ function testVideoStreaming(bot1, bot2) {
pc1.addStream(stream);
bot1.showStream(stream.id, true, true);
createOfferAndAnswer();
createOfferAndAnswer(pc1, pc2);
}
}
@ -55,18 +49,18 @@ function testVideoStreaming(bot1, bot2) {
}
function onIceCandidate(event) {
if(event.candidate){
if(event.candidate) {
test.log(event.candidate.candidate);
this.addIceCandidate(event.candidate,
onAddIceCandidateSuccess, test.fail);
};
}
function onAddIceCandidateSuccess() {
test.log("Candidate added successfully");
};
}
}
function createOfferAndAnswer() {
function createOfferAndAnswer(pc1, pc2) {
test.log("Creating offer.");
pc1.createOffer(gotOffer, test.fail);
@ -103,6 +97,5 @@ function testVideoStreaming(bot1, bot2) {
}
}
test.wait( [ test.spawnBot.bind(test, "alice", "chrome"),
test.spawnBot.bind(test, "bob", "android-chrome") ],
testVideoStreaming);
registerBotTest('testOneWayVideo/chrome=>chrome',
testOneWayVideo, ['chrome', 'chrome']);