xref: /aosp_15_r20/development/tools/winscope/src/parsers/search/parser_search_test.ts (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import {assertDefined} from 'common/assert_utils';
18import {TraceSearchQueryFailed} from 'messaging/user_warnings';
19import {ParserSurfaceFlinger} from 'parsers/surface_flinger/perfetto/parser_surface_flinger';
20import {TimestampConverterUtils} from 'test/unit/timestamp_converter_utils';
21import {UserNotifierChecker} from 'test/unit/user_notifier_checker';
22import {UnitTestUtils} from 'test/unit/utils';
23import {CoarseVersion} from 'trace/coarse_version';
24import {TraceType} from 'trace/trace_type';
25import {ParserSearch} from './parser_search';
26
27describe('ParserSearch', () => {
28  let userNotifierChecker: UserNotifierChecker;
29  let parser: ParserSearch;
30
31  beforeAll(() => {
32    userNotifierChecker = new UserNotifierChecker();
33    jasmine.addCustomEqualityTester(UnitTestUtils.timestampEqualityTester);
34  });
35
36  afterEach(() => {
37    userNotifierChecker.reset();
38  });
39
40  describe('valid query with timestamps', () => {
41    beforeAll(async () => {
42      parser = await createParser(
43        'SELECT * FROM surfaceflinger_layers_snapshot',
44      );
45    });
46
47    afterEach(() => {
48      userNotifierChecker.expectNone();
49    });
50
51    it('has expected trace type', () => {
52      expect(parser.getTraceType()).toEqual(TraceType.SEARCH);
53    });
54
55    it('has expected coarse version', () => {
56      expect(parser.getCoarseVersion()).toEqual(CoarseVersion.LATEST);
57    });
58
59    it('has length entries equal to number of rows', () => {
60      expect(parser.getLengthEntries()).toEqual(21);
61    });
62
63    it('provides timestamps', () => {
64      const expected = [
65        TimestampConverterUtils.makeElapsedTimestamp(14500282843n),
66        TimestampConverterUtils.makeElapsedTimestamp(14631249355n),
67        TimestampConverterUtils.makeElapsedTimestamp(15403446377n),
68      ];
69      const actual = assertDefined(parser.getTimestamps()).slice(0, 3);
70      expect(actual).toEqual(expected);
71      userNotifierChecker.expectNone();
72    });
73
74    it('provides query result', async () => {
75      const entry = await parser.getEntry(0);
76      expect(entry.numRows()).toEqual(21);
77      const firstRow = entry.iter({});
78      expect(firstRow.get('id')).toEqual(0n);
79      expect(firstRow.get('ts')).toEqual(14500282843n);
80      expect(firstRow.get('type')).toEqual('surfaceflinger_layers_snapshot');
81      expect(firstRow.get('arg_set_id')).toEqual(176n);
82    });
83  });
84
85  describe('valid query without timestamps', () => {
86    beforeAll(async () => {
87      parser = await createParser('SELECT * FROM surfaceflinger_layer');
88      userNotifierChecker.expectNone();
89    });
90
91    afterEach(() => {
92      userNotifierChecker.expectNone();
93    });
94
95    it('has length entries equal to 1 so query result can be accessed', () => {
96      expect(parser.getLengthEntries()).toEqual(1);
97    });
98
99    it('provides one invalid timestamp so query result can be accessed', () => {
100      expect(parser.getTimestamps()).toEqual([
101        TimestampConverterUtils.makeZeroTimestamp(),
102      ]);
103    });
104
105    it('provides query result', async () => {
106      const entry = await parser.getEntry(0);
107      expect(entry.numRows()).toEqual(1815);
108      const firstRow = entry.iter({});
109      expect(firstRow.get('id')).toEqual(0n);
110      expect(firstRow.get('type')).toEqual('surfaceflinger_layer');
111      expect(firstRow.get('arg_set_id')).toEqual(1n);
112      expect(firstRow.get('snapshot_id')).toEqual(0n);
113    });
114  });
115
116  describe('valid query without rows', () => {
117    beforeAll(async () => {
118      parser = await createParser('SELECT * FROM surfaceflinger_transactions');
119    });
120
121    afterEach(() => {
122      userNotifierChecker.expectNone();
123    });
124
125    it('has length entries equal to 1 so query result can be accessed', () => {
126      expect(parser.getLengthEntries()).toEqual(1);
127    });
128
129    it('provides one invalid timestamp so query result can be accessed', () => {
130      expect(parser.getTimestamps()).toEqual([
131        TimestampConverterUtils.makeZeroTimestamp(),
132      ]);
133    });
134
135    it('provides query result', async () => {
136      const entry = await parser.getEntry(0);
137      expect(entry.columns()).toEqual([
138        'id',
139        'type',
140        'ts',
141        'arg_set_id',
142        'base64_proto',
143        'base64_proto_id',
144      ]);
145      expect(entry.numRows()).toEqual(0);
146    });
147  });
148
149  it('notifies user of parsing error before throwing error', async () => {
150    const createFailingParser = () => createParser('SELECT * FROM fake_table');
151    await expectAsync(createFailingParser()).toBeRejected();
152    userNotifierChecker.reset();
153    try {
154      parser = await createFailingParser();
155    } catch (e) {
156      userNotifierChecker.expectNotified([
157        new TraceSearchQueryFailed((e as Error).message),
158      ]);
159    }
160  });
161
162  async function createParser(query: string): Promise<ParserSearch> {
163    await (
164      (await UnitTestUtils.getPerfettoParser(
165        TraceType.SURFACE_FLINGER,
166        'traces/perfetto/layers_trace.perfetto-trace',
167      )) as ParserSurfaceFlinger
168    ).parse();
169    parser = new ParserSearch(query, UnitTestUtils.getTimestampConverter());
170    await parser.parse();
171    return parser;
172  }
173});
174