• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 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 {test, Page, Locator} from '@playwright/test';
16import {PerfettoTestHelper} from './perfetto_ui_test_helper';
17
18test.describe.configure({mode: 'parallel'});
19
20let pth: PerfettoTestHelper;
21let page: Page;
22
23async function clickTableHeader(headerName: string | RegExp) {
24  await page
25    .locator('.pf-content tr.header a.pf-anchor', {hasText: headerName})
26    .click();
27}
28
29function getTableCells(text?: string | RegExp): Locator {
30  return page.locator(
31    '.pf-details-shell .generic-table tr:not(.header) a.pf-anchor',
32    {
33      hasText: text,
34    },
35  );
36}
37
38async function clickFirstTableCell(text: string | RegExp) {
39  await getTableCells(text).nth(0).click();
40}
41
42test.beforeEach(async ({browser}, _testInfo) => {
43  page = await browser.newPage();
44  pth = new PerfettoTestHelper(page);
45});
46
47test('slices with same name', async () => {
48  await pth.openTraceFile('chrome_scroll_without_vsync.pftrace');
49
50  const sliceName = 'LatencyInfo.Flow';
51  await pth.searchSlice(sliceName);
52  await page
53    .locator('.pf-details-shell a.pf-anchor', {hasText: sliceName})
54    .click();
55  await pth.clickMenuItem('Slices with the same name');
56  await clickTableHeader(/^id/);
57  await pth.clickMenuItem('Sort: lowest first');
58  await pth.waitForIdleAndScreenshot(`slices-with-same-name.png`);
59});
60
61test('Table interactions', async () => {
62  await pth.openTraceFile('chrome_scroll_without_vsync.pftrace');
63
64  // Show the slice table via command.
65  await pth.runCommand('perfetto.ShowTable.slice');
66  // Sort the table by id for consistent ordering.
67  await clickTableHeader(/^id/);
68  await pth.clickMenuItem('Sort: lowest first');
69  await pth.waitForIdleAndScreenshot(`slices-table.png`);
70
71  // Hide `category` column.
72  await clickTableHeader('category');
73  await pth.clickMenuItem('Hide');
74  await pth.waitForIdleAndScreenshot(`slices-table-hide-column.png`);
75
76  // Sort the table by dur in descending order. Note that we must explicitly exclude
77  // the "thread_dur" column, as it also contains "dur" in its name.
78  clickTableHeader(/^dur/);
79  await pth.clickMenuItem('Sort: highest first');
80  await pth.waitForIdleAndScreenshot(`slices-table-sorted.png`);
81
82  // Filter out all "EventLatency" slices.
83  clickFirstTableCell('EventLatency');
84  await pth.clickMenuItem('Add filter');
85  await pth.clickMenuItem('not equals');
86  await pth.waitForIdleAndScreenshot(`slices-table-filter1.png`);
87
88  // Filter to thread-only slices by clicking on the second NULL value.
89  await getTableCells('NULL').nth(1).click();
90  await pth.clickMenuItem('Add filter');
91  await pth.clickMenuItem('is not null');
92  await pth.waitForIdleAndScreenshot(`slices-table-filter2.png`);
93
94  // Filter to LatencyInfo.Flow events.
95  clickFirstTableCell('LatencyInfo.Flow');
96  await pth.clickMenuItem('Add filter');
97  await pth.clickMenuItem(/^equals/);
98  await pth.waitForIdleAndScreenshot(`slices-table-filter3.png`);
99
100  // Add argument.
101  await clickTableHeader(/^name/);
102  await pth.clickMenuItem('Add column');
103  await pth.clickMenuItem('arg_set_id');
104  await pth.clickMenuItem('chrome_latency_info.trace_id');
105  await pth.waitForIdleAndScreenshot(`slices-table-add-argument.png`);
106
107  // Sort by argument.
108  await clickTableHeader('chrome_latency_info.trace_id');
109  await pth.clickMenuItem('Sort: highest first');
110  await pth.waitForIdleAndScreenshot(`slices-table-sort-by-argument.png`);
111
112  // Sort by argument.
113  await clickFirstTableCell('3390');
114  await pth.clickMenuItem('Add filter');
115  await pth.clickMenuItem('not equals');
116  await pth.waitForIdleAndScreenshot(`slices-table-filter-by-argument.png`);
117});
118
119//
120// These tests check that the "go to" functionality for ID columns of the key tables
121// (slice, sched, thread_state, process and thread) —- for example, clicking on a
122// slice id column should update the selection and focus the relevant slice.
123//
124
125test('Go to slice', async () => {
126  await pth.openTraceFile('chrome_scroll_without_vsync.pftrace');
127
128  // Show the slice table via command.
129  await pth.runCommand('perfetto.ShowTable.slice');
130  // Sort the table by id for consistent ordering.
131  await clickTableHeader(/^id/);
132  await pth.clickMenuItem('Sort: lowest first');
133  await pth.waitForIdleAndScreenshot(`open-table.png`);
134
135  // Sort the table by dur in descending order. Note that we must explicitly exclude
136  // the "thread_dur" column, as it also contains "dur" in its name.
137  await clickTableHeader(/^dur/);
138  await pth.clickMenuItem('Sort: highest first');
139  await pth.waitForIdleAndScreenshot(`sorted.png`);
140
141  // Go to the first slice.
142  await getTableCells().nth(0).click();
143  await pth.waitForIdleAndScreenshot(`go-to.png`);
144
145  // Go to current selection tab.
146  await pth.switchToTab('Current Selection');
147  await pth.waitForIdleAndScreenshot(`current-selection.png`);
148});
149
150test('Go to thread_state', async () => {
151  // Open Android trace with kernel scheduling data.
152  await pth.openTraceFile('api34_startup_cold.perfetto-trace');
153
154  // Show the slice table via command.
155  await pth.runCommand('perfetto.ShowTable.thread_state');
156  // Sort the table by id for consistent ordering.
157  await clickTableHeader(/^id/);
158  await pth.clickMenuItem('Sort: lowest first');
159  await pth.waitForIdleAndScreenshot(`open-table.png`);
160
161  // Sort the table by dur in descending order. Note that we must explicitly exclude
162  // the "thread_dur" column, as it also contains "dur" in its name.
163  await clickTableHeader(/^dur/);
164  await pth.clickMenuItem('Sort: highest first');
165  await pth.waitForIdleAndScreenshot(`sorted.png`);
166
167  // Filter out sleeps.
168  await clickFirstTableCell(/^S/);
169  await pth.clickMenuItem('Add filter');
170  await pth.clickMenuItem('not equals');
171  await pth.waitForIdleAndScreenshot(`filtered.png`);
172
173  // Go to the first thread_state.
174  await getTableCells().nth(0).click();
175  await pth.waitForIdleAndScreenshot(`go-to.png`);
176
177  // Go to current selection tab.
178  await pth.switchToTab('Current Selection');
179  await pth.waitForIdleAndScreenshot(`current-selection.png`);
180});
181
182test('Go to sched', async () => {
183  // Open Android trace with kernel scheduling data.
184  await pth.openTraceFile('api34_startup_cold.perfetto-trace');
185
186  // Show the slice table via command.
187  await pth.runCommand('perfetto.ShowTable.sched');
188  // Sort the table by id for consistent ordering.
189  await clickTableHeader(/^id/);
190  await pth.clickMenuItem('Sort: lowest first');
191  await pth.waitForIdleAndScreenshot(`open-table.png`);
192
193  // Sort the table by dur in descending order. Note that we must explicitly exclude
194  // the "thread_dur" column, as it also contains "dur" in its name.
195  await clickTableHeader(/^dur/);
196  await pth.clickMenuItem('Sort: highest first');
197  await pth.waitForIdleAndScreenshot(`sorted.png`);
198
199  // Filter out idle.
200  await clickFirstTableCell('swapper');
201  await pth.clickMenuItem('Add filter');
202  await getTableCells('120').nth(0).click();
203  await pth.clickMenuItem('Add filter');
204  await pth.clickMenuItem('not equals');
205  await pth.waitForIdleAndScreenshot(`filtered.png`);
206
207  // Go to the first slice.
208  await getTableCells().nth(0).click();
209  await pth.waitForIdleAndScreenshot(`go-to.png`);
210
211  // Go to current selection tab.
212  await pth.switchToTab('Current Selection');
213  await pth.waitForIdleAndScreenshot(`current-selection.png`);
214});
215
216//
217// For process and thread tables, we open a new tab instead of updating selection.
218//
219
220test('Go to process', async () => {
221  await pth.openTraceFile('chrome_scroll_without_vsync.pftrace');
222
223  // Show the slice table via command.
224  await pth.runCommand('perfetto.ShowTable.process');
225  // Sort the table by id for consistent ordering.
226  await clickTableHeader(/^upid/);
227  await pth.clickMenuItem('Sort: lowest first');
228  await pth.waitForIdleAndScreenshot(`open-table.png`);
229
230  // Sort the table by dur in descending order. Note that we must explicitly exclude
231  // the "thread_dur" column, as it also contains "dur" in its name.
232  await clickTableHeader(/^name/);
233  await pth.clickMenuItem('Sort: highest first');
234  await pth.waitForIdleAndScreenshot(`sorted.png`);
235
236  // Go to the first process.
237  await getTableCells().nth(0).click();
238  await pth.clickMenuItem('Show process details');
239  await pth.waitForIdleAndScreenshot(`go-to.png`);
240});
241
242test('Go to thread', async () => {
243  await pth.openTraceFile('chrome_scroll_without_vsync.pftrace');
244
245  // Show the slice table via command.
246  await pth.runCommand('perfetto.ShowTable.thread');
247  // Sort the table by id for consistent ordering.
248  await clickTableHeader(/^utid/);
249  await pth.clickMenuItem('Sort: lowest first');
250  await pth.waitForIdleAndScreenshot(`open-table.png`);
251
252  // Sort the table by dur in descending order. Note that we must explicitly exclude
253  // the "thread_dur" column, as it also contains "dur" in its name.
254  await clickTableHeader(/^name/);
255  await pth.clickMenuItem('Sort: highest first');
256  await pth.waitForIdleAndScreenshot(`sorted.png`);
257
258  // Go to the first thread.
259  await getTableCells().nth(0).click();
260  await pth.clickMenuItem('Show thread details');
261  await pth.waitForIdleAndScreenshot(`go-to.png`);
262});
263