From c4114c2f66ba9a657e6b081fbddb7fceefbf2b34 Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Thu, 15 Sep 2016 07:49:05 -0700 Subject: [PATCH] finished refactoring --- .../benchpress/src/metric/perflog_metric.ts | 89 ++-- .../benchpress/src/web_driver_extension.ts | 4 +- .../src/webdriver/chrome_driver_extension.ts | 84 ++-- .../webdriver/chrome_driver_extension_spec.ts | 426 ++++++------------ 4 files changed, 228 insertions(+), 375 deletions(-) diff --git a/modules/@angular/benchpress/src/metric/perflog_metric.ts b/modules/@angular/benchpress/src/metric/perflog_metric.ts index ed8009bfa7..6f714eb6ad 100644 --- a/modules/@angular/benchpress/src/metric/perflog_metric.ts +++ b/modules/@angular/benchpress/src/metric/perflog_metric.ts @@ -9,8 +9,6 @@ import {Inject, Injectable, OpaqueToken} from '@angular/core'; import {Options} from '../common_options'; -import {ListWrapper, StringMapWrapper} from '../facade/collection'; -import {Math, NumberWrapper, StringWrapper, isBlank, isPresent} from '../facade/lang'; import {Metric} from '../metric'; import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension'; @@ -95,8 +93,9 @@ export class PerflogMetric extends Metric { res['frameTime.smooth'] = 'percentage of frames that hit 60fps'; } } - StringMapWrapper.forEach( - this._microMetrics, (desc, name) => { StringMapWrapper.set(res, name, desc); }); + for (let name in this._microMetrics) { + res[name] = this._microMetrics[name]; + } return res; } @@ -126,8 +125,8 @@ export class PerflogMetric extends Metric { .then((_) => this._endMeasure(restartMeasure)) .then((forceGcMeasureValues) => { this._captureFrames = originalFrameCaptureValue; - StringMapWrapper.set(measureValues, 'forcedGcTime', forceGcMeasureValues['gcTime']); - StringMapWrapper.set(measureValues, 'forcedGcAmount', forceGcMeasureValues['gcAmount']); + measureValues['forcedGcTime'] = forceGcMeasureValues['gcTime']; + measureValues['forcedGcAmount'] = forceGcMeasureValues['gcAmount']; return measureValues; }); }); @@ -152,7 +151,7 @@ export class PerflogMetric extends Metric { return this._driverExtension.readPerfLog().then((events) => { this._addEvents(events); var result = this._aggregateEvents(this._remainingEvents, markName); - if (isPresent(result)) { + if (result) { this._remainingEvents = events; return result; } @@ -166,14 +165,14 @@ export class PerflogMetric extends Metric { private _addEvents(events: PerfLogEvent[]) { var needSort = false; events.forEach(event => { - if (StringWrapper.equals(event['ph'], 'X')) { + if (event['ph'] === 'X') { needSort = true; var startEvent: PerfLogEvent = {}; var endEvent: PerfLogEvent = {}; - StringMapWrapper.forEach(event, (value, prop) => { - (startEvent)[prop] = value; - (endEvent)[prop] = value; - }); + for (let prop in event) { + startEvent[prop] = event[prop]; + endEvent[prop] = event[prop]; + } startEvent['ph'] = 'B'; endEvent['ph'] = 'E'; endEvent['ts'] = startEvent['ts'] + startEvent['dur']; @@ -185,7 +184,7 @@ export class PerflogMetric extends Metric { }); if (needSort) { // Need to sort because of the ph==='X' events - ListWrapper.sort(this._remainingEvents, (a, b) => { + this._remainingEvents.sort((a, b) => { var diff = a['ts'] - b['ts']; return diff > 0 ? 1 : diff < 0 ? -1 : 0; }); @@ -208,7 +207,9 @@ export class PerflogMetric extends Metric { result['frameTime.worst'] = 0; result['frameTime.smooth'] = 0; } - StringMapWrapper.forEach(this._microMetrics, (desc, name) => { result[name] = 0; }); + for (let name in this._microMetrics) { + result[name] = 0; + } if (this._receivedData) { result['receivedData'] = 0; } @@ -233,23 +234,23 @@ export class PerflogMetric extends Metric { var name = event['name']; var microIterations = 1; var microIterationsMatch = name.match(_MICRO_ITERATIONS_REGEX); - if (isPresent(microIterationsMatch)) { + if (microIterationsMatch) { name = microIterationsMatch[1]; - microIterations = NumberWrapper.parseInt(microIterationsMatch[2], 10); + microIterations = parseInt(microIterationsMatch[2], 10); } - if (StringWrapper.equals(ph, 'b') && StringWrapper.equals(name, markName)) { + if (ph === 'b' && name === markName) { markStartEvent = event; - } else if (StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, markName)) { + } else if (ph === 'e' && name === markName) { markEndEvent = event; } - let isInstant = StringWrapper.equals(ph, 'I') || StringWrapper.equals(ph, 'i'); - if (this._requestCount && StringWrapper.equals(name, 'sendRequest')) { + let isInstant = ph === 'I' || ph === 'i'; + if (this._requestCount && name === 'sendRequest') { result['requestCount'] += 1; - } else if (this._receivedData && StringWrapper.equals(name, 'receivedData') && isInstant) { + } else if (this._receivedData && name === 'receivedData' && isInstant) { result['receivedData'] += event['args']['encodedDataLength']; - } else if (StringWrapper.equals(name, 'navigationStart')) { + } else if (name === 'navigationStart') { // We count data + requests since the last navigationStart // (there might be chrome extensions loaded by selenium before our page, so there // will likely be more than one navigationStart). @@ -260,10 +261,9 @@ export class PerflogMetric extends Metric { result['requestCount'] = 0; } } - if (isPresent(markStartEvent) && isBlank(markEndEvent) && - event['pid'] === markStartEvent['pid']) { - if (StringWrapper.equals(ph, 'b') && StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) { - if (isPresent(frameCaptureStartEvent)) { + if (markStartEvent && !markEndEvent && event['pid'] === markStartEvent['pid']) { + if (ph === 'b' && name === _MARK_NAME_FRAME_CAPUTRE) { + if (frameCaptureStartEvent) { throw new Error('can capture frames only once per benchmark run'); } if (!this._captureFrames) { @@ -271,17 +271,15 @@ export class PerflogMetric extends Metric { 'found start event for frame capture, but frame capture was not requested in benchpress'); } frameCaptureStartEvent = event; - } else if ( - StringWrapper.equals(ph, 'e') && StringWrapper.equals(name, _MARK_NAME_FRAME_CAPUTRE)) { - if (isBlank(frameCaptureStartEvent)) { + } else if (ph === 'e' && name === _MARK_NAME_FRAME_CAPUTRE) { + if (!frameCaptureStartEvent) { throw new Error('missing start event for frame capture'); } frameCaptureEndEvent = event; } if (isInstant) { - if (isPresent(frameCaptureStartEvent) && isBlank(frameCaptureEndEvent) && - StringWrapper.equals(name, 'frame')) { + if (frameCaptureStartEvent && !frameCaptureEndEvent && name === 'frame') { frameTimestamps.push(event['ts']); if (frameTimestamps.length >= 2) { frameTimes.push( @@ -291,57 +289,54 @@ export class PerflogMetric extends Metric { } } - if (StringWrapper.equals(ph, 'B') || StringWrapper.equals(ph, 'b')) { - if (isBlank(intervalStarts[name])) { + if (ph === 'B' || ph === 'b') { + if (!intervalStarts[name]) { intervalStartCount[name] = 1; intervalStarts[name] = event; } else { intervalStartCount[name]++; } - } else if ( - (StringWrapper.equals(ph, 'E') || StringWrapper.equals(ph, 'e')) && - isPresent(intervalStarts[name])) { + } else if ((ph === 'E' || ph === 'e') && intervalStarts[name]) { intervalStartCount[name]--; if (intervalStartCount[name] === 0) { var startEvent = intervalStarts[name]; var duration = (event['ts'] - startEvent['ts']); intervalStarts[name] = null; - if (StringWrapper.equals(name, 'gc')) { + if (name === 'gc') { result['gcTime'] += duration; var amount = (startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000; result['gcAmount'] += amount; var majorGc = event['args']['majorGc']; - if (isPresent(majorGc) && majorGc) { + if (majorGc && majorGc) { result['majorGcTime'] += duration; } - if (isPresent(intervalStarts['script'])) { + if (intervalStarts['script']) { gcTimeInScript += duration; } - } else if (StringWrapper.equals(name, 'render')) { + } else if (name === 'render') { result['renderTime'] += duration; - if (isPresent(intervalStarts['script'])) { + if (intervalStarts['script']) { renderTimeInScript += duration; } - } else if (StringWrapper.equals(name, 'script')) { + } else if (name === 'script') { result['scriptTime'] += duration; - } else if (isPresent(this._microMetrics[name])) { + } else if (this._microMetrics[name]) { (result)[name] += duration / microIterations; } } } } }); - if (!isPresent(markStartEvent) || !isPresent(markEndEvent)) { + if (!markStartEvent || !markEndEvent) { // not all events have been received, no further processing for now return null; } - if (isPresent(markEndEvent) && isPresent(frameCaptureStartEvent) && - isBlank(frameCaptureEndEvent)) { + if (markEndEvent && frameCaptureStartEvent && !frameCaptureEndEvent) { throw new Error('missing end event for frame capture'); } - if (this._captureFrames && isBlank(frameCaptureStartEvent)) { + if (this._captureFrames && !frameCaptureStartEvent) { throw new Error('frame capture requested in benchpress, but no start event was found'); } if (frameTimes.length > 0) { diff --git a/modules/@angular/benchpress/src/web_driver_extension.ts b/modules/@angular/benchpress/src/web_driver_extension.ts index 3ddcc89aa3..2d21ddd3dd 100644 --- a/modules/@angular/benchpress/src/web_driver_extension.ts +++ b/modules/@angular/benchpress/src/web_driver_extension.ts @@ -12,8 +12,10 @@ import {Options} from './common_options'; import {isBlank, isPresent} from './facade/lang'; export type PerfLogEvent = { + [key: string]: any +} & { cat?: string, - ph?: 'X' | 'B' | 'E' | 'b' | 'e', + ph?: 'X' | 'B' | 'E' | 'b' | 'e' | 'i' | 'I', ts?: number, dur?: number, name?: string, diff --git a/modules/@angular/benchpress/src/webdriver/chrome_driver_extension.ts b/modules/@angular/benchpress/src/webdriver/chrome_driver_extension.ts index 448538c3a3..60cf2e6589 100644 --- a/modules/@angular/benchpress/src/webdriver/chrome_driver_extension.ts +++ b/modules/@angular/benchpress/src/webdriver/chrome_driver_extension.ts @@ -14,7 +14,7 @@ import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_e /** * Set the following 'traceCategories' to collect metrics in Chrome: - * 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline' + * 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline,blink.user_timing' * * In order to collect the frame rate related metrics, add 'benchmark' * to the list above. @@ -28,7 +28,6 @@ export class ChromeDriverExtension extends WebDriverExtension { constructor(private _driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string) { super(); this._majorChromeVersion = this._parseChromeVersion(userAgent); - } private _parseChromeVersion(userAgent: string): number { @@ -74,7 +73,7 @@ export class ChromeDriverExtension extends WebDriverExtension { if (message['method'] === 'Tracing.dataCollected') { events.push(message['params']); } - if (message['method'] === 'Tracing.bufferUsage') { + if (message['method'] === 'Tracing.bufferUsage') { throw new Error('The DevTools trace buffer filled during the test!'); } }); @@ -87,64 +86,59 @@ export class ChromeDriverExtension extends WebDriverExtension { if (!normalizedEvents) { normalizedEvents = []; } - var majorGCPids = {}; chromeEvents.forEach((event) => { - var categories = this._parseCategories(event['cat']); - var name = event['name']; - if (this._isEvent(categories, name, ['blink.console'])) { - normalizedEvents.push(normalizeEvent(event, {'name': name})); - } else if (this._isEvent( - categories, name, ['benchmark'], - 'BenchmarkInstrumentation::ImplThreadRenderingStats')) { - // TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the - // following events should be used (if available) for more accurate measurments: - // 1st choice: vsync_before - ground truth on Android - // 2nd choice: BenchmarkInstrumentation::DisplayRenderingStats - available on systems with - // new surfaces framework (not broadly enabled yet) - // 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is - // always available if something is rendered - var frameCount = event['args']['data']['frame_count']; - if (frameCount > 1) { - throw new Error('multi-frame render stats not supported'); - } - if (frameCount == 1) { - normalizedEvents.push(normalizeEvent(event, {'name': 'frame'})); - } - } else if ( - this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') || - this._isEvent( - categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) { - normalizedEvents.push(normalizeEvent(event, {'name': 'render'})); - } else { - var normalizedEvent = this._processAsPostChrome44Event(event, categories); - if (normalizedEvent != null) normalizedEvents.push(normalizedEvent); - } + const categories = this._parseCategories(event['cat']); + const normalizedEvent = this._convertEvent(event, categories); + if (normalizedEvent != null) normalizedEvents.push(normalizedEvent); }); return normalizedEvents; } - private _processAsPostChrome44Event(event: {[key: string]: any}, categories: string[]) { + private _convertEvent(event: {[key: string]: any}, categories: string[]) { var name = event['name']; var args = event['args']; - if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MajorGC')) { + if (this._isEvent(categories, name, ['blink.console'])) { + return normalizeEvent(event, {'name': name}); + } else if (this._isEvent( + categories, name, ['benchmark'], + 'BenchmarkInstrumentation::ImplThreadRenderingStats')) { + // TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the + // following events should be used (if available) for more accurate measurments: + // 1st choice: vsync_before - ground truth on Android + // 2nd choice: BenchmarkInstrumentation::DisplayRenderingStats - available on systems with + // new surfaces framework (not broadly enabled yet) + // 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is + // always available if something is rendered + var frameCount = event['args']['data']['frame_count']; + if (frameCount > 1) { + throw new Error('multi-frame render stats not supported'); + } + if (frameCount == 1) { + return normalizeEvent(event, {'name': 'frame'}); + } + } else if ( + this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') || + this._isEvent( + categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) { + return normalizeEvent(event, {'name': 'render'}); + } else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MajorGC')) { var normArgs = { 'majorGc': true, 'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] : - args['usedHeapSizeBefore'] + args['usedHeapSizeBefore'] }; return normalizeEvent(event, {'name': 'gc', 'args': normArgs}); } else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MinorGC')) { var normArgs = { 'majorGc': false, 'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] : - args['usedHeapSizeBefore'] + args['usedHeapSizeBefore'] }; return normalizeEvent(event, {'name': 'gc', 'args': normArgs}); } else if ( this._isEvent(categories, name, ['devtools.timeline'], 'FunctionCall') && (!args || !args['data'] || - (args['data']['scriptName'] !== 'InjectedScript' && - args['data']['scriptName'] !== ''))) { + (args['data']['scriptName'] !== 'InjectedScript' && args['data']['scriptName'] !== ''))) { return normalizeEvent(event, {'name': 'script'}); } else if (this._isEvent( categories, name, ['devtools.timeline', 'blink'], 'UpdateLayoutTree')) { @@ -174,8 +168,7 @@ export class ChromeDriverExtension extends WebDriverExtension { expectedName: string = null): boolean { var hasCategories = expectedCategories.reduce( (value, cat) => { return value && eventCategories.indexOf(cat) !== -1; }, true); - return !expectedName ? hasCategories : - hasCategories && eventName === expectedName; + return !expectedName ? hasCategories : hasCategories && eventName === expectedName; } perfLogFeatures(): PerfLogFeatures { @@ -183,17 +176,16 @@ export class ChromeDriverExtension extends WebDriverExtension { } supports(capabilities: {[key: string]: any}): boolean { - return this._majorChromeVersion >=44 && - capabilities['browserName'].toLowerCase() === 'chrome'; + return this._majorChromeVersion >= 44 && capabilities['browserName'].toLowerCase() === 'chrome'; } } function normalizeEvent( chromeEvent: {[key: string]: any}, data: {[key: string]: any}): PerfLogEvent { var ph = chromeEvent['ph']; - if (ph === 'S') { + if (ph === 'S') { ph = 'b'; - } else if (ph === 'F') { + } else if (ph === 'F') { ph = 'e'; } var result: {[key: string]: any} = diff --git a/modules/@angular/benchpress/test/webdriver/chrome_driver_extension_spec.ts b/modules/@angular/benchpress/test/webdriver/chrome_driver_extension_spec.ts index 5920e2ca6e..2fc842a60a 100644 --- a/modules/@angular/benchpress/test/webdriver/chrome_driver_extension_spec.ts +++ b/modules/@angular/benchpress/test/webdriver/chrome_driver_extension_spec.ts @@ -14,8 +14,6 @@ import {TraceEventFactory} from '../trace_event_factory'; export function main() { describe('chrome driver extension', () => { - var CHROME44_USER_AGENT = - '"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.0 Safari/537.36"'; var CHROME45_USER_AGENT = '"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2499.0 Safari/537.36"'; @@ -41,7 +39,7 @@ export function main() { perfRecords = []; } if (isBlank(userAgent)) { - userAgent = CHROME44_USER_AGENT; + userAgent = CHROME45_USER_AGENT; } log = []; extension = ReflectiveInjector @@ -89,228 +87,83 @@ export function main() { }); })); - describe('readPerfLog Chrome44', () => { - it('should normalize times to ms and forward ph and pid event properties', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([chromeTimelineEvents.complete('FunctionCall', 1100, 5500, null)]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.complete('script', 1.1, 5.5, null), - ]); - async.done(); - }); - })); + it('should normalize times to ms and forward ph and pid event properties', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)]) + .readPerfLog() + .then((events) => { + expect(events).toEqual([ + normEvents.complete('script', 1.1, 5.5, null), + ]); + async.done(); + }); + })); - it('should normalize "tdur" to "dur"', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var event: any = chromeTimelineEvents.create('X', 'FunctionCall', 1100, null); - event['tdur'] = 5500; - createExtension([event]).readPerfLog().then((events) => { - expect(events).toEqual([ - normEvents.complete('script', 1.1, 5.5, null), - ]); - async.done(); - }); - })); + it('should normalize "tdur" to "dur"', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + var event: any = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null); + event['tdur'] = 5500; + createExtension([event]).readPerfLog().then((events) => { + expect(events).toEqual([ + normEvents.complete('script', 1.1, 5.5, null), + ]); + async.done(); + }); + })); - it('should report FunctionCall events as "script"', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([chromeTimelineEvents.start('FunctionCall', 0)]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('script', 0), - ]); - async.done(); - }); - })); + it('should report FunctionCall events as "script"', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chromeTimelineV8Events.start('FunctionCall', 0)]) + .readPerfLog() + .then((events) => { + expect(events).toEqual([ + normEvents.start('script', 0), + ]); + async.done(); + }); + })); - it('should report gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([ - chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}), - chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}), - ]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('gc', 1.0, {'usedHeapSize': 1000}), - normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}), - ]); - async.done(); - }); - })); + it('should report minor gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([ + chromeTimelineV8Events.start('MinorGC', 1000, {'usedHeapSizeBefore': 1000}), + chromeTimelineV8Events.end('MinorGC', 2000, {'usedHeapSizeAfter': 0}), + ]) + .readPerfLog() + .then((events) => { + expect(events.length).toEqual(2); + expect(events[0]).toEqual( + normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false})); + expect(events[1]).toEqual( + normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false})); + async.done(); + }); + })); - it('should ignore major gc from different processes', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([ - chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}), - v8EventsOtherProcess.start('majorGC', 1100, null), - v8EventsOtherProcess.end('majorGC', 1200, null), - chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}), - ]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('gc', 1.0, {'usedHeapSize': 1000}), - normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}), - ]); - async.done(); - }); - })); + it('should report major gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension( + [ + chromeTimelineV8Events.start('MajorGC', 1000, {'usedHeapSizeBefore': 1000}), + chromeTimelineV8Events.end('MajorGC', 2000, {'usedHeapSizeAfter': 0}), + ], ) + .readPerfLog() + .then((events) => { + expect(events.length).toEqual(2); + expect(events[0]).toEqual( + normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true})); + expect(events[1]).toEqual( + normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true})); + async.done(); + }); + })); - it('should report major gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([ - chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}), - v8Events.start('majorGC', 1100, null), - v8Events.end('majorGC', 1200, null), - chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}), - ]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('gc', 1.0, {'usedHeapSize': 1000}), - normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}), - ]); - async.done(); - }); - })); - - ['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => { - it(`should report ${recordType} as "render"`, - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([ - chromeTimelineEvents.start(recordType, 1234), - chromeTimelineEvents.end(recordType, 2345) - ]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('render', 1.234), - normEvents.end('render', 2.345), - ]); - async.done(); - }); - })); - }); - - it('should ignore FunctionCalls from webdriver', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([chromeTimelineEvents.start( - 'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([]); - async.done(); - }); - })); - - - }); - - describe('readPerfLog Chrome45', () => { - it('should normalize times to ms and forward ph and pid event properties', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.complete('script', 1.1, 5.5, null), - ]); - async.done(); - }); - })); - - it('should normalize "tdur" to "dur"', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - var event: any = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null); - event['tdur'] = 5500; - createExtension([event], CHROME45_USER_AGENT).readPerfLog().then((events) => { - expect(events).toEqual([ - normEvents.complete('script', 1.1, 5.5, null), - ]); - async.done(); - }); - })); - - it('should report FunctionCall events as "script"', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([chromeTimelineV8Events.start('FunctionCall', 0)], CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('script', 0), - ]); - async.done(); - }); - })); - - it('should report minor gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [ - chromeTimelineV8Events.start('MinorGC', 1000, {'usedHeapSizeBefore': 1000}), - chromeTimelineV8Events.end('MinorGC', 2000, {'usedHeapSizeAfter': 0}), - ], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events.length).toEqual(2); - expect(events[0]).toEqual( - normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false})); - expect(events[1]).toEqual( - normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false})); - async.done(); - }); - })); - - it('should report major gc', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [ - chromeTimelineV8Events.start('MajorGC', 1000, {'usedHeapSizeBefore': 1000}), - chromeTimelineV8Events.end('MajorGC', 2000, {'usedHeapSizeAfter': 0}), - ], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events.length).toEqual(2); - expect(events[0]).toEqual( - normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true})); - expect(events[1]).toEqual( - normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true})); - async.done(); - }); - })); - - ['Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => { - it(`should report ${recordType} as "render"`, - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [ - chrome45TimelineEvents.start(recordType, 1234), - chrome45TimelineEvents.end(recordType, 2345) - ], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual([ - normEvents.start('render', 1.234), - normEvents.end('render', 2.345), - ]); - async.done(); - }); - })); - }); - - it(`should report UpdateLayoutTree as "render"`, + ['Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => { + it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { createExtension( [ - chromeBlinkTimelineEvents.start('UpdateLayoutTree', 1234), - chromeBlinkTimelineEvents.end('UpdateLayoutTree', 2345) - ], - CHROME45_USER_AGENT) + chrome45TimelineEvents.start(recordType, 1234), + chrome45TimelineEvents.end(recordType, 2345) + ], ) .readPerfLog() .then((events) => { expect(events).toEqual([ @@ -320,70 +173,82 @@ export function main() { async.done(); }); })); - - - - it('should ignore FunctionCalls from webdriver', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension([chromeTimelineV8Events.start( - 'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([]); - async.done(); - }); - })); - - it('should ignore FunctionCalls with empty scriptName', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [chromeTimelineV8Events.start('FunctionCall', 0, {'data': {'scriptName': ''}})]) - .readPerfLog() - .then((events) => { - expect(events).toEqual([]); - async.done(); - }); - })); - - it('should report navigationStart', - inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [chromeBlinkUserTimingEvents.start('navigationStart', 1234)], CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual([normEvents.start('navigationStart', 1.234)]); - async.done(); - }); - })); - - it('should report receivedData', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [chrome45TimelineEvents.instant( - 'ResourceReceivedData', 1234, {'data': {'encodedDataLength': 987}})], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual( - [normEvents.instant('receivedData', 1.234, {'encodedDataLength': 987})]); - async.done(); - }); - })); - - it('should report sendRequest', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { - createExtension( - [chrome45TimelineEvents.instant( - 'ResourceSendRequest', 1234, - {'data': {'url': 'http://here', 'requestMethod': 'GET'}})], - CHROME45_USER_AGENT) - .readPerfLog() - .then((events) => { - expect(events).toEqual([normEvents.instant( - 'sendRequest', 1.234, {'url': 'http://here', 'method': 'GET'})]); - async.done(); - }); - })); }); + it(`should report UpdateLayoutTree as "render"`, + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension( + [ + chromeBlinkTimelineEvents.start('UpdateLayoutTree', 1234), + chromeBlinkTimelineEvents.end('UpdateLayoutTree', 2345) + ], ) + .readPerfLog() + .then((events) => { + expect(events).toEqual([ + normEvents.start('render', 1.234), + normEvents.end('render', 2.345), + ]); + async.done(); + }); + })); + + + + it('should ignore FunctionCalls from webdriver', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chromeTimelineV8Events.start( + 'FunctionCall', 0, {'data': {'scriptName': 'InjectedScript'}})]) + .readPerfLog() + .then((events) => { + expect(events).toEqual([]); + async.done(); + }); + })); + + it('should ignore FunctionCalls with empty scriptName', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension( + [chromeTimelineV8Events.start('FunctionCall', 0, {'data': {'scriptName': ''}})]) + .readPerfLog() + .then((events) => { + expect(events).toEqual([]); + async.done(); + }); + })); + + it('should report navigationStart', + inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chromeBlinkUserTimingEvents.start('navigationStart', 1234)]) + .readPerfLog() + .then((events) => { + expect(events).toEqual([normEvents.start('navigationStart', 1.234)]); + async.done(); + }); + })); + + it('should report receivedData', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chrome45TimelineEvents.instant( + 'ResourceReceivedData', 1234, {'data': {'encodedDataLength': 987}})], ) + .readPerfLog() + .then((events) => { + expect(events).toEqual( + [normEvents.instant('receivedData', 1.234, {'encodedDataLength': 987})]); + async.done(); + }); + })); + + it('should report sendRequest', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => { + createExtension([chrome45TimelineEvents.instant( + 'ResourceSendRequest', 1234, + {'data': {'url': 'http://here', 'requestMethod': 'GET'}})], ) + .readPerfLog() + .then((events) => { + expect(events).toEqual([normEvents.instant( + 'sendRequest', 1.234, {'url': 'http://here', 'method': 'GET'})]); + async.done(); + }); + })); + describe('readPerfLog (common)', () => { it('should execute a dummy script before reading them', @@ -404,8 +269,7 @@ export function main() { [ chromeTimelineEvents.start(recordType, 1234), chromeTimelineEvents.end(recordType, 2345) - ], - CHROME45_USER_AGENT) + ], ) .readPerfLog() .then((events) => { expect(events).toEqual([