Remove rtcbot.
Bug: None Change-Id: I8bd33860356613f3f342a52bbd28183f6f0b1b08 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/146717 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#28888}
This commit is contained in:
committed by
Commit Bot
parent
6b430867b8
commit
637f110667
@ -1 +0,0 @@
|
|||||||
andresp@webrtc.org
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
=== RTCBot ===
|
|
||||||
RTCBot is a framework to write tests that need to spawn multiple webrtc
|
|
||||||
endpoints.
|
|
||||||
|
|
||||||
== Description ==
|
|
||||||
RTCBot is a framework that allows to write tests where logic runs on a single
|
|
||||||
host that controls multiple endpoints ("bots"). It allows creating complex
|
|
||||||
scenarios that would otherwise require non-trival signalling between multiple
|
|
||||||
parties.
|
|
||||||
|
|
||||||
The host runs in node.js, but the test code is run in an isolated context with
|
|
||||||
no access to node.js specifics other than the exposed api via a test variable.
|
|
||||||
|
|
||||||
Part of the exposed api (test.spawnBot) allows a test to spawn a bot and
|
|
||||||
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
|
|
||||||
$ mkdir configurations
|
|
||||||
$ cd configurations
|
|
||||||
$ openssl genrsa -out priv.pem 1024
|
|
||||||
$ openssl req -x509 -new -key priv.pem -days 3650 -out cert.crt
|
|
||||||
$ cd trunk/webrtc/tool/rtcbot
|
|
||||||
$ node main.js "<test_name>"
|
|
||||||
|
|
||||||
* Note:
|
|
||||||
In first time you will use rtcBot you will receive a warning telling
|
|
||||||
you that your connection is not private. Just avoid this warning and
|
|
||||||
click Proceed to localhost (unsafe).
|
|
||||||
|
|
||||||
== How can I see the list of available tests? ==
|
|
||||||
$ node main.js
|
|
||||||
|
|
||||||
== Example on how to install nodejs ==
|
|
||||||
$ cd /work/tools/
|
|
||||||
$ git clone https://github.com/creationix/nvm.git
|
|
||||||
$ export NVM_DIR=/work/tools/nvm; source $NVM_DIR/nvm.sh
|
|
||||||
$ nvm install 0.10
|
|
||||||
$ nvm use 0.10
|
|
||||||
|
|
||||||
== Why generating the private key and self signed certificate? ==
|
|
||||||
- Private key and certificate are used for creating HTTPs server in
|
|
||||||
rtcBot for loading the required files on the different types of the bots.
|
|
||||||
|
|
||||||
== Supported Bot Types ==
|
|
||||||
- "chrome": chrome on host machine.
|
|
||||||
- "android-chrome": chrome on android device. Details in "Android" Section.
|
|
||||||
|
|
||||||
* Bot type is specified directly by the test.
|
|
||||||
|
|
||||||
== Android ==
|
|
||||||
Before running test with Android one MUST forward the device port 8080 to the
|
|
||||||
host machine. That is easy to achieve with chrome port forwarding tools.
|
|
||||||
- Visit chrome://inspect/devices on the host machine.
|
|
||||||
- Configure and enable port forwarding 8080 -> localhost:8080
|
|
||||||
- Open chrome on you Android device before running test, and leave it
|
|
||||||
running until the end of test.
|
|
||||||
- Run your test.
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
// 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 file exposes the api for the bot to connect to the host script
|
|
||||||
// waiting a websocket connection and using dnode for javascript rpc.
|
|
||||||
//
|
|
||||||
// This file is served to the browser via browserify to resolve the
|
|
||||||
// dnode requires.
|
|
||||||
var WebSocketStream = require('websocket-stream');
|
|
||||||
var Dnode = require('dnode');
|
|
||||||
|
|
||||||
function connectToServer(api) {
|
|
||||||
var stream = new WebSocketStream("wss://localhost:8080/");
|
|
||||||
var dnode = new Dnode(api);
|
|
||||||
dnode.on('error', function (error) { console.log(error); });
|
|
||||||
dnode.pipe(stream).pipe(dnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dnode loses certain method calls when exposing native browser objects such as
|
|
||||||
// peer connections. This methods helps work around that by allowing one to
|
|
||||||
// redefine a non-native method in a target "obj" from "src" that applies a list
|
|
||||||
// of casts to the arguments (types are lost in dnode).
|
|
||||||
function expose(obj, src, method, casts) {
|
|
||||||
obj[method] = function () {
|
|
||||||
for (index in casts)
|
|
||||||
arguments[index] = new (casts[index])(arguments[index]);
|
|
||||||
src[method].apply(src, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.expose = expose;
|
|
||||||
window.connectToServer = connectToServer;
|
|
||||||
@ -1,140 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
var localStreams = [];
|
|
||||||
var remoteStreams = [];
|
|
||||||
|
|
||||||
function ping(callback) {
|
|
||||||
callback("pong");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserMedia(constraints, onSuccessCallback, onFailCallback){
|
|
||||||
console.log("Getting user media.");
|
|
||||||
navigator.webkitGetUserMedia(constraints,
|
|
||||||
onSuccessCallbackWraper, onFailCallback);
|
|
||||||
|
|
||||||
function onSuccessCallbackWraper(stream) {
|
|
||||||
console.log("GetUserMedia success.");
|
|
||||||
localStreams[stream.id] = stream;
|
|
||||||
onSuccessCallback(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPeerConnection(config, doneCallback, failCallback) {
|
|
||||||
console.log("Creating peer connection");
|
|
||||||
var obj = {};
|
|
||||||
var pc = new webkitRTCPeerConnection(config);
|
|
||||||
|
|
||||||
expose(obj, pc, "close");
|
|
||||||
expose(obj, pc, "createOffer");
|
|
||||||
expose(obj, pc, "createAnswer");
|
|
||||||
expose(obj, pc, "addEventListener");
|
|
||||||
expose(obj, pc, "addIceCandidate", { 0: RTCIceCandidate});
|
|
||||||
expose(obj, pc, "setRemoteDescription", { 0: RTCSessionDescription });
|
|
||||||
expose(obj, pc, "setLocalDescription", { 0: RTCSessionDescription });
|
|
||||||
|
|
||||||
obj.addStream = function(stream) {
|
|
||||||
console.log("Adding local stream.");
|
|
||||||
var tempStream = localStreams[stream.id];
|
|
||||||
if (!tempStream) {
|
|
||||||
console.log("Undefined stream!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pc.addStream(tempStream);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return an array of Objects, each Object is a copy of RTCStateReport
|
|
||||||
// and has the following attributes (id, type, names, and stats).
|
|
||||||
// names: array originaly returned by calling RTCStateReport.names().
|
|
||||||
// stats: dictionary of stat name as key and stat value as dictionary
|
|
||||||
// value.
|
|
||||||
obj.getStats = function(callback, mediaTrack) {
|
|
||||||
pc.getStats(onStatsReady, mediaTrack);
|
|
||||||
|
|
||||||
function onStatsReady(stateResponse) {
|
|
||||||
var outputReports = [];
|
|
||||||
var reports = stateResponse.result();
|
|
||||||
for (index in reports) {
|
|
||||||
var report = {};
|
|
||||||
report.id = reports[index].id;
|
|
||||||
report.type = reports[index].type;
|
|
||||||
report.names = reports[index].names();
|
|
||||||
report.stats = [];
|
|
||||||
populateStats(reports[index], report.stats);
|
|
||||||
|
|
||||||
outputReports.push(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(outputReports);
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateStats(report, stats) {
|
|
||||||
var names = report.names();
|
|
||||||
for (index in names) {
|
|
||||||
stats.push({
|
|
||||||
name: names[index],
|
|
||||||
stat: report.stat(names[index]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pc.addEventListener('addstream', function(event) {
|
|
||||||
remoteStreams[event.stream.id] = event.stream;
|
|
||||||
});
|
|
||||||
|
|
||||||
doneCallback(obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
function showStream(streamId, autoplay, muted) {
|
|
||||||
var stream = getStreamFromIdentifier_(streamId);
|
|
||||||
var video = document.createElement('video');
|
|
||||||
video.autoplay = autoplay;
|
|
||||||
video.muted = muted;
|
|
||||||
document.body.appendChild(video);
|
|
||||||
video.src = URL.createObjectURL(stream);
|
|
||||||
console.log("Stream " + stream.id + " attached to video element");
|
|
||||||
};
|
|
||||||
|
|
||||||
function getStreamFromIdentifier_(id) {
|
|
||||||
var tempStream = localStreams[id];
|
|
||||||
if (tempStream)
|
|
||||||
return tempStream;
|
|
||||||
tempStream = remoteStreams[id];
|
|
||||||
if (tempStream)
|
|
||||||
return tempStream;
|
|
||||||
console.log(id + " is not id for stream.");
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
function downloadFile(path, onSuccess, onError) {
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
function onResult() {
|
|
||||||
if (xhr.readyState != 4)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (xhr.status != 200) {
|
|
||||||
onError("Download request failed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onSuccess(xhr.responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
xhr.onreadystatechange = onResult;
|
|
||||||
xhr.open('GET', path, true);
|
|
||||||
xhr.send();
|
|
||||||
};
|
|
||||||
|
|
||||||
connectToServer({
|
|
||||||
ping: ping,
|
|
||||||
getUserMedia: getUserMedia,
|
|
||||||
createPeerConnection: createPeerConnection,
|
|
||||||
showStream: showStream,
|
|
||||||
downloadFile: downloadFile,
|
|
||||||
});
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
<!--
|
|
||||||
// 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.
|
|
||||||
-->
|
|
||||||
<script src="../api.js"></script>
|
|
||||||
<script src="bot.js"></script>
|
|
||||||
@ -1,216 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// botmanager.js module allows a test to spawn bots that expose an RPC API
|
|
||||||
// to be controlled by tests.
|
|
||||||
var https = require('https');
|
|
||||||
var fs = require('fs');
|
|
||||||
var child = require('child_process');
|
|
||||||
var Browserify = require('browserify');
|
|
||||||
var Dnode = require('dnode');
|
|
||||||
var Express = require('express');
|
|
||||||
var WebSocketServer = require('ws').Server;
|
|
||||||
var WebSocketStream = require('websocket-stream');
|
|
||||||
|
|
||||||
// BotManager runs a HttpsServer that serves bots assets and and WebSocketServer
|
|
||||||
// that listens to incoming connections. Once a connection is available it
|
|
||||||
// connects it to bots pending endpoints.
|
|
||||||
//
|
|
||||||
// TODO(andresp): There should be a way to control which bot was spawned
|
|
||||||
// and what bot instance it gets connected to.
|
|
||||||
BotManager = function () {
|
|
||||||
this.webSocketServer_ = null;
|
|
||||||
this.bots_ = [];
|
|
||||||
this.pendingConnections_ = [];
|
|
||||||
this.androidDeviceManager_ = new AndroidDeviceManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
BotManager.BotTypes = {
|
|
||||||
CHROME : 'chrome',
|
|
||||||
ANDROID_CHROME : 'android-chrome',
|
|
||||||
};
|
|
||||||
|
|
||||||
BotManager.prototype = {
|
|
||||||
createBot_: function (name, botType, callback) {
|
|
||||||
switch(botType) {
|
|
||||||
case BotManager.BotTypes.CHROME:
|
|
||||||
return new BrowserBot(name, callback);
|
|
||||||
case BotManager.BotTypes.ANDROID_CHROME:
|
|
||||||
return new AndroidChromeBot(name, this.androidDeviceManager_,
|
|
||||||
callback);
|
|
||||||
default:
|
|
||||||
console.log('Error: Type ' + botType + ' not supported by rtc-Bot!');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
spawnNewBot: function (name, botType, callback) {
|
|
||||||
this.startWebSocketServer_();
|
|
||||||
var bot = this.createBot_(name, botType, callback);
|
|
||||||
this.bots_.push(bot);
|
|
||||||
this.pendingConnections_.push(bot.onBotConnected.bind(bot));
|
|
||||||
},
|
|
||||||
|
|
||||||
startWebSocketServer_: function () {
|
|
||||||
if (this.webSocketServer_) return;
|
|
||||||
|
|
||||||
this.app_ = new Express();
|
|
||||||
|
|
||||||
this.app_.use('/bot/api.js',
|
|
||||||
this.serveBrowserifyFile_.bind(this,
|
|
||||||
__dirname + '/bot/api.js'));
|
|
||||||
|
|
||||||
this.app_.use('/bot/', Express.static(__dirname + '/bot'));
|
|
||||||
|
|
||||||
var options = options = {
|
|
||||||
key: fs.readFileSync('configurations/priv.pem', 'utf8'),
|
|
||||||
cert: fs.readFileSync('configurations/cert.crt', 'utf8')
|
|
||||||
};
|
|
||||||
this.server_ = https.createServer(options, this.app_);
|
|
||||||
|
|
||||||
this.webSocketServer_ = new WebSocketServer({ server: this.server_ });
|
|
||||||
this.webSocketServer_.on('connection', this.onConnection_.bind(this));
|
|
||||||
|
|
||||||
this.server_.listen(8080);
|
|
||||||
},
|
|
||||||
|
|
||||||
onConnection_: function (ws) {
|
|
||||||
var callback = this.pendingConnections_.shift();
|
|
||||||
callback(new WebSocketStream(ws));
|
|
||||||
},
|
|
||||||
|
|
||||||
serveBrowserifyFile_: function (file, request, result) {
|
|
||||||
// TODO(andresp): Cache browserify result for future serves.
|
|
||||||
var browserify = new Browserify();
|
|
||||||
browserify.add(file);
|
|
||||||
browserify.bundle().pipe(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A basic bot waits for onBotConnected to be called with a stream to the actual
|
|
||||||
// endpoint with the bot. Once that stream is available it establishes a dnode
|
|
||||||
// connection and calls the callback with the other endpoint interface so the
|
|
||||||
// test can interact with it.
|
|
||||||
Bot = function (name, callback) {
|
|
||||||
this.name_ = name;
|
|
||||||
this.onbotready_ = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bot.prototype = {
|
|
||||||
log: function (msg) {
|
|
||||||
console.log("bot:" + this.name_ + " > " + msg);
|
|
||||||
},
|
|
||||||
|
|
||||||
name: function () { return this.name_; },
|
|
||||||
|
|
||||||
onBotConnected: function (stream) {
|
|
||||||
this.log('Connected');
|
|
||||||
this.stream_ = stream;
|
|
||||||
this.dnode_ = new Dnode();
|
|
||||||
this.dnode_.on('remote', this.onRemoteFromDnode_.bind(this));
|
|
||||||
this.dnode_.pipe(this.stream_).pipe(this.dnode_);
|
|
||||||
},
|
|
||||||
|
|
||||||
onRemoteFromDnode_: function (remote) {
|
|
||||||
this.onbotready_(remote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BrowserBot spawns a process to open "https://localhost:8080/bot/browser".
|
|
||||||
//
|
|
||||||
// That page once loaded, connects to the websocket server run by BotManager
|
|
||||||
// and exposes the bot api.
|
|
||||||
BrowserBot = function (name, callback) {
|
|
||||||
Bot.call(this, name, callback);
|
|
||||||
this.spawnBotProcess_();
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowserBot.prototype = {
|
|
||||||
spawnBotProcess_: function () {
|
|
||||||
this.log('Spawning browser');
|
|
||||||
child.exec('google-chrome "https://localhost:8080/bot/browser/"');
|
|
||||||
},
|
|
||||||
|
|
||||||
__proto__: Bot.prototype
|
|
||||||
}
|
|
||||||
|
|
||||||
// AndroidChromeBot spawns a process to open
|
|
||||||
// "https://localhost:8080/bot/browser/" on chrome for Android.
|
|
||||||
AndroidChromeBot = function (name, androidDeviceManager, callback) {
|
|
||||||
Bot.call(this, name, callback);
|
|
||||||
androidDeviceManager.getNewDevice(function (serialNumber) {
|
|
||||||
this.serialNumber_ = serialNumber;
|
|
||||||
this.spawnBotProcess_();
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidChromeBot.prototype = {
|
|
||||||
spawnBotProcess_: function () {
|
|
||||||
this.log('Spawning Android device with serial ' + this.serialNumber_);
|
|
||||||
var runChrome = 'adb -s ' + this.serialNumber_ + ' shell am start ' +
|
|
||||||
'-n com.android.chrome/com.google.android.apps.chrome.Main ' +
|
|
||||||
'-d https://localhost:8080/bot/browser/';
|
|
||||||
child.exec(runChrome, function (error, stdout, stderr) {
|
|
||||||
if (error) {
|
|
||||||
this.log(error);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
this.log('Opening Chrome for Android...');
|
|
||||||
this.log(stdout);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
__proto__: Bot.prototype
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidDeviceManager = function () {
|
|
||||||
this.connectedDevices_ = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidDeviceManager.prototype = {
|
|
||||||
getNewDevice: function (callback) {
|
|
||||||
this.listDevices_(function (devices) {
|
|
||||||
for (var i = 0; i < devices.length; i++) {
|
|
||||||
if (!this.connectedDevices_[devices[i]]) {
|
|
||||||
this.connectedDevices_[devices[i]] = devices[i];
|
|
||||||
callback(this.connectedDevices_[devices[i]]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (devices.length == 0) {
|
|
||||||
console.log('Error: No connected devices!');
|
|
||||||
} else {
|
|
||||||
console.log('Error: There is no enough connected devices.');
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
|
|
||||||
listDevices_: function (callback) {
|
|
||||||
child.exec('adb devices' , function (error, stdout, stderr) {
|
|
||||||
var devices = [];
|
|
||||||
if (error || stderr) {
|
|
||||||
console.log(error || stderr);
|
|
||||||
}
|
|
||||||
if (stdout) {
|
|
||||||
// The first line is "List of devices attached"
|
|
||||||
// and the following lines:
|
|
||||||
// <serial number> <device/emulator>
|
|
||||||
var tempList = stdout.split("\n").slice(1);
|
|
||||||
for (var i = 0; i < tempList.length; i++) {
|
|
||||||
if (tempList[i] == "") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
devices.push(tempList[i].split("\t")[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(devices);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
module.exports = BotManager;
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
// 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);
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<!--
|
|
||||||
// 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.
|
|
||||||
-->
|
|
||||||
<html>
|
|
||||||
<script src="https://www.google.com/jsapi"></script>
|
|
||||||
<script type="text/javascript" src="main.js"></script>
|
|
||||||
<input type="file" onchange="openFiles(event)" multiple>
|
|
||||||
</html>
|
|
||||||
@ -1,191 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
google.load("visualization", "1", {packages:["corechart"]});
|
|
||||||
|
|
||||||
function openFiles(event) {
|
|
||||||
var files = event.target.files;
|
|
||||||
readAndAnalyzeFiles(files)
|
|
||||||
}
|
|
||||||
|
|
||||||
function readAndAnalyzeFiles(files) {
|
|
||||||
if(!files) {
|
|
||||||
alert("No files have been selected!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reports = [];
|
|
||||||
var filesNames = [];
|
|
||||||
missingFiles = files.length;
|
|
||||||
|
|
||||||
for(var i = 0; i < files.length; i++) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = onReaderLoad.bind(reader, files[i].name);
|
|
||||||
reader.readAsText(files[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onReaderLoad(fileName) {
|
|
||||||
reports.push(JSON.parse(this.result));
|
|
||||||
filesNames.push(fileName);
|
|
||||||
|
|
||||||
missingFiles--;
|
|
||||||
if(missingFiles == 0) {
|
|
||||||
analyzeReports_(reports, filesNames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(houssainy) take the input stats from the select list or
|
|
||||||
// drop down menu in html.
|
|
||||||
function analyzeReports_(reports, filesNames) {
|
|
||||||
filesNames.unshift(""); // ned
|
|
||||||
|
|
||||||
// Rtt
|
|
||||||
analyzeRttData(reports, filesNames, "bot1");
|
|
||||||
analyzeRttData(reports, filesNames, "bot2");
|
|
||||||
|
|
||||||
// Send Packets Lost
|
|
||||||
analyzePacketsLostData(reports, filesNames, "bot1");
|
|
||||||
analyzePacketsLostData(reports, filesNames, "bot2");
|
|
||||||
|
|
||||||
// Send bandwidth
|
|
||||||
analyzeData(reports, filesNames, "Available Send Bandwidth-bot1", "bot1",
|
|
||||||
"bweforvideo", "googAvailableSendBandwidth");
|
|
||||||
analyzeData(reports, filesNames, "Available Send Bandwidth-bot2", "bot2",
|
|
||||||
"bweforvideo", "googAvailableSendBandwidth");
|
|
||||||
|
|
||||||
// Receive bandwidth
|
|
||||||
analyzeData(reports, filesNames, "Available Receive Bandwidth-bot1", "bot1",
|
|
||||||
"bweforvideo", "googAvailableReceiveBandwidth");
|
|
||||||
analyzeData(reports, filesNames, "Available Receive Bandwidth-bot2", "bot2",
|
|
||||||
"bweforvideo", "googAvailableReceiveBandwidth");
|
|
||||||
|
|
||||||
drawSeparatorLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
function analyzeRttData(reports, filesNames, botName) {
|
|
||||||
var outPut = [];
|
|
||||||
outPut.push(filesNames);
|
|
||||||
|
|
||||||
var avergaData = ['Average Rtt x10'];
|
|
||||||
var maxData = ['Max Rtt'];
|
|
||||||
|
|
||||||
var average;
|
|
||||||
var max;
|
|
||||||
for(var index in reports) {
|
|
||||||
average = getStateAverage(reports[index], botName, "Conn-audio-1-0",
|
|
||||||
"googRtt");
|
|
||||||
avergaData.push(average*10);
|
|
||||||
|
|
||||||
max = getStateMax(reports[index], botName, "Conn-audio-1-0",
|
|
||||||
"googRtt");
|
|
||||||
maxData.push(max);
|
|
||||||
}
|
|
||||||
outPut.push(avergaData);
|
|
||||||
outPut.push(maxData);
|
|
||||||
|
|
||||||
drawChart("Rtt-" + botName, outPut);
|
|
||||||
}
|
|
||||||
|
|
||||||
function analyzePacketsLostData(reports, filesNames, botName) {
|
|
||||||
var outPut = [];
|
|
||||||
outPut.push(filesNames);
|
|
||||||
|
|
||||||
var maxData = ['Max Send PacketsLost'];
|
|
||||||
var max;
|
|
||||||
for(var index in reports) {
|
|
||||||
max = getStateMax(reports[index], botName, "ssrc_[0-9]+_send",
|
|
||||||
"packetsLost");
|
|
||||||
maxData.push(max);
|
|
||||||
}
|
|
||||||
outPut.push(maxData);
|
|
||||||
|
|
||||||
drawChart("Send PacketsLost-" + botName, outPut);
|
|
||||||
}
|
|
||||||
|
|
||||||
function analyzeData(reports, filesNames, chartName, botName, reportId,
|
|
||||||
statName) {
|
|
||||||
var outPut = [];
|
|
||||||
outPut.push(filesNames);
|
|
||||||
|
|
||||||
var avergaData = ['Average ' + statName];
|
|
||||||
var maxData = ['Max ' + statName];
|
|
||||||
|
|
||||||
var average;
|
|
||||||
var max;
|
|
||||||
for(var index in reports) {
|
|
||||||
average = getStateAverage(reports[index], botName, reportId, statName);
|
|
||||||
avergaData.push(average);
|
|
||||||
|
|
||||||
max = getStateMax(reports[index], botName, reportId, statName);
|
|
||||||
maxData.push(max);
|
|
||||||
}
|
|
||||||
outPut.push(avergaData);
|
|
||||||
outPut.push(maxData);
|
|
||||||
|
|
||||||
drawChart(chartName, outPut);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateAverage(reports, botName, reportId, statName) {
|
|
||||||
var sum = 0;
|
|
||||||
var count = 0;
|
|
||||||
|
|
||||||
for (var index in reports) {
|
|
||||||
var data = reports[index].data;
|
|
||||||
if(index == 0 || !data.hasOwnProperty(botName))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var stats = data[botName];
|
|
||||||
for (var key in stats) {
|
|
||||||
if(key.search(reportId) != -1) {
|
|
||||||
var value = parseInt(stats[key][statName]);
|
|
||||||
sum += value;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Math.round(sum/count);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateMax(reports, botName, reportId, statName) {
|
|
||||||
var max = -1;
|
|
||||||
|
|
||||||
for (var index in reports) {
|
|
||||||
var data = reports[index].data;
|
|
||||||
if(index == 0 || !data.hasOwnProperty(botName))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var stats = data[botName];
|
|
||||||
for (var key in stats) {
|
|
||||||
if(key.search(reportId) != -1) {
|
|
||||||
var value = parseInt(stats[key][statName]);
|
|
||||||
max = Math.max(value, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawChart(title, data) {
|
|
||||||
var dataTable = google.visualization.arrayToDataTable(data);
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
title: title,
|
|
||||||
};
|
|
||||||
|
|
||||||
var div = document.createElement('div');
|
|
||||||
document.body.appendChild(div);
|
|
||||||
|
|
||||||
var chart = new google.visualization.ColumnChart(div);
|
|
||||||
chart.draw(dataTable, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawSeparatorLine() {
|
|
||||||
var hr = document.createElement('hr');
|
|
||||||
document.body.appendChild(hr);
|
|
||||||
}
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// Provides a Test class that exposes api to the tests.
|
|
||||||
// Read test.prototype to see what methods are exposed.
|
|
||||||
var fs = require('fs');
|
|
||||||
var request = require('request');
|
|
||||||
var BotManager = require('./botmanager.js');
|
|
||||||
|
|
||||||
function Test() {
|
|
||||||
this.timeout_ = setTimeout(
|
|
||||||
this.fail.bind(this, "Test timeout!"),
|
|
||||||
100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Test.prototype = {
|
|
||||||
log: function () {
|
|
||||||
console.log.apply(console.log, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
abort: function (error) {
|
|
||||||
var error = new Error(error || "Test aborted");
|
|
||||||
console.log(error.stack);
|
|
||||||
process.exit(1);
|
|
||||||
},
|
|
||||||
|
|
||||||
assert: function (value, message) {
|
|
||||||
if (value !== true) {
|
|
||||||
this.abort(message || "Assert failed.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
fail: function () {
|
|
||||||
this.assert(false, "Test failed.");
|
|
||||||
},
|
|
||||||
|
|
||||||
done: function () {
|
|
||||||
clearTimeout(this.timeout_);
|
|
||||||
console.log("Test succeeded");
|
|
||||||
process.exit(0);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Utility method to wait for multiple callbacks to be executed.
|
|
||||||
// functions - array of functions to call with a callback.
|
|
||||||
// doneCallback - called when all callbacks on the array have completed.
|
|
||||||
wait: function (functions, doneCallback) {
|
|
||||||
var result = new Array(functions.length);
|
|
||||||
var missingResult = functions.length;
|
|
||||||
for (var i = 0; i != functions.length; ++i)
|
|
||||||
functions[i](complete.bind(this, i));
|
|
||||||
|
|
||||||
function complete(index, value) {
|
|
||||||
missingResult--;
|
|
||||||
result[index] = value;
|
|
||||||
if (missingResult == 0)
|
|
||||||
doneCallback.apply(null, result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
spawnBot: function (name, botType, doneCallback) {
|
|
||||||
// Lazy initialization of botmanager.
|
|
||||||
if (!this.botManager_)
|
|
||||||
this.botManager_ = new BotManager();
|
|
||||||
this.botManager_.spawnNewBot(name, botType, doneCallback);
|
|
||||||
},
|
|
||||||
|
|
||||||
createStatisticsReport: function (outputFileName) {
|
|
||||||
return new StatisticsReport(outputFileName);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Ask computeengineondemand to give us TURN server credentials and URIs.
|
|
||||||
createTurnConfig: function (onSuccess, onError) {
|
|
||||||
request('https://computeengineondemand.appspot.com/turn?username=1234&key=5678',
|
|
||||||
function (error, response, body) {
|
|
||||||
if (error || response.statusCode != 200) {
|
|
||||||
onError('TURN request failed');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = JSON.parse(body);
|
|
||||||
var iceServer = {
|
|
||||||
'username': response.username,
|
|
||||||
'credential': response.password,
|
|
||||||
'urls': response.uris
|
|
||||||
};
|
|
||||||
onSuccess({ 'iceServers': [ iceServer ] });
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
StatisticsReport = function (outputFileName) {
|
|
||||||
this.output_ = [];
|
|
||||||
this.output_.push("Version: 1");
|
|
||||||
this.outputFileName_ = outputFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
StatisticsReport.prototype = {
|
|
||||||
collectStatsFromPeerConnection: function (prefix, pc) {
|
|
||||||
setInterval(this.addPeerConnectionStats.bind(this, prefix, pc), 100);
|
|
||||||
},
|
|
||||||
|
|
||||||
addPeerConnectionStats: function (prefix, pc) {
|
|
||||||
pc.getStats(onStatsReady.bind(this));
|
|
||||||
|
|
||||||
function onStatsReady(reports) {
|
|
||||||
for (index in reports) {
|
|
||||||
var stats = {};
|
|
||||||
stats[reports[index].id] = collectStats(reports[index].stats);
|
|
||||||
|
|
||||||
var data = {};
|
|
||||||
data[prefix] = stats;
|
|
||||||
|
|
||||||
this.output_.push({
|
|
||||||
type: "UpdateCounters",
|
|
||||||
startTime: (new Date()).getTime(),
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function collectStats(stats) {
|
|
||||||
var outputStats = {};
|
|
||||||
for (index in stats) {
|
|
||||||
var statValue = parseFloat(stats[index].stat);
|
|
||||||
outputStats[stats[index].name] = isNaN(statValue)?
|
|
||||||
stats[index].stat : statValue;
|
|
||||||
}
|
|
||||||
return outputStats;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
finish: function (doneCallback) {
|
|
||||||
fs.exists("test/reports/", function (exists) {
|
|
||||||
if(exists) {
|
|
||||||
writeFile.bind(this)();
|
|
||||||
} else {
|
|
||||||
fs.mkdir("test/reports/", 0777, writeFile.bind(this));
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
function writeFile () {
|
|
||||||
fs.writeFile("test/reports/" + this.outputFileName_ + "_" +
|
|
||||||
(new Date()).getTime() +".json", JSON.stringify(this.output_),
|
|
||||||
doneCallback);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = Test;
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// A unidirectional video and audio flowing test from bot 1 to bot 2,
|
|
||||||
// and download a file from a server after 2 seconds of establishing
|
|
||||||
// the call.
|
|
||||||
//
|
|
||||||
// The test succeeds after collecting stats for 10 seconds from both bots
|
|
||||||
// and then write these stats to a file.
|
|
||||||
//
|
|
||||||
// Note: the source of the video and audio stream is getUserMedia().
|
|
||||||
//
|
|
||||||
function testOneWayVideoWithDownloading(test, bot1, bot2) {
|
|
||||||
var report = test.createStatisticsReport("testOneWayVideoWithDownloading");
|
|
||||||
|
|
||||||
test.wait([
|
|
||||||
createPeerConnection.bind(bot1),
|
|
||||||
createPeerConnection.bind(bot2) ],
|
|
||||||
onPeerConnectionCreated);
|
|
||||||
|
|
||||||
function createPeerConnection(done) {
|
|
||||||
test.createTurnConfig(onTurnConfig.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onTurnConfig(config) {
|
|
||||||
this.createPeerConnection(config, done, test.fail);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPeerConnectionCreated(pc1, pc2) {
|
|
||||||
test.log("RTC Peers created.");
|
|
||||||
pc1.addEventListener('addstream', test.fail);
|
|
||||||
pc2.addEventListener('addstream', onAddStream);
|
|
||||||
pc1.addEventListener('icecandidate', onIceCandidate.bind(pc2));
|
|
||||||
pc2.addEventListener('icecandidate', onIceCandidate.bind(pc1));
|
|
||||||
|
|
||||||
bot1.getUserMedia({video:true, audio:true}, onUserMediaSuccess, test.fail);
|
|
||||||
|
|
||||||
function onUserMediaSuccess(stream) {
|
|
||||||
test.log("User has granted access to local media.");
|
|
||||||
pc1.addStream(stream);
|
|
||||||
bot1.showStream(stream.id, true, true);
|
|
||||||
|
|
||||||
createOfferAndAnswer(pc1, pc2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddStream(event) {
|
|
||||||
test.log("On Add stream.");
|
|
||||||
bot2.showStream(event.stream.id, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidate(event) {
|
|
||||||
if(event.candidate) {
|
|
||||||
test.log(event.candidate.candidate);
|
|
||||||
this.addIceCandidate(event.candidate,
|
|
||||||
onAddIceCandidateSuccess, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddIceCandidateSuccess() {
|
|
||||||
test.log("Candidate added successfully");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOfferAndAnswer(pc1, pc2) {
|
|
||||||
test.log("Creating offer.");
|
|
||||||
pc1.createOffer(gotOffer, test.fail);
|
|
||||||
|
|
||||||
function gotOffer(offer) {
|
|
||||||
test.log("Got offer");
|
|
||||||
pc1.setLocalDescription(offer, onSetSessionDescriptionSuccess, test.fail);
|
|
||||||
pc2.setRemoteDescription(offer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
test.log("Creating answer");
|
|
||||||
pc2.createAnswer(gotAnswer, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log("Got answer");
|
|
||||||
pc2.setLocalDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
pc1.setRemoteDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
collectStats();
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
downloadFile(bot1, "bot1");
|
|
||||||
downloadFile(bot2, "bot2");
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSetSessionDescriptionSuccess() {
|
|
||||||
test.log("Set session description success.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectStats() {
|
|
||||||
report.collectStatsFromPeerConnection("bot1", pc1);
|
|
||||||
report.collectStatsFromPeerConnection("bot2", pc2);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
report.finish(test.done);
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadFile(bot, name) {
|
|
||||||
bot.downloadFile("https://test.webrtc.org/test-download-file/9000KB.data",
|
|
||||||
onDownloadSuccess.bind(null, name), test.fail);
|
|
||||||
|
|
||||||
function onDownloadSuccess(name, data) {
|
|
||||||
test.log( name + " downloaded " +
|
|
||||||
Math.round(data.length/(1024*1024)) + "MB.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('testOneWayVideoWithDownloading/chrome-chrome',
|
|
||||||
testOneWayVideoWithDownloading, ['chrome', 'chrome']);
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
function testPingPong(test, bot) {
|
|
||||||
test.assert(typeof bot.ping === 'function', 'Bot does not exposes ping.');
|
|
||||||
|
|
||||||
bot.ping(gotAnswer);
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log('bot > ' + answer);
|
|
||||||
test.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('testPingPong/chrome', testPingPong, ['chrome']);
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// Test that offer/answer between 2 peers completes successfully.
|
|
||||||
//
|
|
||||||
// Note: This test does not performs ice candidate exchange and
|
|
||||||
// does not verifies that media can flow between the peers.
|
|
||||||
function testOfferAnswer(test, bot1, bot2) {
|
|
||||||
test.wait( [ bot1.createPeerConnection.bind(bot1, null),
|
|
||||||
bot2.createPeerConnection.bind(bot2, null) ],
|
|
||||||
run);
|
|
||||||
|
|
||||||
function run(pc1, pc2) {
|
|
||||||
test.log("Establishing call.");
|
|
||||||
pc1.createOffer(gotOffer);
|
|
||||||
|
|
||||||
function gotOffer(offer) {
|
|
||||||
test.log("Got offer");
|
|
||||||
expectedCall();
|
|
||||||
pc1.setLocalDescription(offer, expectedCall, test.fail);
|
|
||||||
pc2.setRemoteDescription(offer, expectedCall, test.fail);
|
|
||||||
pc2.createAnswer(gotAnswer, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log("Got answer");
|
|
||||||
expectedCall();
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('testOfferAnswer/chrome-chrome',
|
|
||||||
testOfferAnswer, ['chrome', 'chrome']);
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// A video conference between 3 bots streaming video and audio between
|
|
||||||
// each other.
|
|
||||||
// The test succeeds after establishing the call between the three
|
|
||||||
// devices.
|
|
||||||
//
|
|
||||||
// Note: the source of the video and audio stream is getUserMedia().
|
|
||||||
function testTwoWayVideoStreaming(test, bot1, bot2, bot3) {
|
|
||||||
var answersCount = 0;
|
|
||||||
var statsCollector;
|
|
||||||
|
|
||||||
test.wait([
|
|
||||||
createBotPeerConnectionsWithLocalStream.bind(bot1),
|
|
||||||
createBotPeerConnectionsWithLocalStream.bind(bot2),
|
|
||||||
createBotPeerConnectionsWithLocalStream.bind(bot3)],
|
|
||||||
onPeerConnectionCreated);
|
|
||||||
|
|
||||||
// done() callback is called with list of peers as argument.
|
|
||||||
function createBotPeerConnectionsWithLocalStream(done) {
|
|
||||||
var peerConnections = [];
|
|
||||||
|
|
||||||
this.getUserMedia({video:true, audio:true},
|
|
||||||
onUserMediaSuccess.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onUserMediaSuccess(stream) {
|
|
||||||
test.log("User has granted access to local media.");
|
|
||||||
this.showStream(stream.id, true, true);
|
|
||||||
|
|
||||||
test.createTurnConfig(onTurnConfig.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onTurnConfig(config) {
|
|
||||||
this.createPeerConnection(config, addStream.bind(this),
|
|
||||||
test.fail);
|
|
||||||
this.createPeerConnection(config, addStream.bind(this),
|
|
||||||
test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addStream(pc) {
|
|
||||||
pc.addStream(stream);
|
|
||||||
pc.addEventListener('addstream', onAddStream.bind(this));
|
|
||||||
|
|
||||||
peerConnections.push(pc);
|
|
||||||
if(peerConnections.length == 2)
|
|
||||||
done(peerConnections);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPeerConnectionCreated(peerConnections1,
|
|
||||||
peerConnections2, peerConnections3) {
|
|
||||||
test.log("RTC Peers created.");
|
|
||||||
|
|
||||||
// Bot1 and Bot2
|
|
||||||
establichCall(peerConnections1[0], peerConnections2[1]);
|
|
||||||
// Bot2 and Bot3
|
|
||||||
establichCall(peerConnections2[0], peerConnections3[1]);
|
|
||||||
// Bot3 and Bot1
|
|
||||||
establichCall(peerConnections3[0], peerConnections1[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function establichCall(pc1, pc2) {
|
|
||||||
pc1.addEventListener('icecandidate', onIceCandidate.bind(pc2));
|
|
||||||
pc2.addEventListener('icecandidate', onIceCandidate.bind(pc1));
|
|
||||||
|
|
||||||
createOfferAndAnswer(pc1, pc2);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddStream(event) {
|
|
||||||
test.log("On Add stream.");
|
|
||||||
this.showStream(event.stream.id, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidate(event) {
|
|
||||||
if(event.candidate) {
|
|
||||||
this.addIceCandidate(event.candidate,
|
|
||||||
onAddIceCandidateSuccess, test.fail);
|
|
||||||
};
|
|
||||||
|
|
||||||
function onAddIceCandidateSuccess() {
|
|
||||||
test.log("Candidate added successfully");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOfferAndAnswer(pc1, pc2) {
|
|
||||||
test.log("Creating offer.");
|
|
||||||
pc1.createOffer(gotOffer, test.fail);
|
|
||||||
|
|
||||||
function gotOffer(offer) {
|
|
||||||
test.log("Got offer");
|
|
||||||
pc1.setLocalDescription(offer, onSetSessionDescriptionSuccess, test.fail);
|
|
||||||
pc2.setRemoteDescription(offer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
test.log("Creating answer");
|
|
||||||
pc2.createAnswer(gotAnswer, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log("Got answer");
|
|
||||||
pc2.setLocalDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
pc1.setRemoteDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
|
|
||||||
answersCount++;
|
|
||||||
if(answersCount == 3) {
|
|
||||||
// SetTimeout used because creating the three answers will very fast
|
|
||||||
// and test will success and the vm will be closed before establishing
|
|
||||||
// the calls.
|
|
||||||
setTimeout(function() {
|
|
||||||
test.done();
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSetSessionDescriptionSuccess() {
|
|
||||||
test.log("Set session description success.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('threeBotsVideoConference/android+android+chrome',
|
|
||||||
testTwoWayVideoStreaming, ['android-chrome', 'android-chrome',
|
|
||||||
'chrome']);
|
|
||||||
registerBotTest('threeBotsVideoConference/chrome-chrome-chrome',
|
|
||||||
testTwoWayVideoStreaming, ['chrome', 'chrome', 'chrome']);
|
|
||||||
registerBotTest('threeBotsVideoConference/android-android-android',
|
|
||||||
testTwoWayVideoStreaming, ['android-chrome', 'android-chrome',
|
|
||||||
'android-chrome']);
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// A two way video and audio flowing test between bot 1 and bot 2.
|
|
||||||
// The test succeeds after collecting stats for 10 seconds from both bots
|
|
||||||
// and then write these stats to a file.
|
|
||||||
//
|
|
||||||
// Note: the source of the video and audio stream is getUserMedia().
|
|
||||||
function testTwoWayVideoStreaming(test, bot1, bot2) {
|
|
||||||
var report = test.createStatisticsReport("two_way_video_streaming");
|
|
||||||
var statsCollector;
|
|
||||||
|
|
||||||
test.wait([
|
|
||||||
createPeerConnectionWithLocalStream.bind(bot1),
|
|
||||||
createPeerConnectionWithLocalStream.bind(bot2)],
|
|
||||||
onPeerConnectionCreated);
|
|
||||||
|
|
||||||
function createPeerConnectionWithLocalStream(done) {
|
|
||||||
this.getUserMedia({video:true, audio:true},
|
|
||||||
onUserMediaSuccess.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onUserMediaSuccess(stream) {
|
|
||||||
test.log("User has granted access to local media.");
|
|
||||||
test.createTurnConfig(onTurnConfig.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onTurnConfig(config) {
|
|
||||||
this.createPeerConnection(config, addAndShowStream.bind(this),
|
|
||||||
test.fail);
|
|
||||||
};
|
|
||||||
|
|
||||||
function addAndShowStream(pc) {
|
|
||||||
pc.addStream(stream);
|
|
||||||
this.showStream(stream.id, true, true);
|
|
||||||
|
|
||||||
done(pc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPeerConnectionCreated(pc1, pc2) {
|
|
||||||
test.log("RTC Peers created.");
|
|
||||||
pc1.addEventListener('addstream', onAddStream.bind(bot1));
|
|
||||||
pc2.addEventListener('addstream', onAddStream.bind(bot2));
|
|
||||||
pc1.addEventListener('icecandidate', onIceCandidate.bind(pc2));
|
|
||||||
pc2.addEventListener('icecandidate', onIceCandidate.bind(pc1));
|
|
||||||
|
|
||||||
createOfferAndAnswer(pc1, pc2);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddStream(event) {
|
|
||||||
test.log("On Add stream.");
|
|
||||||
this.showStream(event.stream.id, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidate(event) {
|
|
||||||
if(event.candidate) {
|
|
||||||
test.log(event.candidate.candidate);
|
|
||||||
this.addIceCandidate(event.candidate,
|
|
||||||
onAddIceCandidateSuccess, test.fail);
|
|
||||||
};
|
|
||||||
|
|
||||||
function onAddIceCandidateSuccess() {
|
|
||||||
test.log("Candidate added successfully");
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOfferAndAnswer(pc1, pc2) {
|
|
||||||
test.log("Creating offer.");
|
|
||||||
pc1.createOffer(gotOffer, test.fail);
|
|
||||||
|
|
||||||
function gotOffer(offer) {
|
|
||||||
test.log("Got offer");
|
|
||||||
pc1.setLocalDescription(offer, onSetSessionDescriptionSuccess, test.fail);
|
|
||||||
pc2.setRemoteDescription(offer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
test.log("Creating answer");
|
|
||||||
pc2.createAnswer(gotAnswer, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log("Got answer");
|
|
||||||
pc2.setLocalDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
pc1.setRemoteDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
collectStats();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSetSessionDescriptionSuccess() {
|
|
||||||
test.log("Set session description success.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectStats() {
|
|
||||||
report.collectStatsFromPeerConnection("bot1", pc1);
|
|
||||||
report.collectStatsFromPeerConnection("bot2", pc2);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
report.finish(test.done);
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('testTwoWayVideo/android-android',
|
|
||||||
testTwoWayVideoStreaming, ['android-chrome', 'android-chrome']);
|
|
||||||
registerBotTest('testTwoWayVideo/chrome-chrome',
|
|
||||||
testTwoWayVideoStreaming, ['chrome', 'chrome']);
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
// 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.
|
|
||||||
//
|
|
||||||
// A unidirectional video and audio flowing test from bot 1 to bot 2.
|
|
||||||
// The test succeeds after collecting stats for 10 seconds from both bots
|
|
||||||
// and then write these stats to a file.
|
|
||||||
//
|
|
||||||
// Note: the source of the video and audio stream is getUserMedia().
|
|
||||||
function testOneWayVideo(test, bot1, bot2) {
|
|
||||||
var report = test.createStatisticsReport("webrtc_video_streaming");
|
|
||||||
|
|
||||||
test.wait([
|
|
||||||
createPeerConnection.bind(bot1),
|
|
||||||
createPeerConnection.bind(bot2) ],
|
|
||||||
onPeerConnectionCreated);
|
|
||||||
|
|
||||||
function createPeerConnection(done) {
|
|
||||||
test.createTurnConfig(onTurnConfig.bind(this), test.fail);
|
|
||||||
|
|
||||||
function onTurnConfig(config) {
|
|
||||||
this.createPeerConnection(config, done, test.fail);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPeerConnectionCreated(pc1, pc2) {
|
|
||||||
test.log("RTC Peers created.");
|
|
||||||
pc1.addEventListener('addstream', test.fail);
|
|
||||||
pc2.addEventListener('addstream', onAddStream);
|
|
||||||
pc1.addEventListener('icecandidate', onIceCandidate.bind(pc2));
|
|
||||||
pc2.addEventListener('icecandidate', onIceCandidate.bind(pc1));
|
|
||||||
|
|
||||||
bot1.getUserMedia({video:true, audio:true}, onUserMediaSuccess, test.fail);
|
|
||||||
|
|
||||||
function onUserMediaSuccess(stream) {
|
|
||||||
test.log("User has granted access to local media.");
|
|
||||||
pc1.addStream(stream);
|
|
||||||
bot1.showStream(stream.id, true, true);
|
|
||||||
|
|
||||||
createOfferAndAnswer(pc1, pc2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddStream(event) {
|
|
||||||
test.log("On Add stream.");
|
|
||||||
bot2.showStream(event.stream.id, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onIceCandidate(event) {
|
|
||||||
if(event.candidate) {
|
|
||||||
test.log(event.candidate.candidate);
|
|
||||||
this.addIceCandidate(event.candidate,
|
|
||||||
onAddIceCandidateSuccess, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddIceCandidateSuccess() {
|
|
||||||
test.log("Candidate added successfully");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createOfferAndAnswer(pc1, pc2) {
|
|
||||||
test.log("Creating offer.");
|
|
||||||
pc1.createOffer(gotOffer, test.fail);
|
|
||||||
|
|
||||||
function gotOffer(offer) {
|
|
||||||
test.log("Got offer");
|
|
||||||
pc1.setLocalDescription(offer, onSetSessionDescriptionSuccess, test.fail);
|
|
||||||
pc2.setRemoteDescription(offer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
test.log("Creating answer");
|
|
||||||
pc2.createAnswer(gotAnswer, test.fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gotAnswer(answer) {
|
|
||||||
test.log("Got answer");
|
|
||||||
pc2.setLocalDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
pc1.setRemoteDescription(answer, onSetSessionDescriptionSuccess,
|
|
||||||
test.fail);
|
|
||||||
collectStats();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSetSessionDescriptionSuccess() {
|
|
||||||
test.log("Set session description success.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectStats() {
|
|
||||||
report.collectStatsFromPeerConnection("bot1", pc1);
|
|
||||||
report.collectStatsFromPeerConnection("bot2", pc2);
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
report.finish(test.done);
|
|
||||||
}, 10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerBotTest('testOneWayVideo/chrome-chrome',
|
|
||||||
testOneWayVideo, ['chrome', 'chrome']);
|
|
||||||
Reference in New Issue
Block a user