1/*
2 * Copyright (C) 2022 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 {Timestamp} from 'common/time';
19import {TimestampConverterUtils} from 'test/unit/timestamp_converter_utils';
20import {UnitTestUtils} from 'test/unit/utils';
21import {CoarseVersion} from 'trace/coarse_version';
22import {Parser} from 'trace/parser';
23import {TraceType} from 'trace/trace_type';
24import {PropertyTreeNode} from 'trace/tree_node/property_tree_node';
25
26interface ExpectedMessage {
27  'message': string;
28  'ts': string;
29  'at': string;
30  'level': string;
31  'tag': string;
32}
33
34const genProtoLogTest =
35  (
36    traceFile: string,
37    timestampCount: number,
38    first3ExpectedRealTimestamps: Timestamp[],
39    expectedFirstMessage: ExpectedMessage,
40  ) =>
41  () => {
42    let parser: Parser<PropertyTreeNode>;
43
44    beforeAll(async () => {
45      jasmine.addCustomEqualityTester(UnitTestUtils.timestampEqualityTester);
46      parser = (await UnitTestUtils.getParser(
47        traceFile,
48      )) as Parser<PropertyTreeNode>;
49    });
50
51    it('has expected trace type', () => {
52      expect(parser.getTraceType()).toEqual(TraceType.PROTO_LOG);
53    });
54
55    it('has expected coarse version', () => {
56      expect(parser.getCoarseVersion()).toEqual(CoarseVersion.LEGACY);
57    });
58
59    it('has expected length', () => {
60      expect(parser.getLengthEntries()).toEqual(timestampCount);
61    });
62
63    it('provides timestamps', () => {
64      const timestamps = assertDefined(parser.getTimestamps());
65      expect(timestamps.length).toEqual(timestampCount);
66
67      expect(timestamps.slice(0, 3)).toEqual(first3ExpectedRealTimestamps);
68    });
69
70    it('reconstructs human-readable log message', async () => {
71      const message = await parser.getEntry(0);
72
73      expect(
74        assertDefined(message.getChildByName('text')).formattedValue(),
75      ).toEqual(expectedFirstMessage['message']);
76      expect(
77        assertDefined(message.getChildByName('timestamp')).formattedValue(),
78      ).toEqual(expectedFirstMessage['ts']);
79      expect(
80        assertDefined(message.getChildByName('tag')).formattedValue(),
81      ).toEqual(expectedFirstMessage['tag']);
82      expect(
83        assertDefined(message.getChildByName('level')).formattedValue(),
84      ).toEqual(expectedFirstMessage['level']);
85      expect(
86        assertDefined(message.getChildByName('at')).formattedValue(),
87      ).toEqual(expectedFirstMessage['at']);
88    });
89
90    it('reconstructs human-readable log message (REAL time)', async () => {
91      const message = await parser.getEntry(0);
92
93      expect(
94        assertDefined(message.getChildByName('text')).formattedValue(),
95      ).toEqual(expectedFirstMessage['message']);
96      expect(
97        assertDefined(message.getChildByName('timestamp')).formattedValue(),
98      ).toEqual(expectedFirstMessage['ts']);
99      expect(
100        assertDefined(message.getChildByName('tag')).formattedValue(),
101      ).toEqual(expectedFirstMessage['tag']);
102      expect(
103        assertDefined(message.getChildByName('level')).formattedValue(),
104      ).toEqual(expectedFirstMessage['level']);
105      expect(
106        assertDefined(message.getChildByName('at')).formattedValue(),
107      ).toEqual(expectedFirstMessage['at']);
108    });
109  };
110
111describe('ParserProtoLog', () => {
112  describe(
113    '32',
114    genProtoLogTest(
115      'traces/elapsed_and_real_timestamp/ProtoLog32.pb',
116      50,
117      [
118        TimestampConverterUtils.makeRealTimestamp(1655727125377266486n),
119        TimestampConverterUtils.makeRealTimestamp(1655727125377336718n),
120        TimestampConverterUtils.makeRealTimestamp(1655727125377350430n),
121      ],
122      {
123        'message':
124          'InsetsSource updateVisibility for ITYPE_IME, serverVisible: false clientVisible: false',
125        'ts': '2022-06-20, 12:12:05.377',
126        'tag': 'WindowManager',
127        'level': 'DEBUG',
128        'at': 'com/android/server/wm/InsetsSourceProvider.java',
129      },
130    ),
131  );
132  describe(
133    '64',
134    genProtoLogTest(
135      'traces/elapsed_and_real_timestamp/ProtoLog64.pb',
136      4615,
137      [
138        TimestampConverterUtils.makeRealTimestamp(1709196806399529939n),
139        TimestampConverterUtils.makeRealTimestamp(1709196806399763866n),
140        TimestampConverterUtils.makeRealTimestamp(1709196806400297151n),
141      ],
142      {
143        'message': 'Starting activity when config will change = false',
144        'ts': '2024-02-29, 08:53:26.399',
145        'tag': 'WindowManager',
146        'level': 'VERBOSE',
147        'at': 'com/android/server/wm/ActivityStarter.java',
148      },
149    ),
150  );
151  describe(
152    'Missing config message',
153    genProtoLogTest(
154      'traces/elapsed_and_real_timestamp/ProtoLogMissingConfigMessage.pb',
155      7295,
156      [
157        TimestampConverterUtils.makeRealTimestamp(1669053909777144978n),
158        TimestampConverterUtils.makeRealTimestamp(1669053909778011697n),
159        TimestampConverterUtils.makeRealTimestamp(1669053909778800707n),
160      ],
161      {
162        'message': 'SURFACE isColorSpaceAgnostic=true: NotificationShade',
163        'ts': '2022-11-21, 18:05:09.777',
164        'tag': 'WindowManager',
165        'level': 'INFO',
166        'at': 'com/android/server/wm/WindowSurfaceController.java',
167      },
168    ),
169  );
170});
171