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 {Transform} from 'parsers/surface_flinger/transform_utils';
19import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
20import {TraceRectBuilder} from 'trace/trace_rect_builder';
21import {HierarchyTreeNode} from 'trace/tree_node/hierarchy_tree_node';
22import {UiRect} from 'viewers/components/rects/types2d';
23import {UiRectBuilder} from 'viewers/components/rects/ui_rect_builder';
24import {UI_RECT_FACTORY} from './ui_rect_factory';
25
26describe('UI_RECT_FACTORY', () => {
27  let hierarchyRoot: HierarchyTreeNode;
28  let node1: HierarchyTreeNode;
29  let node2: HierarchyTreeNode;
30
31  beforeEach(() => {
32    hierarchyRoot = new HierarchyTreeBuilder()
33      .setId('TreeEntry')
34      .setName('root')
35      .setChildren([
36        {id: 1, name: 'node1'},
37        {id: 2, name: 'node2'},
38      ])
39      .build();
40    node1 = assertDefined(hierarchyRoot.getChildByName('node1'));
41    node2 = assertDefined(hierarchyRoot.getChildByName('node2'));
42  });
43
44  it('extracts rects from hierarchy tree', () => {
45    buildRectAndSetToNode(node1, 0);
46    buildRectAndSetToNode(node2, 1);
47
48    const expectedUiRect1 = new UiRectBuilder()
49      .setX(0)
50      .setY(0)
51      .setWidth(1)
52      .setHeight(1)
53      .setId('1 node1')
54      .setLabel('node1')
55      .setCornerRadius(0)
56      .setGroupId(0)
57      .setTransform(Transform.EMPTY.matrix)
58      .setIsVisible(true)
59      .setIsDisplay(false)
60      .setIsClickable(true)
61      .setIsVirtual(false)
62      .setHasContent(false)
63      .setDepth(0)
64      .setOpacity(0.5)
65      .build();
66
67    const expectedUiRect2 = new UiRectBuilder()
68      .setX(0)
69      .setY(0)
70      .setWidth(1)
71      .setHeight(1)
72      .setId('2 node2')
73      .setLabel('node2')
74      .setCornerRadius(0)
75      .setGroupId(0)
76      .setTransform(Transform.EMPTY.matrix)
77      .setIsVisible(true)
78      .setIsDisplay(false)
79      .setIsClickable(true)
80      .setIsVirtual(false)
81      .setHasContent(false)
82      .setDepth(1)
83      .setOpacity(0.5)
84      .build();
85
86    const expectedRects: UiRect[] = [expectedUiRect1, expectedUiRect2];
87
88    expect(UI_RECT_FACTORY.makeUiRects(hierarchyRoot)).toEqual(expectedRects);
89  });
90
91  it('handles depth order different to dfs order', () => {
92    buildRectAndSetToNode(node1, 1);
93    buildRectAndSetToNode(node2, 0);
94
95    const expectedUiRect1 = new UiRectBuilder()
96      .setX(0)
97      .setY(0)
98      .setWidth(1)
99      .setHeight(1)
100      .setId('1 node1')
101      .setLabel('node1')
102      .setCornerRadius(0)
103      .setGroupId(0)
104      .setTransform(Transform.EMPTY.matrix)
105      .setIsVisible(true)
106      .setIsDisplay(false)
107      .setIsClickable(true)
108      .setIsVirtual(false)
109      .setHasContent(false)
110      .setDepth(1)
111      .setOpacity(0.5)
112      .build();
113
114    const expectedUiRect2 = new UiRectBuilder()
115      .setX(0)
116      .setY(0)
117      .setWidth(1)
118      .setHeight(1)
119      .setId('2 node2')
120      .setLabel('node2')
121      .setCornerRadius(0)
122      .setGroupId(0)
123      .setTransform(Transform.EMPTY.matrix)
124      .setIsVisible(true)
125      .setIsDisplay(false)
126      .setIsClickable(true)
127      .setIsVirtual(false)
128      .setHasContent(false)
129      .setDepth(0)
130      .setOpacity(0.5)
131      .build();
132
133    const expectedRects: UiRect[] = [expectedUiRect1, expectedUiRect2];
134    expect(UI_RECT_FACTORY.makeUiRects(hierarchyRoot)).toEqual(expectedRects);
135  });
136
137  it('makes vc rects with groupId, content and empty label', () => {
138    const GROUP_ID = 11;
139
140    buildRectAndSetToNode(node1, 1);
141    buildRectAndSetToNode(node2, 0);
142
143    const expectedVcUiRect1 = new UiRectBuilder()
144      .setX(0)
145      .setY(0)
146      .setWidth(1)
147      .setHeight(1)
148      .setId('1 node1')
149      .setLabel('')
150      .setCornerRadius(0)
151      .setGroupId(GROUP_ID)
152      .setTransform(Transform.EMPTY.matrix)
153      .setIsVisible(true)
154      .setIsDisplay(false)
155      .setIsClickable(true)
156      .setIsVirtual(false)
157      .setHasContent(true)
158      .setDepth(1)
159      .setOpacity(0.5)
160      .build();
161
162    const expectedVcUiRect2 = new UiRectBuilder()
163      .setX(0)
164      .setY(0)
165      .setWidth(1)
166      .setHeight(1)
167      .setId('2 node2')
168      .setLabel('')
169      .setCornerRadius(0)
170      .setGroupId(GROUP_ID)
171      .setTransform(Transform.EMPTY.matrix)
172      .setIsVisible(true)
173      .setIsDisplay(false)
174      .setIsClickable(true)
175      .setIsVirtual(false)
176      .setHasContent(true)
177      .setDepth(0)
178      .setOpacity(0.5)
179      .build();
180
181    const expectedRects: UiRect[] = [expectedVcUiRect1, expectedVcUiRect2];
182    expect(UI_RECT_FACTORY.makeVcUiRects(hierarchyRoot, GROUP_ID)).toEqual(
183      expectedRects,
184    );
185  });
186
187  it('discards vc trace rects with zero height or width', () => {
188    const GROUP_ID = 11;
189
190    buildRectAndSetToNode(node1, 1, 0, 1);
191    buildRectAndSetToNode(node2, 0, 1, 0);
192
193    expect(UI_RECT_FACTORY.makeVcUiRects(hierarchyRoot, GROUP_ID)).toEqual([]);
194  });
195
196  function buildRectAndSetToNode(
197    node: HierarchyTreeNode,
198    depth: number,
199    width = 1,
200    height = 1,
201  ) {
202    const rect = new TraceRectBuilder()
203      .setX(0)
204      .setY(0)
205      .setWidth(width)
206      .setHeight(height)
207      .setId(node.id)
208      .setName(node.name)
209      .setCornerRadius(0)
210      .setTransform(Transform.EMPTY.matrix)
211      .setDepth(depth)
212      .setGroupId(0)
213      .setIsVisible(true)
214      .setIsDisplay(false)
215      .setIsVirtual(false)
216      .setOpacity(0.5)
217      .build();
218
219    node.setRects([rect]);
220  }
221});
222