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 {browser, by, element, ElementFinder} from 'protractor'; 18import {E2eTestUtils} from './utils'; 19 20describe('Cross-Tool Protocol', () => { 21 beforeEach(async () => { 22 await browser.restart(); 23 24 jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; 25 await browser.manage().timeouts().implicitlyWait(20000); 26 await E2eTestUtils.checkServerIsUp( 27 'Remote tool mock', 28 E2eTestUtils.REMOTE_TOOL_MOCK_URL, 29 ); 30 await E2eTestUtils.checkServerIsUp('Winscope', E2eTestUtils.WINSCOPE_URL); 31 32 await browser.get(E2eTestUtils.REMOTE_TOOL_MOCK_URL); 33 }); 34 35 it('allows communication with ABT', async () => { 36 const TIMESTAMP_IN_BUGREPORT_MESSAGE = '1670509911000000000'; 37 const TIMESTAMP_FROM_ABT_TO_WINSCOPE = '1670509912000000000'; 38 const TIMESTAMP_FROM_WINSCOPE = '1670509913000000000'; 39 40 await openWinscopeTabFromRemoteTool(); 41 await waitWinscopeTabIsOpen(); 42 43 await sendBugreportToWinscope(); 44 await checkWinscopeRendersUploadView(); 45 await closeWinscopeSnackBar(); 46 47 await clickWinscopeViewTracesButton(); 48 await checkWinscopeRenderedSurfaceFlingerView(); 49 await checkWinscopeRenderedAllViewTabs(); 50 await checkWinscopeTimestamp(TIMESTAMP_IN_BUGREPORT_MESSAGE); 51 52 await sendRealtimeTimestampToWinscope(TIMESTAMP_FROM_ABT_TO_WINSCOPE); 53 await checkWinscopeTimestamp(TIMESTAMP_FROM_ABT_TO_WINSCOPE); 54 55 await sendTimestampToRemoteTool(TIMESTAMP_FROM_WINSCOPE); 56 await checkRemoteToolRealtimeTimestamp(TIMESTAMP_FROM_WINSCOPE); 57 }); 58 59 it('allows communication with Perfetto', async () => { 60 // real-to-boottime offset = 1659107074601779989 61 const TIMESTAMP_IN_FILES_MESSAGE_REALTIME = '1659107090327674405'; 62 const TIMESTAMP_FROM_PERFETTO_BOOTTIME = '15795654466'; 63 const TIMESTAMP_FROM_PERFETTO_REALTIME = '1659107090397434455'; 64 const TIMESTAMP_FROM_WINSCOPE_BOOTTIME = '15970486213'; 65 const TIMESTAMP_FROM_WINSCOPE_REALTIME = '1659107090572266202'; 66 67 await openWinscopeTabFromRemoteTool(); 68 await waitWinscopeTabIsOpen(); 69 70 await sendFilesToWinscope(); 71 await checkWinscopeRendersUploadView(); 72 73 await clickWinscopeViewTracesButton(); 74 await checkWinscopeRenderedSurfaceFlingerView(); 75 await checkWinscopeTimestamp(TIMESTAMP_IN_FILES_MESSAGE_REALTIME); 76 77 await sendBoottimeTimestampToWinscope(TIMESTAMP_FROM_PERFETTO_BOOTTIME); 78 await checkWinscopeTimestamp(TIMESTAMP_FROM_PERFETTO_REALTIME); 79 80 await sendTimestampToRemoteTool(TIMESTAMP_FROM_WINSCOPE_REALTIME); 81 await checkRemoteToolBoottimeTimestamp(TIMESTAMP_FROM_WINSCOPE_BOOTTIME); 82 }); 83 84 it('can turn timestamp sync off/on', async () => { 85 // real-to-boottime offset = 1659107074601779989 86 const TIMESTAMP_IN_FILES_MESSAGE_REALTIME = '1659107090327674405'; 87 const TIMESTAMP_FROM_PERFETTO_BOOTTIME = '15725894416'; 88 89 await openWinscopeTabFromRemoteTool(); 90 await waitWinscopeTabIsOpen(); 91 92 await sendFilesToWinscope(); 93 await checkWinscopeRendersUploadView(); 94 95 await clickWinscopeViewTracesButton(); 96 await checkWinscopeRenderedSurfaceFlingerView(); 97 98 await clickCrossToolSyncButton(); 99 100 await checkWinscopeTimestamp(TIMESTAMP_IN_FILES_MESSAGE_REALTIME); 101 await sendBoottimeTimestampToWinscope(TIMESTAMP_FROM_PERFETTO_BOOTTIME); 102 await checkWinscopeTimestamp(TIMESTAMP_IN_FILES_MESSAGE_REALTIME); 103 104 await checkRemoteToolBoottimeTimestamp(''); 105 await sendTimestampToRemoteTool(TIMESTAMP_IN_FILES_MESSAGE_REALTIME); 106 await checkRemoteToolBoottimeTimestamp(''); 107 }); 108 109 async function openWinscopeTabFromRemoteTool() { 110 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 111 const buttonElement = element(by.css('.button-open-winscope')); 112 await buttonElement.click(); 113 } 114 115 async function sendBugreportToWinscope() { 116 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 117 const inputFileElement = element(by.css('.button-send-bugreport')); 118 await inputFileElement.sendKeys( 119 E2eTestUtils.getFixturePath('bugreports/bugreport_stripped.zip'), 120 ); 121 } 122 123 async function sendFilesToWinscope() { 124 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 125 const inputFileElement = element(by.css('.button-send-files')); 126 await inputFileElement.sendKeys( 127 E2eTestUtils.getFixturePath( 128 'traces/perfetto/layers_trace.perfetto-trace', 129 ), 130 ); 131 } 132 133 async function checkWinscopeRendersUploadView() { 134 await browser.switchTo().window(await getWindowHandleWinscope()); 135 const isPresent = await element(by.css('.uploaded-files')).isPresent(); 136 expect(isPresent).toBeTruthy(); 137 } 138 139 async function clickWinscopeViewTracesButton() { 140 await browser.switchTo().window(await getWindowHandleWinscope()); 141 await E2eTestUtils.clickViewTracesButton(); 142 } 143 144 async function closeWinscopeSnackBar() { 145 await browser.switchTo().window(await getWindowHandleWinscope()); 146 await E2eTestUtils.closeSnackBar(); 147 } 148 149 async function waitWinscopeTabIsOpen() { 150 await browser.wait( 151 async () => { 152 const handles = await browser.getAllWindowHandles(); 153 return handles.length >= 2; 154 }, 155 20000, 156 'The Winscope tab did not open', 157 ); 158 } 159 160 async function checkWinscopeRenderedSurfaceFlingerView() { 161 await browser.switchTo().window(await getWindowHandleWinscope()); 162 const viewerPresent = await element( 163 by.css('viewer-surface-flinger'), 164 ).isPresent(); 165 expect(viewerPresent).toBeTruthy(); 166 } 167 168 async function checkWinscopeRenderedAllViewTabs() { 169 const tabParagraphs = await element.all( 170 by.css('.tabs-navigation-bar a span'), 171 ); 172 173 const actualTabParagraphs = await Promise.all( 174 (tabParagraphs as ElementFinder[]).map( 175 async (paragraph) => await paragraph.getText(), 176 ), 177 ); 178 179 const expectedTabParagraphs = [ 180 'Surface Flinger', 181 'Transactions', 182 'Transitions', 183 'Window Manager', 184 ]; 185 186 expect(actualTabParagraphs.sort()).toEqual(expectedTabParagraphs.sort()); 187 } 188 189 async function sendRealtimeTimestampToWinscope(value: string) { 190 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 191 const inputElement = element(by.css('.input-timestamp')); 192 await inputElement.sendKeys(value); 193 const buttonElement = element(by.css('.button-send-realtime-timestamp')); 194 await buttonElement.click(); 195 } 196 197 async function sendBoottimeTimestampToWinscope(value: string) { 198 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 199 const inputElement = element(by.css('.input-timestamp')); 200 await inputElement.sendKeys(value); 201 const buttonElement = element(by.css('.button-send-boottime-timestamp')); 202 await buttonElement.click(); 203 } 204 205 async function sendTimestampToRemoteTool(value: string) { 206 browser.switchTo().window(await getWindowHandleWinscope()); 207 await E2eTestUtils.changeNsTimestampInWinscope(value); 208 } 209 210 async function checkWinscopeTimestamp(expectedValue: string) { 211 await browser.switchTo().window(await getWindowHandleWinscope()); 212 await E2eTestUtils.checkWinscopeNsTimestamp(expectedValue); 213 } 214 215 async function checkRemoteToolRealtimeTimestamp(expectedValue: string) { 216 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 217 const paragraphElement = element( 218 by.css('.paragraph-received-realtime-timestamp'), 219 ); 220 const actualValue = await paragraphElement.getText(); 221 expect(actualValue).toEqual(expectedValue); 222 } 223 224 async function checkRemoteToolBoottimeTimestamp(expectedValue: string) { 225 await browser.switchTo().window(await getWindowHandleRemoteToolMock()); 226 const paragraphElement = element( 227 by.css('.paragraph-received-boottime-timestamp'), 228 ); 229 const actualValue = await paragraphElement.getText(); 230 expect(actualValue).toEqual(expectedValue); 231 } 232 233 async function getWindowHandleRemoteToolMock(): Promise<string> { 234 const handles = await browser.getAllWindowHandles(); 235 expect(handles.length).toBeGreaterThan(0); 236 return handles[0]; 237 } 238 239 async function getWindowHandleWinscope(): Promise<string> { 240 const handles = await browser.getAllWindowHandles(); 241 expect(handles.length).toEqual(2); 242 return handles[1]; 243 } 244 245 async function clickCrossToolSyncButton() { 246 const button = element(by.css('.cross-tool-sync-button')); 247 await button.click(); 248 } 249}); 250