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