• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.d
15 */
16
17import {assertDefined} from 'common/assert_utils';
18import {HierarchyTreeBuilder} from 'test/unit/hierarchy_tree_builder';
19import {MockStorage} from 'test/unit/mock_storage';
20import {TracesBuilder} from 'test/unit/traces_builder';
21import {TraceBuilder} from 'test/unit/trace_builder';
22import {UnitTestUtils} from 'test/unit/utils';
23import {Traces} from 'trace/traces';
24import {TracePosition} from 'trace/trace_position';
25import {TraceType} from 'trace/trace_type';
26import {ImeUiData} from 'viewers/common/ime_ui_data';
27import {HierarchyTreeNode, PropertiesTreeNode} from 'viewers/common/ui_tree_utils';
28import {UserOptions} from 'viewers/common/user_options';
29import {PresenterInputMethodClients} from 'viewers/viewer_input_method_clients/presenter_input_method_clients';
30import {PresenterInputMethodManagerService} from 'viewers/viewer_input_method_manager_service/presenter_input_method_manager_service';
31import {PresenterInputMethodService} from 'viewers/viewer_input_method_service/presenter_input_method_service';
32import {PresenterInputMethod} from './presenter_input_method';
33
34export function executePresenterInputMethodTests(
35  selected: HierarchyTreeNode,
36  propertiesTreeFilterString: string,
37  expectedChildren: [number, number],
38  expectHierarchyTreeWithSfSubtree: boolean,
39  PresenterInputMethod:
40    | typeof PresenterInputMethodClients
41    | typeof PresenterInputMethodService
42    | typeof PresenterInputMethodManagerService,
43  imeTraceType: TraceType
44) {
45  describe('PresenterInputMethod', () => {
46    let presenter: PresenterInputMethod;
47    let uiData: ImeUiData;
48    let position: TracePosition;
49    let selectedTree: HierarchyTreeNode;
50
51    beforeEach(async () => {
52      selectedTree = selected;
53      await setUpTestEnvironment([
54        imeTraceType,
55        TraceType.SURFACE_FLINGER,
56        TraceType.WINDOW_MANAGER,
57      ]);
58    });
59
60    it('is robust to empty trace', async () => {
61      const traces = new TracesBuilder().setEntries(imeTraceType, []).build();
62      presenter = createPresenter(traces);
63
64      expect(uiData.hierarchyUserOptions).toBeTruthy();
65      expect(uiData.propertiesUserOptions).toBeTruthy();
66      expect(uiData.tree).toBeFalsy();
67
68      await presenter.onTracePositionUpdate(position);
69      expect(uiData.hierarchyUserOptions).toBeTruthy();
70      expect(uiData.propertiesUserOptions).toBeTruthy();
71      expect(uiData.tree).toBeFalsy();
72    });
73
74    it('is robust to traces without SF', async () => {
75      await setUpTestEnvironment([imeTraceType, TraceType.WINDOW_MANAGER]);
76      await presenter.onTracePositionUpdate(position);
77      expect(uiData.hierarchyUserOptions).toBeTruthy();
78      expect(uiData.propertiesUserOptions).toBeTruthy();
79      expect(Object.keys(uiData.tree!).length > 0).toBeTrue();
80    });
81
82    it('is robust to traces without WM', async () => {
83      await setUpTestEnvironment([imeTraceType, TraceType.SURFACE_FLINGER]);
84      await presenter.onTracePositionUpdate(position);
85      expect(uiData.hierarchyUserOptions).toBeTruthy();
86      expect(uiData.propertiesUserOptions).toBeTruthy();
87      expect(Object.keys(uiData.tree!).length > 0).toBeTrue();
88    });
89
90    it('is robust to traces without WM and SF', async () => {
91      await setUpTestEnvironment([imeTraceType]);
92      await presenter.onTracePositionUpdate(position);
93      expect(uiData.hierarchyUserOptions).toBeTruthy();
94      expect(uiData.propertiesUserOptions).toBeTruthy();
95      expect(Object.keys(uiData.tree!).length > 0).toBeTrue();
96    });
97
98    it('processes trace position updates', async () => {
99      await presenter.onTracePositionUpdate(position);
100      expect(uiData.hierarchyUserOptions).toBeTruthy();
101      expect(uiData.propertiesUserOptions).toBeTruthy();
102      expect(Object.keys(uiData.tree!).length > 0).toBeTrue();
103    });
104
105    it('can update pinned items', () => {
106      expect(uiData.pinnedItems).toEqual([]);
107      const pinnedItem = new HierarchyTreeBuilder()
108        .setName('FirstPinnedItem')
109        .setStableId('TestItem 4')
110        .setLayerId(4)
111        .build();
112      presenter.updatePinnedItems(pinnedItem);
113      expect(uiData.pinnedItems).toContain(pinnedItem);
114    });
115
116    it('can update highlighted items', () => {
117      expect(uiData.highlightedItems).toEqual([]);
118      const id = 'entry';
119      presenter.updateHighlightedItems(id);
120      expect(uiData.highlightedItems).toContain(id);
121    });
122
123    it('can update hierarchy tree', async () => {
124      //change flat view to true
125      const userOptions: UserOptions = {
126        onlyVisible: {
127          name: 'Only visible',
128          enabled: true,
129        },
130        simplifyNames: {
131          name: 'Simplify names',
132          enabled: true,
133        },
134        flat: {
135          name: 'Flat',
136          enabled: false,
137        },
138      };
139
140      let expectedChildren = expectHierarchyTreeWithSfSubtree ? 2 : 1;
141      await presenter.onTracePositionUpdate(position);
142      expect(uiData.tree?.children.length).toEqual(expectedChildren);
143
144      // Filter out non-visible child
145      expectedChildren = expectHierarchyTreeWithSfSubtree ? 1 : 0;
146      presenter.updateHierarchyTree(userOptions);
147      expect(uiData.hierarchyUserOptions).toEqual(userOptions);
148      expect(uiData.tree?.children.length).toEqual(expectedChildren);
149    });
150
151    it('can filter hierarchy tree', async () => {
152      const userOptions: UserOptions = {
153        onlyVisible: {
154          name: 'Only visible',
155          enabled: false,
156        },
157        simplifyNames: {
158          name: 'Simplify names',
159          enabled: true,
160        },
161        flat: {
162          name: 'Flat',
163          enabled: true,
164        },
165      };
166
167      const expectedChildren = expectHierarchyTreeWithSfSubtree ? 12 : 1;
168      await presenter.onTracePositionUpdate(position);
169      presenter.updateHierarchyTree(userOptions);
170      expect(uiData.tree?.children.length).toEqual(expectedChildren);
171
172      // Filter out all children
173      presenter.filterHierarchyTree('Reject all');
174      expect(uiData.tree?.children.length).toEqual(0);
175    });
176
177    it('can set new properties tree and associated ui data', async () => {
178      await presenter.onTracePositionUpdate(position);
179      presenter.newPropertiesTree(selectedTree);
180      // does not check specific tree values as tree transformation method may change
181      expect(uiData.propertiesTree).toBeTruthy();
182    });
183
184    it('can filter properties tree', async () => {
185      await presenter.onTracePositionUpdate(position);
186      presenter.newPropertiesTree(selectedTree);
187      let nonTerminalChildren =
188        uiData.propertiesTree?.children?.filter(
189          (child: PropertiesTreeNode) => typeof child.propertyKey === 'string'
190        ) ?? [];
191
192      expect(nonTerminalChildren.length).toEqual(expectedChildren[0]);
193      presenter.filterPropertiesTree(propertiesTreeFilterString);
194
195      nonTerminalChildren =
196        uiData.propertiesTree?.children?.filter(
197          (child: PropertiesTreeNode) => typeof child.propertyKey === 'string'
198        ) ?? [];
199      expect(nonTerminalChildren.length).toEqual(expectedChildren[1]);
200    });
201
202    const setUpTestEnvironment = async (traceTypes: TraceType[]) => {
203      const traces = new Traces();
204      const entries = await UnitTestUtils.getImeTraceEntries();
205
206      traceTypes.forEach((traceType) => {
207        const trace = new TraceBuilder<object>()
208          .setEntries([entries.get(traceType)])
209          .setFrame(0, 0)
210          .build();
211        traces.setTrace(traceType, trace);
212      });
213
214      presenter = createPresenter(traces);
215
216      position = TracePosition.fromTraceEntry(
217        assertDefined(traces.getTrace(imeTraceType)).getEntry(0)
218      );
219    };
220
221    const createPresenter = (traces: Traces): PresenterInputMethod => {
222      return new PresenterInputMethod(
223        traces,
224        new MockStorage(),
225        [imeTraceType],
226        (newData: ImeUiData) => {
227          uiData = newData;
228        }
229      );
230    };
231  });
232}
233