chore(benchpress): clang-format and lint

This commit is contained in:
Jason Choi 2016-08-03 15:00:07 -07:00 committed by Alex Rickabaugh
parent 3fcd6fd93f
commit fd19671c07
50 changed files with 1273 additions and 1074 deletions

View File

@ -11,7 +11,8 @@ const path = require('path');
const os = require('os');
const srcsToFmt =
['tools/**/*.ts', 'modules/@angular/**/*.ts', '!tools/public_api_guard/**/*.d.ts'];
['tools/**/*.ts', 'modules/@angular/**/*.ts', '!tools/public_api_guard/**/*.d.ts',
'modules/benchpress/**/*.ts'];
gulp.task('format:enforce', () => {
const format = require('gulp-clang-format');
@ -97,7 +98,7 @@ gulp.task('lint', ['format:enforce', 'tools:build'], () => {
// Built-in rules are at
// https://github.com/palantir/tslint#supported-rules
const tslintConfig = require('./tslint.json');
return gulp.src(['modules/@angular/**/*.ts'])
return gulp.src(['modules/@angular/**/*.ts', 'modules/benchpress/**/*.ts'])
.pipe(tslint({
tslint: require('tslint').default,
configuration: tslintConfig,

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {bind} from '@angular/core/src/di';
import {Options} from './common';
@ -22,5 +30,5 @@ function writeFile(filename, content): Promise<any> {
resolve();
}
});
})
});
}

View File

@ -1,23 +1,30 @@
export {Sampler, SampleState} from './src/sampler';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export {Injector, OpaqueToken, ReflectiveInjector, bind, provide} from '@angular/core/src/di';
export {Options} from './src/common_options';
export {MeasureValues} from './src/measure_values';
export {Metric} from './src/metric';
export {Validator} from './src/validator';
export {MultiMetric} from './src/metric/multi_metric';
export {PerflogMetric} from './src/metric/perflog_metric';
export {UserMetric} from './src/metric/user_metric';
export {Reporter} from './src/reporter';
export {WebDriverExtension, PerfLogFeatures} from './src/web_driver_extension';
export {WebDriverAdapter} from './src/web_driver_adapter';
export {SizeValidator} from './src/validator/size_validator';
export {RegressionSlopeValidator} from './src/validator/regression_slope_validator';
export {ConsoleReporter} from './src/reporter/console_reporter';
export {JsonFileReporter} from './src/reporter/json_file_reporter';
export {MultiReporter} from './src/reporter/multi_reporter';
export {Runner} from './src/runner';
export {SampleDescription} from './src/sample_description';
export {PerflogMetric} from './src/metric/perflog_metric';
export {SampleState, Sampler} from './src/sampler';
export {Validator} from './src/validator';
export {RegressionSlopeValidator} from './src/validator/regression_slope_validator';
export {SizeValidator} from './src/validator/size_validator';
export {WebDriverAdapter} from './src/web_driver_adapter';
export {PerfLogFeatures, WebDriverExtension} from './src/web_driver_extension';
export {ChromeDriverExtension} from './src/webdriver/chrome_driver_extension';
export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension';
export {IOsDriverExtension} from './src/webdriver/ios_driver_extension';
export {Runner} from './src/runner';
export {Options} from './src/common_options';
export {MeasureValues} from './src/measure_values';
export {MultiMetric} from './src/metric/multi_metric';
export {UserMetric} from './src/metric/user_metric';
export {MultiReporter} from './src/reporter/multi_reporter';
export {bind, provide, Injector, ReflectiveInjector, OpaqueToken} from '@angular/core/src/di';

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
require('reflect-metadata');
require('es6-shim');
module.exports = require('./benchpress.js');

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core/src/di';
import {DateWrapper} from '@angular/facade/src/lang';
@ -52,14 +60,9 @@ var _REQUEST_COUNT = new OpaqueToken('Options.requestCount');
var _CAPTURE_FRAMES = new OpaqueToken('Options.frameCapture');
var _DEFAULT_PROVIDERS = [
{provide: _DEFAULT_DESCRIPTION, useValue: {}},
{provide: _SAMPLE_DESCRIPTION, useValue: {}},
{provide: _FORCE_GC, useValue: false},
{provide: _PREPARE, useValue: false},
{provide: _MICRO_METRICS, useValue: {}},
{provide: _USER_METRICS, useValue: {}},
{provide: _NOW, useValue: () => DateWrapper.now()},
{provide: _RECEIVED_DATA, useValue: false},
{provide: _REQUEST_COUNT, useValue: false},
{provide: _CAPTURE_FRAMES, useValue: false}
{provide: _DEFAULT_DESCRIPTION, useValue: {}}, {provide: _SAMPLE_DESCRIPTION, useValue: {}},
{provide: _FORCE_GC, useValue: false}, {provide: _PREPARE, useValue: false},
{provide: _MICRO_METRICS, useValue: {}}, {provide: _USER_METRICS, useValue: {}},
{provide: _NOW, useValue: () => DateWrapper.now()}, {provide: _RECEIVED_DATA, useValue: false},
{provide: _REQUEST_COUNT, useValue: false}, {provide: _CAPTURE_FRAMES, useValue: false}
];

View File

@ -1,28 +1,38 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
declare var exportFunction;
declare var unsafeWindow;
exportFunction(function() {
var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('startProfiler', curTime);
}, unsafeWindow, {defineAs: "startProfiler"});
}, unsafeWindow, {defineAs: 'startProfiler'});
exportFunction(function() { (<any>self).port.emit('stopProfiler'); }, unsafeWindow,
{defineAs: "stopProfiler"});
exportFunction(function() {
(<any>self).port.emit('stopProfiler');
}, unsafeWindow, {defineAs: 'stopProfiler'});
exportFunction(function(cb) {
(<any>self).port.once('perfProfile', cb);
(<any>self).port.emit('getProfile');
}, unsafeWindow, {defineAs: "getProfile"});
}, unsafeWindow, {defineAs: 'getProfile'});
exportFunction(function() { (<any>self).port.emit('forceGC'); }, unsafeWindow,
{defineAs: "forceGC"});
exportFunction(function() {
(<any>self).port.emit('forceGC');
}, unsafeWindow, {defineAs: 'forceGC'});
exportFunction(function(name) {
var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markStart', name, curTime);
}, unsafeWindow, {defineAs: "markStart"});
}, unsafeWindow, {defineAs: 'markStart'});
exportFunction(function(name) {
var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markEnd', name, curTime);
}, unsafeWindow, {defineAs: "markEnd"});
}, unsafeWindow, {defineAs: 'markEnd'});

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var {Cc, Ci, Cu} = require('chrome');
var os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
var ParserUtil = require('./parser_util');
@ -25,7 +33,8 @@ class Profiler {
return perfEvents;
}
_mergeMarkerEvents(perfEvents: any[]): any[] {
/** @internal */
private _mergeMarkerEvents(perfEvents: any[]): any[] {
this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); });
return perfEvents;
}
@ -51,12 +60,13 @@ mod.PageMod({
include: ['*'],
contentScriptFile: data.url('installed_script.js'),
onAttach: worker => {
worker.port.on('startProfiler',
(timeStarted) => profiler.start(/* = profiler memory */ 3000000, 0.1,
['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
worker.port.on(
'startProfiler',
(timeStarted) => profiler.start(
/* = profiler memory */ 3000000, 0.1, ['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
worker.port.on('stopProfiler', () => profiler.stop());
worker.port.on('getProfile',
() => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
worker.port.on(
'getProfile', () => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
worker.port.on('forceGC', forceGC);
worker.port.on('markStart', (name, timeStarted) => profiler.addStartEvent(name, timeStarted));
worker.port.on('markEnd', (name, timeEnded) => profiler.addEndEvent(name, timeEnded));

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @param {Object} perfProfile The perf profile JSON object.
* @return {Object[]} An array of recognized events that are captured

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var q = require('q');
var FirefoxProfile = require('firefox-profile');
var jpm = require('jpm/lib/xpi');
@ -36,9 +44,8 @@ exports.getFirefoxProfileWithExtension = function() {
var savedCwd = process.cwd();
process.chdir(absPackageJsonDir);
return jpm(packageJson)
.then(xpiPath => {
process.chdir(savedCwd);
return exports.getFirefoxProfile(xpiPath);
});
return jpm(packageJson).then(xpiPath => {
process.chdir(savedCwd);
return exports.getFirefoxProfile(xpiPath);
});
};

View File

@ -1,9 +1,17 @@
import {Date, DateWrapper} from '@angular/facade/src/lang';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Map} from '@angular/facade/src/collection';
import {Date, DateWrapper} from '@angular/facade/src/lang';
export class MeasureValues {
constructor(public runIndex: number, public timeStamp: Date,
public values: {[key: string]: any}) {}
constructor(
public runIndex: number, public timeStamp: Date, public values: {[key: string]: any}) {}
toJson() {
return {

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/**

View File

@ -1,6 +1,14 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core/src/di';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {PromiseWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {Metric} from '../metric';
@ -9,14 +17,10 @@ export class MultiMetric extends Metric {
return [
{
provide: _CHILDREN,
useFactory:(injector: Injector) => childTokens.map(token => injector.get(token)),
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector]
},
{
provide: MultiMetric,
useFactory: children => new MultiMetric(children),
deps: [_CHILDREN]
}
{provide: MultiMetric, useFactory: children => new MultiMetric(children), deps: [_CHILDREN]}
];
}
@ -48,7 +52,7 @@ export class MultiMetric extends Metric {
}
}
function mergeStringMaps(maps: { [key: string]: string }[]): Object {
function mergeStringMaps(maps: {[key: string]: string}[]): Object {
var result = {};
maps.forEach(
map => { StringMapWrapper.forEach(map, (value, prop) => { result[prop] = value; }); });

View File

@ -1,12 +1,21 @@
import {PromiseWrapper, TimerWrapper} from '@angular/facade/src/async';
import {isPresent, isBlank, StringWrapper, Math, RegExpWrapper, NumberWrapper} from '@angular/facade/src/lang';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core/src/di';
import {PromiseWrapper, TimerWrapper} from '@angular/facade/src/async';
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {Math, NumberWrapper, RegExpWrapper, StringWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {Metric} from '../metric';
import {Options} from '../common_options';
import {Metric} from '../metric';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
/**
* A metric that reads out the performance log
@ -17,9 +26,12 @@ export class PerflogMetric extends Metric {
// TODO(tbosch): use static values when our transpiler supports them
static get SET_TIMEOUT(): OpaqueToken { return _SET_TIMEOUT; }
/** @internal */
private _remainingEvents: Array<{[key: string]: any}>;
/** @internal */
private _measureCount: number;
_perfLogFeatures: PerfLogFeatures;
/** @internal */
private _perfLogFeatures: PerfLogFeatures;
/**
@ -27,10 +39,21 @@ export class PerflogMetric extends Metric {
* @param setTimeout
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
**/
constructor(private _driverExtension: WebDriverExtension, private _setTimeout: Function,
private _microMetrics: {[key: string]: any}, private _forceGc: boolean,
private _captureFrames: boolean, private _receivedData: boolean,
private _requestCount: boolean) {
constructor(
/** @internal */
private _driverExtension: WebDriverExtension,
/** @internal */
private _setTimeout: Function,
/** @internal */
private _microMetrics: {[key: string]: any},
/** @internal */
private _forceGc: boolean,
/** @internal */
private _captureFrames: boolean,
/** @internal */
private _receivedData: boolean,
/** @internal */
private _requestCount: boolean) {
super();
this._remainingEvents = [];
@ -81,8 +104,8 @@ export class PerflogMetric extends Metric {
res['frameTime.smooth'] = 'percentage of frames that hit 60fps';
}
}
StringMapWrapper.forEach(this._microMetrics,
(desc, name) => { StringMapWrapper.set(res, name, desc); });
StringMapWrapper.forEach(
this._microMetrics, (desc, name) => { StringMapWrapper.set(res, name, desc); });
return res;
}
@ -102,7 +125,8 @@ export class PerflogMetric extends Metric {
}
}
_endPlainMeasureAndMeasureForceGc(restartMeasure: boolean) {
/** @internal */
private _endPlainMeasureAndMeasureForceGc(restartMeasure: boolean) {
return this._endMeasure(true).then((measureValues) => {
// disable frame capture for measurements during forced gc
var originalFrameCaptureValue = this._captureFrames;
@ -118,18 +142,21 @@ export class PerflogMetric extends Metric {
});
}
_beginMeasure(): Promise<any> {
/** @internal */
private _beginMeasure(): Promise<any> {
return this._driverExtension.timeBegin(this._markName(this._measureCount++));
}
_endMeasure(restart: boolean): Promise<{[key: string]: any}> {
/** @internal */
private _endMeasure(restart: boolean): Promise<{[key: string]: any}> {
var markName = this._markName(this._measureCount - 1);
var nextMarkName = restart ? this._markName(this._measureCount++) : null;
return this._driverExtension.timeEnd(markName, nextMarkName)
.then((_) => this._readUntilEndMark(markName));
}
_readUntilEndMark(markName: string, loopCount: number = 0, startEvent = null) {
/** @internal */
private _readUntilEndMark(markName: string, loopCount: number = 0, startEvent = null) {
if (loopCount > _MAX_RETRY_COUNT) {
throw new BaseException(`Tried too often to get the ending mark: ${loopCount}`);
}
@ -141,13 +168,14 @@ export class PerflogMetric extends Metric {
return result;
}
var completer = PromiseWrapper.completer();
this._setTimeout(() => completer.resolve(this._readUntilEndMark(markName, loopCount + 1)),
100);
this._setTimeout(
() => completer.resolve(this._readUntilEndMark(markName, loopCount + 1)), 100);
return completer.promise;
});
}
_addEvents(events: { [key: string]: string }[]) {
/** @internal */
private _addEvents(events: {[key: string]: string}[]) {
var needSort = false;
events.forEach(event => {
if (StringWrapper.equals(event['ph'], 'X')) {
@ -176,7 +204,8 @@ export class PerflogMetric extends Metric {
}
}
_aggregateEvents(events: Array<{[key: string]: any}>, markName): {[key: string]: any} {
/** @internal */
private _aggregateEvents(events: Array<{[key: string]: any}>, markName): {[key: string]: any} {
var result = {'scriptTime': 0, 'pureScriptTime': 0};
if (this._perfLogFeatures.gc) {
result['gcTime'] = 0;
@ -252,11 +281,11 @@ export class PerflogMetric extends Metric {
}
if (!this._captureFrames) {
throw new BaseException(
'found start event for frame capture, but frame capture was not requested in benchpress')
'found start event for frame capture, but frame capture was not requested in benchpress');
}
frameCaptureStartEvent = event;
} else if (StringWrapper.equals(ph, 'e') &&
StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) {
} else if (
StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) {
if (isBlank(frameCaptureStartEvent)) {
throw new BaseException('missing start event for frame capture');
}
@ -268,8 +297,9 @@ export class PerflogMetric extends Metric {
StringWrapper.equals(name, 'frame')) {
frameTimestamps.push(event['ts']);
if (frameTimestamps.length >= 2) {
frameTimes.push(frameTimestamps[frameTimestamps.length - 1] -
frameTimestamps[frameTimestamps.length - 2]);
frameTimes.push(
frameTimestamps[frameTimestamps.length - 1] -
frameTimestamps[frameTimestamps.length - 2]);
}
}
}
@ -281,8 +311,9 @@ export class PerflogMetric extends Metric {
} else {
intervalStartCount[name]++;
}
} else if ((StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) &&
isPresent(intervalStarts[name])) {
} else if (
(StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) &&
isPresent(intervalStarts[name])) {
intervalStartCount[name]--;
if (intervalStartCount[name] === 0) {
var startEvent = intervalStarts[name];
@ -334,7 +365,8 @@ export class PerflogMetric extends Metric {
return result;
}
_addFrameMetrics(result: {[key: string]: any}, frameTimes: any[]) {
/** @internal */
private _addFrameMetrics(result: {[key: string]: any}, frameTimes: any[]) {
result['frameTime.mean'] = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
var firstFrame = frameTimes[0];
result['frameTime.worst'] = frameTimes.reduce((a, b) => a > b ? a : b, firstFrame);
@ -343,7 +375,8 @@ export class PerflogMetric extends Metric {
frameTimes.filter(t => t < _FRAME_TIME_SMOOTH_THRESHOLD).length / frameTimes.length;
}
_markName(index) { return `${_MARK_NAME_PREFIX}${index}`; }
/** @internal */
private _markName(index) { return `${_MARK_NAME_PREFIX}${index}`; }
}
var _MICRO_ITERATIONS_REGEX = /(.+)\*(\d+)$/g;
@ -359,18 +392,14 @@ var _FRAME_TIME_SMOOTH_THRESHOLD = 17;
var _PROVIDERS = [
{
provide: PerflogMetric,
useFactory:
(driverExtension, setTimeout, microMetrics, forceGc, captureFrames, receivedData,
requestCount) => new PerflogMetric(driverExtension, setTimeout, microMetrics, forceGc,
captureFrames, receivedData, requestCount),
useFactory: (driverExtension, setTimeout, microMetrics, forceGc, captureFrames, receivedData,
requestCount) =>
new PerflogMetric(
driverExtension, setTimeout, microMetrics, forceGc, captureFrames,
receivedData, requestCount),
deps: [
WebDriverExtension,
_SET_TIMEOUT,
Options.MICRO_METRICS,
Options.FORCE_GC,
Options.CAPTURE_FRAMES,
Options.RECEIVED_DATA,
Options.REQUEST_COUNT
WebDriverExtension, _SET_TIMEOUT, Options.MICRO_METRICS, Options.FORCE_GC,
Options.CAPTURE_FRAMES, Options.RECEIVED_DATA, Options.REQUEST_COUNT
]
},
{provide: _SET_TIMEOUT, useValue: (fn, millis) => TimerWrapper.setTimeout(fn, millis)}

View File

@ -1,10 +1,18 @@
import {bind, Provider, OpaqueToken} from '@angular/core';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken, Provider, bind} from '@angular/core';
import {PromiseWrapper, TimerWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {isNumber} from '@angular/facade/src/lang';
import {Metric} from '../metric';
import {Options} from '../common_options';
import {Metric} from '../metric';
import {WebDriverAdapter} from '../web_driver_adapter';
export class UserMetric extends Metric {
@ -56,8 +64,7 @@ export class UserMetric extends Metric {
describe(): {[key: string]: any} { return this._userMetrics; }
}
var _PROVIDERS = [
bind(UserMetric)
.toFactory((userMetrics, wdAdapter) => new UserMetric(userMetrics, wdAdapter),
[Options.USER_METRICS, WebDriverAdapter])
];
var _PROVIDERS = [bind(UserMetric)
.toFactory(
(userMetrics, wdAdapter) => new UserMetric(userMetrics, wdAdapter),
[Options.USER_METRICS, WebDriverAdapter])];

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {MeasureValues} from './measure_values';

View File

@ -1,13 +1,22 @@
import {print, isPresent, isBlank, NumberWrapper} from '@angular/facade/src/lang';
import {StringMapWrapper, ListWrapper} from '@angular/facade/src/collection';
import {PromiseWrapper} from '@angular/facade/src/async';
import {Math} from '@angular/facade/src/math';
import {OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Statistic} from '../statistic';
import {OpaqueToken} from '@angular/core/src/di';
import {PromiseWrapper} from '@angular/facade/src/async';
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {NumberWrapper, isBlank, isPresent, print} from '@angular/facade/src/lang';
import {Math} from '@angular/facade/src/math';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
/**
* A reporter for the console
@ -21,7 +30,8 @@ export class ConsoleReporter extends Reporter {
static get PROVIDERS(): any[] { return _PROVIDERS; }
static _lpad(value, columnWidth, fill = ' ') {
/** @internal */
private static _lpad(value, columnWidth, fill = ' ') {
var result = '';
for (var i = 0; i < columnWidth - value.length; i++) {
result += fill;
@ -29,15 +39,18 @@ export class ConsoleReporter extends Reporter {
return result + value;
}
static _formatNum(n) { return NumberWrapper.toFixed(n, 2); }
/** @internal */
private static _formatNum(n) { return NumberWrapper.toFixed(n, 2); }
static _sortedProps(obj) {
/** @internal */
private static _sortedProps(obj) {
var props = [];
StringMapWrapper.forEach(obj, (value, prop) => props.push(prop));
props.sort();
return props;
}
/** @internal */
private _metricNames: string[];
constructor(private _columnWidth: number, sampleDescription, private _print: Function) {
@ -46,7 +59,8 @@ export class ConsoleReporter extends Reporter {
this._printDescription(sampleDescription);
}
_printDescription(sampleDescription) {
/** @internal */
private _printDescription(sampleDescription) {
this._print(`BENCHMARK ${sampleDescription.id}`);
this._print('Description:');
var props = ConsoleReporter._sortedProps(sampleDescription.description);
@ -75,17 +89,16 @@ export class ConsoleReporter extends Reporter {
var samples = validSamples.map(measureValues => measureValues.values[metricName]);
var mean = Statistic.calculateMean(samples);
var cv = Statistic.calculateCoefficientOfVariation(samples, mean);
var formattedMean = ConsoleReporter._formatNum(mean)
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return NumberWrapper.isNaN(cv) ?
formattedMean :
`${formattedMean}+-${Math.floor(cv)}%`;
var formattedMean = ConsoleReporter._formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause
// hickups for consoles...
return NumberWrapper.isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
}));
return PromiseWrapper.resolve(null);
}
_printStringRow(parts: any[], fill = ' ') {
/** @internal */
private _printStringRow(parts: any[], fill = ' ') {
this._print(
parts.map(part => ConsoleReporter._lpad(part, this._columnWidth, fill)).join(' | '));
}
@ -97,9 +110,8 @@ var _PROVIDERS = [
{
provide: ConsoleReporter,
useFactory: (columnWidth, sampleDescription, print) =>
new ConsoleReporter(columnWidth, sampleDescription, print),
new ConsoleReporter(columnWidth, sampleDescription, print),
deps: [_COLUMN_WIDTH, SampleDescription, _PRINT]
},
{provide: _COLUMN_WIDTH, useValue: 18},
{provide: _PRINT, useValue: print}
{provide: _COLUMN_WIDTH, useValue: 18}, {provide: _PRINT, useValue: print}
];

View File

@ -1,12 +1,20 @@
import {DateWrapper, isPresent, isBlank, Json} from '@angular/facade/src/lang';
import {PromiseWrapper} from '@angular/facade/src/async';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core/src/di';
import {PromiseWrapper} from '@angular/facade/src/async';
import {DateWrapper, Json, isBlank, isPresent} from '@angular/facade/src/lang';
import {Options} from '../common_options';
import {MeasureValues} from '../measure_values';
import {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description';
import {MeasureValues} from '../measure_values';
import {Options} from '../common_options';
/**
* A reporter that writes results into a json file.
@ -17,10 +25,14 @@ export class JsonFileReporter extends Reporter {
// TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; }
_writeFile: Function;
_path: string;
_description: SampleDescription;
_now: Function;
/** @internal */
private _writeFile: Function;
/** @internal */
private _path: string;
/** @internal */
private _description: SampleDescription;
/** @internal */
private _now: Function;
constructor(sampleDescription, path, writeFile, now) {
super();
@ -51,7 +63,7 @@ var _PROVIDERS = [
{
provide: JsonFileReporter,
useFactory: (sampleDescription, path, writeFile, now) =>
new JsonFileReporter(sampleDescription, path, writeFile, now),
new JsonFileReporter(sampleDescription, path, writeFile, now),
deps: [SampleDescription, _PATH, Options.WRITE_FILE, Options.NOW]
},
{provide: _PATH, useValue: '.'}

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, OpaqueToken} from '@angular/core/src/di';
import {PromiseWrapper} from '@angular/facade/src/async';
@ -12,11 +20,16 @@ export class MultiReporter extends Reporter {
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector],
},
{provide: MultiReporter, useFactory: children => new MultiReporter(children), deps: [_CHILDREN]}
{
provide: MultiReporter,
useFactory: children => new MultiReporter(children),
deps: [_CHILDREN]
}
];
}
_reporters: Reporter[];
/** @internal */
private _reporters: Reporter[];
constructor(reporters) {
super();

View File

@ -1,25 +1,34 @@
import {ReflectiveInjector} from '@angular/core';
import {isPresent, isBlank} from '@angular/facade/src/lang';
import {PromiseWrapper} from '@angular/facade/src/async';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Sampler, SampleState} from './sampler';
import {ReflectiveInjector} from '@angular/core';
import {PromiseWrapper} from '@angular/facade/src/async';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {Options} from './common_options';
import {Metric} from './metric';
import {MultiMetric} from './metric/multi_metric';
import {PerflogMetric} from './metric/perflog_metric';
import {UserMetric} from './metric/user_metric';
import {Reporter} from './reporter';
import {ConsoleReporter} from './reporter/console_reporter';
import {MultiReporter} from './reporter/multi_reporter';
import {SampleDescription} from './sample_description';
import {SampleState, Sampler} from './sampler';
import {Validator} from './validator';
import {RegressionSlopeValidator} from './validator/regression_slope_validator';
import {SizeValidator} from './validator/size_validator';
import {Validator} from './validator';
import {PerflogMetric} from './metric/perflog_metric';
import {MultiMetric} from './metric/multi_metric';
import {UserMetric} from './metric/user_metric';
import {WebDriverAdapter} from './web_driver_adapter';
import {WebDriverExtension} from './web_driver_extension';
import {ChromeDriverExtension} from './webdriver/chrome_driver_extension';
import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension';
import {IOsDriverExtension} from './webdriver/ios_driver_extension';
import {WebDriverExtension} from './web_driver_extension';
import {SampleDescription} from './sample_description';
import {WebDriverAdapter} from './web_driver_adapter';
import {Reporter} from './reporter';
import {Metric} from './metric';
import {Options} from './common_options';
/**
* The Runner is the main entry point for executing a sample run.
@ -34,13 +43,16 @@ export class Runner {
this._defaultProviders = defaultProviders;
}
sample({id, execute, prepare, microMetrics, providers, userMetrics}:
{id: string, execute?: any, prepare?: any, microMetrics?: any, providers?: any, userMetrics?: any}):
Promise<SampleState> {
sample({id, execute, prepare, microMetrics, providers, userMetrics}: {
id: string,
execute?: any,
prepare?: any,
microMetrics?: any,
providers?: any,
userMetrics?: any
}): Promise<SampleState> {
var sampleProviders = [
_DEFAULT_PROVIDERS,
this._defaultProviders,
{provide: Options.SAMPLE_ID, useValue: id},
_DEFAULT_PROVIDERS, this._defaultProviders, {provide: Options.SAMPLE_ID, useValue: id},
{provide: Options.EXECUTE, useValue: execute}
];
if (isPresent(prepare)) {
@ -71,8 +83,7 @@ export class Runner {
// TODO vsavkin consider changing it when toAsyncFactory is added back or when child
// injectors are handled better.
var injector = ReflectiveInjector.resolveAndCreate([
sampleProviders,
{provide: Options.CAPABILITIES, useValue: capabilities},
sampleProviders, {provide: Options.CAPABILITIES, useValue: capabilities},
{provide: Options.USER_AGENT, useValue: userAgent},
{provide: WebDriverAdapter, useValue: adapter}
]);

View File

@ -1,7 +1,17 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {StringMapWrapper} from '@angular/facade/src/collection';
import {Validator} from './validator';
import {Metric} from './metric';
import {Options} from './common_options';
import {Metric} from './metric';
import {Validator} from './validator';
/**
* SampleDescription merges all available descriptions about a sample
@ -11,8 +21,9 @@ export class SampleDescription {
static get PROVIDERS(): any[] { return _PROVIDERS; }
description: {[key: string]: any};
constructor(public id: string, descriptions: Array<{[key: string]: any}>,
public metrics: {[key: string]: any}) {
constructor(
public id: string, descriptions: Array<{[key: string]: any}>,
public metrics: {[key: string]: any}) {
this.description = {};
descriptions.forEach(description => {
StringMapWrapper.forEach(description, (value, prop) => this.description[prop] = value);
@ -22,26 +33,18 @@ export class SampleDescription {
toJson() { return {'id': this.id, 'description': this.description, 'metrics': this.metrics}; }
}
var _PROVIDERS = [
{
provide: SampleDescription,
useFactory: (metric, id, forceGc, userAgent, validator, defaultDesc, userDesc) =>
new SampleDescription(id,
[
{'forceGc': forceGc, 'userAgent': userAgent},
validator.describe(),
defaultDesc,
userDesc
],
metric.describe()),
deps: [
Metric,
Options.SAMPLE_ID,
Options.FORCE_GC,
Options.USER_AGENT,
Validator,
Options.DEFAULT_DESCRIPTION,
Options.SAMPLE_DESCRIPTION
]
}
];
var _PROVIDERS = [{
provide: SampleDescription,
useFactory: (metric, id, forceGc, userAgent, validator, defaultDesc, userDesc) =>
new SampleDescription(
id,
[
{'forceGc': forceGc, 'userAgent': userAgent}, validator.describe(),
defaultDesc, userDesc
],
metric.describe()),
deps: [
Metric, Options.SAMPLE_ID, Options.FORCE_GC, Options.USER_AGENT, Validator,
Options.DEFAULT_DESCRIPTION, Options.SAMPLE_DESCRIPTION
]
}];

View File

@ -1,13 +1,21 @@
import {isPresent, isBlank, Date, DateWrapper} from '@angular/facade/src/lang';
import {PromiseWrapper} from '@angular/facade/src/async';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Metric} from './metric';
import {Validator} from './validator';
import {Reporter} from './reporter';
import {WebDriverAdapter} from './web_driver_adapter';
import {PromiseWrapper} from '@angular/facade/src/async';
import {Date, DateWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {Options} from './common_options';
import {MeasureValues} from './measure_values';
import {Metric} from './metric';
import {Reporter} from './reporter';
import {Validator} from './validator';
import {WebDriverAdapter} from './web_driver_adapter';
/**
* The Sampler owns the sample loop:
@ -21,13 +29,20 @@ export class Sampler {
// TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; }
_driver: WebDriverAdapter;
_metric: Metric;
_reporter: Reporter;
_validator: Validator;
_prepare: Function;
_execute: Function;
_now: Function;
/** @internal */
private _driver: WebDriverAdapter;
/** @internal */
private _metric: Metric;
/** @internal */
private _reporter: Reporter;
/** @internal */
private _validator: Validator;
/** @internal */
private _prepare: Function;
/** @internal */
private _execute: Function;
/** @internal */
private _now: Function;
constructor({driver, metric, reporter, validator, prepare, execute, now}: {
driver?: WebDriverAdapter,
@ -61,7 +76,8 @@ export class Sampler {
return loop(new SampleState([], null));
}
_iterate(lastState): Promise<SampleState> {
/** @internal */
private _iterate(lastState): Promise<SampleState> {
var resultPromise: Promise<any>;
if (isPresent(this._prepare)) {
resultPromise = this._driver.waitFor(this._prepare);
@ -76,14 +92,15 @@ export class Sampler {
.then((measureValues) => this._report(lastState, measureValues));
}
_report(state: SampleState, metricValues: {[key: string]: any}): Promise<SampleState> {
/** @internal */
private _report(state: SampleState, metricValues: {[key: string]: any}): Promise<SampleState> {
var measureValues = new MeasureValues(state.completeSample.length, this._now(), metricValues);
var completeSample = state.completeSample.concat([measureValues]);
var validSample = this._validator.validate(completeSample);
var resultPromise = this._reporter.reportMeasureValues(measureValues);
if (isPresent(validSample)) {
resultPromise =
resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample))
resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample));
}
return resultPromise.then((_) => new SampleState(completeSample, validSample));
}
@ -93,29 +110,21 @@ export class SampleState {
constructor(public completeSample: any[], public validSample: any[]) {}
}
var _PROVIDERS = [
{
provide: Sampler,
useFactory: (driver, metric, reporter, validator, prepare, execute, now) => new Sampler({
driver: driver,
reporter: reporter,
validator: validator,
metric: metric,
// TODO(tbosch): DI right now does not support null/undefined objects
// Mostly because the cache would have to be initialized with a
// special null object, which is expensive.
prepare: prepare !== false ? prepare : null,
execute: execute,
now: now
}),
deps: [
WebDriverAdapter,
Metric,
Reporter,
Validator,
Options.PREPARE,
Options.EXECUTE,
Options.NOW
]
}
];
var _PROVIDERS = [{
provide: Sampler,
useFactory: (driver, metric, reporter, validator, prepare, execute, now) => new Sampler({
driver: driver,
reporter: reporter,
validator: validator,
metric: metric,
// TODO(tbosch): DI right now does not support null/undefined objects
// Mostly because the cache would have to be initialized with a
// special null object, which is expensive.
prepare: prepare !== false ? prepare : null,
execute: execute,
now: now
}),
deps: [
WebDriverAdapter, Metric, Reporter, Validator, Options.PREPARE, Options.EXECUTE, Options.NOW
]
}];

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Math} from '@angular/facade/src/math';
export class Statistic {
@ -21,8 +29,8 @@ export class Statistic {
return deviation;
}
static calculateRegressionSlope(xValues: number[], xMean: number, yValues: number[],
yMean: number) {
static calculateRegressionSlope(
xValues: number[], xMean: number, yValues: number[], yMean: number) {
// See http://en.wikipedia.org/wiki/Simple_linear_regression
var dividendSum = 0;
var divisorSum = 0;

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {MeasureValues} from './measure_values';

View File

@ -1,9 +1,18 @@
import {ListWrapper} from '@angular/facade/src/collection';
import {OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core/src/di';
import {ListWrapper} from '@angular/facade/src/collection';
import {Validator} from '../validator';
import {Statistic} from '../statistic';
import {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
import {Validator} from '../validator';
/**
* A validator that checks the regression slope of a specific metric.
@ -17,8 +26,10 @@ export class RegressionSlopeValidator extends Validator {
// TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; }
_sampleSize: number;
_metric: string;
/** @internal */
private _sampleSize: number;
/** @internal */
private _metric: string;
constructor(sampleSize, metric) {
super();
@ -32,8 +43,8 @@ export class RegressionSlopeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
var latestSample = ListWrapper.slice(completeSample, completeSample.length - this._sampleSize,
completeSample.length);
var latestSample = ListWrapper.slice(
completeSample, completeSample.length - this._sampleSize, completeSample.length);
var xValues = [];
var yValues = [];
for (var i = 0; i < latestSample.length; i++) {
@ -59,6 +70,5 @@ var _PROVIDERS = [
useFactory: (sampleSize, metric) => new RegressionSlopeValidator(sampleSize, metric),
deps: [_SAMPLE_SIZE, _METRIC]
},
{provide: _SAMPLE_SIZE, useValue: 10},
{provide: _METRIC, useValue: 'scriptTime'}
{provide: _SAMPLE_SIZE, useValue: 10}, {provide: _METRIC, useValue: 'scriptTime'}
];

View File

@ -1,8 +1,17 @@
import {ListWrapper} from '@angular/facade/src/collection';
import {OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {OpaqueToken} from '@angular/core/src/di';
import {ListWrapper} from '@angular/facade/src/collection';
import {Validator} from '../validator';
import {MeasureValues} from '../measure_values';
import {Validator} from '../validator';
/**
* A validator that waits for the sample to have a certain size.
@ -13,7 +22,8 @@ export class SizeValidator extends Validator {
// TODO(tbosch): use static values when our transpiler supports them
static get SAMPLE_SIZE() { return _SAMPLE_SIZE; }
_sampleSize: number;
/** @internal */
private _sampleSize: number;
constructor(size) {
super();
@ -24,8 +34,8 @@ export class SizeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) {
return ListWrapper.slice(completeSample, completeSample.length - this._sampleSize,
completeSample.length);
return ListWrapper.slice(
completeSample, completeSample.length - this._sampleSize, completeSample.length);
} else {
return null;
}
@ -34,10 +44,6 @@ export class SizeValidator extends Validator {
var _SAMPLE_SIZE = new OpaqueToken('SizeValidator.sampleSize');
var _PROVIDERS = [
{
provide: SizeValidator,
useFactory: (size) => new SizeValidator(size),
deps: [_SAMPLE_SIZE]
},
{provide: SizeValidator, useFactory: (size) => new SizeValidator(size), deps: [_SAMPLE_SIZE]},
{provide: _SAMPLE_SIZE, useValue: 10}
];

View File

@ -1,5 +1,14 @@
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Map} from '@angular/facade/src/collection';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/**
* A WebDriverAdapter bridges API differences between different WebDriver clients,

View File

@ -1,10 +1,18 @@
import {Injector, OpaqueToken} from '@angular/core/src/di';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {Injector, OpaqueToken} from '@angular/core/src/di';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {Options} from './common_options';
/**
* A WebDriverExtension implements extended commands of the webdriver protocol
* for a given browser, independent of the WebDriverAdapter.
@ -20,7 +28,7 @@ export abstract class WebDriverExtension {
},
{
provide: WebDriverExtension,
useFactory: (children:WebDriverExtension[], capabilities) => {
useFactory: (children: WebDriverExtension[], capabilities) => {
var delegate;
children.forEach(extension => {
if (extension.supports(capabilities)) {

View File

@ -1,17 +1,19 @@
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {
Json,
isPresent,
isBlank,
RegExpWrapper,
StringWrapper,
NumberWrapper
} from '@angular/facade/src/lang';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {Json, NumberWrapper, RegExpWrapper, StringWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {WebDriverAdapter} from '../web_driver_adapter';
import {Options} from '../common_options';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
/**
* Set the following 'traceCategories' to collect metrics in Chrome:
@ -55,7 +57,7 @@ export class ChromeDriverExtension extends WebDriverExtension {
timeEnd(name: string, restartName: string = null): Promise<any> {
var script = `console.timeEnd('${name}');`;
if (isPresent(restartName)) {
script += `console.time('${restartName}');`
script += `console.time('${restartName}');`;
}
return this._driver.executeScript(script);
}
@ -82,8 +84,9 @@ export class ChromeDriverExtension extends WebDriverExtension {
});
}
private _convertPerfRecordsToEvents(chromeEvents: Array<{[key: string]: any}>,
normalizedEvents: Array<{[key: string]: any}> = null) {
private _convertPerfRecordsToEvents(
chromeEvents: Array<{[key: string]: any}>,
normalizedEvents: Array<{[key: string]: any}> = null) {
if (isBlank(normalizedEvents)) {
normalizedEvents = [];
}
@ -93,8 +96,9 @@ export class ChromeDriverExtension extends WebDriverExtension {
var name = event['name'];
if (this._isEvent(categories, name, ['blink.console'])) {
normalizedEvents.push(normalizeEvent(event, {'name': name}));
} else if (this._isEvent(categories, name, ['benchmark'],
'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
} else if (this._isEvent(
categories, name, ['benchmark'],
'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
// following events should be used (if available) for more accurate measurments:
// 1st choice: vsync_before - ground truth on Android
@ -109,10 +113,10 @@ export class ChromeDriverExtension extends WebDriverExtension {
if (frameCount == 1) {
normalizedEvents.push(normalizeEvent(event, {'name': 'frame'}));
}
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Rasterize') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'CompositeLayers')) {
} else if (
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') ||
this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) {
normalizedEvents.push(normalizeEvent(event, {'name': 'render'}));
} else if (this._majorChromeVersion < 45) {
var normalizedEvent = this._processAsPreChrome45Event(event, categories, majorGCPids);
@ -130,22 +134,21 @@ export class ChromeDriverExtension extends WebDriverExtension {
var args = event['args'];
var pid = event['pid'];
var ph = event['ph'];
if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'FunctionCall') &&
if (this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'RecalculateStyles') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Layout') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'UpdateLayerTree') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'Paint')) {
} else if (
this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'RecalculateStyles') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Layout') ||
this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Paint')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'],
'GCEvent')) {
} else if (this._isEvent(
categories, name, ['disabled-by-default-devtools.timeline'], 'GCEvent')) {
var normArgs = {
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore']
@ -155,8 +158,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
}
majorGCPids[pid] = false;
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['v8'], 'majorGC') &&
StringWrapper.equals(ph, 'B')) {
} else if (
this._isEvent(categories, name, ['v8'], 'majorGC') && StringWrapper.equals(ph, 'B')) {
majorGCPids[pid] = true;
}
return null; // nothing useful in this event
@ -179,17 +182,19 @@ export class ChromeDriverExtension extends WebDriverExtension {
args['usedHeapSizeBefore']
};
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
(!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript') &&
!StringWrapper.equals(args['data']['scriptName'], '')))) {
} else if (
this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) ||
(!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript') &&
!StringWrapper.equals(args['data']['scriptName'], '')))) {
return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'blink'],
'UpdateLayoutTree')) {
} else if (this._isEvent(
categories, name, ['devtools.timeline', 'blink'], 'UpdateLayoutTree')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
} else if (
this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceReceivedData')) {
let normArgs = {'encodedDataLength': args['data']['encodedDataLength']};
@ -206,8 +211,9 @@ export class ChromeDriverExtension extends WebDriverExtension {
private _parseCategories(categories: string): string[] { return categories.split(','); }
private _isEvent(eventCategories: string[], eventName: string, expectedCategories: string[],
expectedName: string = null): boolean {
private _isEvent(
eventCategories: string[], eventName: string, expectedCategories: string[],
expectedName: string = null): boolean {
var hasCategories = expectedCategories.reduce(
(value, cat) => { return value && ListWrapper.contains(eventCategories, cat); }, true);
return isBlank(expectedName) ? hasCategories :
@ -220,12 +226,12 @@ export class ChromeDriverExtension extends WebDriverExtension {
supports(capabilities: {[key: string]: any}): boolean {
return this._majorChromeVersion != -1 &&
StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'chrome');
StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'chrome');
}
}
function normalizeEvent(chromeEvent: {[key: string]: any},
data: {[key: string]: any}): {[key: string]: any} {
function normalizeEvent(
chromeEvent: {[key: string]: any}, data: {[key: string]: any}): {[key: string]: any} {
var ph = chromeEvent['ph'];
if (StringWrapper.equals(ph, 'S')) {
ph = 'b';
@ -245,10 +251,8 @@ function normalizeEvent(chromeEvent: {[key: string]: any},
return result;
}
var _PROVIDERS = [
{
provide: ChromeDriverExtension,
useFactory: (driver, userAgent) => new ChromeDriverExtension(driver, userAgent),
deps: [WebDriverAdapter, Options.USER_AGENT]
}
];
var _PROVIDERS = [{
provide: ChromeDriverExtension,
useFactory: (driver, userAgent) => new ChromeDriverExtension(driver, userAgent),
deps: [WebDriverAdapter, Options.USER_AGENT]
}];

View File

@ -1,6 +1,15 @@
import {isPresent, StringWrapper} from '@angular/facade/src/lang';
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {StringWrapper, isPresent} from '@angular/facade/src/lang';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
export class FirefoxDriverExtension extends WebDriverExtension {
static get PROVIDERS(): any[] { return _PROVIDERS; }
@ -41,10 +50,8 @@ export class FirefoxDriverExtension extends WebDriverExtension {
}
}
var _PROVIDERS = [
{
provide: FirefoxDriverExtension,
useFactory: (driver) => new FirefoxDriverExtension(driver),
deps: [WebDriverAdapter]
}
];
var _PROVIDERS = [{
provide: FirefoxDriverExtension,
useFactory: (driver) => new FirefoxDriverExtension(driver),
deps: [WebDriverAdapter]
}];

View File

@ -1,8 +1,16 @@
import {Json, isPresent, isBlank, RegExpWrapper, StringWrapper} from '@angular/facade/src/lang';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {Json, RegExpWrapper, StringWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
import {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
export class IOsDriverExtension extends WebDriverExtension {
// TODO(tbosch): use static values when our transpiler supports them
@ -19,7 +27,7 @@ export class IOsDriverExtension extends WebDriverExtension {
timeEnd(name: string, restartName: string = null): Promise<any> {
var script = `console.timeEnd('${name}');`;
if (isPresent(restartName)) {
script += `console.time('${restartName}');`
script += `console.time('${restartName}');`;
}
return this._driver.executeScript(script);
}
@ -42,7 +50,8 @@ export class IOsDriverExtension extends WebDriverExtension {
});
}
_convertPerfRecordsToEvents(records: any[], events: any[] = null) {
/** @internal */
private _convertPerfRecordsToEvents(records: any[], events: any[] = null) {
if (isBlank(events)) {
events = [];
}
@ -61,11 +70,11 @@ export class IOsDriverExtension extends WebDriverExtension {
events.push(createMarkStartEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'TimeEnd')) {
events.push(createMarkEndEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'RecalculateStyles') ||
StringWrapper.equals(type, 'Layout') ||
StringWrapper.equals(type, 'UpdateLayerTree') ||
StringWrapper.equals(type, 'Paint') || StringWrapper.equals(type, 'Rasterize') ||
StringWrapper.equals(type, 'CompositeLayers')) {
} else if (
StringWrapper.equals(type, 'RecalculateStyles') || StringWrapper.equals(type, 'Layout') ||
StringWrapper.equals(type, 'UpdateLayerTree') || StringWrapper.equals(type, 'Paint') ||
StringWrapper.equals(type, 'Rasterize') ||
StringWrapper.equals(type, 'CompositeLayers')) {
events.push(createStartEvent('render', startTime));
endEvent = createEndEvent('render', endTime);
}
@ -119,6 +128,8 @@ function createMarkEndEvent(name, time) {
return createEvent('e', name, time);
}
var _PROVIDERS = [
{provide: IOsDriverExtension, useFactory: (driver) => new IOsDriverExtension(driver), deps: [WebDriverAdapter]}
];
var _PROVIDERS = [{
provide: IOsDriverExtension,
useFactory: (driver) => new IOsDriverExtension(driver),
deps: [WebDriverAdapter]
}];

View File

@ -1,7 +1,16 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {PromiseWrapper} from '@angular/facade/src/async';
import * as webdriver from 'selenium-webdriver';
import {WebDriverAdapter} from '../web_driver_adapter';
import * as webdriver from 'selenium-webdriver';
/**
* Adapter for the selenium-webdriver.
@ -11,7 +20,8 @@ export class SeleniumWebDriverAdapter extends WebDriverAdapter {
constructor(private _driver: any) { super(); }
_convertPromise(thenable) {
/** @internal */
private _convertPromise(thenable) {
var completer = PromiseWrapper.completer();
thenable.then(
// selenium-webdriver uses an own Node.js context,
@ -55,6 +65,8 @@ function convertToLocalProcess(data): Object {
return JSON.parse(serialized);
}
var _PROTRACTOR_BINDINGS = [
{provide: WebDriverAdapter, useFactory: () => new SeleniumWebDriverAdapter((<any>global).browser), deps: []}
];
var _PROTRACTOR_BINDINGS = [{
provide: WebDriverAdapter,
useFactory: () => new SeleniumWebDriverAdapter((<any>global).browser),
deps: []
}];

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
require('es6-shim/es6-shim.js');
require('reflect-metadata');
var testHelper = require('../../src/firefox_extension/lib/test_helper.js');

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {convertPerfProfileToEvents} from 'benchpress/src/firefox_extension/lib/parser_util';
function assertEventsEqual(actualEvents, expectedEvents) {
@ -25,56 +33,48 @@ export function main() {
it('should convert single non-instantaneous event', function() {
var profileData = {
threads: [
{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}
]
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}]
};
var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents,
[{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
assertEventsEqual(
perfEvents, [{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
});
it('should convert multiple instantaneous events', function() {
var profileData = {
threads: [
{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]}
]
}
]
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]}
]
}]
};
var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents,
[{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
assertEventsEqual(
perfEvents, [{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
});
it('should convert multiple mixed events', function() {
var profileData = {
threads: [
{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]},
{time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}
]
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]},
{time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}]
};
var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [
{ph: 'X', ts: 1, name: 'script'},
{ph: 'X', ts: 2, name: 'render'},
{ph: 'B', ts: 5, name: 'script'},
{ph: 'E', ts: 10, name: 'script'}
{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'},
{ph: 'B', ts: 5, name: 'script'}, {ph: 'E', ts: 10, name: 'script'}
]);
});
@ -86,14 +86,12 @@ export function main() {
it('should skip unknown events', function() {
var profileData = {
threads: [
{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'foo'}]}
]
}
]
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'foo'}]}
]
}]
};
var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var benchpress = require('../../index.js');
var runner = new benchpress.Runner([
// use protractor as Webdriver client
@ -21,12 +29,12 @@ describe('deep tree baseline', function() {
* Benchpress will log the collected metrics after each sample is collected, and will stop
* sampling as soon as the calculated regression slope for last 20 samples is stable.
*/
runner.sample({
id: 'baseline',
execute: function() { $('button')
.click(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
})
runner
.sample({
id: 'baseline',
execute: function() { $('button').click(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
})
.then(done, done.fail);
});
});

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var assertEventsContainsName = function(events, eventName) {
var found = false;
for (var i = 0; i < events.length; ++i) {
@ -17,8 +25,9 @@ describe('firefox extension', function() {
browser.driver.get(TEST_URL);
browser.executeScript('window.startProfiler()')
.then(function() { console.log('started measuring perf'); });
browser.executeScript('window.startProfiler()').then(function() {
console.log('started measuring perf');
});
browser.executeAsyncScript('setTimeout(arguments[0], 1000);');
browser.executeScript('window.forceGC()');
@ -28,5 +37,5 @@ describe('firefox extension', function() {
assertEventsContainsName(profile, 'gc');
assertEventsContainsName(profile, 'script');
});
})
});
});

View File

@ -1,44 +1,48 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Metric, MultiMetric, ReflectiveInjector} from 'benchpress/common';
export function main() {
function createMetric(ids: any[]) {
var m = ReflectiveInjector.resolveAndCreate([
ids.map(id => {return {provide: id, useValue: new MockMetric(id)}}),
MultiMetric.createBindings(ids)
])
var m = ReflectiveInjector
.resolveAndCreate([
ids.map(id => { return {provide: id, useValue: new MockMetric(id)}; }),
MultiMetric.createBindings(ids)
])
.get(MultiMetric);
return Promise.resolve(m);
}
describe('multi metric', () => {
it('should merge descriptions', inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2'])
.then((m) => {
expect(m.describe()).toEqual({'m1': 'describe', 'm2': 'describe'});
async.done();
});
createMetric(['m1', 'm2']).then((m) => {
expect(m.describe()).toEqual({'m1': 'describe', 'm2': 'describe'});
async.done();
});
}));
it('should merge all beginMeasure calls', inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2'])
.then((m) => m.beginMeasure())
.then((values) => {
expect(values).toEqual(['m1_beginMeasure', 'm2_beginMeasure']);
async.done();
});
createMetric(['m1', 'm2']).then((m) => m.beginMeasure()).then((values) => {
expect(values).toEqual(['m1_beginMeasure', 'm2_beginMeasure']);
async.done();
});
}));
[false, true].forEach((restartFlag) => {
it(`should merge all endMeasure calls for restart=${restartFlag}`,
inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2'])
.then((m) => m.endMeasure(restartFlag))
.then((values) => {
expect(values)
.toEqual({'m1': {'restart': restartFlag}, 'm2': {'restart': restartFlag}});
async.done();
});
createMetric(['m1', 'm2']).then((m) => m.endMeasure(restartFlag)).then((values) => {
expect(values).toEqual(
{'m1': {'restart': restartFlag}, 'm2': {'restart': restartFlag}});
async.done();
});
}));
});
@ -46,7 +50,8 @@ export function main() {
}
class MockMetric extends Metric {
_id: string;
/** @internal */
private _id: string;
constructor(id) {
super();

View File

@ -1,17 +1,16 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {StringMapWrapper} from '@angular/facade/src/collection';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {isPresent, isBlank} from '@angular/facade/src/lang';
import {
Metric,
PerflogMetric,
WebDriverExtension,
PerfLogFeatures,
ReflectiveInjector,
Options
} from 'benchpress/common';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {Metric, Options, PerfLogFeatures, PerflogMetric, ReflectiveInjector, WebDriverExtension} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory';
@ -19,14 +18,15 @@ export function main() {
var commandLog: any[];
var eventFactory = new TraceEventFactory('timeline', 'pid0');
function createMetric(perfLogs, perfLogFeatures,
{microMetrics, forceGc, captureFrames, receivedData, requestCount}: {
microMetrics?: {[key: string]: string},
forceGc?: boolean,
captureFrames?: boolean,
receivedData?: boolean,
requestCount?: boolean
} = {}): Metric {
function createMetric(
perfLogs, perfLogFeatures,
{microMetrics, forceGc, captureFrames, receivedData, requestCount}: {
microMetrics?: {[key: string]: string},
forceGc?: boolean,
captureFrames?: boolean,
receivedData?: boolean,
requestCount?: boolean
} = {}): Metric {
commandLog = [];
if (isBlank(perfLogFeatures)) {
perfLogFeatures =
@ -36,10 +36,8 @@ export function main() {
microMetrics = StringMapWrapper.create();
}
var providers: any[] = [
Options.DEFAULT_PROVIDERS,
PerflogMetric.PROVIDERS,
{provide: Options.MICRO_METRICS, useValue: microMetrics},
{
Options.DEFAULT_PROVIDERS, PerflogMetric.PROVIDERS,
{provide: Options.MICRO_METRICS, useValue: microMetrics}, {
provide: PerflogMetric.SET_TIMEOUT,
useValue: (fn, millis) => {
commandLog.push(['setTimeout', millis]);
@ -76,35 +74,31 @@ export function main() {
}
it('should describe itself based on the perfLogFeatrues', () => {
expect(sortedKeys(createMetric([[]], new PerfLogFeatures()).describe()))
.toEqual(['pureScriptTime', 'scriptTime']);
expect(sortedKeys(createMetric([[]], new PerfLogFeatures()).describe())).toEqual([
'pureScriptTime', 'scriptTime'
]);
expect(
sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: false})).describe()))
.toEqual(['pureScriptTime', 'renderTime', 'scriptTime']);
expect(sortedKeys(createMetric([[]], null).describe()))
.toEqual(
['gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime', 'renderTime', 'scriptTime']);
expect(sortedKeys(createMetric([[]], null).describe())).toEqual([
'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime', 'renderTime', 'scriptTime'
]);
expect(sortedKeys(
createMetric([[]], new PerfLogFeatures({render: true, gc: true}), {forceGc: true})
.describe()))
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: true}), {
forceGc: true
}).describe()))
.toEqual([
'forcedGcAmount',
'forcedGcTime',
'gcAmount',
'gcTime',
'majorGcTime',
'pureScriptTime',
'renderTime',
'scriptTime'
'forcedGcAmount', 'forcedGcTime', 'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime',
'renderTime', 'scriptTime'
]);
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({userTiming: true}),
{receivedData: true, requestCount: true})
.describe()))
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({userTiming: true}), {
receivedData: true,
requestCount: true
}).describe()))
.toEqual(['pureScriptTime', 'receivedData', 'requestCount', 'scriptTime']);
});
@ -115,9 +109,9 @@ export function main() {
});
it('should describe itself if frame capture is requested and available', () => {
var description =
createMetric([[]], new PerfLogFeatures({frameCapture: true}), {captureFrames: true})
.describe();
var description = createMetric([[]], new PerfLogFeatures({frameCapture: true}), {
captureFrames: true
}).describe();
expect(description['frameTime.mean']).not.toContain('WARNING');
expect(description['frameTime.best']).not.toContain('WARNING');
expect(description['frameTime.worst']).not.toContain('WARNING');
@ -125,9 +119,9 @@ export function main() {
});
it('should describe itself if frame capture is requested and not available', () => {
var description =
createMetric([[]], new PerfLogFeatures({frameCapture: false}), {captureFrames: true})
.describe();
var description = createMetric([[]], new PerfLogFeatures({frameCapture: false}), {
captureFrames: true
}).describe();
expect(description['frameTime.mean']).toContain('WARNING');
expect(description['frameTime.best']).toContain('WARNING');
expect(description['frameTime.worst']).toContain('WARNING');
@ -160,28 +154,19 @@ export function main() {
it('should mark and aggregate events in between the marks',
inject([AsyncTestCompleter], (async) => {
var events = [
[
eventFactory.markStart('benchpress0', 0),
eventFactory.start('script', 4),
eventFactory.end('script', 6),
eventFactory.markEnd('benchpress0', 10)
]
];
var events = [[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10)
]];
var metric = createMetric(events, null);
metric.beginMeasure()
.then((_) => metric.endMeasure(false))
.then((data) => {
expect(commandLog)
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', null],
'readPerfLog'
]);
expect(data['scriptTime']).toBe(2);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(2);
async.done();
});
async.done();
});
}));
it('should restart timing', inject([AsyncTestCompleter], (async) => {
@ -198,14 +183,10 @@ export function main() {
.then((_) => metric.endMeasure(true))
.then((_) => metric.endMeasure(true))
.then((_) => {
expect(commandLog)
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['timeEnd', 'benchpress1', 'benchpress2'],
'readPerfLog'
]);
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
]);
async.done();
});
@ -217,44 +198,32 @@ export function main() {
[eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 1)],
[eventFactory.end('script', 2)],
[
eventFactory.start('script', 3),
eventFactory.end('script', 5),
eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.markEnd('benchpress0', 10)
]
];
var metric = createMetric(events, null);
metric.beginMeasure()
.then((_) => metric.endMeasure(false))
.then((data) => {
expect(commandLog)
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', null],
'readPerfLog',
['setTimeout', 100],
'readPerfLog',
['setTimeout', 100],
'readPerfLog'
]);
expect(data['scriptTime']).toBe(3);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog',
['setTimeout', 100], 'readPerfLog', ['setTimeout', 100], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(3);
async.done();
});
async.done();
});
}));
it('should store events after the end mark for the next call',
inject([AsyncTestCompleter], (async) => {
var events = [
[
eventFactory.markStart('benchpress0', 0),
eventFactory.markEnd('benchpress0', 1),
eventFactory.markStart('benchpress1', 1),
eventFactory.start('script', 1),
eventFactory.markStart('benchpress0', 0), eventFactory.markEnd('benchpress0', 1),
eventFactory.markStart('benchpress1', 1), eventFactory.start('script', 1),
eventFactory.end('script', 2)
],
[
eventFactory.start('script', 3),
eventFactory.end('script', 5),
eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.markEnd('benchpress1', 6)
]
];
@ -263,17 +232,13 @@ export function main() {
.then((_) => metric.endMeasure(true))
.then((data) => {
expect(data['scriptTime']).toBe(0);
return metric.endMeasure(true)
return metric.endMeasure(true);
})
.then((data) => {
expect(commandLog)
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['timeEnd', 'benchpress1', 'benchpress2'],
'readPerfLog'
]);
expect(commandLog).toEqual([
['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
]);
expect(data['scriptTime']).toBe(3);
async.done();
@ -283,51 +248,37 @@ export function main() {
describe('with forced gc', () => {
var events;
beforeEach(() => {
events = [
[
eventFactory.markStart('benchpress0', 0),
eventFactory.start('script', 4),
eventFactory.end('script', 6),
eventFactory.markEnd('benchpress0', 10),
eventFactory.markStart('benchpress1', 11),
eventFactory.start('gc', 12, {'usedHeapSize': 2500}),
eventFactory.end('gc', 15, {'usedHeapSize': 1000}),
eventFactory.markEnd('benchpress1', 20)
]
];
events = [[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10),
eventFactory.markStart('benchpress1', 11),
eventFactory.start('gc', 12, {'usedHeapSize': 2500}),
eventFactory.end('gc', 15, {'usedHeapSize': 1000}),
eventFactory.markEnd('benchpress1', 20)
]];
});
it('should measure forced gc', inject([AsyncTestCompleter], (async) => {
var metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure()
.then((_) => metric.endMeasure(false))
.then((data) => {
expect(commandLog)
.toEqual([
['gc'],
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['gc'],
['timeEnd', 'benchpress1', null],
'readPerfLog'
]);
expect(data['forcedGcTime']).toBe(3);
expect(data['forcedGcAmount']).toBe(1.5);
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(commandLog).toEqual([
['gc'], ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog', ['gc'], ['timeEnd', 'benchpress1', null], 'readPerfLog'
]);
expect(data['forcedGcTime']).toBe(3);
expect(data['forcedGcAmount']).toBe(1.5);
async.done();
});
async.done();
});
}));
it('should restart after the forced gc if needed', inject([AsyncTestCompleter], (async) => {
var metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure()
.then((_) => metric.endMeasure(true))
.then((data) => {
expect(commandLog[5]).toEqual(['timeEnd', 'benchpress1', 'benchpress2']);
metric.beginMeasure().then((_) => metric.endMeasure(true)).then((data) => {
expect(commandLog[5]).toEqual(['timeEnd', 'benchpress1', 'benchpress2']);
async.done();
});
async.done();
});
}));
});
@ -357,10 +308,8 @@ export function main() {
it('should calculate mean frame time', inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0),
eventFactory.instant('frame', 1),
eventFactory.instant('frame', 3),
eventFactory.instant('frame', 4),
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 3), eventFactory.instant('frame', 4),
eventFactory.markEnd('frameCapture', 5)
],
{captureFrames: true})
@ -376,8 +325,9 @@ export function main() {
[eventFactory.instant('frame', 4), eventFactory.markEnd('frameCapture', 5)],
{captureFrames: true}),
(err): any => {
expect(() => { throw err; })
.toThrowError('missing start event for frame capture');
expect(() => {
throw err;
}).toThrowError('missing start event for frame capture');
async.done();
});
}));
@ -402,8 +352,9 @@ export function main() {
],
{captureFrames: true}),
(err): any => {
expect(() => { throw err; })
.toThrowError('can capture frames only once per benchmark run');
expect(() => {
throw err;
}).toThrowError('can capture frames only once per benchmark run');
async.done();
});
}));
@ -432,14 +383,10 @@ export function main() {
it('should calculate best and worst frame time', inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0),
eventFactory.instant('frame', 1),
eventFactory.instant('frame', 9),
eventFactory.instant('frame', 15),
eventFactory.instant('frame', 18),
eventFactory.instant('frame', 28),
eventFactory.instant('frame', 32),
eventFactory.markEnd('frameCapture', 10)
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 9), eventFactory.instant('frame', 15),
eventFactory.instant('frame', 18), eventFactory.instant('frame', 28),
eventFactory.instant('frame', 32), eventFactory.markEnd('frameCapture', 10)
],
{captureFrames: true})
.then((data) => {
@ -453,10 +400,8 @@ export function main() {
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0),
eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2),
eventFactory.instant('frame', 3),
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2), eventFactory.instant('frame', 3),
eventFactory.markEnd('frameCapture', 4)
],
{captureFrames: true})
@ -470,12 +415,9 @@ export function main() {
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.markStart('frameCapture', 0),
eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2),
eventFactory.instant('frame', 22),
eventFactory.instant('frame', 23),
eventFactory.instant('frame', 24),
eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 2), eventFactory.instant('frame', 22),
eventFactory.instant('frame', 23), eventFactory.instant('frame', 24),
eventFactory.markEnd('frameCapture', 4)
],
{captureFrames: true})
@ -488,173 +430,158 @@ export function main() {
});
it('should report a single interval', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 0), eventFactory.end('script', 5)])
.then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
aggregate([
eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should sum up multiple intervals', inject([AsyncTestCompleter], (async) => {
aggregate([
eventFactory.start('script', 0),
eventFactory.end('script', 5),
eventFactory.start('script', 10),
eventFactory.end('script', 17)
])
.then((data) => {
expect(data['scriptTime']).toBe(12);
async.done();
});
eventFactory.start('script', 0), eventFactory.end('script', 5),
eventFactory.start('script', 10), eventFactory.end('script', 17)
]).then((data) => {
expect(data['scriptTime']).toBe(12);
async.done();
});
}));
it('should ignore not started intervals', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.end('script', 10)])
.then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
aggregate([eventFactory.end('script', 10)]).then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
}));
it('should ignore not ended intervals', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 10)])
.then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
aggregate([eventFactory.start('script', 10)]).then((data) => {
expect(data['scriptTime']).toBe(0);
async.done();
});
}));
it('should ignore nested intervals', inject([AsyncTestCompleter], (async) => {
aggregate([
eventFactory.start('script', 0),
eventFactory.start('script', 5),
eventFactory.end('script', 10),
eventFactory.end('script', 17)
])
.then((data) => {
expect(data['scriptTime']).toBe(17);
async.done();
});
eventFactory.start('script', 0), eventFactory.start('script', 5),
eventFactory.end('script', 10), eventFactory.end('script', 17)
]).then((data) => {
expect(data['scriptTime']).toBe(17);
async.done();
});
}));
it('should ignore events from different processed as the start mark',
inject([AsyncTestCompleter], (async) => {
var otherProcessEventFactory = new TraceEventFactory('timeline', 'pid1');
var metric = createMetric(
[
[
eventFactory.markStart('benchpress0', 0),
eventFactory.start('script', 0, null),
eventFactory.end('script', 5, null),
otherProcessEventFactory.start('script', 10, null),
otherProcessEventFactory.end('script', 17, null),
eventFactory.markEnd('benchpress0', 20)
]
],
[[
eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 0, null),
eventFactory.end('script', 5, null),
otherProcessEventFactory.start('script', 10, null),
otherProcessEventFactory.end('script', 17, null),
eventFactory.markEnd('benchpress0', 20)
]],
null);
metric.beginMeasure()
.then((_) => metric.endMeasure(false))
.then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should support scriptTime metric', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 0), eventFactory.end('script', 5)])
.then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
aggregate([
eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5);
async.done();
});
}));
it('should support renderTime metric', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('render', 0), eventFactory.end('render', 5)])
.then((data) => {
expect(data['renderTime']).toBe(5);
async.done();
});
aggregate([
eventFactory.start('render', 0), eventFactory.end('render', 5)
]).then((data) => {
expect(data['renderTime']).toBe(5);
async.done();
});
}));
it('should support gcTime/gcAmount metric', inject([AsyncTestCompleter], (async) => {
aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000})
])
.then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['gcAmount']).toBe(1.5);
expect(data['majorGcTime']).toBe(0);
async.done();
});
]).then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['gcAmount']).toBe(1.5);
expect(data['majorGcTime']).toBe(0);
async.done();
});
}));
it('should support majorGcTime metric', inject([AsyncTestCompleter], (async) => {
aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true})
])
.then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['majorGcTime']).toBe(5);
async.done();
});
]).then((data) => {
expect(data['gcTime']).toBe(5);
expect(data['majorGcTime']).toBe(5);
async.done();
});
}));
it('should support pureScriptTime = scriptTime-gcTime-renderTime',
inject([AsyncTestCompleter], (async) => {
aggregate([
eventFactory.start('script', 0),
eventFactory.start('gc', 1, {'usedHeapSize': 1000}),
eventFactory.end('gc', 4, {'usedHeapSize': 0}),
eventFactory.start('render', 4),
eventFactory.end('render', 5),
eventFactory.end('script', 6)
])
.then((data) => {
expect(data['scriptTime']).toBe(6);
expect(data['pureScriptTime']).toBe(2);
async.done();
});
eventFactory.start('script', 0), eventFactory.start('gc', 1, {'usedHeapSize': 1000}),
eventFactory.end('gc', 4, {'usedHeapSize': 0}), eventFactory.start('render', 4),
eventFactory.end('render', 5), eventFactory.end('script', 6)
]).then((data) => {
expect(data['scriptTime']).toBe(6);
expect(data['pureScriptTime']).toBe(2);
async.done();
});
}));
describe('receivedData',
() => {it('should report received data since last navigationStart',
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.instant('receivedData', 0, {'encodedDataLength': 1}),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('receivedData', 2, {'encodedDataLength': 2}),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('receivedData', 4, {'encodedDataLength': 4}),
eventFactory.instant('receivedData', 5, {'encodedDataLength': 8})
],
{receivedData: true})
.then((data) => {
expect(data['receivedData']).toBe(12);
async.done();
});
}))});
describe('receivedData', () => {
it('should report received data since last navigationStart',
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.instant('receivedData', 0, {'encodedDataLength': 1}),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('receivedData', 2, {'encodedDataLength': 2}),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('receivedData', 4, {'encodedDataLength': 4}),
eventFactory.instant('receivedData', 5, {'encodedDataLength': 8})
],
{receivedData: true})
.then((data) => {
expect(data['receivedData']).toBe(12);
async.done();
});
}));
});
describe('requestCount',
() => {it('should report count of requests sent since last navigationStart',
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.instant('sendRequest', 0),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('sendRequest', 2),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('sendRequest', 4),
eventFactory.instant('sendRequest', 5)
],
{requestCount: true})
.then((data) => {
expect(data['requestCount']).toBe(2);
async.done();
});
}))});
describe('requestCount', () => {
it('should report count of requests sent since last navigationStart',
inject([AsyncTestCompleter], (async) => {
aggregate(
[
eventFactory.instant('sendRequest', 0),
eventFactory.instant('navigationStart', 1),
eventFactory.instant('sendRequest', 2),
eventFactory.instant('navigationStart', 3),
eventFactory.instant('sendRequest', 4), eventFactory.instant('sendRequest', 5)
],
{requestCount: true})
.then((data) => {
expect(data['requestCount']).toBe(2);
async.done();
});
}));
});
describe('microMetrics', () => {
@ -676,11 +603,10 @@ export function main() {
aggregate([
eventFactory.markStart('mm1', 0),
eventFactory.markEnd('mm1', 5),
])
.then((data) => {
expect(data['mm1']).toBeFalsy();
async.done();
});
]).then((data) => {
expect(data['mm1']).toBeFalsy();
async.done();
});
}));
it('should report micro metric averages', inject([AsyncTestCompleter], (async) => {
@ -704,8 +630,9 @@ export function main() {
}
class MockDriverExtension extends WebDriverExtension {
constructor(private _perfLogs: any[], private _commandLog: any[],
private _perfLogFeatures: PerfLogFeatures) {
constructor(
private _perfLogs: any[], private _commandLog: any[],
private _perfLogFeatures: PerfLogFeatures) {
super();
}

View File

@ -1,30 +1,24 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {ReflectiveInjector} from '@angular/core';
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {TimerWrapper} from '@angular/facade/src/async';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper, TimerWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {PromiseWrapper} from '@angular/facade/src/async';
import {isPresent, isBlank, Json} from '@angular/facade/src/lang';
import {
Metric,
MultiMetric,
PerflogMetric,
UserMetric,
WebDriverAdapter,
WebDriverExtension,
PerfLogFeatures,
bind,
provide,
Injector,
Options
} from 'benchpress/common';
import {Json, isBlank, isPresent} from '@angular/facade/src/lang';
import {Injector, Metric, MultiMetric, Options, PerfLogFeatures, PerflogMetric, UserMetric, WebDriverAdapter, WebDriverExtension, bind, provide} from 'benchpress/common';
export function main() {
var wdAdapter: MockDriverAdapter;
function createMetric(perfLogs, perfLogFeatures,
{userMetrics}: {userMetrics?: {[key: string]: string}} = {}): UserMetric {
function createMetric(
perfLogs, perfLogFeatures,
{userMetrics}: {userMetrics?: {[key: string]: string}} = {}): UserMetric {
if (isBlank(perfLogFeatures)) {
perfLogFeatures =
new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
@ -34,8 +28,7 @@ export function main() {
}
wdAdapter = new MockDriverAdapter();
var bindings = [
Options.DEFAULT_PROVIDERS,
UserMetric.PROVIDERS,
Options.DEFAULT_PROVIDERS, UserMetric.PROVIDERS,
bind(Options.USER_METRICS).toValue(userMetrics),
provide(WebDriverAdapter, {useValue: wdAdapter})
];
@ -45,8 +38,9 @@ export function main() {
describe('user metric', () => {
it('should describe itself based on userMetrics', () => {
expect(createMetric([[]], new PerfLogFeatures(), {userMetrics: {'loadTime': 'time to load'}})
.describe())
expect(createMetric([[]], new PerfLogFeatures(), {
userMetrics: {'loadTime': 'time to load'}
}).describe())
.toEqual({'loadTime': 'time to load'});
});

View File

@ -1,15 +1,14 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent, Date, DateWrapper} from '@angular/facade/src/lang';
import {
SampleState,
Reporter,
ReflectiveInjector,
ConsoleReporter,
SampleDescription,
MeasureValues
} from 'benchpress/common';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Date, DateWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {ConsoleReporter, MeasureValues, ReflectiveInjector, Reporter, SampleDescription, SampleState} from 'benchpress/common';
export function main() {
describe('console reporter', () => {
@ -26,8 +25,10 @@ export function main() {
sampleId = 'null';
}
var bindings = [
ConsoleReporter.PROVIDERS,
{provide: SampleDescription, useValue: new SampleDescription(sampleId, descriptions, metrics)},
ConsoleReporter.PROVIDERS, {
provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: ConsoleReporter.PRINT, useValue: (line) => log.push(line)}
];
if (isPresent(columnWidth)) {

View File

@ -1,16 +1,15 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {DateWrapper, Json, RegExpWrapper, isPresent} from '@angular/facade/src/lang';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {
ReflectiveInjector,
SampleDescription,
MeasureValues,
Options
} from 'benchpress/common';
import {DateWrapper, Json, RegExpWrapper, isPresent} from '@angular/facade/src/lang';
import {MeasureValues, Options, ReflectiveInjector, SampleDescription} from 'benchpress/common';
import {JsonFileReporter} from 'benchpress/src/reporter/json_file_reporter';
export function main() {
@ -19,11 +18,12 @@ export function main() {
function createReporter({sampleId, descriptions, metrics, path}) {
var bindings = [
JsonFileReporter.PROVIDERS,
{provide: SampleDescription, useValue: new SampleDescription(sampleId, descriptions, metrics)},
JsonFileReporter.PROVIDERS, {
provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: JsonFileReporter.PATH, useValue: path},
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(1234)},
{
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(1234)}, {
provide: Options.WRITE_FILE,
useValue: (filename, content) => {
loggedFile = {'filename': filename, 'content': content};
@ -41,35 +41,26 @@ export function main() {
path: 'somePath',
metrics: {'script': 'script time'}
})
.reportSample([mv(0, 0, {'a': 3, 'b': 6})],
[mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]);
.reportSample(
[mv(0, 0, {'a': 3, 'b': 6})],
[mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]);
var regExp = /somePath\/someId_\d+\.json/g;
expect(isPresent(RegExpWrapper.firstMatch(regExp, loggedFile['filename']))).toBe(true);
var parsedContent = Json.parse(loggedFile['content']);
expect(parsedContent)
.toEqual({
"description":
{"id": "someId", "description": {"a": 2}, "metrics": {"script": "script time"}},
"completeSample": [
{
"timeStamp": "1970-01-01T00:00:00.000Z",
"runIndex": 0,
"values": {"a": 3, "b": 6}
}
],
"validSample": [
{
"timeStamp": "1970-01-01T00:00:00.000Z",
"runIndex": 0,
"values": {"a": 3, "b": 6}
},
{
"timeStamp": "1970-01-01T00:00:00.001Z",
"runIndex": 1,
"values": {"a": 5, "b": 9}
}
]
});
expect(parsedContent).toEqual({
'description':
{'id': 'someId', 'description': {'a': 2}, 'metrics': {'script': 'script time'}},
'completeSample': [
{'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}
],
'validSample': [
{'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}, {
'timeStamp': '1970-01-01T00:00:00.001Z',
'runIndex': 1,
'values': {'a': 5, 'b': 9}
}
]
});
async.done();
}));

View File

@ -1,21 +1,23 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {DateWrapper} from '@angular/facade/src/lang';
import {
Reporter,
MultiReporter,
ReflectiveInjector,
MeasureValues
} from 'benchpress/common';
import {MeasureValues, MultiReporter, ReflectiveInjector, Reporter} from 'benchpress/common';
export function main() {
function createReporters(ids: any[]) {
var r = ReflectiveInjector.resolveAndCreate([
ids.map(id => { return {provide: id, useValue: new MockReporter(id)}}),
MultiReporter.createBindings(ids)
])
var r = ReflectiveInjector
.resolveAndCreate([
ids.map(id => { return {provide: id, useValue: new MockReporter(id)}; }),
MultiReporter.createBindings(ids)
])
.get(MultiReporter);
return PromiseWrapper.resolve(r);
}
@ -24,19 +26,16 @@ export function main() {
it('should reportMeasureValues to all', inject([AsyncTestCompleter], (async) => {
var mv = new MeasureValues(0, DateWrapper.now(), {});
createReporters(['m1', 'm2'])
.then((r) => r.reportMeasureValues(mv))
.then((values) => {
createReporters(['m1', 'm2']).then((r) => r.reportMeasureValues(mv)).then((values) => {
expect(values).toEqual([{'id': 'm1', 'values': mv}, {'id': 'm2', 'values': mv}]);
async.done();
});
expect(values).toEqual([{'id': 'm1', 'values': mv}, {'id': 'm2', 'values': mv}]);
async.done();
});
}));
it('should reportSample to call', inject([AsyncTestCompleter], (async) => {
var completeSample = [
new MeasureValues(0, DateWrapper.now(), {}),
new MeasureValues(1, DateWrapper.now(), {})
new MeasureValues(0, DateWrapper.now(), {}), new MeasureValues(1, DateWrapper.now(), {})
];
var validSample = [completeSample[1]];
@ -49,7 +48,7 @@ export function main() {
{'id': 'm2', 'completeSample': completeSample, 'validSample': validSample}
]);
async.done();
})
});
}));
});
@ -62,8 +61,8 @@ class MockReporter extends Reporter {
return PromiseWrapper.resolve({'id': this._id, 'values': values});
}
reportSample(completeSample: MeasureValues[],
validSample: MeasureValues[]): Promise<{[key: string]: any}> {
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]):
Promise<{[key: string]: any}> {
return PromiseWrapper.resolve(
{'id': this._id, 'completeSample': completeSample, 'validSample': validSample});
}

View File

@ -1,18 +1,15 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {
Runner,
Sampler,
SampleDescription,
Validator,
ReflectiveInjector,
Injector,
Metric,
Options,
WebDriverAdapter,
SampleState
} from 'benchpress/common';
import {isBlank} from '@angular/facade/src/lang';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {isBlank} from '@angular/facade/src/lang';
import {Injector, Metric, Options, ReflectiveInjector, Runner, SampleDescription, SampleState, Sampler, Validator, WebDriverAdapter} from 'benchpress/common';
export function main() {
describe('runner', () => {
@ -24,8 +21,7 @@ export function main() {
defaultBindings = [];
}
runner = new Runner([
defaultBindings,
{
defaultBindings, {
provide: Sampler,
useFactory: (_injector) => {
injector = _injector;
@ -33,9 +29,9 @@ export function main() {
},
deps: [Injector]
},
{ provide: Metric, useFactory: () => new MockMetric(), deps: []},
{ provide: Validator, useFactory: () => new MockValidator(), deps: []},
{ provide: WebDriverAdapter, useFactory: () => new MockWebDriverAdapter(), deps: []}
{provide: Metric, useFactory: () => new MockMetric(), deps: []},
{provide: Validator, useFactory: () => new MockValidator(), deps: []},
{provide: WebDriverAdapter, useFactory: () => new MockWebDriverAdapter(), deps: []}
]);
return runner;
}
@ -52,7 +48,10 @@ export function main() {
it('should merge SampleDescription.description', inject([AsyncTestCompleter], (async) => {
createRunner([{provide: Options.DEFAULT_DESCRIPTION, useValue: {'a': 1}}])
.sample({id: 'someId', providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: {'b': 2}}]})
.sample({
id: 'someId',
providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: {'b': 2}}]
})
.then((_) => injector.get(SampleDescription))
.then((desc) => {
expect(desc.description)
@ -76,31 +75,25 @@ export function main() {
it('should bind Options.EXECUTE', inject([AsyncTestCompleter], (async) => {
var execute = () => {};
createRunner()
.sample({id: 'someId', execute: execute})
.then((_) => {
expect(injector.get(Options.EXECUTE)).toEqual(execute);
async.done();
});
createRunner().sample({id: 'someId', execute: execute}).then((_) => {
expect(injector.get(Options.EXECUTE)).toEqual(execute);
async.done();
});
}));
it('should bind Options.PREPARE', inject([AsyncTestCompleter], (async) => {
var prepare = () => {};
createRunner()
.sample({id: 'someId', prepare: prepare})
.then((_) => {
expect(injector.get(Options.PREPARE)).toEqual(prepare);
async.done();
});
createRunner().sample({id: 'someId', prepare: prepare}).then((_) => {
expect(injector.get(Options.PREPARE)).toEqual(prepare);
async.done();
});
}));
it('should bind Options.MICRO_METRICS', inject([AsyncTestCompleter], (async) => {
createRunner()
.sample({id: 'someId', microMetrics: {'a': 'b'}})
.then((_) => {
expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
async.done();
});
createRunner().sample({id: 'someId', microMetrics: {'a': 'b'}}).then((_) => {
expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
async.done();
});
}));
it('should overwrite bindings per sample call', inject([AsyncTestCompleter], (async) => {

View File

@ -1,18 +1,15 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isBlank, isPresent, stringify, Date, DateWrapper} from '@angular/facade/src/lang';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {
Sampler,
WebDriverAdapter,
Validator,
Metric,
Reporter,
ReflectiveInjector,
Options,
MeasureValues
} from 'benchpress/common';
import {Date, DateWrapper, isBlank, isPresent, stringify} from '@angular/facade/src/lang';
import {MeasureValues, Metric, Options, ReflectiveInjector, Reporter, Sampler, Validator, WebDriverAdapter} from 'benchpress/common';
export function main() {
var EMPTY_EXECUTE = () => {};
@ -39,13 +36,9 @@ export function main() {
driver = new MockDriverAdapter([]);
}
var providers = [
Options.DEFAULT_PROVIDERS,
Sampler.PROVIDERS,
{provide: Metric, useValue: metric},
{provide: Reporter, useValue: reporter},
{provide: WebDriverAdapter, useValue: driver},
{provide: Options.EXECUTE, useValue: execute},
{provide: Validator, useValue: validator},
Options.DEFAULT_PROVIDERS, Sampler.PROVIDERS, {provide: Metric, useValue: metric},
{provide: Reporter, useValue: reporter}, {provide: WebDriverAdapter, useValue: driver},
{provide: Options.EXECUTE, useValue: execute}, {provide: Validator, useValue: validator},
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(time++)}
];
if (isPresent(prepare)) {
@ -131,12 +124,13 @@ export function main() {
var iterationCount = 1;
createSampler({
validator: createCountingValidator(2),
metric: new MockMetric([],
() => {
var result = PromiseWrapper.resolve({'script': scriptTime});
scriptTime = 0;
return result;
}),
metric: new MockMetric(
[],
() => {
var result = PromiseWrapper.resolve({'script': scriptTime});
scriptTime = 0;
return result;
}),
prepare: () => { scriptTime = 1 * iterationCount; },
execute: () => {
scriptTime = 10 * iterationCount;
@ -198,9 +192,7 @@ export function main() {
expect(log[0]).toEqual(['reportMeasureValues', mv(0, 1000, {'script': 0})]);
expect(log[1]).toEqual(['reportMeasureValues', mv(1, 1001, {'script': 1})]);
expect(log[2]).toEqual([
'reportSample',
[mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})],
validSample
'reportSample', [mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})], validSample
]);
async.done();
@ -231,6 +223,7 @@ function createCountingMetric(log = null) {
}
class MockDriverAdapter extends WebDriverAdapter {
/** @internal */
private _log: any[];
private _waitFor: Function;
constructor(log = null, waitFor = null) {
@ -252,6 +245,7 @@ class MockDriverAdapter extends WebDriverAdapter {
class MockValidator extends Validator {
/** @internal */
private _log: any[];
constructor(log = null, private _validate: Function = null) {
super();
@ -268,6 +262,7 @@ class MockValidator extends Validator {
}
class MockMetric extends Metric {
/** @internal */
private _log: any[];
constructor(log = null, private _endMeasure: Function = null) {
super();
@ -288,7 +283,8 @@ class MockMetric extends Metric {
}
class MockReporter extends Reporter {
_log: any[];
/** @internal */
private _log: any[];
constructor(log = null) {
super();
if (isBlank(log)) {

View File

@ -1,5 +1,12 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Statistic} from 'benchpress/src/statistic';
export function main() {

View File

@ -1,3 +1,11 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isPresent} from '@angular/facade/src/lang';
export class TraceEventFactory {

View File

@ -1,23 +1,27 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Date, DateWrapper} from '@angular/facade/src/lang';
import {ListWrapper} from '@angular/facade/src/collection';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
RegressionSlopeValidator,
ReflectiveInjector,
MeasureValues
} from 'benchpress/common';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {ListWrapper} from '@angular/facade/src/collection';
import {Date, DateWrapper} from '@angular/facade/src/lang';
import {MeasureValues, ReflectiveInjector, RegressionSlopeValidator} from 'benchpress/common';
export function main() {
describe('regression slope validator', () => {
var validator;
function createValidator({size, metric}) {
validator = ReflectiveInjector.resolveAndCreate([
RegressionSlopeValidator.PROVIDERS,
{provide: RegressionSlopeValidator.METRIC, useValue: metric},
{provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: size}
])
validator = ReflectiveInjector
.resolveAndCreate([
RegressionSlopeValidator.PROVIDERS,
{provide: RegressionSlopeValidator.METRIC, useValue: metric},
{provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: size}
])
.get(RegressionSlopeValidator);
}

View File

@ -1,24 +1,26 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {Date, DateWrapper} from '@angular/facade/src/lang';
import {ListWrapper} from '@angular/facade/src/collection';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
Validator,
SizeValidator,
ReflectiveInjector,
MeasureValues
} from 'benchpress/common';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {ListWrapper} from '@angular/facade/src/collection';
import {Date, DateWrapper} from '@angular/facade/src/lang';
import {MeasureValues, ReflectiveInjector, SizeValidator, Validator} from 'benchpress/common';
export function main() {
describe('size validator', () => {
var validator;
function createValidator(size) {
validator = ReflectiveInjector.resolveAndCreate([
SizeValidator.PROVIDERS,
{provide: SizeValidator.SAMPLE_SIZE, useValue: size}
])
.get(SizeValidator);
validator =
ReflectiveInjector
.resolveAndCreate(
[SizeValidator.PROVIDERS, {provide: SizeValidator.SAMPLE_SIZE, useValue: size}])
.get(SizeValidator);
}
it('should return sampleSize as description', () => {

View File

@ -1,18 +1,24 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {isPresent, StringWrapper} from '@angular/facade/src/lang';
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {WebDriverExtension, ReflectiveInjector, Options} from 'benchpress/common';
import {StringWrapper, isPresent} from '@angular/facade/src/lang';
import {Options, ReflectiveInjector, WebDriverExtension} from 'benchpress/common';
export function main() {
function createExtension(ids: any[], caps) {
return PromiseWrapper.wrap(() => {
return ReflectiveInjector.resolveAndCreate([
ids.map((id) => { return {provide: id, useValue: new MockExtension(id)}}),
{provide: Options.CAPABILITIES, useValue: caps},
WebDriverExtension.bindTo(ids)
])
return ReflectiveInjector
.resolveAndCreate([
ids.map((id) => { return {provide: id, useValue: new MockExtension(id)}; }),
{provide: Options.CAPABILITIES, useValue: caps}, WebDriverExtension.bindTo(ids)
])
.get(WebDriverExtension);
});
}
@ -21,11 +27,10 @@ export function main() {
it('should bind the extension that matches the capabilities',
inject([AsyncTestCompleter], (async) => {
createExtension(['m1', 'm2', 'm3'], {'browser': 'm2'})
.then((m) => {
expect(m.id).toEqual('m2');
async.done();
});
createExtension(['m1', 'm2', 'm3'], {'browser': 'm2'}).then((m) => {
expect(m.id).toEqual('m2');
async.done();
});
}));
it('should throw if there is no match', inject([AsyncTestCompleter], (async) => {

View File

@ -1,15 +1,15 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {Json, isBlank} from '@angular/facade/src/lang';
import {
WebDriverExtension,
ChromeDriverExtension,
WebDriverAdapter,
ReflectiveInjector,
Options
} from 'benchpress/common';
import {ChromeDriverExtension, Options, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory';
@ -35,8 +35,9 @@ export function main() {
var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0');
var normEvents = new TraceEventFactory('timeline', 'pid0');
function createExtension(perfRecords = null, userAgent = null,
messageMethod = 'Tracing.dataCollected'): WebDriverExtension {
function createExtension(
perfRecords = null, userAgent = null,
messageMethod = 'Tracing.dataCollected'): WebDriverExtension {
if (isBlank(perfRecords)) {
perfRecords = [];
}
@ -44,13 +45,15 @@ export function main() {
userAgent = CHROME44_USER_AGENT;
}
log = [];
extension =
ReflectiveInjector.resolveAndCreate([
ChromeDriverExtension.PROVIDERS,
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords, messageMethod)},
{provide: Options.USER_AGENT, useValue: userAgent}
])
.get(ChromeDriverExtension);
extension = ReflectiveInjector
.resolveAndCreate([
ChromeDriverExtension.PROVIDERS, {
provide: WebDriverAdapter,
useValue: new MockDriverAdapter(log, perfRecords, messageMethod)
},
{provide: Options.USER_AGENT, useValue: userAgent}
])
.get(ChromeDriverExtension);
return extension;
}
@ -62,32 +65,26 @@ export function main() {
}));
it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
createExtension()
.timeBegin('someName')
.then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
createExtension().timeBegin('someName').then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
createExtension()
.timeEnd('someName', null)
.then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
createExtension().timeEnd('someName', null).then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async) => {
createExtension()
.timeEnd('name1', 'name2')
.then((_) => {
expect(log)
.toEqual([['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
createExtension().timeEnd('name1', 'name2').then((_) => {
expect(log).toEqual(
[['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
}));
describe('readPerfLog Chrome44', () => {
@ -193,10 +190,8 @@ export function main() {
});
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineEvents.start('FunctionCall', 0,
{'data': {'scriptName': 'InjectedScript'}})
])
createExtension([chromeTimelineEvents.start(
'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
@ -210,8 +205,9 @@ export function main() {
describe('readPerfLog Chrome45', () => {
it('should normalize times to ms and forward ph and pid event properties',
inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)],
CHROME45_USER_AGENT)
createExtension(
[chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
@ -224,14 +220,12 @@ export function main() {
it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
var event = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500;
createExtension([event], CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
createExtension([event], CHROME45_USER_AGENT).readPerfLog().then((events) => {
expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null),
]);
async.done();
});
}));
it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
@ -257,8 +251,8 @@ export function main() {
expect(events.length).toEqual(2);
expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false}));
expect(events[1])
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
expect(events[1]).toEqual(
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
async.done();
});
}));
@ -273,10 +267,10 @@ export function main() {
.readPerfLog()
.then((events) => {
expect(events.length).toEqual(2);
expect(events[0])
.toEqual(normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
expect(events[1])
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
expect(events[1]).toEqual(
normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
async.done();
});
}));
@ -320,10 +314,8 @@ export function main() {
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([
chromeTimelineV8Events.start('FunctionCall', 0,
{'data': {'scriptName': 'InjectedScript'}})
])
createExtension([chromeTimelineV8Events.start(
'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
@ -343,8 +335,8 @@ export function main() {
}));
it('should report navigationStart', inject([AsyncTestCompleter], (async) => {
createExtension([chromeBlinkUserTimingEvents.start('navigationStart', 1234)],
CHROME45_USER_AGENT)
createExtension(
[chromeBlinkUserTimingEvents.start('navigationStart', 1234)], CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.start('navigationStart', 1.234)]);
@ -354,10 +346,8 @@ export function main() {
it('should report receivedData', inject([AsyncTestCompleter], (async) => {
createExtension(
[
chrome45TimelineEvents.instant('ResourceReceivedData', 1234,
{'data': {'encodedDataLength': 987}})
],
[chrome45TimelineEvents.instant(
'ResourceReceivedData', 1234, {'data': {'encodedDataLength': 987}})],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
@ -369,18 +359,14 @@ export function main() {
it('should report sendRequest', inject([AsyncTestCompleter], (async) => {
createExtension(
[
chrome45TimelineEvents.instant(
'ResourceSendRequest', 1234,
{'data': {'url': 'http://here', 'requestMethod': 'GET'}})
],
[chrome45TimelineEvents.instant(
'ResourceSendRequest', 1234,
{'data': {'url': 'http://here', 'requestMethod': 'GET'}})],
CHROME45_USER_AGENT)
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.instant('sendRequest', 1.234,
{'url': 'http://here', 'method': 'GET'})
]);
expect(events).toEqual([normEvents.instant(
'sendRequest', 1.234, {'url': 'http://here', 'method': 'GET'})]);
async.done();
});
}));
@ -421,10 +407,9 @@ export function main() {
describe('frame metrics', () => {
it('should report ImplThreadRenderingStats as frame event',
inject([AsyncTestCompleter], (async) => {
createExtension([
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 1}})
])
createExtension([benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 1}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([
@ -436,10 +421,9 @@ export function main() {
it('should not report ImplThreadRenderingStats with zero frames',
inject([AsyncTestCompleter], (async) => {
createExtension([
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 0}})
])
createExtension([benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 0}})])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
@ -451,12 +435,14 @@ export function main() {
inject([AsyncTestCompleter], (async) => {
PromiseWrapper.catchError(
createExtension([
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats',
1100, {'data': {'frame_count': 2}})
benchmarkEvents.instant(
'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 2}})
]).readPerfLog(),
(err): any => {
expect(() => { throw err; })
.toThrowError('multi-frame render stats not supported');
expect(() => {
throw err;
}).toThrowError('multi-frame render stats not supported');
async.done();
});
}));
@ -490,8 +476,9 @@ export function main() {
CHROME45_USER_AGENT, 'Tracing.bufferUsage')
.readPerfLog(),
(err): any => {
expect(() => { throw err; })
.toThrowError('The DevTools trace buffer filled during the test!');
expect(() => {
throw err;
}).toThrowError('The DevTools trace buffer filled during the test!');
async.done();
});
}));

View File

@ -1,14 +1,16 @@
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {PromiseWrapper} from '@angular/facade/src/async';
import {Json, isBlank, isPresent} from '@angular/facade/src/lang';
import {
WebDriverExtension,
IOsDriverExtension,
WebDriverAdapter,
ReflectiveInjector,
} from 'benchpress/common';
import {WebDriverExtension, IOsDriverExtension, WebDriverAdapter, ReflectiveInjector,} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory';
@ -24,11 +26,13 @@ export function main() {
perfRecords = [];
}
log = [];
extension = ReflectiveInjector.resolveAndCreate([
IOsDriverExtension.PROVIDERS,
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)}
])
.get(IOsDriverExtension);
extension =
ReflectiveInjector
.resolveAndCreate([
IOsDriverExtension.PROVIDERS,
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)}
])
.get(IOsDriverExtension);
return extension;
}
@ -37,32 +41,26 @@ export function main() {
});
it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
createExtension()
.timeBegin('someName')
.then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
createExtension().timeBegin('someName').then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
createExtension()
.timeEnd('someName', null)
.then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
createExtension().timeEnd('someName', null).then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done();
});
}));
it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async) => {
createExtension()
.timeEnd('name1', 'name2')
.then((_) => {
expect(log)
.toEqual([['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
createExtension().timeEnd('name1', 'name2').then((_) => {
expect(log).toEqual(
[['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done();
});
}));
describe('readPerfLog', () => {
@ -79,40 +77,31 @@ export function main() {
}));
it('should report FunctionCall records as "script"', inject([AsyncTestCompleter], (async) => {
createExtension([durationRecord('FunctionCall', 1, 5)])
.readPerfLog()
.then((events) => {
expect(events)
.toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
async.done();
});
createExtension([durationRecord('FunctionCall', 1, 5)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
async.done();
});
}));
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([internalScriptRecord(1, 5)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([]);
async.done();
});
createExtension([internalScriptRecord(1, 5)]).readPerfLog().then((events) => {
expect(events).toEqual([]);
async.done();
});
}));
it('should report begin time', inject([AsyncTestCompleter], (async) => {
createExtension([timeBeginRecord('someName', 12)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markStart('someName', 12)]);
async.done();
});
createExtension([timeBeginRecord('someName', 12)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.markStart('someName', 12)]);
async.done();
});
}));
it('should report end timestamps', inject([AsyncTestCompleter], (async) => {
createExtension([timeEndRecord('someName', 12)])
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markEnd('someName', 12)]);
async.done();
});
createExtension([timeEndRecord('someName', 12)]).readPerfLog().then((events) => {
expect(events).toEqual([normEvents.markEnd('someName', 12)]);
async.done();
});
}));
['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint', 'Rasterize', 'CompositeLayers']
@ -136,8 +125,7 @@ export function main() {
.readPerfLog()
.then((events) => {
expect(events).toEqual([
normEvents.start('script', 1),
normEvents.markStart('someName', 2),
normEvents.start('script', 1), normEvents.markStart('someName', 2),
normEvents.end('script', 5)
]);
async.done();