1/* 2 * Copyright 2017 The Chromium Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6/*jshint esversion: 6 */ 7 8'use strict'; 9 10const $ = document.getElementById.bind(document); 11 12class TestRunner { 13 constructor(runtimeSeconds, pausePlayIterationDelayMillis) { 14 this.runtimeSeconds = runtimeSeconds; 15 this.pausePlayIterationDelayMillis = pausePlayIterationDelayMillis; 16 this.elements = []; 17 this.peerConnections = []; 18 this.iteration = 0; 19 this.startTime; 20 } 21 22 addPeerConnection(elementType) { 23 const element = document.createElement(elementType); 24 element.autoplay = false; 25 $('body').appendChild(element); 26 let resolution; 27 if (elementType === 'video') { 28 resolution = {w: 300, h: 225}; 29 } else if (elementType === 'audio') { 30 resolution = {w: -1, h: -1}; // -1 is interpreted as disabled 31 } else { 32 throw new Error('elementType must be one of "audio" or "video"'); 33 } 34 this.elements.push(element); 35 this.peerConnections.push( 36 new PeerConnection(element, [resolution], cpuOveruseDetection)); 37 } 38 39 runTest() { 40 let promises = this.peerConnections.map((conn) => conn.start()); 41 Promise.all(promises) 42 .then(() => { 43 this.startTime = Date.now(); 44 this.pauseAndPlayLoop(); 45 }) 46 .catch((e) => {throw e}); 47 } 48 49 pauseAndPlayLoop() { 50 this.iteration++; 51 this.elements.forEach((feed) => { 52 if (Math.random() >= 0.5) { 53 feed.play(); 54 } else { 55 feed.pause(); 56 } 57 }); 58 const status = this.getStatus(); 59 $('status').textContent = status 60 if (status != 'ok-done') { 61 setTimeout( 62 () => {this.pauseAndPlayLoop()}, this.pausePlayIterationDelayMillis); 63 } else { // We're done. Pause all feeds. 64 this.elements.forEach((feed) => { 65 feed.pause(); 66 }); 67 } 68 } 69 70 getStatus() { 71 if (this.iteration == 0) { 72 return 'not-started'; 73 } 74 try { 75 this.peerConnections.forEach((conn) => conn.verifyState()); 76 } catch (e) { 77 return `failure: ${e.message}`; 78 } 79 const timeSpent = Date.now() - this.startTime; 80 if (timeSpent >= this.runtimeSeconds * 1000) { 81 return 'ok-done'; 82 } else { 83 return `running, iteration: ${this.iteration}`; 84 } 85 } 86} 87 88// Declare testRunner so that the Python code can access it to query status. 89// Also allows us to access it easily in dev tools for debugging. 90let testRunner; 91// Set from the Python test runner 92let cpuOveruseDetection = null; 93let elementType; 94 95function startTest( 96 runtimeSeconds, numPeerConnections, pausePlayIterationDelayMillis) { 97 testRunner = new TestRunner( 98 runtimeSeconds, pausePlayIterationDelayMillis); 99 for (let i = 0; i < numPeerConnections; i++) { 100 testRunner.addPeerConnection(elementType); 101 } 102 testRunner.runTest(); 103} 104 105function getStatus() { 106 return testRunner ? testRunner.getStatus() : 'not-initialized'; 107} 108 109