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 os = require('os');
const srcsToFmt = 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', () => { gulp.task('format:enforce', () => {
const format = require('gulp-clang-format'); const format = require('gulp-clang-format');
@ -97,7 +98,7 @@ gulp.task('lint', ['format:enforce', 'tools:build'], () => {
// Built-in rules are at // Built-in rules are at
// https://github.com/palantir/tslint#supported-rules // https://github.com/palantir/tslint#supported-rules
const tslintConfig = require('./tslint.json'); const tslintConfig = require('./tslint.json');
return gulp.src(['modules/@angular/**/*.ts']) return gulp.src(['modules/@angular/**/*.ts', 'modules/benchpress/**/*.ts'])
.pipe(tslint({ .pipe(tslint({
tslint: require('tslint').default, tslint: require('tslint').default,
configuration: tslintConfig, 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 {bind} from '@angular/core/src/di';
import {Options} from './common'; import {Options} from './common';
@ -22,5 +30,5 @@ function writeFile(filename, content): Promise<any> {
resolve(); 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 {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 {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 {ConsoleReporter} from './src/reporter/console_reporter';
export {JsonFileReporter} from './src/reporter/json_file_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 {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 {ChromeDriverExtension} from './src/webdriver/chrome_driver_extension';
export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension'; export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension';
export {IOsDriverExtension} from './src/webdriver/ios_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('reflect-metadata');
require('es6-shim'); require('es6-shim');
module.exports = require('./benchpress.js'); 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 {OpaqueToken} from '@angular/core/src/di';
import {DateWrapper} from '@angular/facade/src/lang'; 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 _CAPTURE_FRAMES = new OpaqueToken('Options.frameCapture');
var _DEFAULT_PROVIDERS = [ var _DEFAULT_PROVIDERS = [
{provide: _DEFAULT_DESCRIPTION, useValue: {}}, {provide: _DEFAULT_DESCRIPTION, useValue: {}}, {provide: _SAMPLE_DESCRIPTION, useValue: {}},
{provide: _SAMPLE_DESCRIPTION, useValue: {}}, {provide: _FORCE_GC, useValue: false}, {provide: _PREPARE, useValue: false},
{provide: _FORCE_GC, useValue: false}, {provide: _MICRO_METRICS, useValue: {}}, {provide: _USER_METRICS, useValue: {}},
{provide: _PREPARE, useValue: false}, {provide: _NOW, useValue: () => DateWrapper.now()}, {provide: _RECEIVED_DATA, useValue: false},
{provide: _MICRO_METRICS, useValue: {}}, {provide: _REQUEST_COUNT, useValue: false}, {provide: _CAPTURE_FRAMES, useValue: false}
{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 exportFunction;
declare var unsafeWindow; declare var unsafeWindow;
exportFunction(function() { exportFunction(function() {
var curTime = unsafeWindow.performance.now(); var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('startProfiler', curTime); (<any>self).port.emit('startProfiler', curTime);
}, unsafeWindow, {defineAs: "startProfiler"}); }, unsafeWindow, {defineAs: 'startProfiler'});
exportFunction(function() { (<any>self).port.emit('stopProfiler'); }, unsafeWindow, exportFunction(function() {
{defineAs: "stopProfiler"}); (<any>self).port.emit('stopProfiler');
}, unsafeWindow, {defineAs: 'stopProfiler'});
exportFunction(function(cb) { exportFunction(function(cb) {
(<any>self).port.once('perfProfile', cb); (<any>self).port.once('perfProfile', cb);
(<any>self).port.emit('getProfile'); (<any>self).port.emit('getProfile');
}, unsafeWindow, {defineAs: "getProfile"}); }, unsafeWindow, {defineAs: 'getProfile'});
exportFunction(function() { (<any>self).port.emit('forceGC'); }, unsafeWindow, exportFunction(function() {
{defineAs: "forceGC"}); (<any>self).port.emit('forceGC');
}, unsafeWindow, {defineAs: 'forceGC'});
exportFunction(function(name) { exportFunction(function(name) {
var curTime = unsafeWindow.performance.now(); var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markStart', name, curTime); (<any>self).port.emit('markStart', name, curTime);
}, unsafeWindow, {defineAs: "markStart"}); }, unsafeWindow, {defineAs: 'markStart'});
exportFunction(function(name) { exportFunction(function(name) {
var curTime = unsafeWindow.performance.now(); var curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markEnd', name, curTime); (<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 {Cc, Ci, Cu} = require('chrome');
var os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService); var os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
var ParserUtil = require('./parser_util'); var ParserUtil = require('./parser_util');
@ -25,7 +33,8 @@ class Profiler {
return perfEvents; return perfEvents;
} }
_mergeMarkerEvents(perfEvents: any[]): any[] { /** @internal */
private _mergeMarkerEvents(perfEvents: any[]): any[] {
this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); }); this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); });
return perfEvents; return perfEvents;
} }
@ -51,12 +60,13 @@ mod.PageMod({
include: ['*'], include: ['*'],
contentScriptFile: data.url('installed_script.js'), contentScriptFile: data.url('installed_script.js'),
onAttach: worker => { onAttach: worker => {
worker.port.on('startProfiler', worker.port.on(
(timeStarted) => profiler.start(/* = profiler memory */ 3000000, 0.1, 'startProfiler',
['leaf', 'js', 'stackwalk', 'gc'], timeStarted)); (timeStarted) => profiler.start(
/* = profiler memory */ 3000000, 0.1, ['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
worker.port.on('stopProfiler', () => profiler.stop()); worker.port.on('stopProfiler', () => profiler.stop());
worker.port.on('getProfile', worker.port.on(
() => worker.port.emit('perfProfile', profiler.getProfilePerfEvents())); 'getProfile', () => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
worker.port.on('forceGC', forceGC); worker.port.on('forceGC', forceGC);
worker.port.on('markStart', (name, timeStarted) => profiler.addStartEvent(name, timeStarted)); worker.port.on('markStart', (name, timeStarted) => profiler.addStartEvent(name, timeStarted));
worker.port.on('markEnd', (name, timeEnded) => profiler.addEndEvent(name, timeEnded)); 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. * @param {Object} perfProfile The perf profile JSON object.
* @return {Object[]} An array of recognized events that are captured * @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 q = require('q');
var FirefoxProfile = require('firefox-profile'); var FirefoxProfile = require('firefox-profile');
var jpm = require('jpm/lib/xpi'); var jpm = require('jpm/lib/xpi');
@ -36,8 +44,7 @@ exports.getFirefoxProfileWithExtension = function() {
var savedCwd = process.cwd(); var savedCwd = process.cwd();
process.chdir(absPackageJsonDir); process.chdir(absPackageJsonDir);
return jpm(packageJson) return jpm(packageJson).then(xpiPath => {
.then(xpiPath => {
process.chdir(savedCwd); process.chdir(savedCwd);
return exports.getFirefoxProfile(xpiPath); 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 {Map} from '@angular/facade/src/collection';
import {Date, DateWrapper} from '@angular/facade/src/lang';
export class MeasureValues { export class MeasureValues {
constructor(public runIndex: number, public timeStamp: Date, constructor(
public values: {[key: string]: any}) {} public runIndex: number, public timeStamp: Date, public values: {[key: string]: any}) {}
toJson() { toJson() {
return { 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'; 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 {Injector, OpaqueToken} from '@angular/core/src/di';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {PromiseWrapper} from '@angular/facade/src/async'; import {PromiseWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection';
import {Metric} from '../metric'; import {Metric} from '../metric';
@ -9,14 +17,10 @@ export class MultiMetric extends Metric {
return [ return [
{ {
provide: _CHILDREN, provide: _CHILDREN,
useFactory:(injector: Injector) => childTokens.map(token => injector.get(token)), useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector] 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 = {}; var result = {};
maps.forEach( maps.forEach(
map => { StringMapWrapper.forEach(map, (value, prop) => { result[prop] = value; }); }); 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'; * @license
import {BaseException, WrappedException} from '@angular/facade/src/exceptions'; * Copyright Google Inc. All Rights Reserved.
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection'; *
import {OpaqueToken} from '@angular/core/src/di'; * 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 {Options} from '../common_options';
import {Metric} from '../metric';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
/** /**
* A metric that reads out the performance log * 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 // TODO(tbosch): use static values when our transpiler supports them
static get SET_TIMEOUT(): OpaqueToken { return _SET_TIMEOUT; } static get SET_TIMEOUT(): OpaqueToken { return _SET_TIMEOUT; }
/** @internal */
private _remainingEvents: Array<{[key: string]: any}>; private _remainingEvents: Array<{[key: string]: any}>;
/** @internal */
private _measureCount: number; private _measureCount: number;
_perfLogFeatures: PerfLogFeatures; /** @internal */
private _perfLogFeatures: PerfLogFeatures;
/** /**
@ -27,9 +39,20 @@ export class PerflogMetric extends Metric {
* @param setTimeout * @param setTimeout
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd * @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
**/ **/
constructor(private _driverExtension: WebDriverExtension, private _setTimeout: Function, constructor(
private _microMetrics: {[key: string]: any}, private _forceGc: boolean, /** @internal */
private _captureFrames: boolean, private _receivedData: boolean, 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) { private _requestCount: boolean) {
super(); super();
@ -81,8 +104,8 @@ export class PerflogMetric extends Metric {
res['frameTime.smooth'] = 'percentage of frames that hit 60fps'; res['frameTime.smooth'] = 'percentage of frames that hit 60fps';
} }
} }
StringMapWrapper.forEach(this._microMetrics, StringMapWrapper.forEach(
(desc, name) => { StringMapWrapper.set(res, name, desc); }); this._microMetrics, (desc, name) => { StringMapWrapper.set(res, name, desc); });
return res; 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) => { return this._endMeasure(true).then((measureValues) => {
// disable frame capture for measurements during forced gc // disable frame capture for measurements during forced gc
var originalFrameCaptureValue = this._captureFrames; 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++)); 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 markName = this._markName(this._measureCount - 1);
var nextMarkName = restart ? this._markName(this._measureCount++) : null; var nextMarkName = restart ? this._markName(this._measureCount++) : null;
return this._driverExtension.timeEnd(markName, nextMarkName) return this._driverExtension.timeEnd(markName, nextMarkName)
.then((_) => this._readUntilEndMark(markName)); .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) { if (loopCount > _MAX_RETRY_COUNT) {
throw new BaseException(`Tried too often to get the ending mark: ${loopCount}`); throw new BaseException(`Tried too often to get the ending mark: ${loopCount}`);
} }
@ -141,13 +168,14 @@ export class PerflogMetric extends Metric {
return result; return result;
} }
var completer = PromiseWrapper.completer(); var completer = PromiseWrapper.completer();
this._setTimeout(() => completer.resolve(this._readUntilEndMark(markName, loopCount + 1)), this._setTimeout(
100); () => completer.resolve(this._readUntilEndMark(markName, loopCount + 1)), 100);
return completer.promise; return completer.promise;
}); });
} }
_addEvents(events: { [key: string]: string }[]) { /** @internal */
private _addEvents(events: {[key: string]: string}[]) {
var needSort = false; var needSort = false;
events.forEach(event => { events.forEach(event => {
if (StringWrapper.equals(event['ph'], 'X')) { 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}; var result = {'scriptTime': 0, 'pureScriptTime': 0};
if (this._perfLogFeatures.gc) { if (this._perfLogFeatures.gc) {
result['gcTime'] = 0; result['gcTime'] = 0;
@ -252,11 +281,11 @@ export class PerflogMetric extends Metric {
} }
if (!this._captureFrames) { if (!this._captureFrames) {
throw new BaseException( 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; frameCaptureStartEvent = event;
} else if (StringWrapper.equals(ph, 'e') && } else if (
StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) { StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) {
if (isBlank(frameCaptureStartEvent)) { if (isBlank(frameCaptureStartEvent)) {
throw new BaseException('missing start event for frame capture'); throw new BaseException('missing start event for frame capture');
} }
@ -268,7 +297,8 @@ export class PerflogMetric extends Metric {
StringWrapper.equals(name, 'frame')) { StringWrapper.equals(name, 'frame')) {
frameTimestamps.push(event['ts']); frameTimestamps.push(event['ts']);
if (frameTimestamps.length >= 2) { if (frameTimestamps.length >= 2) {
frameTimes.push(frameTimestamps[frameTimestamps.length - 1] - frameTimes.push(
frameTimestamps[frameTimestamps.length - 1] -
frameTimestamps[frameTimestamps.length - 2]); frameTimestamps[frameTimestamps.length - 2]);
} }
} }
@ -281,7 +311,8 @@ export class PerflogMetric extends Metric {
} else { } else {
intervalStartCount[name]++; intervalStartCount[name]++;
} }
} else if ((StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) && } else if (
(StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) &&
isPresent(intervalStarts[name])) { isPresent(intervalStarts[name])) {
intervalStartCount[name]--; intervalStartCount[name]--;
if (intervalStartCount[name] === 0) { if (intervalStartCount[name] === 0) {
@ -334,7 +365,8 @@ export class PerflogMetric extends Metric {
return result; 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; result['frameTime.mean'] = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
var firstFrame = frameTimes[0]; var firstFrame = frameTimes[0];
result['frameTime.worst'] = frameTimes.reduce((a, b) => a > b ? a : b, firstFrame); 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; 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; var _MICRO_ITERATIONS_REGEX = /(.+)\*(\d+)$/g;
@ -359,18 +392,14 @@ var _FRAME_TIME_SMOOTH_THRESHOLD = 17;
var _PROVIDERS = [ var _PROVIDERS = [
{ {
provide: PerflogMetric, provide: PerflogMetric,
useFactory: useFactory: (driverExtension, setTimeout, microMetrics, forceGc, captureFrames, receivedData,
(driverExtension, setTimeout, microMetrics, forceGc, captureFrames, receivedData, requestCount) =>
requestCount) => new PerflogMetric(driverExtension, setTimeout, microMetrics, forceGc, new PerflogMetric(
captureFrames, receivedData, requestCount), driverExtension, setTimeout, microMetrics, forceGc, captureFrames,
receivedData, requestCount),
deps: [ deps: [
WebDriverExtension, WebDriverExtension, _SET_TIMEOUT, Options.MICRO_METRICS, Options.FORCE_GC,
_SET_TIMEOUT, Options.CAPTURE_FRAMES, Options.RECEIVED_DATA, Options.REQUEST_COUNT
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)} {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 {PromiseWrapper, TimerWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection'; import {StringMapWrapper} from '@angular/facade/src/collection';
import {isNumber} from '@angular/facade/src/lang'; import {isNumber} from '@angular/facade/src/lang';
import {Metric} from '../metric';
import {Options} from '../common_options'; import {Options} from '../common_options';
import {Metric} from '../metric';
import {WebDriverAdapter} from '../web_driver_adapter'; import {WebDriverAdapter} from '../web_driver_adapter';
export class UserMetric extends Metric { export class UserMetric extends Metric {
@ -56,8 +64,7 @@ export class UserMetric extends Metric {
describe(): {[key: string]: any} { return this._userMetrics; } describe(): {[key: string]: any} { return this._userMetrics; }
} }
var _PROVIDERS = [ var _PROVIDERS = [bind(UserMetric)
bind(UserMetric) .toFactory(
.toFactory((userMetrics, wdAdapter) => new UserMetric(userMetrics, wdAdapter), (userMetrics, wdAdapter) => new UserMetric(userMetrics, wdAdapter),
[Options.USER_METRICS, WebDriverAdapter]) [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 {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {MeasureValues} from './measure_values'; 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'; * @license
import {PromiseWrapper} from '@angular/facade/src/async'; * Copyright Google Inc. All Rights Reserved.
import {Math} from '@angular/facade/src/math'; *
import {OpaqueToken} from '@angular/core/src/di'; * 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 {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description'; import {SampleDescription} from '../sample_description';
import {MeasureValues} from '../measure_values'; import {Statistic} from '../statistic';
/** /**
* A reporter for the console * A reporter for the console
@ -21,7 +30,8 @@ export class ConsoleReporter extends Reporter {
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
static _lpad(value, columnWidth, fill = ' ') { /** @internal */
private static _lpad(value, columnWidth, fill = ' ') {
var result = ''; var result = '';
for (var i = 0; i < columnWidth - value.length; i++) { for (var i = 0; i < columnWidth - value.length; i++) {
result += fill; result += fill;
@ -29,15 +39,18 @@ export class ConsoleReporter extends Reporter {
return result + value; 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 = []; var props = [];
StringMapWrapper.forEach(obj, (value, prop) => props.push(prop)); StringMapWrapper.forEach(obj, (value, prop) => props.push(prop));
props.sort(); props.sort();
return props; return props;
} }
/** @internal */
private _metricNames: string[]; private _metricNames: string[];
constructor(private _columnWidth: number, sampleDescription, private _print: Function) { constructor(private _columnWidth: number, sampleDescription, private _print: Function) {
@ -46,7 +59,8 @@ export class ConsoleReporter extends Reporter {
this._printDescription(sampleDescription); this._printDescription(sampleDescription);
} }
_printDescription(sampleDescription) { /** @internal */
private _printDescription(sampleDescription) {
this._print(`BENCHMARK ${sampleDescription.id}`); this._print(`BENCHMARK ${sampleDescription.id}`);
this._print('Description:'); this._print('Description:');
var props = ConsoleReporter._sortedProps(sampleDescription.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 samples = validSamples.map(measureValues => measureValues.values[metricName]);
var mean = Statistic.calculateMean(samples); var mean = Statistic.calculateMean(samples);
var cv = Statistic.calculateCoefficientOfVariation(samples, mean); var cv = Statistic.calculateCoefficientOfVariation(samples, mean);
var formattedMean = ConsoleReporter._formatNum(mean) var formattedMean = ConsoleReporter._formatNum(mean);
// Note: Don't use the unicode character for +- as it might cause // Note: Don't use the unicode character for +- as it might cause
// hickups for consoles... // hickups for consoles...
return NumberWrapper.isNaN(cv) ? return NumberWrapper.isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
formattedMean :
`${formattedMean}+-${Math.floor(cv)}%`;
})); }));
return PromiseWrapper.resolve(null); return PromiseWrapper.resolve(null);
} }
_printStringRow(parts: any[], fill = ' ') { /** @internal */
private _printStringRow(parts: any[], fill = ' ') {
this._print( this._print(
parts.map(part => ConsoleReporter._lpad(part, this._columnWidth, fill)).join(' | ')); parts.map(part => ConsoleReporter._lpad(part, this._columnWidth, fill)).join(' | '));
} }
@ -100,6 +113,5 @@ var _PROVIDERS = [
new ConsoleReporter(columnWidth, sampleDescription, print), new ConsoleReporter(columnWidth, sampleDescription, print),
deps: [_COLUMN_WIDTH, SampleDescription, _PRINT] deps: [_COLUMN_WIDTH, SampleDescription, _PRINT]
}, },
{provide: _COLUMN_WIDTH, useValue: 18}, {provide: _COLUMN_WIDTH, useValue: 18}, {provide: _PRINT, useValue: print}
{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 {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 {Reporter} from '../reporter';
import {SampleDescription} from '../sample_description'; import {SampleDescription} from '../sample_description';
import {MeasureValues} from '../measure_values';
import {Options} from '../common_options';
/** /**
* A reporter that writes results into a json file. * 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 // TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
_writeFile: Function; /** @internal */
_path: string; private _writeFile: Function;
_description: SampleDescription; /** @internal */
_now: Function; private _path: string;
/** @internal */
private _description: SampleDescription;
/** @internal */
private _now: Function;
constructor(sampleDescription, path, writeFile, now) { constructor(sampleDescription, path, writeFile, now) {
super(); super();

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 {Injector, OpaqueToken} from '@angular/core/src/di';
import {PromiseWrapper} from '@angular/facade/src/async'; 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)), useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
deps: [Injector], 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) { constructor(reporters) {
super(); super();

View File

@ -1,25 +1,34 @@
import {ReflectiveInjector} from '@angular/core'; /**
import {isPresent, isBlank} from '@angular/facade/src/lang'; * @license
import {PromiseWrapper} from '@angular/facade/src/async'; * 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 {ConsoleReporter} from './reporter/console_reporter';
import {MultiReporter} from './reporter/multi_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 {RegressionSlopeValidator} from './validator/regression_slope_validator';
import {SizeValidator} from './validator/size_validator'; import {SizeValidator} from './validator/size_validator';
import {Validator} from './validator'; import {WebDriverAdapter} from './web_driver_adapter';
import {PerflogMetric} from './metric/perflog_metric'; import {WebDriverExtension} from './web_driver_extension';
import {MultiMetric} from './metric/multi_metric';
import {UserMetric} from './metric/user_metric';
import {ChromeDriverExtension} from './webdriver/chrome_driver_extension'; import {ChromeDriverExtension} from './webdriver/chrome_driver_extension';
import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension'; import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension';
import {IOsDriverExtension} from './webdriver/ios_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. * The Runner is the main entry point for executing a sample run.
@ -34,13 +43,16 @@ export class Runner {
this._defaultProviders = defaultProviders; this._defaultProviders = defaultProviders;
} }
sample({id, execute, prepare, microMetrics, providers, userMetrics}: sample({id, execute, prepare, microMetrics, providers, userMetrics}: {
{id: string, execute?: any, prepare?: any, microMetrics?: any, providers?: any, userMetrics?: any}): id: string,
Promise<SampleState> { execute?: any,
prepare?: any,
microMetrics?: any,
providers?: any,
userMetrics?: any
}): Promise<SampleState> {
var sampleProviders = [ var sampleProviders = [
_DEFAULT_PROVIDERS, _DEFAULT_PROVIDERS, this._defaultProviders, {provide: Options.SAMPLE_ID, useValue: id},
this._defaultProviders,
{provide: Options.SAMPLE_ID, useValue: id},
{provide: Options.EXECUTE, useValue: execute} {provide: Options.EXECUTE, useValue: execute}
]; ];
if (isPresent(prepare)) { if (isPresent(prepare)) {
@ -71,8 +83,7 @@ export class Runner {
// TODO vsavkin consider changing it when toAsyncFactory is added back or when child // TODO vsavkin consider changing it when toAsyncFactory is added back or when child
// injectors are handled better. // injectors are handled better.
var injector = ReflectiveInjector.resolveAndCreate([ var injector = ReflectiveInjector.resolveAndCreate([
sampleProviders, sampleProviders, {provide: Options.CAPABILITIES, useValue: capabilities},
{provide: Options.CAPABILITIES, useValue: capabilities},
{provide: Options.USER_AGENT, useValue: userAgent}, {provide: Options.USER_AGENT, useValue: userAgent},
{provide: WebDriverAdapter, useValue: adapter} {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 {StringMapWrapper} from '@angular/facade/src/collection';
import {Validator} from './validator';
import {Metric} from './metric';
import {Options} from './common_options'; import {Options} from './common_options';
import {Metric} from './metric';
import {Validator} from './validator';
/** /**
* SampleDescription merges all available descriptions about a sample * SampleDescription merges all available descriptions about a sample
@ -11,7 +21,8 @@ export class SampleDescription {
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
description: {[key: string]: any}; description: {[key: string]: any};
constructor(public id: string, descriptions: Array<{[key: string]: any}>, constructor(
public id: string, descriptions: Array<{[key: string]: any}>,
public metrics: {[key: string]: any}) { public metrics: {[key: string]: any}) {
this.description = {}; this.description = {};
descriptions.forEach(description => { descriptions.forEach(description => {
@ -22,26 +33,18 @@ export class SampleDescription {
toJson() { return {'id': this.id, 'description': this.description, 'metrics': this.metrics}; } toJson() { return {'id': this.id, 'description': this.description, 'metrics': this.metrics}; }
} }
var _PROVIDERS = [ var _PROVIDERS = [{
{
provide: SampleDescription, provide: SampleDescription,
useFactory: (metric, id, forceGc, userAgent, validator, defaultDesc, userDesc) => useFactory: (metric, id, forceGc, userAgent, validator, defaultDesc, userDesc) =>
new SampleDescription(id, new SampleDescription(
id,
[ [
{'forceGc': forceGc, 'userAgent': userAgent}, {'forceGc': forceGc, 'userAgent': userAgent}, validator.describe(),
validator.describe(), defaultDesc, userDesc
defaultDesc,
userDesc
], ],
metric.describe()), metric.describe()),
deps: [ deps: [
Metric, Metric, Options.SAMPLE_ID, Options.FORCE_GC, Options.USER_AGENT, Validator,
Options.SAMPLE_ID, Options.DEFAULT_DESCRIPTION, Options.SAMPLE_DESCRIPTION
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 {PromiseWrapper} from '@angular/facade/src/async';
import {Validator} from './validator'; import {Date, DateWrapper, isBlank, isPresent} from '@angular/facade/src/lang';
import {Reporter} from './reporter';
import {WebDriverAdapter} from './web_driver_adapter';
import {Options} from './common_options'; import {Options} from './common_options';
import {MeasureValues} from './measure_values'; 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: * The Sampler owns the sample loop:
@ -21,13 +29,20 @@ export class Sampler {
// TODO(tbosch): use static values when our transpiler supports them // TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
_driver: WebDriverAdapter; /** @internal */
_metric: Metric; private _driver: WebDriverAdapter;
_reporter: Reporter; /** @internal */
_validator: Validator; private _metric: Metric;
_prepare: Function; /** @internal */
_execute: Function; private _reporter: Reporter;
_now: Function; /** @internal */
private _validator: Validator;
/** @internal */
private _prepare: Function;
/** @internal */
private _execute: Function;
/** @internal */
private _now: Function;
constructor({driver, metric, reporter, validator, prepare, execute, now}: { constructor({driver, metric, reporter, validator, prepare, execute, now}: {
driver?: WebDriverAdapter, driver?: WebDriverAdapter,
@ -61,7 +76,8 @@ export class Sampler {
return loop(new SampleState([], null)); return loop(new SampleState([], null));
} }
_iterate(lastState): Promise<SampleState> { /** @internal */
private _iterate(lastState): Promise<SampleState> {
var resultPromise: Promise<any>; var resultPromise: Promise<any>;
if (isPresent(this._prepare)) { if (isPresent(this._prepare)) {
resultPromise = this._driver.waitFor(this._prepare); resultPromise = this._driver.waitFor(this._prepare);
@ -76,14 +92,15 @@ export class Sampler {
.then((measureValues) => this._report(lastState, measureValues)); .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 measureValues = new MeasureValues(state.completeSample.length, this._now(), metricValues);
var completeSample = state.completeSample.concat([measureValues]); var completeSample = state.completeSample.concat([measureValues]);
var validSample = this._validator.validate(completeSample); var validSample = this._validator.validate(completeSample);
var resultPromise = this._reporter.reportMeasureValues(measureValues); var resultPromise = this._reporter.reportMeasureValues(measureValues);
if (isPresent(validSample)) { if (isPresent(validSample)) {
resultPromise = resultPromise =
resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample)) resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample));
} }
return resultPromise.then((_) => new SampleState(completeSample, validSample)); return resultPromise.then((_) => new SampleState(completeSample, validSample));
} }
@ -93,8 +110,7 @@ export class SampleState {
constructor(public completeSample: any[], public validSample: any[]) {} constructor(public completeSample: any[], public validSample: any[]) {}
} }
var _PROVIDERS = [ var _PROVIDERS = [{
{
provide: Sampler, provide: Sampler,
useFactory: (driver, metric, reporter, validator, prepare, execute, now) => new Sampler({ useFactory: (driver, metric, reporter, validator, prepare, execute, now) => new Sampler({
driver: driver, driver: driver,
@ -109,13 +125,6 @@ var _PROVIDERS = [
now: now now: now
}), }),
deps: [ deps: [
WebDriverAdapter, WebDriverAdapter, Metric, Reporter, Validator, Options.PREPARE, Options.EXECUTE, Options.NOW
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'; import {Math} from '@angular/facade/src/math';
export class Statistic { export class Statistic {
@ -21,8 +29,8 @@ export class Statistic {
return deviation; return deviation;
} }
static calculateRegressionSlope(xValues: number[], xMean: number, yValues: number[], static calculateRegressionSlope(
yMean: number) { xValues: number[], xMean: number, yValues: number[], yMean: number) {
// See http://en.wikipedia.org/wiki/Simple_linear_regression // See http://en.wikipedia.org/wiki/Simple_linear_regression
var dividendSum = 0; var dividendSum = 0;
var divisorSum = 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 {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {MeasureValues} from './measure_values'; 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 {MeasureValues} from '../measure_values';
import {Statistic} from '../statistic';
import {Validator} from '../validator';
/** /**
* A validator that checks the regression slope of a specific metric. * 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 // TODO(tbosch): use static values when our transpiler supports them
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
_sampleSize: number; /** @internal */
_metric: string; private _sampleSize: number;
/** @internal */
private _metric: string;
constructor(sampleSize, metric) { constructor(sampleSize, metric) {
super(); super();
@ -32,8 +43,8 @@ export class RegressionSlopeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] { validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) { if (completeSample.length >= this._sampleSize) {
var latestSample = ListWrapper.slice(completeSample, completeSample.length - this._sampleSize, var latestSample = ListWrapper.slice(
completeSample.length); completeSample, completeSample.length - this._sampleSize, completeSample.length);
var xValues = []; var xValues = [];
var yValues = []; var yValues = [];
for (var i = 0; i < latestSample.length; i++) { for (var i = 0; i < latestSample.length; i++) {
@ -59,6 +70,5 @@ var _PROVIDERS = [
useFactory: (sampleSize, metric) => new RegressionSlopeValidator(sampleSize, metric), useFactory: (sampleSize, metric) => new RegressionSlopeValidator(sampleSize, metric),
deps: [_SAMPLE_SIZE, _METRIC] deps: [_SAMPLE_SIZE, _METRIC]
}, },
{provide: _SAMPLE_SIZE, useValue: 10}, {provide: _SAMPLE_SIZE, useValue: 10}, {provide: _METRIC, useValue: 'scriptTime'}
{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 {MeasureValues} from '../measure_values';
import {Validator} from '../validator';
/** /**
* A validator that waits for the sample to have a certain size. * 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 // TODO(tbosch): use static values when our transpiler supports them
static get SAMPLE_SIZE() { return _SAMPLE_SIZE; } static get SAMPLE_SIZE() { return _SAMPLE_SIZE; }
_sampleSize: number; /** @internal */
private _sampleSize: number;
constructor(size) { constructor(size) {
super(); super();
@ -24,8 +34,8 @@ export class SizeValidator extends Validator {
validate(completeSample: MeasureValues[]): MeasureValues[] { validate(completeSample: MeasureValues[]): MeasureValues[] {
if (completeSample.length >= this._sampleSize) { if (completeSample.length >= this._sampleSize) {
return ListWrapper.slice(completeSample, completeSample.length - this._sampleSize, return ListWrapper.slice(
completeSample.length); completeSample, completeSample.length - this._sampleSize, completeSample.length);
} else { } else {
return null; return null;
} }
@ -34,10 +44,6 @@ export class SizeValidator extends Validator {
var _SAMPLE_SIZE = new OpaqueToken('SizeValidator.sampleSize'); var _SAMPLE_SIZE = new OpaqueToken('SizeValidator.sampleSize');
var _PROVIDERS = [ 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} {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 {Map} from '@angular/facade/src/collection';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions';
/** /**
* A WebDriverAdapter bridges API differences between different WebDriver clients, * 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 {BaseException, WrappedException} from '@angular/facade/src/exceptions';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import {Options} from './common_options'; import {Options} from './common_options';
/** /**
* A WebDriverExtension implements extended commands of the webdriver protocol * A WebDriverExtension implements extended commands of the webdriver protocol
* for a given browser, independent of the WebDriverAdapter. * for a given browser, independent of the WebDriverAdapter.
@ -20,7 +28,7 @@ export abstract class WebDriverExtension {
}, },
{ {
provide: WebDriverExtension, provide: WebDriverExtension,
useFactory: (children:WebDriverExtension[], capabilities) => { useFactory: (children: WebDriverExtension[], capabilities) => {
var delegate; var delegate;
children.forEach(extension => { children.forEach(extension => {
if (extension.supports(capabilities)) { if (extension.supports(capabilities)) {

View File

@ -1,17 +1,19 @@
import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection'; /**
import { * @license
Json, * Copyright Google Inc. All Rights Reserved.
isPresent, *
isBlank, * Use of this source code is governed by an MIT-style license that can be
RegExpWrapper, * found in the LICENSE file at https://angular.io/license
StringWrapper, */
NumberWrapper
} from '@angular/facade/src/lang'; import {ListWrapper, StringMapWrapper} from '@angular/facade/src/collection';
import {BaseException, WrappedException} from '@angular/facade/src/exceptions'; 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 {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: * 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> { timeEnd(name: string, restartName: string = null): Promise<any> {
var script = `console.timeEnd('${name}');`; var script = `console.timeEnd('${name}');`;
if (isPresent(restartName)) { if (isPresent(restartName)) {
script += `console.time('${restartName}');` script += `console.time('${restartName}');`;
} }
return this._driver.executeScript(script); return this._driver.executeScript(script);
} }
@ -82,7 +84,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
}); });
} }
private _convertPerfRecordsToEvents(chromeEvents: Array<{[key: string]: any}>, private _convertPerfRecordsToEvents(
chromeEvents: Array<{[key: string]: any}>,
normalizedEvents: Array<{[key: string]: any}> = null) { normalizedEvents: Array<{[key: string]: any}> = null) {
if (isBlank(normalizedEvents)) { if (isBlank(normalizedEvents)) {
normalizedEvents = []; normalizedEvents = [];
@ -93,7 +96,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
var name = event['name']; var name = event['name'];
if (this._isEvent(categories, name, ['blink.console'])) { if (this._isEvent(categories, name, ['blink.console'])) {
normalizedEvents.push(normalizeEvent(event, {'name': name})); normalizedEvents.push(normalizeEvent(event, {'name': name}));
} else if (this._isEvent(categories, name, ['benchmark'], } else if (this._isEvent(
categories, name, ['benchmark'],
'BenchmarkInstrumentation::ImplThreadRenderingStats')) { 'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the // TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
// following events should be used (if available) for more accurate measurments: // following events should be used (if available) for more accurate measurments:
@ -109,10 +113,10 @@ export class ChromeDriverExtension extends WebDriverExtension {
if (frameCount == 1) { if (frameCount == 1) {
normalizedEvents.push(normalizeEvent(event, {'name': 'frame'})); normalizedEvents.push(normalizeEvent(event, {'name': 'frame'}));
} }
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], } else if (
'Rasterize') || this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], this._isEvent(
'CompositeLayers')) { categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) {
normalizedEvents.push(normalizeEvent(event, {'name': 'render'})); normalizedEvents.push(normalizeEvent(event, {'name': 'render'}));
} else if (this._majorChromeVersion < 45) { } else if (this._majorChromeVersion < 45) {
var normalizedEvent = this._processAsPreChrome45Event(event, categories, majorGCPids); var normalizedEvent = this._processAsPreChrome45Event(event, categories, majorGCPids);
@ -130,22 +134,21 @@ export class ChromeDriverExtension extends WebDriverExtension {
var args = event['args']; var args = event['args'];
var pid = event['pid']; var pid = event['pid'];
var ph = event['ph']; var ph = event['ph'];
if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], if (this._isEvent(
'FunctionCall') && categories, name, ['disabled-by-default-devtools.timeline'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) || (isBlank(args) || isBlank(args['data']) ||
!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) { !StringWrapper.equals(args['data']['scriptName'], 'InjectedScript'))) {
return normalizeEvent(event, {'name': 'script'}); return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], } else if (
'RecalculateStyles') || this._isEvent(
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], categories, name, ['disabled-by-default-devtools.timeline'], 'RecalculateStyles') ||
'Layout') || this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], this._isEvent(
'UpdateLayerTree') || categories, name, ['disabled-by-default-devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Paint')) {
'Paint')) {
return normalizeEvent(event, {'name': 'render'}); return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], } else if (this._isEvent(
'GCEvent')) { categories, name, ['disabled-by-default-devtools.timeline'], 'GCEvent')) {
var normArgs = { var normArgs = {
'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] : 'usedHeapSize': isPresent(args['usedHeapSizeAfter']) ? args['usedHeapSizeAfter'] :
args['usedHeapSizeBefore'] args['usedHeapSizeBefore']
@ -155,8 +158,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
} }
majorGCPids[pid] = false; majorGCPids[pid] = false;
return normalizeEvent(event, {'name': 'gc', 'args': normArgs}); return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['v8'], 'majorGC') && } else if (
StringWrapper.equals(ph, 'B')) { this._isEvent(categories, name, ['v8'], 'majorGC') && StringWrapper.equals(ph, 'B')) {
majorGCPids[pid] = true; majorGCPids[pid] = true;
} }
return null; // nothing useful in this event return null; // nothing useful in this event
@ -179,15 +182,17 @@ export class ChromeDriverExtension extends WebDriverExtension {
args['usedHeapSizeBefore'] args['usedHeapSizeBefore']
}; };
return normalizeEvent(event, {'name': 'gc', 'args': normArgs}); return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'FunctionCall') && } else if (
this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'FunctionCall') &&
(isBlank(args) || isBlank(args['data']) || (isBlank(args) || isBlank(args['data']) ||
(!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript') && (!StringWrapper.equals(args['data']['scriptName'], 'InjectedScript') &&
!StringWrapper.equals(args['data']['scriptName'], '')))) { !StringWrapper.equals(args['data']['scriptName'], '')))) {
return normalizeEvent(event, {'name': 'script'}); return normalizeEvent(event, {'name': 'script'});
} else if (this._isEvent(categories, name, ['devtools.timeline', 'blink'], } else if (this._isEvent(
'UpdateLayoutTree')) { categories, name, ['devtools.timeline', 'blink'], 'UpdateLayoutTree')) {
return normalizeEvent(event, {'name': 'render'}); return normalizeEvent(event, {'name': 'render'});
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') || } else if (
this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') || this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) { this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
return normalizeEvent(event, {'name': 'render'}); return normalizeEvent(event, {'name': 'render'});
@ -206,7 +211,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
private _parseCategories(categories: string): string[] { return categories.split(','); } private _parseCategories(categories: string): string[] { return categories.split(','); }
private _isEvent(eventCategories: string[], eventName: string, expectedCategories: string[], private _isEvent(
eventCategories: string[], eventName: string, expectedCategories: string[],
expectedName: string = null): boolean { expectedName: string = null): boolean {
var hasCategories = expectedCategories.reduce( var hasCategories = expectedCategories.reduce(
(value, cat) => { return value && ListWrapper.contains(eventCategories, cat); }, true); (value, cat) => { return value && ListWrapper.contains(eventCategories, cat); }, true);
@ -224,8 +230,8 @@ export class ChromeDriverExtension extends WebDriverExtension {
} }
} }
function normalizeEvent(chromeEvent: {[key: string]: any}, function normalizeEvent(
data: {[key: string]: any}): {[key: string]: any} { chromeEvent: {[key: string]: any}, data: {[key: string]: any}): {[key: string]: any} {
var ph = chromeEvent['ph']; var ph = chromeEvent['ph'];
if (StringWrapper.equals(ph, 'S')) { if (StringWrapper.equals(ph, 'S')) {
ph = 'b'; ph = 'b';
@ -245,10 +251,8 @@ function normalizeEvent(chromeEvent: {[key: string]: any},
return result; return result;
} }
var _PROVIDERS = [ var _PROVIDERS = [{
{
provide: ChromeDriverExtension, provide: ChromeDriverExtension,
useFactory: (driver, userAgent) => new ChromeDriverExtension(driver, userAgent), useFactory: (driver, userAgent) => new ChromeDriverExtension(driver, userAgent),
deps: [WebDriverAdapter, Options.USER_AGENT] 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 {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
export class FirefoxDriverExtension extends WebDriverExtension { export class FirefoxDriverExtension extends WebDriverExtension {
static get PROVIDERS(): any[] { return _PROVIDERS; } static get PROVIDERS(): any[] { return _PROVIDERS; }
@ -41,10 +50,8 @@ export class FirefoxDriverExtension extends WebDriverExtension {
} }
} }
var _PROVIDERS = [ var _PROVIDERS = [{
{
provide: FirefoxDriverExtension, provide: FirefoxDriverExtension,
useFactory: (driver) => new FirefoxDriverExtension(driver), useFactory: (driver) => new FirefoxDriverExtension(driver),
deps: [WebDriverAdapter] 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 {WebDriverAdapter} from '../web_driver_adapter';
import {PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
export class IOsDriverExtension extends WebDriverExtension { export class IOsDriverExtension extends WebDriverExtension {
// TODO(tbosch): use static values when our transpiler supports them // 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> { timeEnd(name: string, restartName: string = null): Promise<any> {
var script = `console.timeEnd('${name}');`; var script = `console.timeEnd('${name}');`;
if (isPresent(restartName)) { if (isPresent(restartName)) {
script += `console.time('${restartName}');` script += `console.time('${restartName}');`;
} }
return this._driver.executeScript(script); 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)) { if (isBlank(events)) {
events = []; events = [];
} }
@ -61,10 +70,10 @@ export class IOsDriverExtension extends WebDriverExtension {
events.push(createMarkStartEvent(data['message'], startTime)); events.push(createMarkStartEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'TimeEnd')) { } else if (StringWrapper.equals(type, 'TimeEnd')) {
events.push(createMarkEndEvent(data['message'], startTime)); events.push(createMarkEndEvent(data['message'], startTime));
} else if (StringWrapper.equals(type, 'RecalculateStyles') || } else if (
StringWrapper.equals(type, 'Layout') || StringWrapper.equals(type, 'RecalculateStyles') || StringWrapper.equals(type, 'Layout') ||
StringWrapper.equals(type, 'UpdateLayerTree') || StringWrapper.equals(type, 'UpdateLayerTree') || StringWrapper.equals(type, 'Paint') ||
StringWrapper.equals(type, 'Paint') || StringWrapper.equals(type, 'Rasterize') || StringWrapper.equals(type, 'Rasterize') ||
StringWrapper.equals(type, 'CompositeLayers')) { StringWrapper.equals(type, 'CompositeLayers')) {
events.push(createStartEvent('render', startTime)); events.push(createStartEvent('render', startTime));
endEvent = createEndEvent('render', endTime); endEvent = createEndEvent('render', endTime);
@ -119,6 +128,8 @@ function createMarkEndEvent(name, time) {
return createEvent('e', name, time); return createEvent('e', name, time);
} }
var _PROVIDERS = [ var _PROVIDERS = [{
{provide: IOsDriverExtension, useFactory: (driver) => new IOsDriverExtension(driver), deps: [WebDriverAdapter]} 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 {PromiseWrapper} from '@angular/facade/src/async';
import * as webdriver from 'selenium-webdriver';
import {WebDriverAdapter} from '../web_driver_adapter'; import {WebDriverAdapter} from '../web_driver_adapter';
import * as webdriver from 'selenium-webdriver';
/** /**
* Adapter for the selenium-webdriver. * Adapter for the selenium-webdriver.
@ -11,7 +20,8 @@ export class SeleniumWebDriverAdapter extends WebDriverAdapter {
constructor(private _driver: any) { super(); } constructor(private _driver: any) { super(); }
_convertPromise(thenable) { /** @internal */
private _convertPromise(thenable) {
var completer = PromiseWrapper.completer(); var completer = PromiseWrapper.completer();
thenable.then( thenable.then(
// selenium-webdriver uses an own Node.js context, // selenium-webdriver uses an own Node.js context,
@ -55,6 +65,8 @@ function convertToLocalProcess(data): Object {
return JSON.parse(serialized); return JSON.parse(serialized);
} }
var _PROTRACTOR_BINDINGS = [ var _PROTRACTOR_BINDINGS = [{
{provide: WebDriverAdapter, useFactory: () => new SeleniumWebDriverAdapter((<any>global).browser), deps: []} 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('es6-shim/es6-shim.js');
require('reflect-metadata'); require('reflect-metadata');
var testHelper = require('../../src/firefox_extension/lib/test_helper.js'); 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'; import {convertPerfProfileToEvents} from 'benchpress/src/firefox_extension/lib/parser_util';
function assertEventsEqual(actualEvents, expectedEvents) { function assertEventsEqual(actualEvents, expectedEvents) {
@ -25,56 +33,48 @@ export function main() {
it('should convert single non-instantaneous event', function() { it('should convert single non-instantaneous event', function() {
var profileData = { var profileData = {
threads: [ threads: [{
{
samples: [ samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]} {time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
] ]
} }]
]
}; };
var perfEvents = convertPerfProfileToEvents(profileData); var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, assertEventsEqual(
[{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]); perfEvents, [{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
}); });
it('should convert multiple instantaneous events', function() { it('should convert multiple instantaneous events', function() {
var profileData = { var profileData = {
threads: [ threads: [{
{
samples: [ samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]} {time: 2, frames: [{location: 'PresShell::Paint'}]}
] ]
} }]
]
}; };
var perfEvents = convertPerfProfileToEvents(profileData); var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, assertEventsEqual(
[{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]); perfEvents, [{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
}); });
it('should convert multiple mixed events', function() { it('should convert multiple mixed events', function() {
var profileData = { var profileData = {
threads: [ threads: [{
{
samples: [ samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]}, {time: 2, frames: [{location: 'PresShell::Paint'}]},
{time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]} {time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
] ]
} }]
]
}; };
var perfEvents = convertPerfProfileToEvents(profileData); var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [ assertEventsEqual(perfEvents, [
{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'},
{ph: 'X', ts: 2, name: 'render'}, {ph: 'B', ts: 5, name: 'script'}, {ph: 'E', ts: 10, name: 'script'}
{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() { it('should skip unknown events', function() {
var profileData = { var profileData = {
threads: [ threads: [{
{
samples: [ samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}, {time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'foo'}]} {time: 2, frames: [{location: 'foo'}]}
] ]
} }]
]
}; };
var perfEvents = convertPerfProfileToEvents(profileData); var perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]); 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 benchpress = require('../../index.js');
var runner = new benchpress.Runner([ var runner = new benchpress.Runner([
// use protractor as Webdriver client // use protractor as Webdriver client
@ -21,10 +29,10 @@ describe('deep tree baseline', function() {
* Benchpress will log the collected metrics after each sample is collected, and will stop * 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. * sampling as soon as the calculated regression slope for last 20 samples is stable.
*/ */
runner.sample({ runner
.sample({
id: 'baseline', id: 'baseline',
execute: function() { $('button') execute: function() { $('button').click(); },
.click(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})] providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
}) })
.then(done, done.fail); .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 assertEventsContainsName = function(events, eventName) {
var found = false; var found = false;
for (var i = 0; i < events.length; ++i) { for (var i = 0; i < events.length; ++i) {
@ -17,8 +25,9 @@ describe('firefox extension', function() {
browser.driver.get(TEST_URL); browser.driver.get(TEST_URL);
browser.executeScript('window.startProfiler()') browser.executeScript('window.startProfiler()').then(function() {
.then(function() { console.log('started measuring perf'); }); console.log('started measuring perf');
});
browser.executeAsyncScript('setTimeout(arguments[0], 1000);'); browser.executeAsyncScript('setTimeout(arguments[0], 1000);');
browser.executeScript('window.forceGC()'); browser.executeScript('window.forceGC()');
@ -28,5 +37,5 @@ describe('firefox extension', function() {
assertEventsContainsName(profile, 'gc'); assertEventsContainsName(profile, 'gc');
assertEventsContainsName(profile, 'script'); assertEventsContainsName(profile, 'script');
}); });
}) });
}); });

View File

@ -1,10 +1,19 @@
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'; import {Metric, MultiMetric, ReflectiveInjector} from 'benchpress/common';
export function main() { export function main() {
function createMetric(ids: any[]) { function createMetric(ids: any[]) {
var m = ReflectiveInjector.resolveAndCreate([ var m = ReflectiveInjector
ids.map(id => {return {provide: id, useValue: new MockMetric(id)}}), .resolveAndCreate([
ids.map(id => { return {provide: id, useValue: new MockMetric(id)}; }),
MultiMetric.createBindings(ids) MultiMetric.createBindings(ids)
]) ])
.get(MultiMetric); .get(MultiMetric);
@ -13,17 +22,14 @@ export function main() {
describe('multi metric', () => { describe('multi metric', () => {
it('should merge descriptions', inject([AsyncTestCompleter], (async) => { it('should merge descriptions', inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2']) createMetric(['m1', 'm2']).then((m) => {
.then((m) => {
expect(m.describe()).toEqual({'m1': 'describe', 'm2': 'describe'}); expect(m.describe()).toEqual({'m1': 'describe', 'm2': 'describe'});
async.done(); async.done();
}); });
})); }));
it('should merge all beginMeasure calls', inject([AsyncTestCompleter], (async) => { it('should merge all beginMeasure calls', inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2']) createMetric(['m1', 'm2']).then((m) => m.beginMeasure()).then((values) => {
.then((m) => m.beginMeasure())
.then((values) => {
expect(values).toEqual(['m1_beginMeasure', 'm2_beginMeasure']); expect(values).toEqual(['m1_beginMeasure', 'm2_beginMeasure']);
async.done(); async.done();
}); });
@ -32,11 +38,9 @@ export function main() {
[false, true].forEach((restartFlag) => { [false, true].forEach((restartFlag) => {
it(`should merge all endMeasure calls for restart=${restartFlag}`, it(`should merge all endMeasure calls for restart=${restartFlag}`,
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createMetric(['m1', 'm2']) createMetric(['m1', 'm2']).then((m) => m.endMeasure(restartFlag)).then((values) => {
.then((m) => m.endMeasure(restartFlag)) expect(values).toEqual(
.then((values) => { {'m1': {'restart': restartFlag}, 'm2': {'restart': restartFlag}});
expect(values)
.toEqual({'m1': {'restart': restartFlag}, 'm2': {'restart': restartFlag}});
async.done(); async.done();
}); });
})); }));
@ -46,7 +50,8 @@ export function main() {
} }
class MockMetric extends Metric { class MockMetric extends Metric {
_id: string; /** @internal */
private _id: string;
constructor(id) { constructor(id) {
super(); 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 {PromiseWrapper} from '@angular/facade/src/async';
import {isPresent, isBlank} from '@angular/facade/src/lang'; import {StringMapWrapper} from '@angular/facade/src/collection';
import {isBlank, isPresent} from '@angular/facade/src/lang';
import { import {Metric, Options, PerfLogFeatures, PerflogMetric, ReflectiveInjector, WebDriverExtension} from 'benchpress/common';
Metric,
PerflogMetric,
WebDriverExtension,
PerfLogFeatures,
ReflectiveInjector,
Options
} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory'; import {TraceEventFactory} from '../trace_event_factory';
@ -19,7 +18,8 @@ export function main() {
var commandLog: any[]; var commandLog: any[];
var eventFactory = new TraceEventFactory('timeline', 'pid0'); var eventFactory = new TraceEventFactory('timeline', 'pid0');
function createMetric(perfLogs, perfLogFeatures, function createMetric(
perfLogs, perfLogFeatures,
{microMetrics, forceGc, captureFrames, receivedData, requestCount}: { {microMetrics, forceGc, captureFrames, receivedData, requestCount}: {
microMetrics?: {[key: string]: string}, microMetrics?: {[key: string]: string},
forceGc?: boolean, forceGc?: boolean,
@ -36,10 +36,8 @@ export function main() {
microMetrics = StringMapWrapper.create(); microMetrics = StringMapWrapper.create();
} }
var providers: any[] = [ var providers: any[] = [
Options.DEFAULT_PROVIDERS, Options.DEFAULT_PROVIDERS, PerflogMetric.PROVIDERS,
PerflogMetric.PROVIDERS, {provide: Options.MICRO_METRICS, useValue: microMetrics}, {
{provide: Options.MICRO_METRICS, useValue: microMetrics},
{
provide: PerflogMetric.SET_TIMEOUT, provide: PerflogMetric.SET_TIMEOUT,
useValue: (fn, millis) => { useValue: (fn, millis) => {
commandLog.push(['setTimeout', millis]); commandLog.push(['setTimeout', millis]);
@ -76,35 +74,31 @@ export function main() {
} }
it('should describe itself based on the perfLogFeatrues', () => { it('should describe itself based on the perfLogFeatrues', () => {
expect(sortedKeys(createMetric([[]], new PerfLogFeatures()).describe())) expect(sortedKeys(createMetric([[]], new PerfLogFeatures()).describe())).toEqual([
.toEqual(['pureScriptTime', 'scriptTime']); 'pureScriptTime', 'scriptTime'
]);
expect( expect(
sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: false})).describe())) sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: false})).describe()))
.toEqual(['pureScriptTime', 'renderTime', 'scriptTime']); .toEqual(['pureScriptTime', 'renderTime', 'scriptTime']);
expect(sortedKeys(createMetric([[]], null).describe())) expect(sortedKeys(createMetric([[]], null).describe())).toEqual([
.toEqual( 'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime', 'renderTime', 'scriptTime'
['gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime', 'renderTime', 'scriptTime']); ]);
expect(sortedKeys( expect(sortedKeys(createMetric([[]], new PerfLogFeatures({render: true, gc: true}), {
createMetric([[]], new PerfLogFeatures({render: true, gc: true}), {forceGc: true}) forceGc: true
.describe())) }).describe()))
.toEqual([ .toEqual([
'forcedGcAmount', 'forcedGcAmount', 'forcedGcTime', 'gcAmount', 'gcTime', 'majorGcTime', 'pureScriptTime',
'forcedGcTime', 'renderTime', 'scriptTime'
'gcAmount',
'gcTime',
'majorGcTime',
'pureScriptTime',
'renderTime',
'scriptTime'
]); ]);
expect(sortedKeys(createMetric([[]], new PerfLogFeatures({userTiming: true}), expect(sortedKeys(createMetric([[]], new PerfLogFeatures({userTiming: true}), {
{receivedData: true, requestCount: true}) receivedData: true,
.describe())) requestCount: true
}).describe()))
.toEqual(['pureScriptTime', 'receivedData', 'requestCount', 'scriptTime']); .toEqual(['pureScriptTime', 'receivedData', 'requestCount', 'scriptTime']);
}); });
@ -115,9 +109,9 @@ export function main() {
}); });
it('should describe itself if frame capture is requested and available', () => { it('should describe itself if frame capture is requested and available', () => {
var description = var description = createMetric([[]], new PerfLogFeatures({frameCapture: true}), {
createMetric([[]], new PerfLogFeatures({frameCapture: true}), {captureFrames: true}) captureFrames: true
.describe(); }).describe();
expect(description['frameTime.mean']).not.toContain('WARNING'); expect(description['frameTime.mean']).not.toContain('WARNING');
expect(description['frameTime.best']).not.toContain('WARNING'); expect(description['frameTime.best']).not.toContain('WARNING');
expect(description['frameTime.worst']).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', () => { it('should describe itself if frame capture is requested and not available', () => {
var description = var description = createMetric([[]], new PerfLogFeatures({frameCapture: false}), {
createMetric([[]], new PerfLogFeatures({frameCapture: false}), {captureFrames: true}) captureFrames: true
.describe(); }).describe();
expect(description['frameTime.mean']).toContain('WARNING'); expect(description['frameTime.mean']).toContain('WARNING');
expect(description['frameTime.best']).toContain('WARNING'); expect(description['frameTime.best']).toContain('WARNING');
expect(description['frameTime.worst']).toContain('WARNING'); expect(description['frameTime.worst']).toContain('WARNING');
@ -160,23 +154,14 @@ export function main() {
it('should mark and aggregate events in between the marks', it('should mark and aggregate events in between the marks',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
var events = [ var events = [[
[ eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.markStart('benchpress0', 0), eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10)
eventFactory.start('script', 4), ]];
eventFactory.end('script', 6),
eventFactory.markEnd('benchpress0', 10)
]
];
var metric = createMetric(events, null); var metric = createMetric(events, null);
metric.beginMeasure() metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
.then((_) => metric.endMeasure(false)) expect(commandLog).toEqual([
.then((data) => { ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog'
expect(commandLog)
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', null],
'readPerfLog'
]); ]);
expect(data['scriptTime']).toBe(2); expect(data['scriptTime']).toBe(2);
@ -198,13 +183,9 @@ export function main() {
.then((_) => metric.endMeasure(true)) .then((_) => metric.endMeasure(true))
.then((_) => metric.endMeasure(true)) .then((_) => metric.endMeasure(true))
.then((_) => { .then((_) => {
expect(commandLog) expect(commandLog).toEqual([
.toEqual([ ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
['timeBegin', 'benchpress0'], 'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['timeEnd', 'benchpress1', 'benchpress2'],
'readPerfLog'
]); ]);
async.done(); async.done();
@ -217,24 +198,15 @@ export function main() {
[eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 1)], [eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 1)],
[eventFactory.end('script', 2)], [eventFactory.end('script', 2)],
[ [
eventFactory.start('script', 3), eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.end('script', 5),
eventFactory.markEnd('benchpress0', 10) eventFactory.markEnd('benchpress0', 10)
] ]
]; ];
var metric = createMetric(events, null); var metric = createMetric(events, null);
metric.beginMeasure() metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
.then((_) => metric.endMeasure(false)) expect(commandLog).toEqual([
.then((data) => { ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', null], 'readPerfLog',
expect(commandLog) ['setTimeout', 100], 'readPerfLog', ['setTimeout', 100], 'readPerfLog'
.toEqual([
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', null],
'readPerfLog',
['setTimeout', 100],
'readPerfLog',
['setTimeout', 100],
'readPerfLog'
]); ]);
expect(data['scriptTime']).toBe(3); expect(data['scriptTime']).toBe(3);
@ -246,15 +218,12 @@ export function main() {
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
var events = [ var events = [
[ [
eventFactory.markStart('benchpress0', 0), eventFactory.markStart('benchpress0', 0), eventFactory.markEnd('benchpress0', 1),
eventFactory.markEnd('benchpress0', 1), eventFactory.markStart('benchpress1', 1), eventFactory.start('script', 1),
eventFactory.markStart('benchpress1', 1),
eventFactory.start('script', 1),
eventFactory.end('script', 2) eventFactory.end('script', 2)
], ],
[ [
eventFactory.start('script', 3), eventFactory.start('script', 3), eventFactory.end('script', 5),
eventFactory.end('script', 5),
eventFactory.markEnd('benchpress1', 6) eventFactory.markEnd('benchpress1', 6)
] ]
]; ];
@ -263,16 +232,12 @@ export function main() {
.then((_) => metric.endMeasure(true)) .then((_) => metric.endMeasure(true))
.then((data) => { .then((data) => {
expect(data['scriptTime']).toBe(0); expect(data['scriptTime']).toBe(0);
return metric.endMeasure(true) return metric.endMeasure(true);
}) })
.then((data) => { .then((data) => {
expect(commandLog) expect(commandLog).toEqual([
.toEqual([ ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
['timeBegin', 'benchpress0'], 'readPerfLog', ['timeEnd', 'benchpress1', 'benchpress2'], 'readPerfLog'
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['timeEnd', 'benchpress1', 'benchpress2'],
'readPerfLog'
]); ]);
expect(data['scriptTime']).toBe(3); expect(data['scriptTime']).toBe(3);
@ -283,34 +248,22 @@ export function main() {
describe('with forced gc', () => { describe('with forced gc', () => {
var events; var events;
beforeEach(() => { beforeEach(() => {
events = [ events = [[
[ eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 4),
eventFactory.markStart('benchpress0', 0), eventFactory.end('script', 6), eventFactory.markEnd('benchpress0', 10),
eventFactory.start('script', 4),
eventFactory.end('script', 6),
eventFactory.markEnd('benchpress0', 10),
eventFactory.markStart('benchpress1', 11), eventFactory.markStart('benchpress1', 11),
eventFactory.start('gc', 12, {'usedHeapSize': 2500}), eventFactory.start('gc', 12, {'usedHeapSize': 2500}),
eventFactory.end('gc', 15, {'usedHeapSize': 1000}), eventFactory.end('gc', 15, {'usedHeapSize': 1000}),
eventFactory.markEnd('benchpress1', 20) eventFactory.markEnd('benchpress1', 20)
] ]];
];
}); });
it('should measure forced gc', inject([AsyncTestCompleter], (async) => { it('should measure forced gc', inject([AsyncTestCompleter], (async) => {
var metric = createMetric(events, null, {forceGc: true}); var metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure() metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
.then((_) => metric.endMeasure(false)) expect(commandLog).toEqual([
.then((data) => { ['gc'], ['timeBegin', 'benchpress0'], ['timeEnd', 'benchpress0', 'benchpress1'],
expect(commandLog) 'readPerfLog', ['gc'], ['timeEnd', 'benchpress1', null], 'readPerfLog'
.toEqual([
['gc'],
['timeBegin', 'benchpress0'],
['timeEnd', 'benchpress0', 'benchpress1'],
'readPerfLog',
['gc'],
['timeEnd', 'benchpress1', null],
'readPerfLog'
]); ]);
expect(data['forcedGcTime']).toBe(3); expect(data['forcedGcTime']).toBe(3);
expect(data['forcedGcAmount']).toBe(1.5); expect(data['forcedGcAmount']).toBe(1.5);
@ -321,9 +274,7 @@ export function main() {
it('should restart after the forced gc if needed', inject([AsyncTestCompleter], (async) => { it('should restart after the forced gc if needed', inject([AsyncTestCompleter], (async) => {
var metric = createMetric(events, null, {forceGc: true}); var metric = createMetric(events, null, {forceGc: true});
metric.beginMeasure() metric.beginMeasure().then((_) => metric.endMeasure(true)).then((data) => {
.then((_) => metric.endMeasure(true))
.then((data) => {
expect(commandLog[5]).toEqual(['timeEnd', 'benchpress1', 'benchpress2']); 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) => { it('should calculate mean frame time', inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
eventFactory.markStart('frameCapture', 0), eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 1), eventFactory.instant('frame', 3), eventFactory.instant('frame', 4),
eventFactory.instant('frame', 3),
eventFactory.instant('frame', 4),
eventFactory.markEnd('frameCapture', 5) eventFactory.markEnd('frameCapture', 5)
], ],
{captureFrames: true}) {captureFrames: true})
@ -376,8 +325,9 @@ export function main() {
[eventFactory.instant('frame', 4), eventFactory.markEnd('frameCapture', 5)], [eventFactory.instant('frame', 4), eventFactory.markEnd('frameCapture', 5)],
{captureFrames: true}), {captureFrames: true}),
(err): any => { (err): any => {
expect(() => { throw err; }) expect(() => {
.toThrowError('missing start event for frame capture'); throw err;
}).toThrowError('missing start event for frame capture');
async.done(); async.done();
}); });
})); }));
@ -402,8 +352,9 @@ export function main() {
], ],
{captureFrames: true}), {captureFrames: true}),
(err): any => { (err): any => {
expect(() => { throw err; }) expect(() => {
.toThrowError('can capture frames only once per benchmark run'); throw err;
}).toThrowError('can capture frames only once per benchmark run');
async.done(); async.done();
}); });
})); }));
@ -432,14 +383,10 @@ export function main() {
it('should calculate best and worst frame time', inject([AsyncTestCompleter], (async) => { it('should calculate best and worst frame time', inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
eventFactory.markStart('frameCapture', 0), eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 1), eventFactory.instant('frame', 9), eventFactory.instant('frame', 15),
eventFactory.instant('frame', 9), eventFactory.instant('frame', 18), eventFactory.instant('frame', 28),
eventFactory.instant('frame', 15), eventFactory.instant('frame', 32), eventFactory.markEnd('frameCapture', 10)
eventFactory.instant('frame', 18),
eventFactory.instant('frame', 28),
eventFactory.instant('frame', 32),
eventFactory.markEnd('frameCapture', 10)
], ],
{captureFrames: true}) {captureFrames: true})
.then((data) => { .then((data) => {
@ -453,10 +400,8 @@ export function main() {
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
eventFactory.markStart('frameCapture', 0), eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 1), eventFactory.instant('frame', 2), eventFactory.instant('frame', 3),
eventFactory.instant('frame', 2),
eventFactory.instant('frame', 3),
eventFactory.markEnd('frameCapture', 4) eventFactory.markEnd('frameCapture', 4)
], ],
{captureFrames: true}) {captureFrames: true})
@ -470,12 +415,9 @@ export function main() {
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
eventFactory.markStart('frameCapture', 0), eventFactory.markStart('frameCapture', 0), eventFactory.instant('frame', 1),
eventFactory.instant('frame', 1), eventFactory.instant('frame', 2), eventFactory.instant('frame', 22),
eventFactory.instant('frame', 2), eventFactory.instant('frame', 23), eventFactory.instant('frame', 24),
eventFactory.instant('frame', 22),
eventFactory.instant('frame', 23),
eventFactory.instant('frame', 24),
eventFactory.markEnd('frameCapture', 4) eventFactory.markEnd('frameCapture', 4)
], ],
{captureFrames: true}) {captureFrames: true})
@ -488,8 +430,9 @@ export function main() {
}); });
it('should report a single interval', inject([AsyncTestCompleter], (async) => { it('should report a single interval', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 0), eventFactory.end('script', 5)]) aggregate([
.then((data) => { eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5); expect(data['scriptTime']).toBe(5);
async.done(); async.done();
}); });
@ -497,28 +440,23 @@ export function main() {
it('should sum up multiple intervals', inject([AsyncTestCompleter], (async) => { it('should sum up multiple intervals', inject([AsyncTestCompleter], (async) => {
aggregate([ aggregate([
eventFactory.start('script', 0), eventFactory.start('script', 0), eventFactory.end('script', 5),
eventFactory.end('script', 5), eventFactory.start('script', 10), eventFactory.end('script', 17)
eventFactory.start('script', 10), ]).then((data) => {
eventFactory.end('script', 17)
])
.then((data) => {
expect(data['scriptTime']).toBe(12); expect(data['scriptTime']).toBe(12);
async.done(); async.done();
}); });
})); }));
it('should ignore not started intervals', inject([AsyncTestCompleter], (async) => { it('should ignore not started intervals', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.end('script', 10)]) aggregate([eventFactory.end('script', 10)]).then((data) => {
.then((data) => {
expect(data['scriptTime']).toBe(0); expect(data['scriptTime']).toBe(0);
async.done(); async.done();
}); });
})); }));
it('should ignore not ended intervals', inject([AsyncTestCompleter], (async) => { it('should ignore not ended intervals', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 10)]) aggregate([eventFactory.start('script', 10)]).then((data) => {
.then((data) => {
expect(data['scriptTime']).toBe(0); expect(data['scriptTime']).toBe(0);
async.done(); async.done();
}); });
@ -526,12 +464,9 @@ export function main() {
it('should ignore nested intervals', inject([AsyncTestCompleter], (async) => { it('should ignore nested intervals', inject([AsyncTestCompleter], (async) => {
aggregate([ aggregate([
eventFactory.start('script', 0), eventFactory.start('script', 0), eventFactory.start('script', 5),
eventFactory.start('script', 5), eventFactory.end('script', 10), eventFactory.end('script', 17)
eventFactory.end('script', 10), ]).then((data) => {
eventFactory.end('script', 17)
])
.then((data) => {
expect(data['scriptTime']).toBe(17); expect(data['scriptTime']).toBe(17);
async.done(); async.done();
}); });
@ -541,36 +476,33 @@ export function main() {
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
var otherProcessEventFactory = new TraceEventFactory('timeline', 'pid1'); var otherProcessEventFactory = new TraceEventFactory('timeline', 'pid1');
var metric = createMetric( var metric = createMetric(
[ [[
[ eventFactory.markStart('benchpress0', 0), eventFactory.start('script', 0, null),
eventFactory.markStart('benchpress0', 0),
eventFactory.start('script', 0, null),
eventFactory.end('script', 5, null), eventFactory.end('script', 5, null),
otherProcessEventFactory.start('script', 10, null), otherProcessEventFactory.start('script', 10, null),
otherProcessEventFactory.end('script', 17, null), otherProcessEventFactory.end('script', 17, null),
eventFactory.markEnd('benchpress0', 20) eventFactory.markEnd('benchpress0', 20)
] ]],
],
null); null);
metric.beginMeasure() metric.beginMeasure().then((_) => metric.endMeasure(false)).then((data) => {
.then((_) => metric.endMeasure(false))
.then((data) => {
expect(data['scriptTime']).toBe(5); expect(data['scriptTime']).toBe(5);
async.done(); async.done();
}); });
})); }));
it('should support scriptTime metric', inject([AsyncTestCompleter], (async) => { it('should support scriptTime metric', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('script', 0), eventFactory.end('script', 5)]) aggregate([
.then((data) => { eventFactory.start('script', 0), eventFactory.end('script', 5)
]).then((data) => {
expect(data['scriptTime']).toBe(5); expect(data['scriptTime']).toBe(5);
async.done(); async.done();
}); });
})); }));
it('should support renderTime metric', inject([AsyncTestCompleter], (async) => { it('should support renderTime metric', inject([AsyncTestCompleter], (async) => {
aggregate([eventFactory.start('render', 0), eventFactory.end('render', 5)]) aggregate([
.then((data) => { eventFactory.start('render', 0), eventFactory.end('render', 5)
]).then((data) => {
expect(data['renderTime']).toBe(5); expect(data['renderTime']).toBe(5);
async.done(); async.done();
}); });
@ -580,8 +512,7 @@ export function main() {
aggregate([ aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}), eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000}) eventFactory.end('gc', 5, {'usedHeapSize': 1000})
]) ]).then((data) => {
.then((data) => {
expect(data['gcTime']).toBe(5); expect(data['gcTime']).toBe(5);
expect(data['gcAmount']).toBe(1.5); expect(data['gcAmount']).toBe(1.5);
expect(data['majorGcTime']).toBe(0); expect(data['majorGcTime']).toBe(0);
@ -593,8 +524,7 @@ export function main() {
aggregate([ aggregate([
eventFactory.start('gc', 0, {'usedHeapSize': 2500}), eventFactory.start('gc', 0, {'usedHeapSize': 2500}),
eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true}) eventFactory.end('gc', 5, {'usedHeapSize': 1000, 'majorGc': true})
]) ]).then((data) => {
.then((data) => {
expect(data['gcTime']).toBe(5); expect(data['gcTime']).toBe(5);
expect(data['majorGcTime']).toBe(5); expect(data['majorGcTime']).toBe(5);
async.done(); async.done();
@ -604,22 +534,18 @@ export function main() {
it('should support pureScriptTime = scriptTime-gcTime-renderTime', it('should support pureScriptTime = scriptTime-gcTime-renderTime',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
aggregate([ aggregate([
eventFactory.start('script', 0), eventFactory.start('script', 0), eventFactory.start('gc', 1, {'usedHeapSize': 1000}),
eventFactory.start('gc', 1, {'usedHeapSize': 1000}), eventFactory.end('gc', 4, {'usedHeapSize': 0}), eventFactory.start('render', 4),
eventFactory.end('gc', 4, {'usedHeapSize': 0}), eventFactory.end('render', 5), eventFactory.end('script', 6)
eventFactory.start('render', 4), ]).then((data) => {
eventFactory.end('render', 5),
eventFactory.end('script', 6)
])
.then((data) => {
expect(data['scriptTime']).toBe(6); expect(data['scriptTime']).toBe(6);
expect(data['pureScriptTime']).toBe(2); expect(data['pureScriptTime']).toBe(2);
async.done(); async.done();
}); });
})); }));
describe('receivedData', describe('receivedData', () => {
() => {it('should report received data since last navigationStart', it('should report received data since last navigationStart',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
@ -635,10 +561,11 @@ export function main() {
expect(data['receivedData']).toBe(12); expect(data['receivedData']).toBe(12);
async.done(); async.done();
}); });
}))}); }));
});
describe('requestCount', describe('requestCount', () => {
() => {it('should report count of requests sent since last navigationStart', it('should report count of requests sent since last navigationStart',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
aggregate( aggregate(
[ [
@ -646,15 +573,15 @@ export function main() {
eventFactory.instant('navigationStart', 1), eventFactory.instant('navigationStart', 1),
eventFactory.instant('sendRequest', 2), eventFactory.instant('sendRequest', 2),
eventFactory.instant('navigationStart', 3), eventFactory.instant('navigationStart', 3),
eventFactory.instant('sendRequest', 4), eventFactory.instant('sendRequest', 4), eventFactory.instant('sendRequest', 5)
eventFactory.instant('sendRequest', 5)
], ],
{requestCount: true}) {requestCount: true})
.then((data) => { .then((data) => {
expect(data['requestCount']).toBe(2); expect(data['requestCount']).toBe(2);
async.done(); async.done();
}); });
}))}); }));
});
describe('microMetrics', () => { describe('microMetrics', () => {
@ -676,8 +603,7 @@ export function main() {
aggregate([ aggregate([
eventFactory.markStart('mm1', 0), eventFactory.markStart('mm1', 0),
eventFactory.markEnd('mm1', 5), eventFactory.markEnd('mm1', 5),
]) ]).then((data) => {
.then((data) => {
expect(data['mm1']).toBeFalsy(); expect(data['mm1']).toBeFalsy();
async.done(); async.done();
}); });
@ -704,7 +630,8 @@ export function main() {
} }
class MockDriverExtension extends WebDriverExtension { class MockDriverExtension extends WebDriverExtension {
constructor(private _perfLogs: any[], private _commandLog: any[], constructor(
private _perfLogs: any[], private _commandLog: any[],
private _perfLogFeatures: PerfLogFeatures) { private _perfLogFeatures: PerfLogFeatures) {
super(); super();
} }

View File

@ -1,29 +1,23 @@
/**
* @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 {ReflectiveInjector} from '@angular/core';
import {afterEach, AsyncTestCompleter, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal'; 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 {TimerWrapper} from '@angular/facade/src/async';
import {StringMapWrapper} from '@angular/facade/src/collection'; import {StringMapWrapper} from '@angular/facade/src/collection';
import {PromiseWrapper} from '@angular/facade/src/async'; import {Json, isBlank, isPresent} from '@angular/facade/src/lang';
import {isPresent, isBlank, Json} from '@angular/facade/src/lang'; import {Injector, Metric, MultiMetric, Options, PerfLogFeatures, PerflogMetric, UserMetric, WebDriverAdapter, WebDriverExtension, bind, provide} from 'benchpress/common';
import {
Metric,
MultiMetric,
PerflogMetric,
UserMetric,
WebDriverAdapter,
WebDriverExtension,
PerfLogFeatures,
bind,
provide,
Injector,
Options
} from 'benchpress/common';
export function main() { export function main() {
var wdAdapter: MockDriverAdapter; var wdAdapter: MockDriverAdapter;
function createMetric(perfLogs, perfLogFeatures, function createMetric(
perfLogs, perfLogFeatures,
{userMetrics}: {userMetrics?: {[key: string]: string}} = {}): UserMetric { {userMetrics}: {userMetrics?: {[key: string]: string}} = {}): UserMetric {
if (isBlank(perfLogFeatures)) { if (isBlank(perfLogFeatures)) {
perfLogFeatures = perfLogFeatures =
@ -34,8 +28,7 @@ export function main() {
} }
wdAdapter = new MockDriverAdapter(); wdAdapter = new MockDriverAdapter();
var bindings = [ var bindings = [
Options.DEFAULT_PROVIDERS, Options.DEFAULT_PROVIDERS, UserMetric.PROVIDERS,
UserMetric.PROVIDERS,
bind(Options.USER_METRICS).toValue(userMetrics), bind(Options.USER_METRICS).toValue(userMetrics),
provide(WebDriverAdapter, {useValue: wdAdapter}) provide(WebDriverAdapter, {useValue: wdAdapter})
]; ];
@ -45,8 +38,9 @@ export function main() {
describe('user metric', () => { describe('user metric', () => {
it('should describe itself based on userMetrics', () => { it('should describe itself based on userMetrics', () => {
expect(createMetric([[]], new PerfLogFeatures(), {userMetrics: {'loadTime': 'time to load'}}) expect(createMetric([[]], new PerfLogFeatures(), {
.describe()) userMetrics: {'loadTime': 'time to load'}
}).describe())
.toEqual({'loadTime': 'time to load'}); .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 {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 { import {ConsoleReporter, MeasureValues, ReflectiveInjector, Reporter, SampleDescription, SampleState} from 'benchpress/common';
SampleState,
Reporter,
ReflectiveInjector,
ConsoleReporter,
SampleDescription,
MeasureValues
} from 'benchpress/common';
export function main() { export function main() {
describe('console reporter', () => { describe('console reporter', () => {
@ -26,8 +25,10 @@ export function main() {
sampleId = 'null'; sampleId = 'null';
} }
var bindings = [ var bindings = [
ConsoleReporter.PROVIDERS, ConsoleReporter.PROVIDERS, {
{provide: SampleDescription, useValue: new SampleDescription(sampleId, descriptions, metrics)}, provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: ConsoleReporter.PRINT, useValue: (line) => log.push(line)} {provide: ConsoleReporter.PRINT, useValue: (line) => log.push(line)}
]; ];
if (isPresent(columnWidth)) { 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 {PromiseWrapper} from '@angular/facade/src/async';
import {DateWrapper, Json, RegExpWrapper, isPresent} from '@angular/facade/src/lang';
import { import {MeasureValues, Options, ReflectiveInjector, SampleDescription} from 'benchpress/common';
ReflectiveInjector,
SampleDescription,
MeasureValues,
Options
} from 'benchpress/common';
import {JsonFileReporter} from 'benchpress/src/reporter/json_file_reporter'; import {JsonFileReporter} from 'benchpress/src/reporter/json_file_reporter';
export function main() { export function main() {
@ -19,11 +18,12 @@ export function main() {
function createReporter({sampleId, descriptions, metrics, path}) { function createReporter({sampleId, descriptions, metrics, path}) {
var bindings = [ var bindings = [
JsonFileReporter.PROVIDERS, JsonFileReporter.PROVIDERS, {
{provide: SampleDescription, useValue: new SampleDescription(sampleId, descriptions, metrics)}, provide: SampleDescription,
useValue: new SampleDescription(sampleId, descriptions, metrics)
},
{provide: JsonFileReporter.PATH, useValue: path}, {provide: JsonFileReporter.PATH, useValue: path},
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(1234)}, {provide: Options.NOW, useValue: () => DateWrapper.fromMillis(1234)}, {
{
provide: Options.WRITE_FILE, provide: Options.WRITE_FILE,
useValue: (filename, content) => { useValue: (filename, content) => {
loggedFile = {'filename': filename, 'content': content}; loggedFile = {'filename': filename, 'content': content};
@ -41,32 +41,23 @@ export function main() {
path: 'somePath', path: 'somePath',
metrics: {'script': 'script time'} metrics: {'script': 'script time'}
}) })
.reportSample([mv(0, 0, {'a': 3, 'b': 6})], .reportSample(
[mv(0, 0, {'a': 3, 'b': 6})],
[mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]); [mv(0, 0, {'a': 3, 'b': 6}), mv(1, 1, {'a': 5, 'b': 9})]);
var regExp = /somePath\/someId_\d+\.json/g; var regExp = /somePath\/someId_\d+\.json/g;
expect(isPresent(RegExpWrapper.firstMatch(regExp, loggedFile['filename']))).toBe(true); expect(isPresent(RegExpWrapper.firstMatch(regExp, loggedFile['filename']))).toBe(true);
var parsedContent = Json.parse(loggedFile['content']); var parsedContent = Json.parse(loggedFile['content']);
expect(parsedContent) expect(parsedContent).toEqual({
.toEqual({ 'description':
"description": {'id': 'someId', 'description': {'a': 2}, 'metrics': {'script': 'script time'}},
{"id": "someId", "description": {"a": 2}, "metrics": {"script": "script time"}}, 'completeSample': [
"completeSample": [ {'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}
{
"timeStamp": "1970-01-01T00:00:00.000Z",
"runIndex": 0,
"values": {"a": 3, "b": 6}
}
], ],
"validSample": [ 'validSample': [
{ {'timeStamp': '1970-01-01T00:00:00.000Z', 'runIndex': 0, 'values': {'a': 3, 'b': 6}}, {
"timeStamp": "1970-01-01T00:00:00.000Z", 'timeStamp': '1970-01-01T00:00:00.001Z',
"runIndex": 0, 'runIndex': 1,
"values": {"a": 3, "b": 6} 'values': {'a': 5, 'b': 9}
},
{
"timeStamp": "1970-01-01T00:00:00.001Z",
"runIndex": 1,
"values": {"a": 5, "b": 9}
} }
] ]
}); });

View File

@ -1,19 +1,21 @@
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 {PromiseWrapper} from '@angular/facade/src/async';
import {DateWrapper} from '@angular/facade/src/lang'; import {DateWrapper} from '@angular/facade/src/lang';
import {MeasureValues, MultiReporter, ReflectiveInjector, Reporter} from 'benchpress/common';
import {
Reporter,
MultiReporter,
ReflectiveInjector,
MeasureValues
} from 'benchpress/common';
export function main() { export function main() {
function createReporters(ids: any[]) { function createReporters(ids: any[]) {
var r = ReflectiveInjector.resolveAndCreate([ var r = ReflectiveInjector
ids.map(id => { return {provide: id, useValue: new MockReporter(id)}}), .resolveAndCreate([
ids.map(id => { return {provide: id, useValue: new MockReporter(id)}; }),
MultiReporter.createBindings(ids) MultiReporter.createBindings(ids)
]) ])
.get(MultiReporter); .get(MultiReporter);
@ -24,9 +26,7 @@ export function main() {
it('should reportMeasureValues to all', inject([AsyncTestCompleter], (async) => { it('should reportMeasureValues to all', inject([AsyncTestCompleter], (async) => {
var mv = new MeasureValues(0, DateWrapper.now(), {}); var mv = new MeasureValues(0, DateWrapper.now(), {});
createReporters(['m1', 'm2']) createReporters(['m1', 'm2']).then((r) => r.reportMeasureValues(mv)).then((values) => {
.then((r) => r.reportMeasureValues(mv))
.then((values) => {
expect(values).toEqual([{'id': 'm1', 'values': mv}, {'id': 'm2', 'values': mv}]); expect(values).toEqual([{'id': 'm1', 'values': mv}, {'id': 'm2', 'values': mv}]);
async.done(); async.done();
@ -35,8 +35,7 @@ export function main() {
it('should reportSample to call', inject([AsyncTestCompleter], (async) => { it('should reportSample to call', inject([AsyncTestCompleter], (async) => {
var completeSample = [ var completeSample = [
new MeasureValues(0, DateWrapper.now(), {}), new MeasureValues(0, DateWrapper.now(), {}), new MeasureValues(1, DateWrapper.now(), {})
new MeasureValues(1, DateWrapper.now(), {})
]; ];
var validSample = [completeSample[1]]; var validSample = [completeSample[1]];
@ -49,7 +48,7 @@ export function main() {
{'id': 'm2', 'completeSample': completeSample, 'validSample': validSample} {'id': 'm2', 'completeSample': completeSample, 'validSample': validSample}
]); ]);
async.done(); async.done();
}) });
})); }));
}); });
@ -62,8 +61,8 @@ class MockReporter extends Reporter {
return PromiseWrapper.resolve({'id': this._id, 'values': values}); return PromiseWrapper.resolve({'id': this._id, 'values': values});
} }
reportSample(completeSample: MeasureValues[], reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]):
validSample: MeasureValues[]): Promise<{[key: string]: any}> { Promise<{[key: string]: any}> {
return PromiseWrapper.resolve( return PromiseWrapper.resolve(
{'id': this._id, 'completeSample': completeSample, 'validSample': validSample}); {'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 { * @license
Runner, * Copyright Google Inc. All Rights Reserved.
Sampler, *
SampleDescription, * Use of this source code is governed by an MIT-style license that can be
Validator, * found in the LICENSE file at https://angular.io/license
ReflectiveInjector, */
Injector,
Metric, import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
Options,
WebDriverAdapter,
SampleState
} from 'benchpress/common';
import {isBlank} from '@angular/facade/src/lang';
import {PromiseWrapper} from '@angular/facade/src/async'; 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() { export function main() {
describe('runner', () => { describe('runner', () => {
@ -24,8 +21,7 @@ export function main() {
defaultBindings = []; defaultBindings = [];
} }
runner = new Runner([ runner = new Runner([
defaultBindings, defaultBindings, {
{
provide: Sampler, provide: Sampler,
useFactory: (_injector) => { useFactory: (_injector) => {
injector = _injector; injector = _injector;
@ -33,9 +29,9 @@ export function main() {
}, },
deps: [Injector] deps: [Injector]
}, },
{ provide: Metric, useFactory: () => new MockMetric(), deps: []}, {provide: Metric, useFactory: () => new MockMetric(), deps: []},
{ provide: Validator, useFactory: () => new MockValidator(), deps: []}, {provide: Validator, useFactory: () => new MockValidator(), deps: []},
{ provide: WebDriverAdapter, useFactory: () => new MockWebDriverAdapter(), deps: []} {provide: WebDriverAdapter, useFactory: () => new MockWebDriverAdapter(), deps: []}
]); ]);
return runner; return runner;
} }
@ -52,7 +48,10 @@ export function main() {
it('should merge SampleDescription.description', inject([AsyncTestCompleter], (async) => { it('should merge SampleDescription.description', inject([AsyncTestCompleter], (async) => {
createRunner([{provide: Options.DEFAULT_DESCRIPTION, useValue: {'a': 1}}]) 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((_) => injector.get(SampleDescription))
.then((desc) => { .then((desc) => {
expect(desc.description) expect(desc.description)
@ -76,9 +75,7 @@ export function main() {
it('should bind Options.EXECUTE', inject([AsyncTestCompleter], (async) => { it('should bind Options.EXECUTE', inject([AsyncTestCompleter], (async) => {
var execute = () => {}; var execute = () => {};
createRunner() createRunner().sample({id: 'someId', execute: execute}).then((_) => {
.sample({id: 'someId', execute: execute})
.then((_) => {
expect(injector.get(Options.EXECUTE)).toEqual(execute); expect(injector.get(Options.EXECUTE)).toEqual(execute);
async.done(); async.done();
}); });
@ -86,18 +83,14 @@ export function main() {
it('should bind Options.PREPARE', inject([AsyncTestCompleter], (async) => { it('should bind Options.PREPARE', inject([AsyncTestCompleter], (async) => {
var prepare = () => {}; var prepare = () => {};
createRunner() createRunner().sample({id: 'someId', prepare: prepare}).then((_) => {
.sample({id: 'someId', prepare: prepare})
.then((_) => {
expect(injector.get(Options.PREPARE)).toEqual(prepare); expect(injector.get(Options.PREPARE)).toEqual(prepare);
async.done(); async.done();
}); });
})); }));
it('should bind Options.MICRO_METRICS', inject([AsyncTestCompleter], (async) => { it('should bind Options.MICRO_METRICS', inject([AsyncTestCompleter], (async) => {
createRunner() createRunner().sample({id: 'someId', microMetrics: {'a': 'b'}}).then((_) => {
.sample({id: 'someId', microMetrics: {'a': 'b'}})
.then((_) => {
expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'}); expect(injector.get(Options.MICRO_METRICS)).toEqual({'a': 'b'});
async.done(); async.done();
}); });

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 {PromiseWrapper} from '@angular/facade/src/async';
import {Date, DateWrapper, isBlank, isPresent, stringify} from '@angular/facade/src/lang';
import { import {MeasureValues, Metric, Options, ReflectiveInjector, Reporter, Sampler, Validator, WebDriverAdapter} from 'benchpress/common';
Sampler,
WebDriverAdapter,
Validator,
Metric,
Reporter,
ReflectiveInjector,
Options,
MeasureValues
} from 'benchpress/common';
export function main() { export function main() {
var EMPTY_EXECUTE = () => {}; var EMPTY_EXECUTE = () => {};
@ -39,13 +36,9 @@ export function main() {
driver = new MockDriverAdapter([]); driver = new MockDriverAdapter([]);
} }
var providers = [ var providers = [
Options.DEFAULT_PROVIDERS, Options.DEFAULT_PROVIDERS, Sampler.PROVIDERS, {provide: Metric, useValue: metric},
Sampler.PROVIDERS, {provide: Reporter, useValue: reporter}, {provide: WebDriverAdapter, useValue: driver},
{provide: Metric, useValue: metric}, {provide: Options.EXECUTE, useValue: execute}, {provide: Validator, useValue: validator},
{provide: Reporter, useValue: reporter},
{provide: WebDriverAdapter, useValue: driver},
{provide: Options.EXECUTE, useValue: execute},
{provide: Validator, useValue: validator},
{provide: Options.NOW, useValue: () => DateWrapper.fromMillis(time++)} {provide: Options.NOW, useValue: () => DateWrapper.fromMillis(time++)}
]; ];
if (isPresent(prepare)) { if (isPresent(prepare)) {
@ -131,7 +124,8 @@ export function main() {
var iterationCount = 1; var iterationCount = 1;
createSampler({ createSampler({
validator: createCountingValidator(2), validator: createCountingValidator(2),
metric: new MockMetric([], metric: new MockMetric(
[],
() => { () => {
var result = PromiseWrapper.resolve({'script': scriptTime}); var result = PromiseWrapper.resolve({'script': scriptTime});
scriptTime = 0; scriptTime = 0;
@ -198,9 +192,7 @@ export function main() {
expect(log[0]).toEqual(['reportMeasureValues', mv(0, 1000, {'script': 0})]); expect(log[0]).toEqual(['reportMeasureValues', mv(0, 1000, {'script': 0})]);
expect(log[1]).toEqual(['reportMeasureValues', mv(1, 1001, {'script': 1})]); expect(log[1]).toEqual(['reportMeasureValues', mv(1, 1001, {'script': 1})]);
expect(log[2]).toEqual([ expect(log[2]).toEqual([
'reportSample', 'reportSample', [mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})], validSample
[mv(0, 1000, {'script': 0}), mv(1, 1001, {'script': 1})],
validSample
]); ]);
async.done(); async.done();
@ -231,6 +223,7 @@ function createCountingMetric(log = null) {
} }
class MockDriverAdapter extends WebDriverAdapter { class MockDriverAdapter extends WebDriverAdapter {
/** @internal */
private _log: any[]; private _log: any[];
private _waitFor: Function; private _waitFor: Function;
constructor(log = null, waitFor = null) { constructor(log = null, waitFor = null) {
@ -252,6 +245,7 @@ class MockDriverAdapter extends WebDriverAdapter {
class MockValidator extends Validator { class MockValidator extends Validator {
/** @internal */
private _log: any[]; private _log: any[];
constructor(log = null, private _validate: Function = null) { constructor(log = null, private _validate: Function = null) {
super(); super();
@ -268,6 +262,7 @@ class MockValidator extends Validator {
} }
class MockMetric extends Metric { class MockMetric extends Metric {
/** @internal */
private _log: any[]; private _log: any[];
constructor(log = null, private _endMeasure: Function = null) { constructor(log = null, private _endMeasure: Function = null) {
super(); super();
@ -288,7 +283,8 @@ class MockMetric extends Metric {
} }
class MockReporter extends Reporter { class MockReporter extends Reporter {
_log: any[]; /** @internal */
private _log: any[];
constructor(log = null) { constructor(log = null) {
super(); super();
if (isBlank(log)) { 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'; import {Statistic} from 'benchpress/src/statistic';
export function main() { 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'; import {isPresent} from '@angular/facade/src/lang';
export class TraceEventFactory { export class TraceEventFactory {

View File

@ -1,19 +1,23 @@
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'; * @license
import {ListWrapper} from '@angular/facade/src/collection'; * 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 { import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
RegressionSlopeValidator, import {ListWrapper} from '@angular/facade/src/collection';
ReflectiveInjector, import {Date, DateWrapper} from '@angular/facade/src/lang';
MeasureValues import {MeasureValues, ReflectiveInjector, RegressionSlopeValidator} from 'benchpress/common';
} from 'benchpress/common';
export function main() { export function main() {
describe('regression slope validator', () => { describe('regression slope validator', () => {
var validator; var validator;
function createValidator({size, metric}) { function createValidator({size, metric}) {
validator = ReflectiveInjector.resolveAndCreate([ validator = ReflectiveInjector
.resolveAndCreate([
RegressionSlopeValidator.PROVIDERS, RegressionSlopeValidator.PROVIDERS,
{provide: RegressionSlopeValidator.METRIC, useValue: metric}, {provide: RegressionSlopeValidator.METRIC, useValue: metric},
{provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: size} {provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: size}

View File

@ -1,23 +1,25 @@
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'; * @license
import {ListWrapper} from '@angular/facade/src/collection'; * 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 { import {AsyncTestCompleter, afterEach, beforeEach, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
Validator, import {ListWrapper} from '@angular/facade/src/collection';
SizeValidator, import {Date, DateWrapper} from '@angular/facade/src/lang';
ReflectiveInjector, import {MeasureValues, ReflectiveInjector, SizeValidator, Validator} from 'benchpress/common';
MeasureValues
} from 'benchpress/common';
export function main() { export function main() {
describe('size validator', () => { describe('size validator', () => {
var validator; var validator;
function createValidator(size) { function createValidator(size) {
validator = ReflectiveInjector.resolveAndCreate([ validator =
SizeValidator.PROVIDERS, ReflectiveInjector
{provide: SizeValidator.SAMPLE_SIZE, useValue: size} .resolveAndCreate(
]) [SizeValidator.PROVIDERS, {provide: SizeValidator.SAMPLE_SIZE, useValue: size}])
.get(SizeValidator); .get(SizeValidator);
} }

View File

@ -1,17 +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 {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 {PromiseWrapper} from '@angular/facade/src/async';
import {StringWrapper, isPresent} from '@angular/facade/src/lang';
import {WebDriverExtension, ReflectiveInjector, Options} from 'benchpress/common'; import {Options, ReflectiveInjector, WebDriverExtension} from 'benchpress/common';
export function main() { export function main() {
function createExtension(ids: any[], caps) { function createExtension(ids: any[], caps) {
return PromiseWrapper.wrap(() => { return PromiseWrapper.wrap(() => {
return ReflectiveInjector.resolveAndCreate([ return ReflectiveInjector
ids.map((id) => { return {provide: id, useValue: new MockExtension(id)}}), .resolveAndCreate([
{provide: Options.CAPABILITIES, useValue: caps}, ids.map((id) => { return {provide: id, useValue: new MockExtension(id)}; }),
WebDriverExtension.bindTo(ids) {provide: Options.CAPABILITIES, useValue: caps}, WebDriverExtension.bindTo(ids)
]) ])
.get(WebDriverExtension); .get(WebDriverExtension);
}); });
@ -21,8 +27,7 @@ export function main() {
it('should bind the extension that matches the capabilities', it('should bind the extension that matches the capabilities',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension(['m1', 'm2', 'm3'], {'browser': 'm2'}) createExtension(['m1', 'm2', 'm3'], {'browser': 'm2'}).then((m) => {
.then((m) => {
expect(m.id).toEqual('m2'); expect(m.id).toEqual('m2');
async.done(); async.done();
}); });

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 {PromiseWrapper} from '@angular/facade/src/async';
import {Json, isBlank} from '@angular/facade/src/lang'; import {Json, isBlank} from '@angular/facade/src/lang';
import {ChromeDriverExtension, Options, ReflectiveInjector, WebDriverAdapter, WebDriverExtension} from 'benchpress/common';
import {
WebDriverExtension,
ChromeDriverExtension,
WebDriverAdapter,
ReflectiveInjector,
Options
} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory'; import {TraceEventFactory} from '../trace_event_factory';
@ -35,7 +35,8 @@ export function main() {
var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0'); var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0');
var normEvents = new TraceEventFactory('timeline', 'pid0'); var normEvents = new TraceEventFactory('timeline', 'pid0');
function createExtension(perfRecords = null, userAgent = null, function createExtension(
perfRecords = null, userAgent = null,
messageMethod = 'Tracing.dataCollected'): WebDriverExtension { messageMethod = 'Tracing.dataCollected'): WebDriverExtension {
if (isBlank(perfRecords)) { if (isBlank(perfRecords)) {
perfRecords = []; perfRecords = [];
@ -44,10 +45,12 @@ export function main() {
userAgent = CHROME44_USER_AGENT; userAgent = CHROME44_USER_AGENT;
} }
log = []; log = [];
extension = extension = ReflectiveInjector
ReflectiveInjector.resolveAndCreate([ .resolveAndCreate([
ChromeDriverExtension.PROVIDERS, ChromeDriverExtension.PROVIDERS, {
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords, messageMethod)}, provide: WebDriverAdapter,
useValue: new MockDriverAdapter(log, perfRecords, messageMethod)
},
{provide: Options.USER_AGENT, useValue: userAgent} {provide: Options.USER_AGENT, useValue: userAgent}
]) ])
.get(ChromeDriverExtension); .get(ChromeDriverExtension);
@ -62,18 +65,14 @@ export function main() {
})); }));
it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => { it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeBegin('someName').then((_) => {
.timeBegin('someName')
.then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]); expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done(); async.done();
}); });
})); }));
it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => { it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeEnd('someName', null).then((_) => {
.timeEnd('someName', null)
.then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]); expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done(); async.done();
}); });
@ -81,11 +80,9 @@ export function main() {
it('should mark the timeline via console.time() and console.timeEnd()', it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeEnd('name1', 'name2').then((_) => {
.timeEnd('name1', 'name2') expect(log).toEqual(
.then((_) => { [['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
expect(log)
.toEqual([['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done(); async.done();
}); });
})); }));
@ -193,10 +190,8 @@ export function main() {
}); });
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => { it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([ createExtension([chromeTimelineEvents.start(
chromeTimelineEvents.start('FunctionCall', 0, 'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})])
{'data': {'scriptName': 'InjectedScript'}})
])
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([]); expect(events).toEqual([]);
@ -210,7 +205,8 @@ export function main() {
describe('readPerfLog Chrome45', () => { describe('readPerfLog Chrome45', () => {
it('should normalize times to ms and forward ph and pid event properties', it('should normalize times to ms and forward ph and pid event properties',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)], createExtension(
[chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)],
CHROME45_USER_AGENT) CHROME45_USER_AGENT)
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
@ -224,9 +220,7 @@ export function main() {
it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => { it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
var event = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null); var event = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null);
event['tdur'] = 5500; event['tdur'] = 5500;
createExtension([event], CHROME45_USER_AGENT) createExtension([event], CHROME45_USER_AGENT).readPerfLog().then((events) => {
.readPerfLog()
.then((events) => {
expect(events).toEqual([ expect(events).toEqual([
normEvents.complete('script', 1.1, 5.5, null), normEvents.complete('script', 1.1, 5.5, null),
]); ]);
@ -257,8 +251,8 @@ export function main() {
expect(events.length).toEqual(2); expect(events.length).toEqual(2);
expect(events[0]).toEqual( expect(events[0]).toEqual(
normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false})); normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false}));
expect(events[1]) expect(events[1]).toEqual(
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false})); normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
async.done(); async.done();
}); });
})); }));
@ -273,10 +267,10 @@ export function main() {
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events.length).toEqual(2); expect(events.length).toEqual(2);
expect(events[0]) expect(events[0]).toEqual(
.toEqual(normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true})); normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
expect(events[1]) expect(events[1]).toEqual(
.toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true})); normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
async.done(); async.done();
}); });
})); }));
@ -320,10 +314,8 @@ export function main() {
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => { it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([ createExtension([chromeTimelineV8Events.start(
chromeTimelineV8Events.start('FunctionCall', 0, 'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})])
{'data': {'scriptName': 'InjectedScript'}})
])
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([]); expect(events).toEqual([]);
@ -343,8 +335,8 @@ export function main() {
})); }));
it('should report navigationStart', inject([AsyncTestCompleter], (async) => { it('should report navigationStart', inject([AsyncTestCompleter], (async) => {
createExtension([chromeBlinkUserTimingEvents.start('navigationStart', 1234)], createExtension(
CHROME45_USER_AGENT) [chromeBlinkUserTimingEvents.start('navigationStart', 1234)], CHROME45_USER_AGENT)
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([normEvents.start('navigationStart', 1.234)]); expect(events).toEqual([normEvents.start('navigationStart', 1.234)]);
@ -354,10 +346,8 @@ export function main() {
it('should report receivedData', inject([AsyncTestCompleter], (async) => { it('should report receivedData', inject([AsyncTestCompleter], (async) => {
createExtension( createExtension(
[ [chrome45TimelineEvents.instant(
chrome45TimelineEvents.instant('ResourceReceivedData', 1234, 'ResourceReceivedData', 1234, {'data': {'encodedDataLength': 987}})],
{'data': {'encodedDataLength': 987}})
],
CHROME45_USER_AGENT) CHROME45_USER_AGENT)
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
@ -369,18 +359,14 @@ export function main() {
it('should report sendRequest', inject([AsyncTestCompleter], (async) => { it('should report sendRequest', inject([AsyncTestCompleter], (async) => {
createExtension( createExtension(
[ [chrome45TimelineEvents.instant(
chrome45TimelineEvents.instant(
'ResourceSendRequest', 1234, 'ResourceSendRequest', 1234,
{'data': {'url': 'http://here', 'requestMethod': 'GET'}}) {'data': {'url': 'http://here', 'requestMethod': 'GET'}})],
],
CHROME45_USER_AGENT) CHROME45_USER_AGENT)
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([ expect(events).toEqual([normEvents.instant(
normEvents.instant('sendRequest', 1.234, 'sendRequest', 1.234, {'url': 'http://here', 'method': 'GET'})]);
{'url': 'http://here', 'method': 'GET'})
]);
async.done(); async.done();
}); });
})); }));
@ -421,10 +407,9 @@ export function main() {
describe('frame metrics', () => { describe('frame metrics', () => {
it('should report ImplThreadRenderingStats as frame event', it('should report ImplThreadRenderingStats as frame event',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension([ createExtension([benchmarkEvents.instant(
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100, 'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 1}}) {'data': {'frame_count': 1}})])
])
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([ expect(events).toEqual([
@ -436,10 +421,9 @@ export function main() {
it('should not report ImplThreadRenderingStats with zero frames', it('should not report ImplThreadRenderingStats with zero frames',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension([ createExtension([benchmarkEvents.instant(
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100, 'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 0}}) {'data': {'frame_count': 0}})])
])
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([]); expect(events).toEqual([]);
@ -451,12 +435,14 @@ export function main() {
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
PromiseWrapper.catchError( PromiseWrapper.catchError(
createExtension([ createExtension([
benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', benchmarkEvents.instant(
1100, {'data': {'frame_count': 2}}) 'BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
{'data': {'frame_count': 2}})
]).readPerfLog(), ]).readPerfLog(),
(err): any => { (err): any => {
expect(() => { throw err; }) expect(() => {
.toThrowError('multi-frame render stats not supported'); throw err;
}).toThrowError('multi-frame render stats not supported');
async.done(); async.done();
}); });
})); }));
@ -490,8 +476,9 @@ export function main() {
CHROME45_USER_AGENT, 'Tracing.bufferUsage') CHROME45_USER_AGENT, 'Tracing.bufferUsage')
.readPerfLog(), .readPerfLog(),
(err): any => { (err): any => {
expect(() => { throw err; }) expect(() => {
.toThrowError('The DevTools trace buffer filled during the test!'); throw err;
}).toThrowError('The DevTools trace buffer filled during the test!');
async.done(); 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 {PromiseWrapper} from '@angular/facade/src/async';
import {Json, isBlank, isPresent} from '@angular/facade/src/lang'; import {Json, isBlank, isPresent} from '@angular/facade/src/lang';
import { import {WebDriverExtension, IOsDriverExtension, WebDriverAdapter, ReflectiveInjector,} from 'benchpress/common';
WebDriverExtension,
IOsDriverExtension,
WebDriverAdapter,
ReflectiveInjector,
} from 'benchpress/common';
import {TraceEventFactory} from '../trace_event_factory'; import {TraceEventFactory} from '../trace_event_factory';
@ -24,7 +26,9 @@ export function main() {
perfRecords = []; perfRecords = [];
} }
log = []; log = [];
extension = ReflectiveInjector.resolveAndCreate([ extension =
ReflectiveInjector
.resolveAndCreate([
IOsDriverExtension.PROVIDERS, IOsDriverExtension.PROVIDERS,
{provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)} {provide: WebDriverAdapter, useValue: new MockDriverAdapter(log, perfRecords)}
]) ])
@ -37,18 +41,14 @@ export function main() {
}); });
it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => { it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeBegin('someName').then((_) => {
.timeBegin('someName')
.then((_) => {
expect(log).toEqual([['executeScript', `console.time('someName');`]]); expect(log).toEqual([['executeScript', `console.time('someName');`]]);
async.done(); async.done();
}); });
})); }));
it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => { it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeEnd('someName', null).then((_) => {
.timeEnd('someName', null)
.then((_) => {
expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]); expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
async.done(); async.done();
}); });
@ -56,11 +56,9 @@ export function main() {
it('should mark the timeline via console.time() and console.timeEnd()', it('should mark the timeline via console.time() and console.timeEnd()',
inject([AsyncTestCompleter], (async) => { inject([AsyncTestCompleter], (async) => {
createExtension() createExtension().timeEnd('name1', 'name2').then((_) => {
.timeEnd('name1', 'name2') expect(log).toEqual(
.then((_) => { [['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
expect(log)
.toEqual([['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
async.done(); async.done();
}); });
})); }));
@ -79,37 +77,28 @@ export function main() {
})); }));
it('should report FunctionCall records as "script"', inject([AsyncTestCompleter], (async) => { it('should report FunctionCall records as "script"', inject([AsyncTestCompleter], (async) => {
createExtension([durationRecord('FunctionCall', 1, 5)]) createExtension([durationRecord('FunctionCall', 1, 5)]).readPerfLog().then((events) => {
.readPerfLog() expect(events).toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
.then((events) => {
expect(events)
.toEqual([normEvents.start('script', 1), normEvents.end('script', 5)]);
async.done(); async.done();
}); });
})); }));
it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => { it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
createExtension([internalScriptRecord(1, 5)]) createExtension([internalScriptRecord(1, 5)]).readPerfLog().then((events) => {
.readPerfLog()
.then((events) => {
expect(events).toEqual([]); expect(events).toEqual([]);
async.done(); async.done();
}); });
})); }));
it('should report begin time', inject([AsyncTestCompleter], (async) => { it('should report begin time', inject([AsyncTestCompleter], (async) => {
createExtension([timeBeginRecord('someName', 12)]) createExtension([timeBeginRecord('someName', 12)]).readPerfLog().then((events) => {
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markStart('someName', 12)]); expect(events).toEqual([normEvents.markStart('someName', 12)]);
async.done(); async.done();
}); });
})); }));
it('should report end timestamps', inject([AsyncTestCompleter], (async) => { it('should report end timestamps', inject([AsyncTestCompleter], (async) => {
createExtension([timeEndRecord('someName', 12)]) createExtension([timeEndRecord('someName', 12)]).readPerfLog().then((events) => {
.readPerfLog()
.then((events) => {
expect(events).toEqual([normEvents.markEnd('someName', 12)]); expect(events).toEqual([normEvents.markEnd('someName', 12)]);
async.done(); async.done();
}); });
@ -136,8 +125,7 @@ export function main() {
.readPerfLog() .readPerfLog()
.then((events) => { .then((events) => {
expect(events).toEqual([ expect(events).toEqual([
normEvents.start('script', 1), normEvents.start('script', 1), normEvents.markStart('someName', 2),
normEvents.markStart('someName', 2),
normEvents.end('script', 5) normEvents.end('script', 5)
]); ]);
async.done(); async.done();