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 ANYf 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 {InMemoryStorage} from 'common/in_memory_storage'; 19import {TracePositionUpdate} from 'messaging/winscope_event'; 20import {TraceBuilder} from 'test/unit/trace_builder'; 21import {UnitTestUtils} from 'test/unit/utils'; 22import {Parser} from 'trace/parser'; 23import {Trace} from 'trace/trace'; 24import {TraceType} from 'trace/trace_type'; 25import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 26import {NotifyLogViewCallbackType} from 'viewers/common/abstract_log_viewer_presenter'; 27import {AbstractLogViewerPresenterTest} from 'viewers/common/abstract_log_viewer_presenter_test'; 28import {LogSelectFilter} from 'viewers/common/log_filters'; 29import {LogHeader} from 'viewers/common/ui_data_log'; 30import {Presenter} from './presenter'; 31import {UiData} from './ui_data'; 32 33class PresenterTransactionsTest extends AbstractLogViewerPresenterTest<UiData> { 34 override readonly expectedHeaders = [ 35 { 36 header: new LogHeader( 37 {name: 'TX ID', cssClass: 'transaction-id right-align'}, 38 new LogSelectFilter(Array.from({length: 1295}, () => '')), 39 ), 40 }, 41 { 42 header: new LogHeader( 43 {name: 'VSYNC ID', cssClass: 'vsyncid right-align'}, 44 new LogSelectFilter(Array.from({length: 710}, () => '')), 45 ), 46 }, 47 { 48 header: new LogHeader( 49 {name: 'PID', cssClass: 'pid right-align'}, 50 new LogSelectFilter(Array.from({length: 8}, () => '')), 51 ), 52 options: ['N/A', '0', '515', '1593', '2022', '2322', '2463', '3300'], 53 }, 54 { 55 header: new LogHeader( 56 {name: 'UID', cssClass: 'uid right-align'}, 57 new LogSelectFilter(Array.from({length: 6}, () => '')), 58 ), 59 options: ['N/A', '1000', '1003', '10169', '10235', '10239'], 60 }, 61 { 62 header: new LogHeader( 63 {name: 'TYPE', cssClass: 'transaction-type'}, 64 new LogSelectFilter(Array.from({length: 6}, () => '')), 65 ), 66 options: [ 67 'DISPLAY_CHANGED', 68 'LAYER_ADDED', 69 'LAYER_CHANGED', 70 'LAYER_DESTROYED', 71 'LAYER_HANDLE_DESTROYED', 72 'NO_OP', 73 ], 74 }, 75 { 76 header: new LogHeader( 77 {name: 'LAYER/DISP ID', cssClass: 'layer-or-display-id right-align'}, 78 new LogSelectFilter(Array.from({length: 117}, () => '')), 79 ), 80 }, 81 { 82 header: new LogHeader( 83 {name: 'Flags', cssClass: 'flags'}, 84 new LogSelectFilter( 85 Array.from({length: 30}, () => ''), 86 true, 87 '250', 88 '100%', 89 ), 90 ), 91 }, 92 ]; 93 private trace: Trace<PropertyTreeNode> | undefined; 94 private positionUpdate: TracePositionUpdate | undefined; 95 96 override executeSpecializedTests() { 97 describe('Specialized tests', () => { 98 let presenter: Presenter; 99 let uiData: UiData; 100 101 beforeAll(async () => { 102 await this.setUpTestEnvironment(); 103 }); 104 105 beforeEach(async () => { 106 presenter = await this.createPresenter((newData: UiData) => { 107 uiData = newData; 108 }); 109 }); 110 111 it('keeps properties related to what has changed regardless of hide defaults', async () => { 112 await presenter.onAppEvent(this.getPositionUpdate()); 113 await presenter.onLogEntryClick(10); 114 expect( 115 assertDefined(uiData.propertiesTree).getAllChildren().length, 116 ).toEqual(8); 117 expect( 118 uiData.propertiesTree?.getChildByName('transformToDisplayInverse'), 119 ).toBeDefined(); 120 expect( 121 uiData.propertiesTree?.getChildByName('destinationFrame'), 122 ).toBeDefined(); 123 expect( 124 uiData.propertiesTree?.getChildByName('autoRefresh'), 125 ).toBeDefined(); 126 127 await presenter.onLogEntryClick(279); 128 expect(uiData.propertiesTree?.getChildByName('flags')).toBeDefined(); 129 expect(uiData.propertiesTree?.getChildByName('parentId')).toBeDefined(); 130 expect( 131 uiData.propertiesTree?.getChildByName('relativeParentId'), 132 ).toBeDefined(); 133 expect( 134 uiData.propertiesTree?.getChildByName('transformToDisplayInverse'), 135 ).toBeUndefined(); 136 expect( 137 uiData.propertiesTree?.getChildByName('destinationFrame'), 138 ).toBeUndefined(); 139 expect( 140 uiData.propertiesTree?.getChildByName('autoRefresh'), 141 ).toBeUndefined(); 142 143 await presenter.onLogEntryClick(584); 144 expect(uiData.propertiesTree?.getChildByName('flags')).toBeDefined(); 145 expect(uiData.propertiesTree?.getChildByName('layerId')).toBeDefined(); 146 expect(uiData.propertiesTree?.getChildByName('x')).toBeDefined(); 147 expect(uiData.propertiesTree?.getChildByName('y')).toBeDefined(); 148 expect(uiData.propertiesTree?.getChildByName('z')).toBeDefined(); 149 expect( 150 uiData.propertiesTree?.getChildByName('parentId'), 151 ).toBeUndefined(); 152 expect( 153 uiData.propertiesTree?.getChildByName('relativeParentId'), 154 ).toBeUndefined(); 155 }); 156 }); 157 } 158 159 override async setUpTestEnvironment(): Promise<void> { 160 const parser = (await UnitTestUtils.getParser( 161 'traces/elapsed_and_real_timestamp/Transactions.pb', 162 )) as Parser<PropertyTreeNode>; 163 this.trace = new TraceBuilder<PropertyTreeNode>() 164 .setType(TraceType.TRANSACTIONS) 165 .setParser(parser) 166 .build(); 167 this.positionUpdate = TracePositionUpdate.fromTraceEntry( 168 this.trace.getEntry(0), 169 ); 170 } 171 172 override async createPresenterWithEmptyTrace( 173 callback: NotifyLogViewCallbackType<UiData>, 174 ): Promise<Presenter> { 175 const trace = UnitTestUtils.makeEmptyTrace(TraceType.TRANSACTIONS); 176 return new Presenter(trace, new InMemoryStorage(), callback); 177 } 178 179 override async createPresenter( 180 callback: NotifyLogViewCallbackType<UiData>, 181 ): Promise<Presenter> { 182 const presenter = new Presenter( 183 assertDefined(this.trace), 184 new InMemoryStorage(), 185 callback, 186 ); 187 await presenter.onAppEvent(this.getPositionUpdate()); // trigger initialization 188 return presenter; 189 } 190 191 override getPositionUpdate(): TracePositionUpdate { 192 return assertDefined(this.positionUpdate); 193 } 194} 195 196describe('PresenterTransactions', () => { 197 new PresenterTransactionsTest().execute(); 198}); 199