| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import {assert} from 'chai'; |
| import sinon from 'sinon'; |
| |
| import type * as Protocol from '../../generated/protocol.js'; |
| import type * as Trace from '../../models/trace/trace.js'; |
| import {createTarget, describeWithEnvironment} from '../../testing/EnvironmentHelpers.js'; |
| import {MockCDPConnection} from '../../testing/MockCDPConnection.js'; |
| import {makeInstantEvent} from '../../testing/TraceHelpers.js'; |
| |
| import * as Tracing from './tracing.js'; |
| |
| class FakeClient implements Tracing.TracingManager.TracingManagerClient { |
| traceEventsCollected(_events: Trace.Types.Events.Event[]): void { |
| } |
| tracingComplete(): void { |
| } |
| tracingBufferUsage(_usage: number): void { |
| } |
| eventsRetrievalProgress(_progress: number): void { |
| } |
| } |
| |
| const fakeEvents = [ |
| makeInstantEvent('test-event-1', 1), |
| makeInstantEvent('test-event-2', 2), |
| ]; |
| |
| describeWithEnvironment('TracingManager', () => { |
| let connection: MockCDPConnection; |
| let lastStartRequest: Protocol.Tracing.StartRequest|null = null; |
| beforeEach(() => { |
| lastStartRequest = null; |
| connection = new MockCDPConnection(); |
| connection.setSuccessHandler('Tracing.start', request => { |
| lastStartRequest = request ?? {}; |
| return {}; |
| }); |
| connection.setSuccessHandler('Tracing.end', () => { |
| return {}; |
| }); |
| }); |
| |
| it('sends bufferUsage to the client', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| const bufferUsageSpy = sinon.spy(client, 'tracingBufferUsage'); |
| |
| await manager.start(client, 'devtools-timeline'); |
| manager.bufferUsage(10); |
| sinon.assert.calledWith(bufferUsageSpy, 10); |
| }); |
| |
| it('sends events to the client when they are collected and updates the client with progress', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| const eventsRetrievalProgressSpy = sinon.spy(client, 'eventsRetrievalProgress'); |
| const eventsCollectedSpy = sinon.spy(client, 'traceEventsCollected'); |
| |
| await manager.start(client, 'devtools-timeline'); |
| manager.bufferUsage(0); |
| |
| manager.eventsCollected(fakeEvents); |
| sinon.assert.calledWith(eventsCollectedSpy, fakeEvents); |
| assert.approximately(0.15, eventsRetrievalProgressSpy.args[0][0], 0.01); |
| }); |
| |
| it('notifies the client when tracing is complete', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| const tracingCompleteSpy = sinon.spy(client, 'tracingComplete'); |
| await manager.start(client, 'devtools-timeline'); |
| manager.bufferUsage(0); |
| manager.eventsCollected(fakeEvents); |
| manager.tracingComplete(); |
| sinon.assert.calledOnce(tracingCompleteSpy); |
| }); |
| |
| it('errors if tracing is started twice', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| await manager.start(client, 'devtools-timeline'); |
| // The assert.throws() helper does not work with async/await, hence the manual try catch |
| let didThrow = false; |
| try { |
| await manager.start(client, 'devtools-timeline'); |
| } catch (error) { |
| didThrow = true; |
| assert.strictEqual(error.message, 'Tracing is already started'); |
| } |
| assert.isTrue(didThrow, 'Test did not throw an error as expected.'); |
| }); |
| |
| it('errors if you try to stop when tracing is not active', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| assert.throws(() => { |
| manager.stop(); |
| }, /Tracing is not started/); |
| }); |
| |
| it('does not forward screenshot params by default', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| await manager.start(client, 'devtools-timeline'); |
| assert.isNotNull(lastStartRequest); |
| assert.isUndefined(lastStartRequest?.screenshotMaxSize); |
| assert.isUndefined(lastStartRequest?.screenshotMaxCount); |
| }); |
| |
| it('forwards screenshot params when provided', async () => { |
| const target = createTarget({connection}); |
| const manager = new Tracing.TracingManager.TracingManager(target); |
| const client = new FakeClient(); |
| await manager.start(client, 'devtools-timeline', {screenshotMaxSize: 250, screenshotMaxCount: 1800}); |
| assert.isNotNull(lastStartRequest); |
| assert.strictEqual(lastStartRequest?.screenshotMaxSize, 250); |
| assert.strictEqual(lastStartRequest?.screenshotMaxCount, 1800); |
| }); |
| }); |