1// Copyright (C) 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {dingus} from 'dingusjs';
16import {utf8Encode} from '../../base/string_utils';
17import {EnableTracingRequest, TraceConfig} from './protos';
18import {AdbStream, MockAdb, MockAdbStream} from './adb_interfaces';
19import {AdbConsumerPort} from './adb_shell_controller';
20import {Consumer} from './record_controller_interfaces';
21import {createEmptyState} from './empty_state';
22
23function generateMockConsumer(): Consumer {
24  return {
25    onConsumerPortResponse: jest.fn(),
26    onError: jest.fn(),
27    onStatus: jest.fn(),
28  };
29}
30const mainCallback = generateMockConsumer();
31const adbMock = new MockAdb();
32const adbController = new AdbConsumerPort(
33  adbMock,
34  mainCallback,
35  createEmptyState(),
36);
37const mockIntArray = new Uint8Array();
38
39const enableTracingRequest = new EnableTracingRequest();
40enableTracingRequest.traceConfig = new TraceConfig();
41const enableTracingRequestProto =
42  EnableTracingRequest.encode(enableTracingRequest).finish();
43
44test('handleCommand', async () => {
45  adbController.findDevice = () => {
46    return Promise.resolve(dingus<USBDevice>());
47  };
48
49  const enableTracing = jest.fn();
50  adbController.enableTracing = enableTracing;
51  await adbController.invoke('EnableTracing', mockIntArray);
52  expect(enableTracing).toHaveBeenCalledTimes(1);
53
54  const readBuffers = jest.fn();
55  adbController.readBuffers = readBuffers;
56  adbController.invoke('ReadBuffers', mockIntArray);
57  expect(readBuffers).toHaveBeenCalledTimes(1);
58
59  const sendErrorMessage = jest.fn();
60  adbController.sendErrorMessage = sendErrorMessage;
61  adbController.invoke('unknown', mockIntArray);
62  expect(sendErrorMessage).toBeCalledWith('Method not recognized: unknown');
63});
64
65test('enableTracing', async () => {
66  const mainCallback = generateMockConsumer();
67  const adbMock = new MockAdb();
68  const adbController = new AdbConsumerPort(
69    adbMock,
70    mainCallback,
71    createEmptyState(),
72  );
73
74  adbController.sendErrorMessage = jest
75    .fn()
76    .mockImplementation((s) => console.error(s));
77
78  const findDevice = jest.fn().mockImplementation(() => {
79    return Promise.resolve({} as unknown as USBDevice);
80  });
81  adbController.findDevice = findDevice;
82
83  const connectToDevice = jest
84    .fn()
85    .mockImplementation((_: USBDevice) => Promise.resolve());
86  adbMock.connect = connectToDevice;
87
88  const stream: AdbStream = new MockAdbStream();
89  const adbShell = jest
90    .fn()
91    .mockImplementation((_: string) => Promise.resolve(stream));
92  adbMock.shell = adbShell;
93
94  const sendMessage = jest.fn();
95  adbController.sendMessage = sendMessage;
96
97  adbController.generateStartTracingCommand = (_) => 'CMD';
98
99  await adbController.enableTracing(enableTracingRequestProto);
100  expect(adbShell).toBeCalledWith('CMD');
101  expect(sendMessage).toHaveBeenCalledTimes(0);
102
103  stream.onData(utf8Encode('starting tracing Wrote 123 bytes'));
104  stream.onClose();
105
106  expect(adbController.sendErrorMessage).toHaveBeenCalledTimes(0);
107  expect(sendMessage).toBeCalledWith({type: 'EnableTracingResponse'});
108});
109
110test('generateStartTracing', () => {
111  adbController.traceDestFile = 'DEST';
112  const testArray = new Uint8Array(1);
113  testArray[0] = 65;
114  const generatedCmd = adbController.generateStartTracingCommand(testArray);
115  expect(generatedCmd).toBe(
116    `echo '${btoa('A')}' | base64 -d | perfetto -c - -o DEST`,
117  );
118});
119
120test('tracingEndedSuccessfully', () => {
121  expect(
122    adbController.tracingEndedSuccessfully(
123      'Connected to the Perfetto traced service, starting tracing for 10000 ms\nWrote 564 bytes into /data/misc/perfetto-traces/trace',
124    ),
125  ).toBe(true);
126  expect(
127    adbController.tracingEndedSuccessfully(
128      'Connected to the Perfetto traced service, starting tracing for 10000 ms',
129    ),
130  ).toBe(false);
131  expect(
132    adbController.tracingEndedSuccessfully(
133      'Connected to the Perfetto traced service, starting tracing for 0 ms',
134    ),
135  ).toBe(false);
136});
137