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 {PropertyTreeBuilder} from 'test/unit/property_tree_builder'; 21import {TimestampConverterUtils} from 'test/unit/timestamp_converter_utils'; 22import {TraceBuilder} from 'test/unit/trace_builder'; 23import {UnitTestUtils} from 'test/unit/utils'; 24import {Trace} from 'trace/trace'; 25import {TraceType} from 'trace/trace_type'; 26import { 27 DEFAULT_PROPERTY_FORMATTER, 28 TIMESTAMP_NODE_FORMATTER, 29} from 'trace/tree_node/formatters'; 30import {PropertyTreeNode} from 'trace/tree_node/property_tree_node'; 31import {NotifyLogViewCallbackType} from 'viewers/common/abstract_log_viewer_presenter'; 32import {AbstractLogViewerPresenterTest} from 'viewers/common/abstract_log_viewer_presenter_test'; 33import {LogSelectFilter, LogTextFilter} from 'viewers/common/log_filters'; 34import {TextFilter} from 'viewers/common/text_filter'; 35import {LogHeader} from 'viewers/common/ui_data_log'; 36import {Presenter} from './presenter'; 37import {UiData} from './ui_data'; 38 39class PresenterProtologTest extends AbstractLogViewerPresenterTest<UiData> { 40 override readonly expectedHeaders = [ 41 { 42 header: new LogHeader( 43 {name: 'Log Level', cssClass: 'log-level'}, 44 new LogSelectFilter(Array.from({length: 3}, () => '')), 45 ), 46 options: ['level0', 'level1', 'level2'], 47 }, 48 { 49 header: new LogHeader( 50 {name: 'Tag', cssClass: 'tag'}, 51 new LogSelectFilter(Array.from({length: 3}, () => '')), 52 ), 53 options: ['tag0', 'tag1', 'tag2'], 54 }, 55 { 56 header: new LogHeader( 57 {name: 'Source files', cssClass: 'source-file'}, 58 new LogSelectFilter(Array.from({length: 3}, () => '')), 59 ), 60 options: ['sourcefile0', 'sourcefile1', 'sourcefile2'], 61 }, 62 { 63 header: new LogHeader( 64 {name: 'Search text', cssClass: 'text'}, 65 new LogTextFilter(new TextFilter()), 66 ), 67 }, 68 ]; 69 private trace: Trace<PropertyTreeNode> | undefined; 70 private positionUpdate: TracePositionUpdate | undefined; 71 72 override async setUpTestEnvironment(): Promise<void> { 73 const time10 = TimestampConverterUtils.makeRealTimestamp(10n); 74 const time11 = TimestampConverterUtils.makeRealTimestamp(11n); 75 const time12 = TimestampConverterUtils.makeRealTimestamp(12n); 76 const elapsedTime10 = TimestampConverterUtils.makeElapsedTimestamp(10n); 77 const elapsedTime20 = TimestampConverterUtils.makeElapsedTimestamp(20n); 78 const elapsedTime30 = TimestampConverterUtils.makeElapsedTimestamp(30n); 79 80 const entries = [ 81 new PropertyTreeBuilder() 82 .setRootId('ProtologTrace') 83 .setName('message') 84 .setChildren([ 85 {name: 'text', value: 'text0', formatter: DEFAULT_PROPERTY_FORMATTER}, 86 { 87 name: 'timestamp', 88 value: elapsedTime10, 89 formatter: TIMESTAMP_NODE_FORMATTER, 90 }, 91 {name: 'tag', value: 'tag0', formatter: DEFAULT_PROPERTY_FORMATTER}, 92 { 93 name: 'level', 94 value: 'level0', 95 formatter: DEFAULT_PROPERTY_FORMATTER, 96 }, 97 { 98 name: 'at', 99 value: 'sourcefile0', 100 formatter: DEFAULT_PROPERTY_FORMATTER, 101 }, 102 ]) 103 .build(), 104 105 new PropertyTreeBuilder() 106 .setRootId('ProtologTrace') 107 .setName('message') 108 .setChildren([ 109 {name: 'text', value: 'text1', formatter: DEFAULT_PROPERTY_FORMATTER}, 110 { 111 name: 'timestamp', 112 value: elapsedTime20, 113 formatter: TIMESTAMP_NODE_FORMATTER, 114 }, 115 {name: 'tag', value: 'tag1', formatter: DEFAULT_PROPERTY_FORMATTER}, 116 { 117 name: 'level', 118 value: 'level1', 119 formatter: DEFAULT_PROPERTY_FORMATTER, 120 }, 121 { 122 name: 'at', 123 value: 'sourcefile1', 124 formatter: DEFAULT_PROPERTY_FORMATTER, 125 }, 126 ]) 127 .build(), 128 129 new PropertyTreeBuilder() 130 .setRootId('ProtologTrace') 131 .setName('message') 132 .setChildren([ 133 {name: 'text', value: 'text2', formatter: DEFAULT_PROPERTY_FORMATTER}, 134 { 135 name: 'timestamp', 136 value: elapsedTime30, 137 formatter: TIMESTAMP_NODE_FORMATTER, 138 }, 139 {name: 'tag', value: 'tag2', formatter: DEFAULT_PROPERTY_FORMATTER}, 140 { 141 name: 'level', 142 value: 'level2', 143 formatter: DEFAULT_PROPERTY_FORMATTER, 144 }, 145 { 146 name: 'at', 147 value: 'sourcefile2', 148 formatter: DEFAULT_PROPERTY_FORMATTER, 149 }, 150 ]) 151 .build(), 152 ]; 153 154 this.trace = new TraceBuilder<PropertyTreeNode>() 155 .setEntries(entries) 156 .setTimestamps([time10, time11, time12]) 157 .build(); 158 159 this.positionUpdate = TracePositionUpdate.fromTraceEntry( 160 this.trace.getEntry(0), 161 ); 162 } 163 164 override async createPresenterWithEmptyTrace( 165 callback: NotifyLogViewCallbackType<UiData>, 166 ): Promise<Presenter> { 167 const trace = UnitTestUtils.makeEmptyTrace(TraceType.PROTO_LOG); 168 return new Presenter(trace, callback, new InMemoryStorage()); 169 } 170 171 override async createPresenter( 172 callback: NotifyLogViewCallbackType<UiData>, 173 ): Promise<Presenter> { 174 const presenter = new Presenter( 175 assertDefined(this.trace), 176 callback, 177 new InMemoryStorage(), 178 ); 179 await presenter.onAppEvent(this.getPositionUpdate()); // trigger initialization 180 return presenter; 181 } 182 183 override getPositionUpdate(): TracePositionUpdate { 184 return assertDefined(this.positionUpdate); 185 } 186} 187 188describe('PresenterProtolog', () => { 189 new PresenterProtologTest().execute(); 190}); 191