diff options
Diffstat (limited to 'chromium/third_party/catapult/tracing/tracing/importer')
15 files changed, 0 insertions, 3982 deletions
diff --git a/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html b/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html deleted file mode 100644 index 81fa36087e0..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/clock_sync_test.html +++ /dev/null @@ -1,123 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2016 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/core/test_utils.html"> -<link rel="import" href="/tracing/extras/importer/battor_importer.html"> -<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html"> -<link rel="import" href="/tracing/extras/importer/trace_event_importer.html"> -<link rel="import" href="/tracing/model/clock_sync_manager.html"> -<link rel="import" href="/tracing/model/model.html"> - -<script> -'use strict'; - -/** - * @fileoverview This file contains end-to-end clock sync tests that ensure - * clock sync behavior works as expected across traces. There are too many - * possible combinations of trace types to test all of them, but we aim to test - * many of the important ones in this file. - */ -tr.b.unittest.testSuite(function() { - test('import_noClockDomains', function() { - var m = tr.c.TestUtils.newModelWithEvents([]); - - assert.isFalse(m.hasImportWarnings); - }); - - test('import_traceEvent', function() { - var trace = JSON.stringify({ - traceEvents: [ - {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}, - {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata', - args: { issue_ts: 500, sync_id: 'abc' }}, - {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}} - ]}); - var m = tr.c.TestUtils.newModelWithEvents([trace]); - - assert.isFalse(m.hasImportWarnings); - - assert.equal(m.processes[0].threads[0].sliceGroup.slices[0].start, 0); - assert.equal(m.processes[0].threads[0].sliceGroup.slices[1].start, 2); - }); - - - test('import_ftrace', function() { - var ftrace = - 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' + - ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' + - 'parent_ts=0.020\n'; - - var m = tr.c.TestUtils.newModelWithEvents([ftrace]); - - assert.isFalse(m.hasImportWarnings); - assert.equal(m.processes[1].threads[0].sliceGroup.slices[0].start, 0); - }); - - test('import_traceEventWithNoClockDomainAndFtrace', function() { - // Include a clock sync marker that indicates the LINUX_CLOCK_MONOTONIC time - // of 20ms is equal to the LINUX_FTRACE_GLOBAL time of 10ms, effectively - // shifting all ftrace timestamps forward by 10ms. - var ftrace = - 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' + - ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' + - 'parent_ts=0.020\n'; - - var trace = JSON.stringify({ - traceEvents: [ - {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}, - {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata', - args: { issue_ts: 500, sync_id: 'abc' }}, - {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}} - ], - systemTraceEvents: ftrace - }); - var m = tr.c.TestUtils.newModelWithEvents([trace]); - - assert.isFalse(m.hasImportWarnings); - - // Chrome events shouldn't be shifted. - assert.equal(m.processes[0].threads[0].sliceGroup.slices[0].start, 0); - assert.equal(m.processes[0].threads[0].sliceGroup.slices[1].start, 2); - - // Ftrace events should be shifted forward by 10ms. - assert.equal(m.processes[1].threads[0].sliceGroup.slices[0].start, 11); - }); - - test('import_traceEventWithClockDomainAndFtrace', function() { - // Include a clock sync marker that indicates the LINUX_CLOCK_MONOTONIC time - // of 20ms is equal to the LINUX_FTRACE_GLOBAL time of 10ms, effectively - // shifting all ftrace timestamps forward by 10ms. - var ftrace = - 'SurfaceFlinger-0 [001] ...1 0.001: 0: B|1|taskA\n' + - ' chrome-3 [001] ...1 0.010: 0: trace_event_clock_sync: ' + - 'parent_ts=0.020\n'; - - var trace = JSON.stringify({ - traceEvents: [ - {ts: 0, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}}, - {ts: 1000, pid: 0, tid: 0, ph: 'c', cat: 'metadata', - args: { issue_ts: 500, sync_id: 'abc' }}, - {ts: 2000, pid: 0, tid: 0, ph: 'i', cat: 'c', name: 'taskA', args: {}} - ], - metadata: { - 'clock-domain': 'LINUX_CLOCK_MONOTONIC' - }, - systemTraceEvents: ftrace - }); - var m = tr.c.TestUtils.newModelWithEvents([trace]); - - assert.isFalse(m.hasImportWarnings); - - // Chrome events shouldn't be shifted. - assert.equal(m.processes[0].threads[0].sliceGroup.slices[0].start, 0); - assert.equal(m.processes[0].threads[0].sliceGroup.slices[1].start, 2); - - // Ftrace events should be shifted forward by 10ms. - assert.equal(m.processes[1].threads[0].sliceGroup.slices[0].start, 11); - }); -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html b/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html deleted file mode 100644 index d7df00f3923..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/context_processor.html +++ /dev/null @@ -1,196 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2016 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - /** - * The context processor consumes context events and maintains a set of - * active contexts for a single thread. - * - * @constructor - */ - function ContextProcessor(model) { - this.model_ = model; - this.activeContexts_ = []; - this.stackPerType_ = {}; - // Cache of unique context objects. - this.contextCache_ = {}; - // Cache of unique context object sets. - this.contextSetCache_ = {}; - this.cachedEntryForActiveContexts_ = undefined; - // All seen context object snapshots. - this.seenSnapshots_ = {}; - }; - - ContextProcessor.prototype = { - enterContext: function(contextType, scopedId) { - var newActiveContexts = [this.getOrCreateContext_(contextType, scopedId)]; - for (var oldContext of this.activeContexts_) { - if (oldContext.type === contextType) { - // If a previous context of the same type is active, it is removed - // and pushed onto the stack for this type. - this.pushContext_(oldContext); - } else { - // Otherwise the old context is it is still active. - newActiveContexts.push(oldContext); - } - } - this.activeContexts_ = newActiveContexts; - this.cachedEntryForActiveContexts_ = undefined; - }, - - leaveContext: function(contextType, scopedId) { - this.leaveContextImpl_(context => - context.type === contextType && - context.snapshot.scope === scopedId.scope && - context.snapshot.idRef === scopedId.id); - }, - - destroyContext: function(scopedId) { - // Remove all matching contexts from stacks. - tr.b.iterItems(this.stackPerType_, function(contextType, stack) { - // Perform in-place filtering instead of Array.prototype.filter to - // prevent creating a new array. - var newLength = 0; - for (var i = 0; i < stack.length; ++i) { - if (stack[i].snapshot.scope !== scopedId.scope || - stack[i].snapshot.idRef !== scopedId.id) { - stack[newLength++] = stack[i]; - } - } - stack.length = newLength; - }); - - // Remove all matching contexts from active context set. - this.leaveContextImpl_(context => - context.snapshot.scope === scopedId.scope && - context.snapshot.idRef === scopedId.id); - }, - - leaveContextImpl_: function(predicate) { - var newActiveContexts = []; - for (var oldContext of this.activeContexts_) { - if (predicate(oldContext)) { - // If we left this context, remove it from the active set and - // restore any previous context of the same type. - var previousContext = this.popContext_(oldContext.type); - if (previousContext) - newActiveContexts.push(previousContext); - } else { - newActiveContexts.push(oldContext); - } - } - this.activeContexts_ = newActiveContexts; - this.cachedEntryForActiveContexts_ = undefined; - }, - - getOrCreateContext_: function(contextType, scopedId) { - var context = { - type: contextType, - snapshot: { - scope: scopedId.scope, - idRef: scopedId.id - } - }; - var key = this.getContextKey_(context); - if (key in this.contextCache_) - return this.contextCache_[key]; - this.contextCache_[key] = context; - var snapshotKey = this.getSnapshotKey_(scopedId); - this.seenSnapshots_[snapshotKey] = true; - return context; - }, - - pushContext_: function(context) { - if (!(context.type in this.stackPerType_)) - this.stackPerType_[context.type] = []; - this.stackPerType_[context.type].push(context); - }, - - popContext_: function(contextType) { - if (!(contextType in this.stackPerType_)) - return undefined; - return this.stackPerType_[contextType].pop(); - }, - - getContextKey_: function(context) { - return [ - context.type, - context.snapshot.scope, - context.snapshot.idRef - ].join('\x00'); - }, - - getSnapshotKey_: function(scopedId) { - return [ - scopedId.scope, - scopedId.idRef - ].join('\x00'); - }, - - get activeContexts() { - // Keep a single instance for each unique set of active contexts to - // reduce memory usage. - if (this.cachedEntryForActiveContexts_ === undefined) { - var key = []; - for (var context of this.activeContexts_) - key.push(this.getContextKey_(context)); - key.sort(); - key = key.join('\x00'); - if (key in this.contextSetCache_) { - this.cachedEntryForActiveContexts_ = this.contextSetCache_[key]; - } else { - this.activeContexts_.sort(function(a, b) { - var keyA = this.getContextKey_(a); - var keyB = this.getContextKey_(b); - if (keyA < keyB) - return -1; - if (keyA > keyB) - return 1; - return 0; - }.bind(this)); - this.contextSetCache_[key] = Object.freeze(this.activeContexts_); - this.cachedEntryForActiveContexts_ = this.contextSetCache_[key]; - } - } - return this.cachedEntryForActiveContexts_; - }, - - invalidateContextCacheForSnapshot: function(scopedId) { - var snapshotKey = this.getSnapshotKey_(scopedId); - if (!(snapshotKey in this.seenSnapshots_)) - return; - this.contextCache_ = {}; - this.contextSetCache_ = {}; - this.cachedEntryForActiveContexts_ = undefined; - this.activeContexts_ = this.activeContexts_.map(function(context) { - // Do not alter unrelated contexts. - if (context.snapshot.scope !== scopedId.scope || - context.snapshot.idRef !== scopedId.id) - return context; - // Replace the invalidated context by a deep copy. - return { - type: context.type, - snapshot: { - scope: context.snapshot.scope, - idRef: context.snapshot.idRef - } - }; - }); - this.seenSnapshots_ = {}; - }, - }; - - return { - ContextProcessor: ContextProcessor - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html b/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html deleted file mode 100644 index 29a78114bd4..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/context_processor_test.html +++ /dev/null @@ -1,273 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2016 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/core/test_utils.html"> -<link rel="import" href="/tracing/importer/context_processor.html"> -<link rel="import" href="/tracing/model/scoped_id.html"> - -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var ContextProcessor = tr.importer.ContextProcessor; - - test('empty', function() { - var processor = new ContextProcessor(); - assert.deepEqual(processor.activeContexts, []); - }); - - test('enterAndLeave', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - processor.enterContext('type', id); - assert.deepEqual(processor.activeContexts, [expectedContext]); - processor.leaveContext('type', id); - assert.deepEqual(processor.activeContexts, []); - }); - - test('parallelContexts', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContextA = {type: 'A', snapshot: {scope: 'ptr', idRef: 123}}; - var expectedContextB = {type: 'B', snapshot: {scope: 'idx', idRef: 456}}; - - // Entering and leaving in order. - processor.enterContext('A', idA); - assert.deepEqual(processor.activeContexts, [expectedContextA]); - processor.enterContext('B', idB); - assert.deepEqual(processor.activeContexts, [expectedContextA, - expectedContextB]); - processor.leaveContext('B', idB); - assert.deepEqual(processor.activeContexts, [expectedContextA]); - processor.leaveContext('A', idA); - assert.deepEqual(processor.activeContexts, []); - - // Entering and leaving out of order. - processor.enterContext('B', idB); - assert.deepEqual(processor.activeContexts, [expectedContextB]); - processor.enterContext('A', idA); - assert.deepEqual(processor.activeContexts, [expectedContextA, - expectedContextB]); - processor.leaveContext('B', idB); - assert.deepEqual(processor.activeContexts, [expectedContextA]); - processor.leaveContext('A', idA); - assert.deepEqual(processor.activeContexts, []); - }); - - test('contextStack', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContextA = { - type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - var expectedContextB = { - type: 'type', snapshot: {scope: 'idx', idRef: 456}}; - - // Entering and leaving the same context type. - processor.enterContext('type', idA); - assert.deepEqual(processor.activeContexts, [expectedContextA]); - processor.enterContext('type', idB); - assert.deepEqual(processor.activeContexts, [expectedContextB]); - processor.leaveContext('type', idB); - assert.deepEqual(processor.activeContexts, [expectedContextA]); - processor.leaveContext('type', idA); - assert.deepEqual(processor.activeContexts, []); - }); - - test('contextCached', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContextA = { - type: 'A', snapshot: {scope: 'ptr', idRef: 123}}; - var expectedContextB = { - type: 'B', snapshot: {scope: 'idx', idRef: 456}}; - - processor.enterContext('A', idA); - var firstSet = processor.activeContexts; - processor.enterContext('B', idB); - var secondSet = processor.activeContexts; - processor.leaveContext('B', idB); - processor.leaveContext('A', idA); - - assert.deepEqual(firstSet, [expectedContextA]); - assert.deepEqual(secondSet, [expectedContextA, expectedContextB]); - - // Identical context objects should be the same instance. - assert(Object.is(firstSet[0], secondSet[0])); - }); - - test('contextSetCached', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - - processor.enterContext('type', id); - var firstSet = processor.activeContexts; - processor.leaveContext('type', id); - - processor.enterContext('type', id); - var secondSet = processor.activeContexts; - processor.leaveContext('type', id); - - assert.deepEqual(firstSet, [expectedContext]); - assert(Object.is(firstSet, secondSet)); - }); - - test('contextSetIsOrdered', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContextA = {type: 'A', snapshot: {scope: 'ptr', idRef: 123}}; - var expectedContextB = {type: 'B', snapshot: {scope: 'idx', idRef: 456}}; - - processor.enterContext('A', idA); - processor.enterContext('B', idB); - var firstSet = processor.activeContexts; - processor.leaveContext('B', idB); - processor.leaveContext('A', idA); - - processor.enterContext('B', idB); - processor.enterContext('A', idA); - var secondSet = processor.activeContexts; - processor.leaveContext('A', idA); - processor.leaveContext('B', idB); - - assert.deepEqual(firstSet, [expectedContextA, expectedContextB]); - assert(Object.is(firstSet, secondSet)); - }); - - test('contextSetIsFrozen', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - assert(Object.isFrozen(processor.activeContexts)); - processor.enterContext('type', id); - assert(Object.isFrozen(processor.activeContexts)); - processor.leaveContext('type', id); - assert(Object.isFrozen(processor.activeContexts)); - }); - - test('cacheInvalidation', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - - processor.enterContext('type', id); - var firstSet = processor.activeContexts; - processor.leaveContext('type', id); - - processor.invalidateContextCacheForSnapshot(id); - - processor.enterContext('type', id); - var secondSet = processor.activeContexts; - processor.leaveContext('type', id); - - assert.deepEqual(firstSet, [expectedContext]); - assert.deepEqual(secondSet, [expectedContext]); - assert(!Object.is(firstSet, secondSet)); - assert(!Object.is(firstSet[0], secondSet[0])); - assert(!Object.is(firstSet[0].snapshot, secondSet[0].snapshot)); - }); - - test('cacheInvalidationOfAnActiveContext', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - - processor.enterContext('type', id); - var firstSet = processor.activeContexts; - - processor.invalidateContextCacheForSnapshot(id); - - var secondSet = processor.activeContexts; - processor.leaveContext('type', id); - - assert.deepEqual(firstSet, [expectedContext]); - assert.deepEqual(secondSet, [expectedContext]); - assert(!Object.is(firstSet, secondSet)); - assert(!Object.is(firstSet[0], secondSet[0])); - assert(!Object.is(firstSet[0].snapshot, secondSet[0].snapshot)); - }); - - test('cacheInvalidationForUnrelatedSnapshot', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var unrelatedId = new tr.model.ScopedId('ofs', 789); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - - processor.enterContext('type', id); - var firstSet = processor.activeContexts; - processor.leaveContext('type', id); - - processor.invalidateContextCacheForSnapshot(unrelatedId); - - processor.enterContext('type', id); - var secondSet = processor.activeContexts; - processor.leaveContext('type', id); - - assert.deepEqual(firstSet, [expectedContext]); - assert.deepEqual(secondSet, [expectedContext]); - assert(Object.is(firstSet, secondSet)); - }); - - test('destroyBasic', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - processor.enterContext('type', id); - assert.deepEqual(processor.activeContexts, [expectedContext]); - processor.destroyContext(id); - assert.deepEqual(processor.activeContexts, []); - }); - - test('destroyActiveContextWithNonEmptyStack', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContext = {type: 'type', snapshot: {scope: 'ptr', idRef: 123}}; - processor.enterContext('type', idA); - processor.enterContext('type', idB); - processor.destroyContext(idB); - assert.deepEqual(processor.activeContexts, [expectedContext]); - processor.leaveContext('type', idA); - assert.deepEqual(processor.activeContexts, []); - }); - - test('destroyInactiveContextInStack', function() { - var processor = new ContextProcessor(); - var idA = new tr.model.ScopedId('ptr', 123); - var idB = new tr.model.ScopedId('idx', 456); - var expectedContext = {type: 'type', snapshot: {scope: 'idx', idRef: 456}}; - processor.enterContext('type', idA); - processor.enterContext('type', idB); - processor.destroyContext(idA); - assert.deepEqual(processor.activeContexts, [expectedContext]); - processor.leaveContext('type', idB); - assert.deepEqual(processor.activeContexts, []); - }); - - test('destroyContextEnteredWithMultipleTypes', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - processor.enterContext('A', id); - processor.enterContext('B', id); - processor.destroyContext(id); - assert.deepEqual(processor.activeContexts, []); - }); - - test('destroyReenteredContext', function() { - var processor = new ContextProcessor(); - var id = new tr.model.ScopedId('ptr', 123); - processor.enterContext('type', id); - processor.enterContext('type', id); - processor.destroyContext(id); - assert.deepEqual(processor.activeContexts, []); - }); -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html b/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html deleted file mode 100644 index dc5f867b3ff..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/empty_importer.html +++ /dev/null @@ -1,48 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2013 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/base.html"> -<link rel="import" href="/tracing/importer/importer.html"> - -<script> -'use strict'; - -/** - * @fileoverview Base class for trace data importers. - */ -tr.exportTo('tr.importer', function() { - /** - * Importer for empty strings and arrays. - * @constructor - */ - function EmptyImporter(events) { - this.importPriority = 0; - }; - - EmptyImporter.canImport = function(eventData) { - if (eventData instanceof Array && eventData.length == 0) - return true; - if (typeof(eventData) === 'string' || eventData instanceof String) { - return eventData.length == 0; - } - return false; - }; - - EmptyImporter.prototype = { - __proto__: tr.importer.Importer.prototype, - - get importerName() { - return 'EmptyImporter'; - } - }; - - tr.importer.Importer.register(EmptyImporter); - - return { - EmptyImporter: EmptyImporter - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html deleted file mode 100644 index 36e77d32ba5..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/find_input_expectations.html +++ /dev/null @@ -1,1084 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/range_utils.html"> -<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html"> -<link rel="import" href="/tracing/importer/proto_expectation.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - var ProtoExpectation = tr.importer.ProtoExpectation; - - var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES; - - var KEYBOARD_TYPE_NAMES = [ - INPUT_TYPE.CHAR, - INPUT_TYPE.KEY_DOWN_RAW, - INPUT_TYPE.KEY_DOWN, - INPUT_TYPE.KEY_UP - ]; - var MOUSE_RESPONSE_TYPE_NAMES = [ - INPUT_TYPE.CLICK, - INPUT_TYPE.CONTEXT_MENU - ]; - var MOUSE_WHEEL_TYPE_NAMES = [ - INPUT_TYPE.MOUSE_WHEEL - ]; - var MOUSE_DRAG_TYPE_NAMES = [ - INPUT_TYPE.MOUSE_DOWN, - INPUT_TYPE.MOUSE_MOVE, - INPUT_TYPE.MOUSE_UP - ]; - var TAP_TYPE_NAMES = [ - INPUT_TYPE.TAP, - INPUT_TYPE.TAP_CANCEL, - INPUT_TYPE.TAP_DOWN - ]; - var PINCH_TYPE_NAMES = [ - INPUT_TYPE.PINCH_BEGIN, - INPUT_TYPE.PINCH_END, - INPUT_TYPE.PINCH_UPDATE - ]; - var FLING_TYPE_NAMES = [ - INPUT_TYPE.FLING_CANCEL, - INPUT_TYPE.FLING_START - ]; - var TOUCH_TYPE_NAMES = [ - INPUT_TYPE.TOUCH_END, - INPUT_TYPE.TOUCH_MOVE, - INPUT_TYPE.TOUCH_START - ]; - var SCROLL_TYPE_NAMES = [ - INPUT_TYPE.SCROLL_BEGIN, - INPUT_TYPE.SCROLL_END, - INPUT_TYPE.SCROLL_UPDATE - ]; - var ALL_HANDLED_TYPE_NAMES = [].concat( - KEYBOARD_TYPE_NAMES, - MOUSE_RESPONSE_TYPE_NAMES, - MOUSE_WHEEL_TYPE_NAMES, - MOUSE_DRAG_TYPE_NAMES, - PINCH_TYPE_NAMES, - TAP_TYPE_NAMES, - FLING_TYPE_NAMES, - TOUCH_TYPE_NAMES, - SCROLL_TYPE_NAMES - ); - - var RENDERER_FLING_TITLE = 'InputHandlerProxy::HandleGestureFling::started'; - - // TODO(benjhayden) share with rail_ir_finder - var CSS_ANIMATION_TITLE = 'Animation'; - - // If there's less than this much time between the end of one event and the - // start of the next, then they might be merged. - // There was not enough thought given to this value, so if you have any slight - // reason to change it, then please do so. It might also be good to split this - // into multiple values. - var INPUT_MERGE_THRESHOLD_MS = 200; - var ANIMATION_MERGE_THRESHOLD_MS = 32; // 2x 60FPS frames - - // If two MouseWheel events begin this close together, then they're an - // Animation, not two responses. - var MOUSE_WHEEL_THRESHOLD_MS = 40; - - // If two MouseMoves are more than this far apart, then they're two Responses, - // not Animation. - var MOUSE_MOVE_THRESHOLD_MS = 40; - - // Strings used to name IRs. - var KEYBOARD_IR_NAME = 'Keyboard'; - var MOUSE_IR_NAME = 'Mouse'; - var MOUSEWHEEL_IR_NAME = 'MouseWheel'; - var TAP_IR_NAME = 'Tap'; - var PINCH_IR_NAME = 'Pinch'; - var FLING_IR_NAME = 'Fling'; - var TOUCH_IR_NAME = 'Touch'; - var SCROLL_IR_NAME = 'Scroll'; - var CSS_IR_NAME = 'CSS'; - - // TODO(benjhayden) Find a better home for this. - function compareEvents(x, y) { - if (x.start !== y.start) - return x.start - y.start; - if (x.end !== y.end) - return x.end - y.end; - if (x.guid && y.guid) - return x.guid - y.guid; - return 0; - } - - function forEventTypesIn(events, typeNames, cb, opt_this) { - events.forEach(function(event) { - if (typeNames.indexOf(event.typeName) >= 0) { - cb.call(opt_this, event); - } - }); - } - - function causedFrame(event) { - return event.associatedEvents.some( - x => x.title === tr.model.helpers.IMPL_RENDERING_STATS); - } - - function getSortedInputEvents(modelHelper) { - var inputEvents = []; - - var browserProcess = modelHelper.browserHelper.process; - var mainThread = browserProcess.findAtMostOneThreadNamed( - 'CrBrowserMain'); - for (var slice of mainThread.asyncSliceGroup.getDescendantEvents()) { - if (!slice.isTopLevel) - continue; - - if (!(slice instanceof tr.e.cc.InputLatencyAsyncSlice)) - continue; - - // TODO(beaudoin): This should never happen but it does. Investigate - // the trace linked at in #1567 and remove that when it's fixed. - if (isNaN(slice.start) || - isNaN(slice.duration) || - isNaN(slice.end)) - continue; - - inputEvents.push(slice); - } - - return inputEvents.sort(compareEvents); - } - - function findProtoExpectations(modelHelper, sortedInputEvents) { - var protoExpectations = []; - // This order is not important. Handlers are independent. - var handlers = [ - handleKeyboardEvents, - handleMouseResponseEvents, - handleMouseWheelEvents, - handleMouseDragEvents, - handleTapResponseEvents, - handlePinchEvents, - handleFlingEvents, - handleTouchEvents, - handleScrollEvents, - handleCSSAnimations - ]; - handlers.forEach(function(handler) { - protoExpectations.push.apply(protoExpectations, handler( - modelHelper, sortedInputEvents)); - }); - protoExpectations.sort(compareEvents); - return protoExpectations; - } - - // Every keyboard event is a Response. - function handleKeyboardEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - forEventTypesIn(sortedInputEvents, KEYBOARD_TYPE_NAMES, function(event) { - var pe = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, KEYBOARD_IR_NAME); - pe.pushEvent(event); - protoExpectations.push(pe); - }); - return protoExpectations; - } - - // Some mouse events can be translated directly into Responses. - function handleMouseResponseEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - forEventTypesIn( - sortedInputEvents, MOUSE_RESPONSE_TYPE_NAMES, function(event) { - var pe = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME); - pe.pushEvent(event); - protoExpectations.push(pe); - }); - return protoExpectations; - } - - // MouseWheel events are caused either by a physical wheel on a physical - // mouse, or by a touch-drag gesture on a track-pad. The physical wheel - // causes MouseWheel events that are much more spaced out, and have no - // chance of hitting 60fps, so they are each turned into separate Response - // IRs. The track-pad causes MouseWheel events that are much closer - // together, and are expected to be 60fps, so the first event in a sequence - // is turned into a Response, and the rest are merged into an Animation. - // NB this threshold uses the two events' start times, unlike - // ProtoExpectation.isNear, which compares the end time of the previous event - // with the start time of the next. - function handleMouseWheelEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - var prevEvent_ = undefined; - forEventTypesIn( - sortedInputEvents, MOUSE_WHEEL_TYPE_NAMES, function(event) { - // Switch prevEvent in one place so that we can early-return later. - var prevEvent = prevEvent_; - prevEvent_ = event; - - if (currentPE && - (prevEvent.start + MOUSE_WHEEL_THRESHOLD_MS) >= event.start) { - if (currentPE.irType === ProtoExpectation.ANIMATION_TYPE) { - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE, - MOUSEWHEEL_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - return; - } - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, MOUSEWHEEL_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - }); - return protoExpectations; - } - - // Down events followed closely by Up events are click Responses, but the - // Response doesn't start until the Up event. - // - // RRR - // DDD UUU - // - // If there are any Move events in between a Down and an Up, then the Down - // and the first Move are a Response, then the rest of the Moves are an - // Animation: - // - // RRRRRRRAAAAAAAAAAAAAAAAAAAA - // DDD MMM MMM MMM MMM MMM UUU - // - function handleMouseDragEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - var mouseDownEvent = undefined; - forEventTypesIn( - sortedInputEvents, MOUSE_DRAG_TYPE_NAMES, function(event) { - switch (event.typeName) { - case INPUT_TYPE.MOUSE_DOWN: - if (causedFrame(event)) { - var pe = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME); - pe.pushEvent(event); - protoExpectations.push(pe); - } else { - // Responses typically don't start until the mouse up event. - // Add this MouseDown to the Response that starts at the MouseUp. - mouseDownEvent = event; - } - break; - // There may be more than 100ms between the start of the mouse down - // and the start of the mouse up. Chrome and the web don't start to - // respond until the mouse up. ResponseIRs start deducting comfort - // at 100ms duration. If more than that 100ms duration is burned - // through while waiting for the user to release the - // mouse button, then ResponseIR will unfairly start deducting - // comfort before Chrome even has a mouse up to respond to. - // It is technically possible for a site to afford one response on - // mouse down and another on mouse up, but that is an edge case. The - // vast majority of mouse downs are not responses. - - case INPUT_TYPE.MOUSE_MOVE: - if (!causedFrame(event)) { - // Ignore MouseMoves that do not affect the screen. They are not - // part of an interaction record by definition. - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - } else if (!currentPE || - !currentPE.isNear(event, MOUSE_MOVE_THRESHOLD_MS)) { - // The first MouseMove after a MouseDown or after a while is a - // Response. - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME); - currentPE.pushEvent(event); - if (mouseDownEvent) { - currentPE.associatedEvents.push(mouseDownEvent); - mouseDownEvent = undefined; - } - protoExpectations.push(currentPE); - } else { - // Merge this event into an Animation. - if (currentPE.irType === ProtoExpectation.ANIMATION_TYPE) { - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, MOUSE_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - } - break; - - case INPUT_TYPE.MOUSE_UP: - if (!mouseDownEvent) { - var pe = new ProtoExpectation( - causedFrame(event) ? ProtoExpectation.RESPONSE_TYPE : - ProtoExpectation.IGNORED_TYPE, - MOUSE_IR_NAME); - pe.pushEvent(event); - protoExpectations.push(pe); - break; - } - - if (currentPE) { - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, MOUSE_IR_NAME); - if (mouseDownEvent) - currentPE.associatedEvents.push(mouseDownEvent); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - mouseDownEvent = undefined; - currentPE = undefined; - break; - } - }); - if (mouseDownEvent) { - currentPE = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - currentPE.pushEvent(mouseDownEvent); - protoExpectations.push(currentPE); - } - return protoExpectations; - } - - // Solitary Tap events are simple Responses: - // - // RRR - // TTT - // - // TapDowns are part of Responses. - // - // RRRRRRR - // DDD TTT - // - // TapCancels are part of Responses, which seems strange. They always go - // with scrolls, so they'll probably be merged with scroll Responses. - // TapCancels can take a significant amount of time and account for a - // significant amount of work, which should be grouped with the scroll IRs - // if possible. - // - // RRRRRRR - // DDD CCC - // - function handleTapResponseEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - forEventTypesIn(sortedInputEvents, TAP_TYPE_NAMES, function(event) { - switch (event.typeName) { - case INPUT_TYPE.TAP_DOWN: - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - break; - - case INPUT_TYPE.TAP: - if (currentPE) { - currentPE.pushEvent(event); - } else { - // Sometimes we get Tap events with no TapDown, sometimes we get - // TapDown events. Handle both. - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - currentPE = undefined; - break; - - case INPUT_TYPE.TAP_CANCEL: - if (!currentPE) { - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - break; - } - - if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) { - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, TAP_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - currentPE = undefined; - break; - } - }); - return protoExpectations; - } - - // The PinchBegin and the first PinchUpdate comprise a Response, then the - // rest of the PinchUpdates comprise an Animation. - // - // RRRRRRRAAAAAAAAAAAAAAAAAAAA - // BBB UUU UUU UUU UUU UUU EEE - // - function handlePinchEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - var sawFirstUpdate = false; - var modelBounds = modelHelper.model.bounds; - forEventTypesIn(sortedInputEvents, PINCH_TYPE_NAMES, function(event) { - switch (event.typeName) { - case INPUT_TYPE.PINCH_BEGIN: - if (currentPE && - currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) { - currentPE.pushEvent(event); - break; - } - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, PINCH_IR_NAME); - currentPE.pushEvent(event); - currentPE.isAnimationBegin = true; - protoExpectations.push(currentPE); - sawFirstUpdate = false; - break; - - case INPUT_TYPE.PINCH_UPDATE: - // Like ScrollUpdates, the Begin and the first Update constitute a - // Response, then the rest of the Updates constitute an Animation - // that begins when the Response ends. If the user pauses in the - // middle of an extended pinch gesture, then multiple Animations - // will be created. - if (!currentPE || - ((currentPE.irType === ProtoExpectation.RESPONSE_TYPE) && - sawFirstUpdate) || - !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) { - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, PINCH_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } else { - currentPE.pushEvent(event); - sawFirstUpdate = true; - } - break; - - case INPUT_TYPE.PINCH_END: - if (currentPE) { - currentPE.pushEvent(event); - } else { - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - } - currentPE = undefined; - break; - } - }); - return protoExpectations; - } - - // Flings are defined by 3 types of events: FlingStart, FlingCancel, and the - // renderer fling event. Flings do not begin with a Response. Flings end - // either at the beginning of a FlingCancel, or at the end of the renderer - // fling event. - // - // AAAAAAAAAAAAAAAAAAAAAAAAAA - // SSS - // RRRRRRRRRRRRRRRRRRRRRR - // - // - // AAAAAAAAAAA - // SSS CCC - // - function handleFlingEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - - function isRendererFling(event) { - return event.title === RENDERER_FLING_TITLE; - } - var browserHelper = modelHelper.browserHelper; - var flingEvents = browserHelper.getAllAsyncSlicesMatching( - isRendererFling); - - forEventTypesIn(sortedInputEvents, FLING_TYPE_NAMES, function(event) { - flingEvents.push(event); - }); - flingEvents.sort(compareEvents); - - flingEvents.forEach(function(event) { - if (event.title === RENDERER_FLING_TITLE) { - if (currentPE) { - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, FLING_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - return; - } - - switch (event.typeName) { - case INPUT_TYPE.FLING_START: - if (currentPE) { - console.error('Another FlingStart? File a bug with this trace!'); - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, FLING_IR_NAME); - currentPE.pushEvent(event); - // Set end to an invalid value so that it can be noticed and fixed - // later. - currentPE.end = 0; - protoExpectations.push(currentPE); - } - break; - - case INPUT_TYPE.FLING_CANCEL: - if (currentPE) { - currentPE.pushEvent(event); - // FlingCancel events start when TouchStart events start, which is - // typically when a Response starts. FlingCancel events end when - // chrome acknowledges them, not when they update the screen. So - // there might be one more frame during the FlingCancel, after - // this Animation ends. That won't affect the scoring algorithms, - // and it will make the IRs look more correct if they don't - // overlap unnecessarily. - currentPE.end = event.start; - currentPE = undefined; - } else { - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - } - break; - } - }); - // If there was neither a FLING_CANCEL nor a renderer fling after the - // FLING_START, then assume that it ends at the end of the model, so set - // the end of currentPE to the end of the model. - if (currentPE && !currentPE.end) - currentPE.end = modelHelper.model.bounds.max; - return protoExpectations; - } - - // The TouchStart and the first TouchMove comprise a Response, then the - // rest of the TouchMoves comprise an Animation. - // - // RRRRRRRAAAAAAAAAAAAAAAAAAAA - // SSS MMM MMM MMM MMM MMM EEE - // - // If there are no TouchMove events in between a TouchStart and a TouchEnd, - // then it's just a Response. - // - // RRRRRRR - // SSS EEE - // - function handleTouchEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - var sawFirstMove = false; - forEventTypesIn(sortedInputEvents, TOUCH_TYPE_NAMES, function(event) { - switch (event.typeName) { - case INPUT_TYPE.TOUCH_START: - if (currentPE) { - // NB: currentPE will probably be merged with something from - // handlePinchEvents(). Multiple TouchStart events without an - // intervening TouchEnd logically implies that multiple fingers - // are on the screen, so this is probably a pinch gesture. - currentPE.pushEvent(event); - } else { - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, TOUCH_IR_NAME); - currentPE.pushEvent(event); - currentPE.isAnimationBegin = true; - protoExpectations.push(currentPE); - sawFirstMove = false; - } - break; - - case INPUT_TYPE.TOUCH_MOVE: - if (!currentPE) { - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, TOUCH_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - break; - } - - // Like Scrolls and Pinches, the Response is defined to be the - // TouchStart plus the first TouchMove, then the rest of the - // TouchMoves constitute an Animation. - if ((sawFirstMove && - (currentPE.irType === ProtoExpectation.RESPONSE_TYPE)) || - !currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) { - // If there's already a touchmove in the currentPE or it's not - // near event, then finish it and start a new animation. - var prevEnd = currentPE.end; - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, TOUCH_IR_NAME); - currentPE.pushEvent(event); - // It's possible for there to be a gap between TouchMoves, but - // that doesn't mean that there should be an Idle IR there. - currentPE.start = prevEnd; - protoExpectations.push(currentPE); - } else { - currentPE.pushEvent(event); - sawFirstMove = true; - } - break; - - case INPUT_TYPE.TOUCH_END: - if (!currentPE) { - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - break; - } - if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS)) { - currentPE.pushEvent(event); - } else { - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - } - currentPE = undefined; - break; - } - }); - return protoExpectations; - } - - // The first ScrollBegin and the first ScrollUpdate comprise a Response, - // then the rest comprise an Animation. - // - // RRRRRRRAAAAAAAAAAAAAAAAAAAA - // BBB UUU UUU UUU UUU UUU EEE - // - function handleScrollEvents(modelHelper, sortedInputEvents) { - var protoExpectations = []; - var currentPE = undefined; - var sawFirstUpdate = false; - forEventTypesIn(sortedInputEvents, SCROLL_TYPE_NAMES, function(event) { - switch (event.typeName) { - case INPUT_TYPE.SCROLL_BEGIN: - // Always begin a new PE even if there already is one, unlike - // PinchBegin. - currentPE = new ProtoExpectation( - ProtoExpectation.RESPONSE_TYPE, SCROLL_IR_NAME); - currentPE.pushEvent(event); - currentPE.isAnimationBegin = true; - protoExpectations.push(currentPE); - sawFirstUpdate = false; - break; - - case INPUT_TYPE.SCROLL_UPDATE: - if (currentPE) { - if (currentPE.isNear(event, INPUT_MERGE_THRESHOLD_MS) && - ((currentPE.irType === ProtoExpectation.ANIMATION_TYPE) || - !sawFirstUpdate)) { - currentPE.pushEvent(event); - sawFirstUpdate = true; - } else { - currentPE = new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE, - SCROLL_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - } else { - // ScrollUpdate without ScrollBegin. - currentPE = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, SCROLL_IR_NAME); - currentPE.pushEvent(event); - protoExpectations.push(currentPE); - } - break; - - case INPUT_TYPE.SCROLL_END: - if (!currentPE) { - console.error('ScrollEnd without ScrollUpdate? ' + - 'File a bug with this trace!'); - var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); - pe.pushEvent(event); - protoExpectations.push(pe); - break; - } - currentPE.pushEvent(event); - break; - } - }); - return protoExpectations; - } - - // CSS Animations are merged into AnimationExpectations when they intersect. - function handleCSSAnimations(modelHelper, sortedInputEvents) { - // First find all the top-level CSS Animation async events. - var animationEvents = modelHelper.browserHelper. - getAllAsyncSlicesMatching(function(event) { - return ((event.title === CSS_ANIMATION_TITLE) && - event.isTopLevel && - (event.duration > 0)); - }); - - // Memoize the frame events per process. - // There may be many Animation events for each process. We can save a - // significant amount of processing time by avoiding re-computing them for - // each animation. - var framesForProcess = {}; - - function getFramesForAnimationProcess(animation) { - var frames = framesForProcess[animation.parentContainer.parent.guid]; - if (frames === undefined) { - var rendererHelper = new tr.model.helpers.ChromeRendererHelper( - modelHelper, animation.parentContainer.parent); - // Collect all the frame events in the same renderer process as the css - // animation, and memoize them. - frames = rendererHelper.getFrameEventsInRange( - tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds); - framesForProcess[animation.parentContainer.parent.guid] = frames; - } - return frames; - } - - // Time ranges where animations are actually running will be collected here. - // Each element will contain {min, max, animation, frames}. - var animationRanges = []; - - // This helper function will be called when a time range is found - // during which the animation is actually running. - // This helper function collects the frames that happened during the time - // range, and pushes it all to |animationRanges|. - function pushAnimationRange(start, end, animation) { - var range = tr.b.Range.fromExplicitRange(start, end); - range.animation = animation; - - // Collect the frames that happened while the animation was running. - // A more general way to find these frames would be to collect all of - // the trace events caused by this animation, but that will require - // adding flow events to chrome: - // https://github.com/catapult-project/catapult/issues/1433 - range.frames = range.filterArray( - getFramesForAnimationProcess(animation), - function(frameEvent) { return frameEvent.start; }); - - // If a tree falls in a forest... - // If there were not actually any frames while the animation was - // running, then it wasn't really an animation, now, was it? - // Philosophy aside, the system_health Animation metrics fail hard if - // there are no frames in an AnimationExpectation. - if (range.frames.length === 0) - return; - - animationRanges.push(range); - } - - animationEvents.forEach(function(animation) { - if (animation.subSlices.length === 0) { - pushAnimationRange(animation.start, animation.end, animation); - } else { - // Now run a state machine over the animation's subSlices, which - // indicate the animations running/paused/finished states, in order to - // find ranges where the animation was actually running. - var start = undefined; - animation.subSlices.forEach(function(sub) { - if ((sub.args.state === 'running') && - (start === undefined)) { - // It's possible for the state to alternate between running and - // pending, but the animation is still running in that case, - // so only set start if the state is changing from one of the halted - // states. - start = sub.start; - } else if ((sub.args.state === 'paused') || - (sub.args.state === 'idle') || - (sub.args.state === 'finished')) { - if (start === undefined) { - // An animation was already running when the trace started. - // (Actually, it's possible that the animation was in the 'idle' - // state when tracing started, but that should be rare, and will - // be fixed when async events are buffered.) - // http://crbug.com/565627 - start = modelHelper.model.bounds.min; - } - - pushAnimationRange(start, sub.start, animation); - start = undefined; - } - }); - - // An animation was still running when the trace ended. - if (start !== undefined) - pushAnimationRange(start, modelHelper.model.bounds.max, animation); - } - }); - - // Now we have a set of time ranges when css animations were actually - // running, along with their frames. - // Now all that's left for this function is to merge over-lapping ranges - // into ProtoExpectations. - - function merge(ranges) { - var protoExpectation = new ProtoExpectation( - ProtoExpectation.ANIMATION_TYPE, CSS_IR_NAME); - ranges.forEach(function(range) { - protoExpectation.start = Math.min(protoExpectation.start, range.min); - protoExpectation.end = Math.max(protoExpectation.end, range.max); - protoExpectation.associatedEvents.push(range.animation); - protoExpectation.associatedEvents.addEventSet(range.frames); - }); - return protoExpectation; - } - - return tr.b.mergeRanges(animationRanges, - ANIMATION_MERGE_THRESHOLD_MS, - merge); - } - - function postProcessProtoExpectations(protoExpectations) { - // protoExpectations is input only. Returns a modified set of - // ProtoExpectations. The order is important. - protoExpectations = mergeIntersectingResponses(protoExpectations); - protoExpectations = mergeIntersectingAnimations(protoExpectations); - protoExpectations = fixResponseAnimationStarts(protoExpectations); - protoExpectations = fixTapResponseTouchAnimations(protoExpectations); - return protoExpectations; - } - - // TouchStarts happen at the same time as ScrollBegins. - // It's easier to let multiple handlers create multiple overlapping - // Responses and then merge them, rather than make the handlers aware of the - // other handlers' PEs. - // - // For example: - // RR - // RRR -> RRRRR - // RR - // - // protoExpectations is input only. - // Returns a modified set of ProtoExpectations. - function mergeIntersectingResponses(protoExpectations) { - var newPEs = []; - while (protoExpectations.length) { - var pe = protoExpectations.shift(); - newPEs.push(pe); - - // Only consider Responses for now. - if (pe.irType !== ProtoExpectation.RESPONSE_TYPE) - continue; - - for (var i = 0; i < protoExpectations.length; ++i) { - var otherPE = protoExpectations[i]; - - if (otherPE.irType !== pe.irType) - continue; - - if (!otherPE.intersects(pe)) - continue; - - // Don't merge together Responses of the same type. - // If handleTouchEvents wanted two of its Responses to be merged, then - // it would have made them that way to begin with. - var typeNames = pe.associatedEvents.map(function(event) { - return event.typeName; - }); - if (otherPE.containsTypeNames(typeNames)) - continue; - - pe.merge(otherPE); - protoExpectations.splice(i, 1); - // Don't skip the next otherPE! - --i; - } - } - return newPEs; - } - - // An animation is simply an expectation of 60fps between start and end. - // If two animations overlap, then merge them. - // - // For example: - // AA - // AAA -> AAAAA - // AA - // - // protoExpectations is input only. - // Returns a modified set of ProtoExpectations. - function mergeIntersectingAnimations(protoExpectations) { - var newPEs = []; - while (protoExpectations.length) { - var pe = protoExpectations.shift(); - newPEs.push(pe); - - // Only consider Animations for now. - if (pe.irType !== ProtoExpectation.ANIMATION_TYPE) - continue; - - var isCSS = pe.containsSliceTitle(CSS_ANIMATION_TITLE); - var isFling = pe.containsTypeNames([INPUT_TYPE.FLING_START]); - - for (var i = 0; i < protoExpectations.length; ++i) { - var otherPE = protoExpectations[i]; - - if (otherPE.irType !== pe.irType) - continue; - - // Don't merge CSS Animations with any other types. - if (isCSS != otherPE.containsSliceTitle(CSS_ANIMATION_TITLE)) - continue; - - if (!otherPE.intersects(pe)) - continue; - - // Don't merge Fling Animations with any other types. - if (isFling != otherPE.containsTypeNames([INPUT_TYPE.FLING_START])) - continue; - - pe.merge(otherPE); - protoExpectations.splice(i, 1); - // Don't skip the next otherPE! - --i; - } - } - return newPEs; - } - - // The ends of responses frequently overlap the starts of animations. - // Fix the animations to reflect the fact that the user can only start to - // expect 60fps after the response. - // - // For example: - // RRR -> RRRAA - // AAAA - // - // protoExpectations is input only. - // Returns a modified set of ProtoExpectations. - function fixResponseAnimationStarts(protoExpectations) { - protoExpectations.forEach(function(ape) { - // Only consider animations for now. - if (ape.irType !== ProtoExpectation.ANIMATION_TYPE) - return; - - protoExpectations.forEach(function(rpe) { - // Only consider responses for now. - if (rpe.irType !== ProtoExpectation.RESPONSE_TYPE) - return; - - // Only consider responses that end during the animation. - if (!ape.containsTimestampInclusive(rpe.end)) - return; - - // Ignore Responses that are entirely contained by the animation. - if (ape.containsTimestampInclusive(rpe.start)) - return; - - // Move the animation start to the response end. - ape.start = rpe.end; - }); - }); - return protoExpectations; - } - - // Merge Tap Responses that overlap Touch-only Animations. - // https://github.com/catapult-project/catapult/issues/1431 - function fixTapResponseTouchAnimations(protoExpectations) { - function isTapResponse(pe) { - return (pe.irType === ProtoExpectation.RESPONSE_TYPE) && - pe.containsTypeNames([INPUT_TYPE.TAP]); - } - function isTouchAnimation(pe) { - return (pe.irType === ProtoExpectation.ANIMATION_TYPE) && - pe.containsTypeNames([INPUT_TYPE.TOUCH_MOVE]) && - !pe.containsTypeNames([ - INPUT_TYPE.SCROLL_UPDATE, INPUT_TYPE.PINCH_UPDATE]); - } - var newPEs = []; - while (protoExpectations.length) { - var pe = protoExpectations.shift(); - newPEs.push(pe); - - // protoExpectations are sorted by start time, and we don't know whether - // the Tap Response or the Touch Animation will be first - var peIsTapResponse = isTapResponse(pe); - var peIsTouchAnimation = isTouchAnimation(pe); - if (!peIsTapResponse && !peIsTouchAnimation) - continue; - - for (var i = 0; i < protoExpectations.length; ++i) { - var otherPE = protoExpectations[i]; - - if (!otherPE.intersects(pe)) - continue; - - if (peIsTapResponse && !isTouchAnimation(otherPE)) - continue; - - if (peIsTouchAnimation && !isTapResponse(otherPE)) - continue; - - // pe might be the Touch Animation, but the merged ProtoExpectation - // should be a Response. - pe.irType = ProtoExpectation.RESPONSE_TYPE; - - pe.merge(otherPE); - protoExpectations.splice(i, 1); - // Don't skip the next otherPE! - --i; - } - } - return newPEs; - } - - // Check that none of the handlers accidentally ignored an input event. - function checkAllInputEventsHandled(sortedInputEvents, protoExpectations) { - var handledEvents = []; - protoExpectations.forEach(function(protoExpectation) { - protoExpectation.associatedEvents.forEach(function(event) { - // Ignore CSS Animations that might have multiple active ranges. - if ((event.title === CSS_ANIMATION_TITLE) && - (event.subSlices.length > 0)) - return; - - if (handledEvents.indexOf(event) >= 0) { - console.error('double-handled event', event.typeName, - parseInt(event.start), parseInt(event.end), protoExpectation); - return; - } - handledEvents.push(event); - }); - }); - - sortedInputEvents.forEach(function(event) { - if (handledEvents.indexOf(event) < 0) { - console.error('UNHANDLED INPUT EVENT!', - event.typeName, parseInt(event.start), parseInt(event.end)); - } - }); - } - - // Find ProtoExpectations, post-process them, convert them to real IRs. - function findInputExpectations(modelHelper) { - var sortedInputEvents = getSortedInputEvents(modelHelper); - var protoExpectations = findProtoExpectations( - modelHelper, sortedInputEvents); - protoExpectations = postProcessProtoExpectations(protoExpectations); - checkAllInputEventsHandled(sortedInputEvents, protoExpectations); - - var irs = []; - protoExpectations.forEach(function(protoExpectation) { - var ir = protoExpectation.createInteractionRecord(modelHelper.model); - if (ir) - irs.push(ir); - }); - return irs; - } - - return { - findInputExpectations: findInputExpectations, - compareEvents: compareEvents, - CSS_ANIMATION_TITLE: CSS_ANIMATION_TITLE - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html deleted file mode 100644 index c9135599c8c..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/find_load_expectations.html +++ /dev/null @@ -1,64 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/model/user_model/load_expectation.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - // This global instant event marks the start of a navigation. - var NAVIGATION_START = 'NavigationTiming navigationStart'; - - // This render-process instant event marks the first contentful paint in a - // main frame. - var FIRST_CONTENTFUL_PAINT_TITLE = 'firstContentfulPaint'; - - function findLoadExpectations(modelHelper) { - var events = []; - for (var event of modelHelper.model.getDescendantEvents()) { - if ((event.title === NAVIGATION_START) || - (event.title === FIRST_CONTENTFUL_PAINT_TITLE)) - events.push(event); - } - events.sort(tr.importer.compareEvents); - - var loads = []; - var startEvent = undefined; - // TODO(alexandermont): What's supposed to happen if there are two - // NAVIGATION_STARTs with no FIRST_CONTENTFUL_PAINT_TITLE between - // them? Are you supposed to just "lose" the first NAVIGATION_START, - // like what's happening now? - for (var event of events) { - if (event.title === NAVIGATION_START) { - startEvent = event; - } else if (event.title === FIRST_CONTENTFUL_PAINT_TITLE) { - if (startEvent) { - loads.push(new tr.model.um.LoadExpectation( - modelHelper.model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, - startEvent.start, event.start - startEvent.start)); - startEvent = undefined; - } - } - } - - // If the trace ended between navigation start and first contentful paint, - // then make a LoadExpectation that ends at the end of the trace. - if (startEvent) { - loads.push(new tr.model.um.LoadExpectation( - modelHelper.model, tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL, - startEvent.start, modelHelper.model.bounds.max - startEvent.start)); - } - - return loads; - } - - return { - findLoadExpectations: findLoadExpectations - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html b/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html deleted file mode 100644 index 01fc9d7153e..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/find_startup_expectations.html +++ /dev/null @@ -1,89 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/model/user_model/startup_expectation.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - function getAllFrameEvents(modelHelper) { - var frameEvents = []; - frameEvents.push.apply(frameEvents, - modelHelper.browserHelper.getFrameEventsInRange( - tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds)); - - tr.b.iterItems(modelHelper.rendererHelpers, function(pid, renderer) { - frameEvents.push.apply(frameEvents, renderer.getFrameEventsInRange( - tr.model.helpers.IMPL_FRAMETIME_TYPE, modelHelper.model.bounds)); - }); - return frameEvents.sort(tr.importer.compareEvents); - } - - // If a thread contains a typical initialization slice, then the first event - // on that thread is a startup event. - function getStartupEvents(modelHelper) { - function isStartupSlice(slice) { - return slice.title === 'BrowserMainLoop::CreateThreads'; - } - var events = modelHelper.browserHelper.getAllAsyncSlicesMatching( - isStartupSlice); - var deduper = new tr.model.EventSet(); - events.forEach(function(event) { - var sliceGroup = event.parentContainer.sliceGroup; - var slice = sliceGroup && sliceGroup.findFirstSlice(); - if (slice) - deduper.push(slice); - }); - return deduper.toArray(); - } - - // Match every event in |openingEvents| to the first following event from - // |closingEvents| and return an array containing a load interaction record - // for each pair. - function findStartupExpectations(modelHelper) { - var openingEvents = getStartupEvents(modelHelper); - var closingEvents = getAllFrameEvents(modelHelper); - var startups = []; - openingEvents.forEach(function(openingEvent) { - closingEvents.forEach(function(closingEvent) { - // Ignore opening event that already have a closing event. - if (openingEvent.closingEvent) - return; - - // Ignore closing events that already belong to an opening event. - if (closingEvent.openingEvent) - return; - - // Ignore closing events before |openingEvent|. - if (closingEvent.start <= openingEvent.start) - return; - - // Ignore events from different threads. - if (openingEvent.parentContainer.parent.pid !== - closingEvent.parentContainer.parent.pid) - return; - - // This is the first closing event for this opening event, record it. - openingEvent.closingEvent = closingEvent; - closingEvent.openingEvent = openingEvent; - var se = new tr.model.um.StartupExpectation( - modelHelper.model, openingEvent.start, - closingEvent.end - openingEvent.start); - se.associatedEvents.push(openingEvent); - se.associatedEvents.push(closingEvent); - startups.push(se); - }); - }); - return startups; - } - - return { - findStartupExpectations: findStartupExpectations - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import.html b/chromium/third_party/catapult/tracing/tracing/importer/import.html deleted file mode 100644 index 8fe21637c8c..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/import.html +++ /dev/null @@ -1,395 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel='import' href='/tracing/base/base.html'> -<link rel='import' href='/tracing/base/timing.html'> -<link rel="import" href="/tracing/importer/empty_importer.html"> -<link rel="import" href="/tracing/importer/importer.html"> -<link rel="import" href="/tracing/importer/user_model_builder.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - var Timing = tr.b.Timing; - - function ImportOptions() { - this.shiftWorldToZero = true; - this.pruneEmptyContainers = true; - this.showImportWarnings = true; - this.trackDetailedModelStats = false; - - // Callback called after - // importers run in which more data can be added to the model, before it is - // finalized. - this.customizeModelCallback = undefined; - - var auditorTypes = tr.c.Auditor.getAllRegisteredTypeInfos(); - this.auditorConstructors = auditorTypes.map(function(typeInfo) { - return typeInfo.constructor; - }); - } - - function Import(model, opt_options) { - if (model === undefined) - throw new Error('Must provide model to import into.'); - - // TODO(dsinclair): Check the model is empty. - - this.importing_ = false; - this.importOptions_ = opt_options || new ImportOptions(); - - this.model_ = model; - this.model_.importOptions = this.importOptions_; - } - - Import.prototype = { - __proto__: Object.prototype, - - /** - * Imports the provided traces into the model. The eventData type - * is undefined and will be passed to all the importers registered - * via Importer.register. The first importer that returns true - * for canImport(events) will be used to import the events. - * - * The primary trace is provided via the eventData variable. If multiple - * traces are to be imported, specify the first one as events, and the - * remainder in the opt_additionalEventData array. - * - * @param {Array} traces An array of eventData to be imported. Each - * eventData should correspond to a single trace file and will be handled by - * a separate importer. - */ - importTraces: function(traces) { - var progressMeter = { - update: function(msg) {} - }; - - tr.b.Task.RunSynchronously( - this.createImportTracesTask(progressMeter, traces)); - }, - - /** - * Imports a trace with the usual options from importTraces, but - * does so using idle callbacks, putting up an import dialog - * during the import process. - */ - importTracesWithProgressDialog: function(traces) { - if (tr.isHeadless) - throw new Error('Cannot use this method in headless mode.'); - - var overlay = tr.ui.b.Overlay(); - overlay.title = 'Importing...'; - overlay.userCanClose = false; - overlay.msgEl = document.createElement('div'); - overlay.appendChild(overlay.msgEl); - overlay.msgEl.style.margin = '20px'; - overlay.update = function(msg) { - this.msgEl.textContent = msg; - }; - overlay.visible = true; - - var promise = - tr.b.Task.RunWhenIdle(this.createImportTracesTask(overlay, traces)); - promise.then( - function() { overlay.visible = false; }, - function(err) { overlay.visible = false; } - ); - return promise; - }, - - /** - * Creates a task that will import the provided traces into the model, - * updating the progressMeter as it goes. Parameters are as defined in - * importTraces. - */ - createImportTracesTask: function(progressMeter, traces) { - if (this.importing_) - throw new Error('Already importing.'); - this.importing_ = true; - - // Just some simple setup. It is useful to have a no-op first - // task so that we can set up the lastTask = lastTask.after() - // pattern that follows. - var importTask = new tr.b.Task(function prepareImport() { - progressMeter.update('I will now import your traces for you...'); - }, this); - var lastTask = importTask; - - var importers = []; - - lastTask = lastTask.timedAfter('TraceImport', function createImports() { - // Copy the traces array, we may mutate it. - traces = traces.slice(0); - progressMeter.update('Creating importers...'); - // Figure out which importers to use. - for (var i = 0; i < traces.length; ++i) - importers.push(this.createImporter_(traces[i])); - - // Some traces have other traces inside them. Before doing the full - // import, ask the importer if it has any subtraces, and if so, create - // importers for them, also. - for (var i = 0; i < importers.length; i++) { - var subtraces = importers[i].extractSubtraces(); - for (var j = 0; j < subtraces.length; j++) { - try { - traces.push(subtraces[j]); - importers.push(this.createImporter_(subtraces[j])); - } catch (error) { - // TODO(kphanee): Log the subtrace file which has failed. - console.warn(error.name + ': ' + error.message); - continue; - } - } - } - - if (traces.length && !this.hasEventDataDecoder_(importers)) { - throw new Error( - 'Could not find an importer for the provided eventData.'); - } - - // Sort them on priority. This ensures importing happens in a - // predictable order, e.g. ftrace_importer before - // trace_event_importer. - importers.sort(function(x, y) { - return x.importPriority - y.importPriority; - }); - }, this); - - // We import clock sync markers before all other events. This is necessary - // because we need the clock sync markers in order to know by how much we - // need to shift the timestamps of other events. - lastTask = lastTask.timedAfter('TraceImport', - function importClockSyncMarkers(task) { - importers.forEach(function(importer, index) { - task.subTask(Timing.wrapNamedFunction( - 'TraceImport', importer.importerName, - function runImportClockSyncMarkersOnOneImporter() { - progressMeter.update( - 'Importing clock sync markers ' + (index + 1) + ' of ' + - importers.length); - importer.importClockSyncMarkers(); - }), this); - }, this); - }, this); - - // Run the import. - lastTask = lastTask.timedAfter('TraceImport', function runImport(task) { - importers.forEach(function(importer, index) { - task.subTask(Timing.wrapNamedFunction( - 'TraceImport', importer.importerName, - function runImportEventsOnOneImporter() { - progressMeter.update( - 'Importing ' + (index + 1) + ' of ' + importers.length); - importer.importEvents(); - }), this); - }, this); - }, this); - - // Run the cusomizeModelCallback if needed. - if (this.importOptions_.customizeModelCallback) { - lastTask = lastTask.timedAfter('TraceImport', - function runCustomizeCallbacks(task) { - this.importOptions_.customizeModelCallback(this.model_); - }, this); - } - - // Import sample data. - lastTask = lastTask.timedAfter('TraceImport', - function importSampleData(task) { - importers.forEach(function(importer, index) { - progressMeter.update( - 'Importing sample data ' + (index + 1) + '/' + importers.length); - importer.importSampleData(); - }, this); - }, this); - - // Autoclose open slices and create subSlices. - lastTask = lastTask.timedAfter('TraceImport', function runAutoclosers() { - progressMeter.update('Autoclosing open slices...'); - this.model_.autoCloseOpenSlices(); - this.model_.createSubSlices(); - }, this); - - // Finalize import. - lastTask = lastTask.timedAfter('TraceImport', - function finalizeImport(task) { - importers.forEach(function(importer, index) { - progressMeter.update( - 'Finalizing import ' + (index + 1) + '/' + importers.length); - importer.finalizeImport(); - }, this); - }, this); - - // Run preinit. - lastTask = lastTask.timedAfter('TraceImport', function runPreinits() { - progressMeter.update('Initializing objects (step 1/2)...'); - this.model_.preInitializeObjects(); - }, this); - - // Prune empty containers. - if (this.importOptions_.pruneEmptyContainers) { - lastTask = lastTask.timedAfter('TraceImport', - function runPruneEmptyContainers() { - progressMeter.update('Pruning empty containers...'); - this.model_.pruneEmptyContainers(); - }, this); - } - - // Merge kernel and userland slices on each thread. - lastTask = lastTask.timedAfter('TraceImport', - function runMergeKernelWithuserland() { - progressMeter.update('Merging kernel with userland...'); - this.model_.mergeKernelWithUserland(); - }, this); - - // Create auditors - var auditors = []; - lastTask = lastTask.timedAfter('TraceImport', - function createAuditorsAndRunAnnotate() { - progressMeter.update('Adding arbitrary data to model...'); - auditors = this.importOptions_.auditorConstructors.map( - function(auditorConstructor) { - return new auditorConstructor(this.model_); - }, this); - auditors.forEach(function(auditor) { - auditor.runAnnotate(); - auditor.installUserFriendlyCategoryDriverIfNeeded(); - }); - }, this); - - lastTask = lastTask.timedAfter('TraceImport', - function computeWorldBounds() { - progressMeter.update('Computing final world bounds...'); - this.model_.computeWorldBounds(this.importOptions_.shiftWorldToZero); - }, this); - - // Build the flow event interval tree. - lastTask = lastTask.timedAfter('TraceImport', - function buildFlowEventIntervalTree() { - progressMeter.update('Building flow event map...'); - this.model_.buildFlowEventIntervalTree(); - }, this); - - // Join refs. - lastTask = lastTask.timedAfter('TraceImport', function joinRefs() { - progressMeter.update('Joining object refs...'); - this.model_.joinRefs(); - }, this); - - // Delete any undeleted objects. - lastTask = lastTask.timedAfter('TraceImport', - function cleanupUndeletedObjects() { - progressMeter.update('Cleaning up undeleted objects...'); - this.model_.cleanupUndeletedObjects(); - }, this); - - // Sort global and process memory dumps. - lastTask = lastTask.timedAfter('TraceImport', function sortMemoryDumps() { - progressMeter.update('Sorting memory dumps...'); - this.model_.sortMemoryDumps(); - }, this); - - // Finalize memory dump graphs. - lastTask = lastTask.timedAfter('TraceImport', - function finalizeMemoryGraphs() { - progressMeter.update('Finalizing memory dump graphs...'); - this.model_.finalizeMemoryGraphs(); - }, this); - - // Run initializers. - lastTask = lastTask.timedAfter('TraceImport', - function initializeObjects() { - progressMeter.update('Initializing objects (step 2/2)...'); - this.model_.initializeObjects(); - }, this); - - // Build event indices mapping from an event id to all flow events. - lastTask = lastTask.timedAfter('TraceImport', - function buildEventIndices() { - progressMeter.update('Building event indices...'); - this.model_.buildEventIndices(); - }, this); - - // Build the UserModel. - lastTask = lastTask.timedAfter('TraceImport', function buildUserModel() { - progressMeter.update('Building UserModel...'); - var userModelBuilder = new tr.importer.UserModelBuilder(this.model_); - userModelBuilder.buildUserModel(); - }, this); - - // Sort Expectations. - lastTask = lastTask.timedAfter('TraceImport', - function sortExpectations() { - progressMeter.update('Sorting user expectations...'); - this.model_.userModel.sortExpectations(); - }, this); - - // Run audits. - lastTask = lastTask.timedAfter('TraceImport', function runAudits() { - progressMeter.update('Running auditors...'); - auditors.forEach(function(auditor) { - auditor.runAudit(); - }); - }, this); - - lastTask = lastTask.timedAfter('TraceImport', function sortAlerts() { - progressMeter.update('Updating alerts...'); - this.model_.sortAlerts(); - }, this); - - lastTask = lastTask.timedAfter('TraceImport', - function lastUpdateBounds() { - progressMeter.update('Update bounds...'); - this.model_.updateBounds(); - }, this); - - lastTask = lastTask.timedAfter('TraceImport', - function addModelWarnings() { - progressMeter.update('Looking for warnings...'); - // Log an import warning if the clock is low resolution. - if (!this.model_.isTimeHighResolution) { - this.model_.importWarning({ - type: 'low_resolution_timer', - message: 'Trace time is low resolution, trace may be unusable.', - showToUser: true - }); - } - }, this); - - // Cleanup. - lastTask.after(function() { - this.importing_ = false; - }, this); - return importTask; - }, - - createImporter_: function(eventData) { - var importerConstructor = tr.importer.Importer.findImporterFor(eventData); - if (!importerConstructor) { - throw new Error('Couldn\'t create an importer for the provided ' + - 'eventData.'); - } - return new importerConstructor(this.model_, eventData); - }, - - hasEventDataDecoder_: function(importers) { - for (var i = 0; i < importers.length; ++i) { - if (!importers[i].isTraceDataContainer()) - return true; - } - - return false; - } - }; - - return { - ImportOptions: ImportOptions, - Import: Import - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/import_test.html b/chromium/third_party/catapult/tracing/tracing/importer/import_test.html deleted file mode 100644 index a6e11b73241..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/import_test.html +++ /dev/null @@ -1,216 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base64.html"> -<link rel="import" href="/tracing/core/test_utils.html"> -<link rel="import" href="/tracing/extras/importer/linux_perf/ftrace_importer.html"> -<link rel="import" href="/tracing/extras/importer/trace_event_importer.html"> -<link rel="import" href="/tracing/extras/importer/zip_importer.html"> -<link rel="import" href="/tracing/extras/importer/v8/v8_log_importer.html"> -<link rel="import" href="/tracing/model/model.html"> - -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var Base64 = tr.b.Base64; - - test('canImportEmpty', function() { - var m = tr.c.TestUtils.newModelWithEvents([]); - assert.isDefined(m.modelIndices); - m = new tr.Model(''); - }); - - test('canImportSubtraces', function() { - var systraceLines = [ - 'SurfaceFlinger-2 [001] ...1 1000.0: 0: B|1|taskA', - 'SurfaceFlinger-2 [001] ...1 2000.0: 0: E', - ' chrome-3 [001] ...1 2000.0: 0: trace_event_clock_sync: ' + - 'parent_ts=0' - ]; - var traceEvents = [ - {ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: { - my_object: {id_ref: '0x1000'} - }}, - {ts: 2000, pid: 1, tid: 3, ph: 'E', cat: 'c', name: 'taskB', args: {}} - ]; - - var combined = JSON.stringify({ - traceEvents: traceEvents, - systemTraceEvents: systraceLines.join('\n') - }); - - var m = tr.c.TestUtils.newModelWithEvents([combined]); - assert.equal(tr.b.dictionaryValues(m.processes).length, 1); - - var p1 = m.processes[1]; - assert.isDefined(p1); - - var t2 = p1.threads[2]; - var t3 = p1.threads[3]; - assert.isDefined(t2); - assert.isDefined(t3); - - assert.equal(1, 1, t2.sliceGroup.length); - assert.equal(t2.sliceGroup.slices[0].title, 'taskA'); - - assert.equal(t3.sliceGroup.length, 1); - assert.equal(t3.sliceGroup.slices[0].title, 'taskB'); - }); - - test('canImportCompressedSingleSubtrace', function() { - var compressedTrace = Base64.atob( - 'H4sIACKfFVUC/wsuLUpLTE51y8nMS08t0jVSUIg2MDCMV' + - 'dDT0zNUMDQwMNAzsFIAIqcaw5qSxOJsR65gfDqMEDpcATiC61ZbAAAA'); - var m = tr.c.TestUtils.newModelWithEvents([compressedTrace]); - assert.equal(1, tr.b.dictionaryValues(m.processes).length); - - var p1 = m.processes[1]; - assert.isDefined(p1); - - var t2 = p1.threads[2]; - assert.isDefined(t2); - - assert.equal(1, t2.sliceGroup.length, 1); - assert.equal('taskA', t2.sliceGroup.slices[0].title); - }); - - test('canImportSubtracesRecursively', function() { - var systraceLines = [ - 'SurfaceFlinger-2 [001] ...1 1000.0: 0: B|1|taskA', - 'SurfaceFlinger-2 [001] ...1 2000.0: 0: E', - ' chrome-3 [001] ...1 2000.0: 0: trace_event_clock_sync: ' + - 'parent_ts=0' - ]; - var outerTraceEvents = [ - {ts: 1000, pid: 1, tid: 3, ph: 'B', cat: 'c', name: 'taskB', args: { - my_object: {id_ref: '0x1000'} - }} - ]; - - var innerTraceEvents = [ - {ts: 2000, pid: 1, tid: 3, ph: 'E', cat: 'c', name: 'taskB', args: {}} - ]; - - var innerTrace = JSON.stringify({ - traceEvents: innerTraceEvents, - systemTraceEvents: systraceLines.join('\n') - }); - - var outerTrace = JSON.stringify({ - traceEvents: outerTraceEvents, - systemTraceEvents: innerTrace - }); - - var m = tr.c.TestUtils.newModelWithEvents([outerTrace]); - assert.equal(tr.b.dictionaryValues(m.processes).length, 1); - - var p1 = m.processes[1]; - assert.isDefined(p1); - - var t2 = p1.threads[2]; - var t3 = p1.threads[3]; - assert.isDefined(t2); - assert.isDefined(t3); - - assert.equal(1, 1, t2.sliceGroup.length); - assert.equal(t2.sliceGroup.slices[0].title, 'taskA'); - - assert.equal(t3.sliceGroup.length, 1); - assert.equal(t3.sliceGroup.slices[0].title, 'taskB'); - }); - - test('withImportFailure', function() { - assert.throw(function() { - tr.c.TestUtils.newModelWithEvents([malformed]); - }); - }); - - test('customizeCallback', function() { - var m = tr.c.TestUtils.newModelWithEvents([], { - shiftWorldToZero: false, - pruneContainers: false, - customizeModelCallback: function(m) { - var browserProcess = m.getOrCreateProcess(1); - var browserMain = browserProcess.getOrCreateThread(2); - browserMain.sliceGroup.beginSlice('cat', 'Task', 0); - browserMain.sliceGroup.beginSlice('cat', 'SubTask', 1); - browserMain.sliceGroup.endSlice(9); - browserMain.sliceGroup.endSlice(10); - browserMain.sliceGroup.beginSlice('cat', 'Task', 20); - browserMain.sliceGroup.endSlice(30); - } - }); - var t2 = m.processes[1].threads[2]; - assert.equal(t2.sliceGroup.length, 3); - assert.equal(t2.sliceGroup.topLevelSlices.length, 2); - }); - - test('sortsSamples', function() { - // The 184, 0 and 185 are the tick-times - // and irrespective of the order - // in which the lines appear in the trace, - // the samples should always be sorted by sampling time. - var m = tr.c.TestUtils.newModelWithEvents([ - 'tick,0x9a,184,0,0x0,5', - 'tick,0x9b,0,0,0x0,5', - 'tick,0x9c,185,0,0x0,5']); - assert.equal(m.samples[0].start, 0); - assert.equal(m.samples[1].start, 0.184); - assert.equal(m.samples[2].start, 0.185); - }); - - test('sortsGlobalMemoryDumps', function() { - var m = tr.c.TestUtils.newModelWithEvents([], { - pruneContainers: false, - customizeModelCallback: function(m) { - m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 1)); - m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 5)); - m.globalMemoryDumps.push(new tr.model.GlobalMemoryDump(m, 3)); - } - }); - assert.equal(m.globalMemoryDumps[0].start, 0); - assert.equal(m.globalMemoryDumps[1].start, 2); - assert.equal(m.globalMemoryDumps[2].start, 4); - }); - - test('finalizesProcessMemoryDumps', function() { - var p; - var m = tr.c.TestUtils.newModelWithEvents([], { - pruneContainers: false, - customizeModelCallback: function(m) { - p = m.getOrCreateProcess(1); - - var g = new tr.model.GlobalMemoryDump(m, -1); - m.globalMemoryDumps.push(g); - - var pmd1 = new tr.model.ProcessMemoryDump(g, p, 1); - p.memoryDumps.push(pmd1); - - var pmd2 = new tr.model.ProcessMemoryDump(g, p, 5); - p.memoryDumps.push(pmd2); - - var pmd3 = new tr.model.ProcessMemoryDump(g, p, 3); - p.memoryDumps.push(pmd3); - pmd3.vmRegions = []; - } - }); - - // Check the sort order. - assert.equal(p.memoryDumps[0].start, 2); - assert.equal(p.memoryDumps[1].start, 4); - assert.equal(p.memoryDumps[2].start, 6); - - // Check that the most recent VM regions are linked correctly. - assert.isUndefined(p.memoryDumps[0].mostRecentVmRegions); - assert.lengthOf(p.memoryDumps[1].mostRecentVmRegions, 0); - assert.strictEqual( - p.memoryDumps[1].mostRecentVmRegions, - p.memoryDumps[2].mostRecentVmRegions); - }); -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/importer.html b/chromium/third_party/catapult/tracing/tracing/importer/importer.html deleted file mode 100644 index b981c1be8bd..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/importer.html +++ /dev/null @@ -1,85 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2013 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/base.html"> -<link rel="import" href="/tracing/base/extension_registry.html"> -<script> -'use strict'; - -/** - * @fileoverview Base class for trace data importers. - */ -tr.exportTo('tr.importer', function() { - function Importer() { } - - Importer.prototype = { - __proto__: Object.prototype, - - get importerName() { - return 'Importer'; - }, - - /** - * Called by the Model to check whether the importer type stores the actual - * trace data or just holds it as container for further extraction. - */ - isTraceDataContainer: function() { - return false; - }, - - /** - * Called by the Model to extract one or more subtraces from the event data. - */ - extractSubtraces: function() { - return []; - }, - - /** - * Called to import clock sync markers into the Model. - */ - importClockSyncMarkers: function() { - }, - - /** - * Called to import events into the Model. - */ - importEvents: function() { - }, - - /** - * Called to import sample data into the Model. - */ - importSampleData: function() { - }, - - /** - * Called by the Model after all other importers have imported their - * events. - */ - finalizeImport: function() { - } - }; - - - var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE); - options.defaultMetadata = {}; - options.mandatoryBaseClass = Importer; - tr.b.decorateExtensionRegistry(Importer, options); - - Importer.findImporterFor = function(eventData) { - var typeInfo = Importer.findTypeInfoMatching(function(ti) { - return ti.constructor.canImport(eventData); - }); - if (typeInfo) - return typeInfo.constructor; - return undefined; - }; - - return { - Importer: Importer - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html b/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html deleted file mode 100644 index c3b655c00e6..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/proto_expectation.html +++ /dev/null @@ -1,165 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> -<link rel="import" href="/tracing/base/range_utils.html"> -<link rel="import" href="/tracing/core/auditor.html"> -<link rel="import" href="/tracing/model/event_info.html"> -<link rel="import" href="/tracing/model/user_model/animation_expectation.html"> -<link rel="import" href="/tracing/model/user_model/response_expectation.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - // This is an intermediate data format between InputLatencyAsyncSlices and - // Response and Animation IRs. - function ProtoExpectation(irType, name) { - this.irType = irType; - this.names = new Set(name ? [name] : undefined); - this.start = Infinity; - this.end = -Infinity; - this.associatedEvents = new tr.model.EventSet(); - this.isAnimationBegin = false; - } - - ProtoExpectation.RESPONSE_TYPE = 'r'; - ProtoExpectation.ANIMATION_TYPE = 'a'; - - // Explicitly ignore some input events to allow - // UserModelBuilder.checkAllInputEventsHandled() to determine which events - // were unintentionally ignored due to a bug. - ProtoExpectation.IGNORED_TYPE = 'ignored'; - - ProtoExpectation.prototype = { - get isValid() { - return this.end > this.start; - }, - - // Return true if any associatedEvent's typeName is in typeNames. - containsTypeNames: function(typeNames) { - return this.associatedEvents.some( - x => typeNames.indexOf(x.typeName) >= 0); - }, - - containsSliceTitle: function(title) { - return this.associatedEvents.some(x => title === x.title); - }, - - createInteractionRecord: function(model) { - if (!this.isValid) { - console.error('Invalid ProtoExpectation: ' + this.debug() + - ' File a bug with this trace!'); - return undefined; - } - - var initiatorTitles = []; - this.names.forEach(function(name) { - initiatorTitles.push(name); - }); - initiatorTitles = initiatorTitles.sort().join(','); - - var duration = this.end - this.start; - - var ir = undefined; - switch (this.irType) { - case ProtoExpectation.RESPONSE_TYPE: - ir = new tr.model.um.ResponseExpectation( - model, initiatorTitles, this.start, duration, - this.isAnimationBegin); - break; - case ProtoExpectation.ANIMATION_TYPE: - ir = new tr.model.um.AnimationExpectation( - model, initiatorTitles, this.start, duration); - break; - } - if (!ir) - return undefined; - - ir.sourceEvents.addEventSet(this.associatedEvents); - - function pushAssociatedEvents(event) { - ir.associatedEvents.push(event); - - // |event| is either an InputLatencyAsyncSlice (which collects all of - // its associated events transitively) or a CSS Animation (which doesn't - // have any associated events). So this does not need to recurse. - if (event.associatedEvents) - ir.associatedEvents.addEventSet(event.associatedEvents); - } - - this.associatedEvents.forEach(function(event) { - pushAssociatedEvents(event); - - // Old-style InputLatencyAsyncSlices have subSlices. - if (event.subSlices) - event.subSlices.forEach(pushAssociatedEvents); - }); - - return ir; - }, - - // Merge the other ProtoExpectation into this one. - // The irTypes need not match: ignored ProtoExpectations might be merged - // into overlapping ProtoExpectations, and Touch-only Animations are merged - // into Tap Responses. - merge: function(other) { - other.names.forEach(function(name) { this.names.add(name); }.bind(this)); - - // Don't use pushEvent(), which would lose special start, end. - this.associatedEvents.addEventSet(other.associatedEvents); - this.start = Math.min(this.start, other.start); - this.end = Math.max(this.end, other.end); - if (other.isAnimationBegin) - this.isAnimationBegin = true; - }, - - // Include |event| in this ProtoExpectation, expanding start/end to include - // it. - pushEvent: function(event) { - // Usually, this method will be called while iterating over a list of - // events sorted by start time, so this method won't usually change - // this.start. However, this will sometimes be called for - // ProtoExpectations created by previous handlers, in which case - // event.start could possibly be before this.start. - this.start = Math.min(this.start, event.start); - this.end = Math.max(this.end, event.end); - this.associatedEvents.push(event); - }, - - // Returns true if timestamp is contained in this ProtoExpectation. - containsTimestampInclusive: function(timestamp) { - return (this.start <= timestamp) && (timestamp <= this.end); - }, - - // Return true if the other event intersects this ProtoExpectation. - intersects: function(other) { - // http://stackoverflow.com/questions/325933 - return (other.start < this.end) && (other.end > this.start); - }, - - isNear: function(event, threshold) { - return (this.end + threshold) > event.start; - }, - - // Return a string describing this ProtoExpectation for debugging. - debug: function() { - var debugString = this.irType + '('; - debugString += parseInt(this.start) + ' '; - debugString += parseInt(this.end); - this.associatedEvents.forEach(function(event) { - debugString += ' ' + event.typeName; - }); - return debugString + ')'; - } - }; - - return { - ProtoExpectation: ProtoExpectation - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html b/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html deleted file mode 100644 index cff446e2419..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/simple_line_reader.html +++ /dev/null @@ -1,53 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2014 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<link rel="import" href="/tracing/base/base.html"> -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - /** - * @constructor - */ - function SimpleLineReader(text) { - this.lines_ = text.split('\n'); - this.curLine_ = 0; - - this.savedLines_ = undefined; - } - - SimpleLineReader.prototype = { - advanceToLineMatching: function(regex) { - for (; this.curLine_ < this.lines_.length; this.curLine_++) { - var line = this.lines_[this.curLine_]; - if (this.savedLines_ !== undefined) - this.savedLines_.push(line); - if (regex.test(line)) - return true; - } - return false; - }, - - get curLineNumber() { - return this.curLine_; - }, - - beginSavingLines: function() { - this.savedLines_ = []; - }, - - endSavingLinesAndGetResult: function() { - var tmp = this.savedLines_; - this.savedLines_ = undefined; - return tmp; - } - }; - - return { - SimpleLineReader: SimpleLineReader - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html b/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html deleted file mode 100644 index 18c080d4424..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/user_expectation_verifier.html +++ /dev/null @@ -1,77 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html"> -<link rel="import" href="/tracing/importer/user_model_builder.html"> - -<script> -'use strict'; -tr.exportTo('tr.importer', function() { - function compareEvents(x, y) { - if (x.start !== y.start) - return x.start - y.start; - return x.guid - y.guid; - } - - function UserExpectationVerifier() { - this.customizeModelCallback_ = undefined; - this.expectedIRs_ = undefined; - } - - UserExpectationVerifier.prototype = { - set customizeModelCallback(cmc) { - this.customizeModelCallback_ = cmc; - }, - - // |irs| must be sorted by start time. - set expectedIRs(irs) { - this.expectedIRs_ = irs; - }, - - verify: function() { - var model = tr.e.chrome.ChromeTestUtils.newChromeModel( - this.customizeModelCallback_); - - var failure = undefined; - try { - var i = 0; - assert.lengthOf(model.userModel.expectations, - this.expectedIRs_.length); - var actualUE_iterator = model.userModel.expectations[Symbol.iterator](); - for (var expectedIR of this.expectedIRs_) { - var actualUE = actualUE_iterator.next(); - assert.equal(false, actualUE.done); - var at = 'IRs[' + (i++) + '].'; - assert.equal(expectedIR.title, actualUE.value.title, at + 'title'); - if (expectedIR.name !== undefined) - assert.equal(expectedIR.name, actualUE.value.name, at + 'name'); - assert.equal(expectedIR.start, actualUE.value.start, at + 'start'); - assert.equal(expectedIR.end, actualUE.value.end, at + 'end'); - assert.equal(expectedIR.eventCount, - actualUE.value.associatedEvents.length, at + 'eventCount'); - if (actualUE instanceof tr.model.um.ResponseExpectation) { - assert.equal(expectedIR.isAnimationBegin || false, - actualUEs.isAnimationBegin, at + 'isAnimationBegin'); - } - } - } catch (caught) { - failure = caught; - } - - var debug = !tr.isHeadless && ( - location.search.split('&').indexOf('debug') >= 0); - if (!failure && !debug) - return; - - if (failure) - throw failure; - } - }; - - return {UserExpectationVerifier: UserExpectationVerifier}; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html deleted file mode 100644 index 2ee0e452bf7..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder.html +++ /dev/null @@ -1,231 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/base/base.html"> -<link rel="import" href="/tracing/base/range_utils.html"> -<link rel="import" href="/tracing/core/auditor.html"> -<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html"> -<link rel="import" href="/tracing/importer/find_input_expectations.html"> -<link rel="import" href="/tracing/importer/find_load_expectations.html"> -<link rel="import" href="/tracing/importer/find_startup_expectations.html"> -<link rel="import" href="/tracing/model/event_info.html"> -<link rel="import" href="/tracing/model/ir_coverage.html"> -<link rel="import" href="/tracing/model/user_model/idle_expectation.html"> - -<script> -'use strict'; - -tr.exportTo('tr.importer', function() { - var INSIGNIFICANT_MS = 1; - - function UserModelBuilder(model) { - this.model = model; - this.modelHelper = model.getOrCreateHelper( - tr.model.helpers.ChromeModelHelper); - }; - - UserModelBuilder.supportsModelHelper = function(modelHelper) { - return modelHelper.browserHelper !== undefined; - }; - - UserModelBuilder.prototype = { - buildUserModel: function() { - if (!this.modelHelper || !this.modelHelper.browserHelper) - return; - - var expectations = undefined; - try { - expectations = this.findUserExpectations(); - // There are not currently any known cases when this could throw. - } catch (error) { - this.model.importWarning({ - type: 'UserModelBuilder', - message: error, - showToUser: true - }); - return; - } - expectations.forEach(function(expectation) { - this.model.userModel.expectations.push(expectation); - }, this); - - // TODO(benjhayden) Find Gestures here. - }, - - findUserExpectations: function() { - var expectations = []; - expectations.push.apply(expectations, tr.importer.findStartupExpectations( - this.modelHelper)); - expectations.push.apply(expectations, tr.importer.findLoadExpectations( - this.modelHelper)); - expectations.push.apply(expectations, tr.importer.findInputExpectations( - this.modelHelper)); - // findIdleExpectations must be called last! - expectations.push.apply( - expectations, this.findIdleExpectations(expectations)); - this.collectUnassociatedEvents_(expectations); - return expectations; - }, - - // Find all unassociated top-level ThreadSlices. If they start during an - // Idle or Load IR, then add their entire hierarchy to that IR. - collectUnassociatedEvents_: function(rirs) { - var vacuumIRs = []; - rirs.forEach(function(ir) { - if (ir instanceof tr.model.um.IdleExpectation || - ir instanceof tr.model.um.LoadExpectation || - ir instanceof tr.model.um.StartupExpectation) - vacuumIRs.push(ir); - }); - if (vacuumIRs.length === 0) - return; - - var allAssociatedEvents = tr.model.getAssociatedEvents(rirs); - var unassociatedEvents = tr.model.getUnassociatedEvents( - this.model, allAssociatedEvents); - - unassociatedEvents.forEach(function(event) { - if (!(event instanceof tr.model.ThreadSlice)) - return; - - if (!event.isTopLevel) - return; - - for (var iri = 0; iri < vacuumIRs.length; ++iri) { - var ir = vacuumIRs[iri]; - - if ((event.start >= ir.start) && - (event.start < ir.end)) { - ir.associatedEvents.addEventSet(event.entireHierarchy); - return; - } - } - }); - }, - - // Fill in the empty space between IRs with IdleIRs. - findIdleExpectations: function(otherIRs) { - if (this.model.bounds.isEmpty) - return; - var emptyRanges = tr.b.findEmptyRangesBetweenRanges( - tr.b.convertEventsToRanges(otherIRs), - this.model.bounds); - var irs = []; - var model = this.model; - emptyRanges.forEach(function(range) { - // Ignore insignificantly tiny idle ranges. - if (range.max < (range.min + INSIGNIFICANT_MS)) - return; - irs.push(new tr.model.um.IdleExpectation( - model, range.min, range.max - range.min)); - }); - return irs; - } - }; - - function createCustomizeModelLinesFromModel(model) { - var modelLines = []; - modelLines.push(' audits.addEvent(model.browserMain,'); - modelLines.push(' {title: \'model start\', start: 0, end: 1});'); - - var typeNames = {}; - for (var typeName in tr.e.cc.INPUT_EVENT_TYPE_NAMES) { - typeNames[tr.e.cc.INPUT_EVENT_TYPE_NAMES[typeName]] = typeName; - } - - var modelEvents = new tr.model.EventSet(); - model.userModel.expectations.forEach(function(ir, index) { - modelEvents.addEventSet(ir.sourceEvents); - }); - modelEvents = modelEvents.toArray(); - modelEvents.sort(tr.importer.compareEvents); - - modelEvents.forEach(function(event) { - var startAndEnd = 'start: ' + parseInt(event.start) + ', ' + - 'end: ' + parseInt(event.end) + '});'; - if (event instanceof tr.e.cc.InputLatencyAsyncSlice) { - modelLines.push(' audits.addInputEvent(model, INPUT_TYPE.' + - typeNames[event.typeName] + ','); - } else if (event.title === 'RenderFrameImpl::didCommitProvisionalLoad') { - modelLines.push(' audits.addCommitLoadEvent(model,'); - } else if (event.title === - 'InputHandlerProxy::HandleGestureFling::started') { - modelLines.push(' audits.addFlingAnimationEvent(model,'); - } else if (event.title === tr.model.helpers.IMPL_RENDERING_STATS) { - modelLines.push(' audits.addFrameEvent(model,'); - } else if (event.title === tr.importer.CSS_ANIMATION_TITLE) { - modelLines.push(' audits.addEvent(model.rendererMain, {'); - modelLines.push(' title: \'Animation\', ' + startAndEnd); - return; - } else { - throw ('You must extend createCustomizeModelLinesFromModel()' + - 'to support this event:\n' + event.title + '\n'); - } - modelLines.push(' {' + startAndEnd); - }); - - modelLines.push(' audits.addEvent(model.browserMain,'); - modelLines.push(' {' + - 'title: \'model end\', ' + - 'start: ' + (parseInt(model.bounds.max) - 1) + ', ' + - 'end: ' + parseInt(model.bounds.max) + '});'); - return modelLines; - } - - function createExpectedIRLinesFromModel(model) { - var expectedLines = []; - var irCount = model.userModel.expectations.length; - model.userModel.expectations.forEach(function(ir, index) { - var irString = ' {'; - irString += 'title: \'' + ir.title + '\', '; - irString += 'start: ' + parseInt(ir.start) + ', '; - irString += 'end: ' + parseInt(ir.end) + ', '; - irString += 'eventCount: ' + ir.sourceEvents.length; - irString += '}'; - if (index < (irCount - 1)) - irString += ','; - expectedLines.push(irString); - }); - return expectedLines; - } - - function createIRFinderTestCaseStringFromModel(model) { - var filename = window.location.hash.substr(1); - var testName = filename.substr(filename.lastIndexOf('/') + 1); - testName = testName.substr(0, testName.indexOf('.')); - - // createCustomizeModelLinesFromModel() throws an error if there's an - // unsupported event. - try { - var testLines = []; - testLines.push(' /*'); - testLines.push(' This test was generated from'); - testLines.push(' ' + filename + ''); - testLines.push(' */'); - testLines.push(' test(\'' + testName + '\', function() {'); - testLines.push(' var verifier = new UserExpectationVerifier();'); - testLines.push(' verifier.customizeModelCallback = function(model) {'); - testLines.push.apply(testLines, - createCustomizeModelLinesFromModel(model)); - testLines.push(' };'); - testLines.push(' verifier.expectedIRs = ['); - testLines.push.apply(testLines, createExpectedIRLinesFromModel(model)); - testLines.push(' ];'); - testLines.push(' verifier.verify();'); - testLines.push(' });'); - return testLines.join('\n'); - } catch (error) { - return error; - } - } - - return { - UserModelBuilder: UserModelBuilder, - createIRFinderTestCaseStringFromModel: createIRFinderTestCaseStringFromModel - }; -}); -</script> diff --git a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html b/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html deleted file mode 100644 index 9938675bc42..00000000000 --- a/chromium/third_party/catapult/tracing/tracing/importer/user_model_builder_test.html +++ /dev/null @@ -1,883 +0,0 @@ -<!DOCTYPE html> -<!-- -Copyright (c) 2015 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html"> -<link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html"> -<link rel="import" href="/tracing/importer/user_expectation_verifier.html"> - -<script> -'use strict'; - -tr.b.unittest.testSuite(function() { - var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES; - var chrome_test_utils = tr.e.chrome.ChromeTestUtils; - var UserExpectationVerifier = tr.importer.UserExpectationVerifier; - - function addFrameEventForInput(model, event) { - var frame = chrome_test_utils.addFrameEvent(model, - {start: event.start, end: event.end, isTopLevel: true}); - model.flowEvents.push(tr.c.TestUtils.newFlowEventEx({ - id: event.id, - start: event.start, - end: event.end, - startSlice: frame, - endSlice: frame - })); - } - - test('empty', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - }; - verifier.expectedIRs = [ - ]; - verifier.verify(); - }); - - test('slowMouseMoveResponses', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 10}); - var mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 10, end: 20, id: '0x100'}); - addFrameEventForInput(model, mouseMove); - - mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 70, end: 80, id: '0x101'}); - addFrameEventForInput(model, mouseMove); - - mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 130, end: 140, id: '0x102'}); - addFrameEventForInput(model, mouseMove); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 10, eventCount: 0}, - {title: 'Mouse Response', start: 10, end: 20, eventCount: 4}, - {title: 'Idle', start: 20, end: 70, eventCount: 0}, - {title: 'Mouse Response', start: 70, end: 80, eventCount: 3}, - {title: 'Idle', start: 80, end: 130, eventCount: 0}, - {title: 'Mouse Response', start: 130, end: 140, eventCount: 3} - ]; - verifier.verify(); - }); - - test('mouseEventResponses', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - var mouseDown = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 50, id: '0x100'}); - addFrameEventForInput(model, mouseDown); - - var mouseUp = chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_UP, - {start: 50, end: 100, id: '0x101'}); - addFrameEventForInput(model, mouseUp); - - var mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 250, id: '0x102'}); - addFrameEventForInput(model, mouseMove); - }; - verifier.expectedIRs = [ - {title: 'Mouse Response', start: 0, end: 50, eventCount: 3}, - {title: 'Mouse Response', start: 50, end: 100, eventCount: 3}, - {title: 'Idle', start: 100, end: 200, eventCount: 0}, - {title: 'Mouse Response', start: 200, end: 250, eventCount: 3} - ]; - verifier.verify(); - }); - - test('mouseEventsIgnored', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 0, end: 50}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, - {start: 50, end: 100}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 100, eventCount: 0} - ]; - verifier.verify(); - }); - - test('unassociatedEvents', function() { - // Unassociated ThreadSlices that start during an Idle should be associated - // with it. Expect the Idle IR to have 2 associated events: both of the - // ThreadSlices in the model. - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - var start = tr.c.TestUtils.newSliceEx( - {title: 'model start', start: 0, end: 1, type: tr.model.ThreadSlice}); - start.isTopLevel = true; - model.browserMain.sliceGroup.pushSlice(start); - - var end = tr.c.TestUtils.newSliceEx( - {title: 'model end', start: 9, end: 10, type: tr.model.ThreadSlice}); - end.isTopLevel = true; - model.browserMain.sliceGroup.pushSlice(end); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 10, eventCount: 2} - ]; - verifier.verify(); - }); - - test('stillLoading', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - chrome_test_utils.addNavigationStartEvent(model, {start: 10}); - chrome_test_utils.addFrameEvent(model, {start: 19, end: 20}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 10, eventCount: 0}, - {title: 'Successful Load', start: 10, end: 20, eventCount: 0} - ]; - verifier.verify(); - }); - - test('overlappingIdleAndLoadCollectUnassociatedEvents', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - chrome_test_utils.addNavigationStartEvent(model, {start: 10}); - chrome_test_utils.addFirstContentfulPaintEvent(model, {start: 30}); - chrome_test_utils.addFrameEvent(model, {start: 35, end: 40}); - // 3 Idle events. - chrome_test_utils.addRenderingEvent(model, {start: 5, end: 15}); - chrome_test_utils.addRenderingEvent(model, {start: 11, end: 15}); - chrome_test_utils.addRenderingEvent(model, {start: 13, end: 15}); - // 1 Idle event. - chrome_test_utils.addRenderingEvent(model, {start: 35, end: 36}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 10, eventCount: 3}, - {title: 'Successful Load', start: 10, end: 30, eventCount: 0}, - {title: 'Idle', start: 30, end: 40, eventCount: 1} - ]; - verifier.verify(); - }); - - test('flingFlingFling', function() { - // This trace gave me so many different kinds of trouble that I'm just going - // to copy it straight in here, without trying to clarify it at all. - // measurmt-traces/mobile/cnet_fling_up_fling_down_motox_2013.json - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 919, end: 998}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, - {start: 919, end: 1001}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 919, end: 1001}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, - {start: 974, end: 1020}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 974, end: 1020}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 974, end: 1040}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 974, end: 1054}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 990, end: 1021}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 990, end: 1052}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1006, end: 1021}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1022, end: 1036}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1022, end: 1052}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1038, end: 1049}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1038, end: 1068}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 1046, end: 1050}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 1046, end: 1077}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 1432, end: 2238}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, - {start: 1432, end: 2241}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1516, end: 2605}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 1532, end: 2274}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1532, end: 2294}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1549, end: 2310}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 1627, end: 2275}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 1627, end: 2310}); - chrome_test_utils.addFrameEvent(model, {start: 2990, end: 3000}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 919, eventCount: 0}, - {title: 'Scroll,Tap,Touch Response', start: 919, end: 1054, - eventCount: 6, isAnimationBegin: true}, - {title: 'Scroll,Touch Animation', start: 1054, end: 1068, - eventCount: 8}, - {title: 'Fling Animation', start: 1054, end: 1432, - eventCount: 2}, - {title: 'Scroll,Touch Response', start: 1432, end: 2605, - eventCount: 5, isAnimationBegin: true}, - {title: 'Scroll Animation', start: 1549, end: 2310, - eventCount: 1}, - {title: 'Fling Animation', start: 2605, end: 3000, - eventCount: 1} - ]; - verifier.verify(); - }); - - test('keyboardEvents', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.KEY_DOWN_RAW, - {start: 0, end: 45}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.CHAR, - {start: 10, end: 50}); - }; - verifier.expectedIRs = [ - {title: 'Keyboard Response', start: 0, end: 50, eventCount: 2} - ]; - verifier.verify(); - }); - - test('mouseResponses', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.CLICK, - {start: 0, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.CONTEXT_MENU, - {start: 200, end: 300}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 400, end: 500}); - }; - verifier.expectedIRs = [ - {title: 'Mouse Response', start: 0, end: 100, eventCount: 1}, - {title: 'Idle', start: 100, end: 200, eventCount: 0}, - {title: 'Mouse Response', start: 200, end: 300, eventCount: 1}, - {title: 'Idle', start: 300, end: 400, eventCount: 0}, - {title: 'MouseWheel Response', start: 400, end: 500, - eventCount: 1} - ]; - verifier.verify(); - }); - - test('mouseWheelAnimation', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 0, end: 20}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 16, end: 36}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 55, end: 75}); - - // This threshold uses both events' start times, not end...start. - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 100, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 141, end: 191}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_WHEEL, - {start: 182, end: 200}); - }; - verifier.expectedIRs = [ - {title: 'MouseWheel Response', start: 0, end: 20, eventCount: 1}, - {title: 'MouseWheel Animation', start: 20, end: 75, - eventCount: 2}, - {title: 'Idle', start: 75, end: 100, eventCount: 0}, - {title: 'MouseWheel Response', start: 100, end: 150, - eventCount: 1}, - {title: 'MouseWheel Response', start: 141, end: 191, - eventCount: 1}, - {title: 'MouseWheel Response', start: 182, end: 200, - eventCount: 1} - ]; - verifier.verify(); - }); - - test('mouseDownUpResponse', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_DOWN, - {start: 0, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_UP, - {start: 200, end: 210}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 200, eventCount: 0}, - {title: 'Mouse Response', start: 200, end: 210, eventCount: 2} - ]; - verifier.verify(); - }); - - test('ignoreLoneMouseMoves', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.MOUSE_MOVE, - {start: 0, end: 100}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 100, eventCount: 0} - ]; - verifier.verify(); - }); - - test('mouseDrags', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_DOWN, {start: 0, end: 100}); - var mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 200, end: 215}); - addFrameEventForInput(model, mouseMove); - mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 210, end: 220}); - addFrameEventForInput(model, mouseMove); - mouseMove = chrome_test_utils.addInputEvent( - model, INPUT_TYPE.MOUSE_MOVE, {start: 221, end: 240}); - addFrameEventForInput(model, mouseMove); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 200, eventCount: 0}, - {title: 'Mouse Response', start: 200, end: 215, eventCount: 4}, - {title: 'Mouse Animation', start: 215, end: 240, eventCount: 6} - ]; - verifier.verify(); - }); - - test('twoScrollsNoFling', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 0, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 20, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 40, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 60, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 70, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_END, - {start: 80, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 300, end: 400}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 320, end: 400}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 330, end: 450}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 340, end: 450}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 350, end: 500}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_END, - {start: 360, end: 500}); - }; - verifier.expectedIRs = [ - {title: 'Scroll Response', start: 0, end: 100, eventCount: 2, - isAnimationBegin: true}, - {title: 'Scroll Animation', start: 100, end: 150, eventCount: 4}, - {title: 'Idle', start: 150, end: 300, eventCount: 0}, - {title: 'Scroll Response', start: 300, end: 400, eventCount: 2, - isAnimationBegin: true}, - {title: 'Scroll Animation', start: 400, end: 500, eventCount: 4} - ]; - verifier.verify(); - }); - - test('cssAnimations', function() { - // CSS Animations happen on the renderer process, not the browser process. - // They are merged if they overlap. - // They are merged with other kinds of animations. - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addEvent(model.rendererMain, { - title: 'Animation', start: 0, end: 100, isTopLevel: true}); - chrome_test_utils.addFrameEvent(model, {start: 10, end: 20}); - chrome_test_utils.addEvent(model.rendererMain, { - title: 'Animation', start: 131, end: 200, isTopLevel: true}); - chrome_test_utils.addFrameEvent(model, {start: 150, end: 160}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 150, end: 180}); - chrome_test_utils.addFrameEvent(model, {start: 290, end: 300}); - }; - verifier.expectedIRs = [ - {title: 'CSS Animation', start: 0, end: 200, eventCount: 4}, - {title: 'Fling Animation', start: 150, end: 300, eventCount: 1} - ]; - verifier.verify(); - }); - - test('cssAnimationStates', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - // If a top-level Animation async slice does not have state-change instant - // subSlices, then assume that the animation was running throughout the - // async slice. - chrome_test_utils.addEvent(model.rendererMain, { - title: 'Animation', start: 181, end: 250, isTopLevel: true}); - chrome_test_utils.addFrameEvent(model, {start: 200, end: 240}); - - // Animation ranges should be merged if there is less than 32ms dead time - // between them. - - // If a top-level Animation async slice has state-change instant events, - // then run a state machine to find the time ranges when the animation was - // actually running. - - // This animation was running from 10-40 and 50-60. - var animationA = tr.c.TestUtils.newAsyncSliceEx( - {title: 'Animation', start: 50, end: 500, isTopLevel: true}); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 71, args: {state: 'running'}})); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 104, args: {state: 'pending'}})); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 137, args: {state: 'running'}})); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 150, args: {state: 'paused'}})); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 281, args: {state: 'running'}})); - animationA.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 350, args: {state: 'idle'}})); - model.rendererMain.asyncSliceGroup.push(animationA); - chrome_test_utils.addFrameEvent(model, {start: 80, end: 90}); - chrome_test_utils.addFrameEvent(model, {start: 290, end: 300}); - - // An animation without a frame event isn't really an animation. - chrome_test_utils.addEvent(model.rendererMain, { - title: 'Animation', start: 350, end: 382, isTopLevel: true}); - - // This animation was running from model.bounds.min-50 and - // 70-model.bounds.max. - var animationB = tr.c.TestUtils.newAsyncSliceEx( - {title: 'Animation', start: 0, end: 500, isTopLevel: true}); - animationB.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 40, args: {state: 'finished'}})); - animationB.subSlices.push(tr.c.TestUtils.newInstantEvent( - {title: 'Animation', start: 382, args: {state: 'running'}})); - model.rendererMain.asyncSliceGroup.push(animationB); - chrome_test_utils.addFrameEvent(model, {start: 10, end: 20}); - chrome_test_utils.addFrameEvent(model, {start: 390, end: 400}); - }; - verifier.expectedIRs = [ - {title: 'CSS Animation', start: 0, end: 350, eventCount: 15}, - {title: 'Idle', start: 350, end: 382, eventCount: 0}, - {title: 'CSS Animation', start: 382, end: 500, eventCount: 4}, - ]; - verifier.verify(); - }); - - test('flingThatIsntstopped', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 32, end: 100}); - chrome_test_utils.addFlingAnimationEvent(model, {start: 38, end: 200}); - chrome_test_utils.addFrameEvent(model, {start: 290, end: 300}); - }; - verifier.expectedIRs = [ - {title: 'Fling Animation', start: 32, end: 200, eventCount: 2}, - {title: 'Idle', start: 200, end: 300, eventCount: 0} - ]; - verifier.verify(); - }); - - test('flingThatIsStopped', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 32, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, - {start: 105, end: 150}); - }; - verifier.expectedIRs = [ - {title: 'Fling Animation', start: 32, end: 105, eventCount: 2}, - {title: 'Idle', start: 105, end: 150, eventCount: 0} - ]; - verifier.verify(); - }); - - test('flingFling', function() { - // measurmt-traces/mobile/facebook_obama_scroll_dialog_box.html - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 0, end: 30}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 100, end: 130}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, - {start: 100, end: 130}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 110, end: 140}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 170, end: 180}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 200, end: 210}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 200, end: 220}); - chrome_test_utils.addFrameEvent(model, {start: 230, end: 240}); - }; - verifier.expectedIRs = [ - {title: 'Fling Animation', start: 0, end: 100, eventCount: 2}, - {title: 'Touch Response', start: 100, end: 140, eventCount: 2, - isAnimationBegin: true}, - {title: 'Touch Animation', start: 140, end: 210, eventCount: 2}, - {title: 'Fling Animation', start: 200, end: 240, eventCount: 1} - ]; - verifier.verify(); - }); - - test('load', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addNavigationStartEvent(model, {start: 0}); - chrome_test_utils.addFirstContentfulPaintEvent(model, {start: 20}); - }; - verifier.expectedIRs = [ - {title: 'Successful Load', start: 0, end: 20, eventCount: 0} - ]; - verifier.verify(); - }); - - test('loadStartup', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addRenderingEvent(model, {start: 2, end: 3}); - chrome_test_utils.addCreateThreadsEvent(model, {start: 5, end: 10}); - // Throw an second one in there, just to try to confuse the algo. - chrome_test_utils.addCreateThreadsEvent(model, {start: 25, end: 30}); - chrome_test_utils.addFrameEvent(model, {start: 11, end: 20}); - }; - verifier.expectedIRs = [ - {title: 'Startup', start: 2, end: 20, eventCount: 2}, - {title: 'Idle', start: 20, end: 30, eventCount: 0} - ]; - verifier.verify(); - }); - - test('totalIdle', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 10, eventCount: 0} - ]; - verifier.verify(); - }); - - test('multipleIdles', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 1}); - chrome_test_utils.addNavigationStartEvent(model, {start: 1}); - chrome_test_utils.addFirstContentfulPaintEvent(model, {start: 4}); - chrome_test_utils.addFrameEvent(model, {start: 12, end: 13}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 1, eventCount: 0}, - {title: 'Successful Load', start: 1, end: 4, eventCount: 0}, - {title: 'Idle', start: 4, end: 13, eventCount: 0} - ]; - verifier.verify(); - }); - - test('touchStartTouchEndTap', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 200, end: 210}); - }; - verifier.expectedIRs = [ - {title: 'Touch Response', start: 0, end: 210, eventCount: 2, - isAnimationBegin: true} - ]; - verifier.verify(); - }); - - test('touchMoveResponseAnimation', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 50, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 70, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 200, end: 300}); - }; - verifier.expectedIRs = [ - {title: 'Touch Response', start: 0, end: 100, eventCount: 2, - isAnimationBegin: true}, - {title: 'Touch Animation', start: 100, end: 300, eventCount: 2} - ]; - verifier.verify(); - }); - - test('tapEvents', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP, - {start: 0, end: 50}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 300, end: 310}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP, - {start: 320, end: 350}); - }; - verifier.expectedIRs = [ - {title: 'Tap Response', start: 0, end: 50, eventCount: 1}, - {title: 'Idle', start: 50, end: 300, eventCount: 0}, - {title: 'Tap Response', start: 300, end: 350, eventCount: 2} - ]; - verifier.verify(); - }); - - test('tapAndTapCancelResponses', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 0, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, - {start: 300, end: 350}); - }; - verifier.expectedIRs = [ - {title: 'Tap Response', start: 0, end: 100, eventCount: 1}, - {title: 'Idle', start: 100, end: 300, eventCount: 0}, - {title: 'Tap Response', start: 300, end: 350, eventCount: 1} - ]; - verifier.verify(); - }); - - test('tapCancelResponse', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 0, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, - {start: 150, end: 200}); - }; - verifier.expectedIRs = [ - {title: 'Tap Response', start: 0, end: 200, eventCount: 2} - ]; - verifier.verify(); - }); - - test('pinchResponseAnimation', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, - {start: 100, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 130, end: 160}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 140, end: 200}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 150, end: 205}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 210, end: 220}); - // pause > 200ms - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 421, end: 470}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_END, - {start: 460, end: 500}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 100, eventCount: 0}, - {title: 'Pinch Response', start: 100, end: 160, eventCount: 2, - isAnimationBegin: true}, - {title: 'Pinch Animation', start: 160, end: 220, eventCount: 3}, - {title: 'Idle', start: 220, end: 421, eventCount: 0}, - {title: 'Pinch Animation', start: 421, end: 500, eventCount: 2} - ]; - verifier.verify(); - }); - - test('tapThenScroll', function() { - // measurmt-traces/mobile/google_io_instrument_strumming.json - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 0, end: 20}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 40, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 50, end: 120}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 80, end: 150}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 180, end: 200}); - }; - verifier.expectedIRs = [ - {title: 'Touch Response', start: 0, end: 100, eventCount: 2, - isAnimationBegin: true}, - {title: 'Touch Response', start: 50, end: 150, eventCount: 2, - isAnimationBegin: true}, - {title: 'Touch Animation', start: 150, end: 200, eventCount: 1} - ]; - verifier.verify(); - }); - - test('pinchFlingTapTouchEventsOverlap', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addFrameEvent(model, {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 20, end: 50}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 20, end: 30}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_CANCEL, - {start: 20, end: 50}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 60, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 60, end: 110}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_BEGIN, - {start: 60, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, - {start: 65, end: 75}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 70, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.PINCH_UPDATE, - {start: 70, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 75, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 80, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 85, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 75, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 150, end: 200}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 150, end: 200}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 180, end: 210}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 190, end: 210}); - chrome_test_utils.addFrameEvent(model, {start: 215, end: 220}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 20, eventCount: 0}, - {title: 'Pinch,Scroll,Tap,Touch Response', start: 20, end: 110, - eventCount: 9, isAnimationBegin: true}, - {title: 'Scroll,Touch Animation', start: 110, end: 210, - eventCount: 6}, - {title: 'Fling Animation', start: 180, end: 220, eventCount: 1} - ]; - verifier.verify(); - }); - - test('scrollThenFling', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 0, end: 40}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 50, end: 100}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 80, end: 100}); - chrome_test_utils.addFrameEvent(model, {start: 190, end: 200}); - }; - verifier.expectedIRs = [ - {title: 'Scroll Animation', start: 0, end: 100, eventCount: 2}, - {title: 'Fling Animation', start: 80, end: 200, eventCount: 1} - ]; - verifier.verify(); - }); - - /* - This test was generated from - /test_data/measurmt-traces/mobile/fling_HN_to_rest.json - */ - test('flingHNToRest', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addEvent(model.browserMain, - {title: 'model start', start: 0, end: 1}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_START, - {start: 1274, end: 1297}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_DOWN, - {start: 1274, end: 1305}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1343, end: 1350}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1359, end: 1366}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP_CANCEL, - {start: 1359, end: 1366}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_BEGIN, - {start: 1359, end: 1367}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1359, end: 1387}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1375, end: 1385}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1375, end: 1416}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1389, end: 1404}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1389, end: 1429}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1405, end: 1418}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1405, end: 1449}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 1419, end: 1432}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.SCROLL_UPDATE, - {start: 1419, end: 1474}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_END, - {start: 1427, end: 1435}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.FLING_START, - {start: 1427, end: 1474}); - chrome_test_utils.addFlingAnimationEvent(model, {start: 1440, end: 2300}); - chrome_test_utils.addEvent(model.browserMain, - {title: 'model end', start: 3184, end: 3185}); - }; - verifier.expectedIRs = [ - {title: 'Idle', start: 0, end: 1274, eventCount: 0}, - {title: 'Scroll,Tap,Touch Response', start: 1274, end: 1387, - eventCount: 6, isAnimationBegin: true}, - {title: 'Scroll,Touch Animation', start: 1387, end: 1474, - eventCount: 10}, - {title: 'Fling Animation', start: 1427, end: 2300, - eventCount: 2}, - {title: 'Idle', start: 2300, end: 3185, eventCount: 0} - ]; - verifier.verify(); - }); - - test('TapResponseOverlappingTouchAnimation', function() { - var verifier = new UserExpectationVerifier(); - verifier.customizeModelCallback = function(model) { - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 0, end: 10}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 5, end: 15}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TOUCH_MOVE, - {start: 10, end: 20}); - chrome_test_utils.addInputEvent(model, INPUT_TYPE.TAP, - {start: 15, end: 100}); - }; - verifier.expectedIRs = [ - {title: 'Tap,Touch Response', start: 0, end: 100, - eventCount: 4} - ]; - verifier.verify(); - }); -}); -</script> |