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 12function logError(err) { 13 console.error(err); 14} 15 16// Available resolutions to switch between. These are 4:3 resolutions chosen 17// since they have significant distance between them and are quite common. E.g. 18// they can be selected for youtube videos. We also avoid higher resolutions 19// since they consume a lot of resources. 20const RESOLUTIONS = [ 21 {w:320, h:240}, 22 {w:480, h:360}, 23 {w:640, h:480}, 24 {w:1280, h:720}, 25]; 26 27class TestRunner { 28 constructor(runtimeSeconds, switchResolutionDelayMillis) { 29 this.runtimeSeconds = runtimeSeconds; 30 this.switchResolutionDelayMillis = switchResolutionDelayMillis; 31 this.videoElements = []; 32 this.peerConnections = []; 33 this.numConnections = 0; 34 this.iteration = 0; 35 this.startTime = 0; // initialized to dummy value 36 this.status = this.getStatusInternal_(); 37 } 38 39 addPeerConnection() { 40 const videoElement = document.createElement('video'); 41 videoElement.autoplay = true; 42 $('body').appendChild(videoElement); 43 this.videoElements.push(videoElement); 44 this.peerConnections.push( 45 new PeerConnection(videoElement, RESOLUTIONS, cpuOveruseDetection)); 46 } 47 48 runTest() { 49 const promises = this.peerConnections.map((conn) => conn.start()); 50 Promise.all(promises) 51 .then(() => { 52 this.startTime = Date.now(); 53 this.switchResolutionLoop(); 54 }) 55 .catch((e) => {throw e}); 56 } 57 58 switchResolutionLoop() { 59 this.iteration++; 60 this.status = this.getStatusInternal_(); 61 $('status').textContent = this.status; 62 if (this.status != 'ok-done') { 63 Promise.all(this.peerConnections.map((pc) => pc.switchToRandomStream())) 64 .then( 65 () => setTimeout( 66 () => this.switchResolutionLoop(), 67 this.switchResolutionDelayMillis)); 68 } 69 } 70 71 getStatus() { 72 return this.status; 73 } 74 75 getStatusInternal_() { 76 if (this.iteration == 0) { 77 return 'not-started'; 78 } 79 try { 80 this.peerConnections.forEach((conn) => conn.verifyState()); 81 } catch (e) { 82 return `failure: ${e.message}`; 83 } 84 const timeSpent = Date.now() - this.startTime; 85 if (timeSpent >= this.runtimeSeconds * 1000) { 86 return 'ok-done'; 87 } 88 return `running, iteration: ${this.iteration}`; 89 } 90} 91 92// Declare testRunner so that the Python code can access it to query status. 93// Also allows us to access it easily in dev tools for debugging. 94let testRunner; 95// Set from the Python test runner 96let cpuOveruseDetection = null; 97 98function startTest( 99 runtimeSeconds, numPeerConnections, switchResolutionDelayMillis) { 100 testRunner = new TestRunner(runtimeSeconds, switchResolutionDelayMillis); 101 for (let i = 0; i < numPeerConnections; i++) { 102 testRunner.addPeerConnection(); 103 } 104 testRunner.runTest(); 105} 106 107function getStatus() { 108 return testRunner ? testRunner.getStatus() : 'not-initialized'; 109} 110 111