119 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| /*
 | |
|  * Copyright 2017 The Chromium Authors. All rights reserved.
 | |
|  * Use of this source code is governed by a BSD-style license that can be
 | |
|  * found in the LICENSE file.
 | |
|  */
 | |
| /*jshint esversion: 6 */
 | |
| 
 | |
| 'use strict';
 | |
| 
 | |
| const $ = document.getElementById.bind(document);
 | |
| 
 | |
| const MAIN_FEED_RESOLUTION = {w:1280, h:720};
 | |
| 
 | |
| // This resolution is what we typically get on Hangouts Meet.
 | |
| const SMALL_FEED_RESOLUTION = {w:182, h:136};
 | |
| 
 | |
| // This test frequently reports weird resolutions although the visuals look OK.
 | |
| // Hence, require lots of consecutive bad resolutions before failure.
 | |
| // TODO(kerl): Effectively disabled now, investigate why we get so many bad
 | |
| // resolution reports.
 | |
| const NUM_BAD_RESOLUTIONS_FOR_FAILURE = Number.MAX_SAFE_INTEGER;
 | |
| 
 | |
| class TestRunner {
 | |
|   constructor(numConnections, runtimeSeconds, iterationDelayMillis) {
 | |
|     this.runtimeSeconds = runtimeSeconds;
 | |
|     this.iterationDelayMillis = iterationDelayMillis;
 | |
|     this.videoElements = [];
 | |
|     this.mainFeed = null;
 | |
|     this.peerConnections = [];
 | |
|     this.numConnections = numConnections;
 | |
|     this.iteration = 0;
 | |
|     this.startTime = 0;  // initialized to dummy value
 | |
|     this.status = this.getStatusInternal_();
 | |
|   }
 | |
| 
 | |
|   runTest() {
 | |
|     for (let i = 0; i < this.numConnections; i++) {
 | |
|       const videoElement = document.createElement('video');
 | |
|       videoElement.autoplay = true;
 | |
|       $('body').appendChild(videoElement);
 | |
|       if (!this.mainFeed) {
 | |
|         // The first created is the main feed.
 | |
|         setSize(videoElement, MAIN_FEED_RESOLUTION);
 | |
|         this.mainFeed = videoElement;
 | |
|       } else {
 | |
|         setSize(videoElement, SMALL_FEED_RESOLUTION);
 | |
|         this.videoElements.push(videoElement);
 | |
|       }
 | |
|       this.peerConnections.push(new PeerConnection(
 | |
|           videoElement, [MAIN_FEED_RESOLUTION], cpuOveruseDetection));
 | |
|     }
 | |
|     const promises = this.peerConnections.map((conn) => conn.start());
 | |
|     Promise.all(promises)
 | |
|         .then(() => {
 | |
|           this.startTime = Date.now();
 | |
|           this.switchFeedLoop();
 | |
|         })
 | |
|         .catch((e) => {throw e});
 | |
|   }
 | |
| 
 | |
|   switchFeedLoop() {
 | |
|     this.iteration++;
 | |
|     this.status = this.getStatusInternal_();
 | |
|     $('status').textContent = this.status;
 | |
|     if (this.status != 'ok-done') {
 | |
|       const switchWith = Math.floor(Math.random() * this.videoElements.length);
 | |
|       const newMainSrc = this.videoElements[switchWith].srcObject;
 | |
|       this.videoElements[switchWith].srcObject = this.mainFeed.srcObject;
 | |
|       this.mainFeed.srcObject = newMainSrc;
 | |
|       setTimeout(
 | |
|           () => this.switchFeedLoop(), this.iterationDelayMillis);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   getStatus() {
 | |
|     return this.status;
 | |
|   }
 | |
| 
 | |
|   getStatusInternal_() {
 | |
|     if (this.iteration == 0) {
 | |
|       return 'not-started';
 | |
|     }
 | |
|     try {
 | |
|       this.peerConnections.forEach(
 | |
|           (conn) => conn.verifyState(NUM_BAD_RESOLUTIONS_FOR_FAILURE));
 | |
|     } catch (e) {
 | |
|       return `failure: ${e.message}`;
 | |
|     }
 | |
|     const timeSpent = Date.now() - this.startTime;
 | |
|     if (timeSpent >= this.runtimeSeconds * 1000) {
 | |
|       return 'ok-done';
 | |
|     } else {
 | |
|       return `running, iteration: ${this.iteration}`;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function setSize(element, size) {
 | |
|   element.setAttribute('style', `width:${size.w}px;height:${size.h}px`);
 | |
| }
 | |
| 
 | |
| // Declare testRunner so that the Python code can access it to query status.
 | |
| // Also allows us to access it easily in dev tools for debugging.
 | |
| let testRunner;
 | |
| // Set from the Python test runner
 | |
| let cpuOveruseDetection = null;
 | |
| 
 | |
| function startTest(
 | |
|     runtimeSeconds, numPeerConnections, iterationDelayMillis) {
 | |
|   testRunner = new TestRunner(
 | |
|       numPeerConnections, runtimeSeconds, iterationDelayMillis);
 | |
|   testRunner.runTest();
 | |
| }
 | |
| 
 | |
| function getStatus() {
 | |
|   return testRunner ? testRunner.getStatus() : 'not-initialized';
 | |
| }
 | |
| 
 |