1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * The contents of this file are subject to the terms of either the Universal Permissive License 7 * v 1.0 as shown at http://oss.oracle.com/licenses/upl 8 * 9 * or the following license: 10 * 11 * Redistribution and use in source and binary forms, with or without modification, are permitted 12 * provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions 15 * and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 18 * conditions and the following disclaimer in the documentation and/or other materials provided with 19 * the distribution. 20 * 21 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to 22 * endorse or promote products derived from this software without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 26 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 31 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 package org.openjdk.jmc.test.jemmy.misc.wrappers; 34 35 import java.io.File; 36 import java.util.List; 37 38 import org.junit.Assert; 39 import org.openjdk.jmc.test.jemmy.TestHelper; 40 import org.openjdk.jmc.test.jemmy.misc.base.wrappers.MCJemmyBase; 41 import org.openjdk.jmc.test.jemmy.misc.helpers.EventSettingsData; 42 import org.openjdk.jmc.test.jemmy.misc.wrappers.MCButton.Labels; 43 import org.openjdk.jmc.test.jemmy.misc.wrappers.MCTable.TableRow; 44 45 /** 46 * The Jemmy wrapper for the Flight Recorder UI 47 */ 48 public class JfrUi extends MCJemmyBase { 49 public static final String END_TIME_COLUMN_HEADER = "End Time"; 50 public static final String SETTING_VALUE_COULMN_HEADER = "Setting Value"; 51 public static final String SETTING_NAME_COLUMN_HEADER = "Setting Name"; 52 public static final String SETTING_FOR_COLUMN_HEADER = "Setting For"; 53 54 /* 55 * Members ======= List of tabs 56 */ 57 public static enum Tabs { 58 JAVA_APPLICATION, 59 MEMORY, 60 LOCK_INSTANCES, 61 FILE_IO, 62 SOCKET_IO, 63 METHOD_PROFILING, 64 EXCEPTIONS, 65 THREAD_DUMPS, 66 JVM_INTERNALS, 67 GARBAGE_COLLECTIONS, 68 GC_CONFIG, 69 COMPILATIONS, 70 CODE_CACHE, 71 CLASS_LOADING, 72 VM_OPERATIONS, 73 ALLOCATIONS, 74 ENVIRONMENT, 75 PROCESSES, 76 ENVIRONMENT_VARIABLES, 77 SYSTEM_PROPS, 78 RECORDING; 79 80 public static String[] text(Tabs tab) { 81 String[] tabText = {""}; 82 switch (tab) { 83 case JVM_INTERNALS: 84 tabText = new String[] {"JVM Internals"}; 85 break; 86 case SYSTEM_PROPS: 87 tabText = new String[] {"Environment", "System Properties"}; 88 break; 89 case RECORDING: 90 tabText = new String[] {"Environment", "Recording"}; 91 break; 92 case GARBAGE_COLLECTIONS: 93 tabText = new String[] {"JVM Internals", "Garbage Collections"}; 94 break; 95 case GC_CONFIG: 96 tabText = new String[] {"JVM Internals", "GC Configuration"}; 97 break; 98 case ALLOCATIONS: 99 tabText = new String[] {"JVM Internals", "TLAB Allocations"}; 100 break; 101 case MEMORY: 102 tabText = new String[] {"Java Application", "Memory"}; 103 break; 104 case METHOD_PROFILING: 105 tabText = new String[] {"Java Application", "Method Profiling"}; 106 break; 107 case JAVA_APPLICATION: 108 tabText = new String[] {"Java Application"}; 109 break; 110 case EXCEPTIONS: 111 tabText = new String[] {"Java Application", "Exceptions"}; 112 break; 113 case COMPILATIONS: 114 tabText = new String[] {"JVM Internals", "Compilations"}; 115 break; 116 case CODE_CACHE: 117 tabText = new String[] {"JVM Internals", "Compilations", "Code Cache"}; 118 break; 119 case CLASS_LOADING: 120 tabText = new String[] {"JVM Internals", "Class Loading"}; 121 break; 122 case VM_OPERATIONS: 123 tabText = new String[] {"JVM Internals", "VM Operations"}; 124 break; 125 case THREAD_DUMPS: 126 tabText = new String[] {"Java Application", "Thread Dumps"}; 127 break; 128 case LOCK_INSTANCES: 129 tabText = new String[] {"Java Application", "Lock Instances"}; 130 break; 131 case FILE_IO: 132 tabText = new String[] {"Java Application", "File I/O"}; 133 break; 134 case SOCKET_IO: 135 tabText = new String[] {"Java Application", "Socket I/O"}; 136 break; 137 case ENVIRONMENT: 138 tabText = new String[] {"Environment"}; 139 break; 140 case PROCESSES: 141 tabText = new String[] {"Environment", "Processes"}; 142 break; 143 case ENVIRONMENT_VARIABLES: 144 tabText = new String[] {"Environment", "Environment Variables"}; 145 break; 146 default: 147 break; 148 149 } 150 return tabText; 151 } 152 } 153 154 /** 155 * Opens the file in Mission Control, waits for the editor to show up and the system to become idle (all 156 * rendering and rule calculation done) 157 * 158 * @param file 159 * a file representing a flight recording 160 */ 161 public static void openJfr(File file) { 162 openJfr(file, true); 163 } 164 165 /** 166 * Opens the file in Mission Control, optionally waits for the editor to show up and the system to become 167 * idle (all rendering and rule calculation done) 168 * 169 * @param file 170 * a file representing a flight recording 171 * @param waitForEditor 172 * {@code true} if supposed to wait for the editor before returning. Otherwise 173 * will return immediately 174 */ 175 public static void openJfr(File file, boolean waitForEditor) { 176 openJfr(file, true, waitForEditor); 177 } 178 179 /** 180 * Opens the file in Mission Control, waits for the editor to show up and the system to become idle (all 181 * rendering and rule calculation done) 182 * 183 * @param file 184 * a file representing a flight recording 185 * @param handlePotentialDecompressionDialog 186 * {@code true} if a (potential) decompression dialog should be handled by 187 * clicking the Yes button. Otherwise won't check for the dialog 188 * @param waitForEditor 189 * {@code true} if supposed to wait for the editor before returning. Otherwise 190 * will return immediately 191 */ 192 public static void openJfr(File file, boolean handlePotentialDecompressionDialog, boolean waitForEditor) { 193 TestHelper.openJfr(file.getAbsolutePath()); 194 195 if (handlePotentialDecompressionDialog) { 196 String dialogText = org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages.FILE_OPENER_ZIPPED_FILE_TEXT; 197 MCDialog decompressDialog = MCDialog.getByDialogTitleAndText( 198 org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages.FILE_OPENER_ZIPPED_FILE_TITLE, 199 dialogText.replace("{0}", file.getName()).substring(0, dialogText.indexOf("{1}"))); 200 if (decompressDialog != null) { 201 decompressDialog.clickButton(Labels.YES); 202 } 203 } 204 205 if (waitForEditor) { 206 Assert.assertTrue("Could not find JFR editor for file \"" + file.getName() + "\"", 207 waitForSubstringMatchedEditor(30000, file.getName())); 208 } 209 } 210 211 /** 212 * Switches to the Recording tab, parses the event settings table and returns an 213 * EventSettingsData object 214 * 215 * @return an EventSettingsData object with the settings of the currently opened recording 216 */ 217 public static EventSettingsData parseEventSettingsTable() { 218 JfrNavigator.selectTab(Tabs.RECORDING); 219 focusSectionByTitle("Event Settings", false); 220 MCTable settingsTable = getTables(false).get(0); 221 // Turning on the "End Time" column (if not already visible) 222 Integer index = settingsTable.getColumnIndex(END_TIME_COLUMN_HEADER); 223 if (index == null || index == -1) { 224 // ensuring that one (any) table item is focused before trying to context choose 225 settingsTable.click(); 226 settingsTable.contextChoose("Visible Columns", END_TIME_COLUMN_HEADER); 227 } 228 229 EventSettingsData settings = new EventSettingsData(); 230 List<TableRow> tableData = settingsTable.getRows(); 231 232 for (TableRow row : tableData) { 233 String eventName = row.getText(SETTING_FOR_COLUMN_HEADER); 234 String name = row.getText(SETTING_NAME_COLUMN_HEADER).replaceAll("[\\p{Z}]", " "); 235 String value = row.getText(SETTING_VALUE_COULMN_HEADER).replaceAll("[\\p{Z}]", " "); 236 String eventEndtime = row.getText(END_TIME_COLUMN_HEADER).replaceAll("[\\p{Z}]", " "); 237 settings.add(eventName, eventEndtime, name, value); 238 } 239 return settings; 240 } 241 242 public static String getRangeNavigatorStartTime() { 243 return MCLabel.getByName("navigator.start.time").getText(); 244 } 245 246 public static String getRangeNavigatorEndTime() { 247 return MCLabel.getByName("navigator.end.time").getText(); 248 } 249 250 public static void clickRangeNavigatorButton(RangeNavigatorButtons button) { 251 clickRangeNavigatorButton(button, 1); 252 } 253 254 public static void clickRangeNavigatorButton(RangeNavigatorButtons button, int times) { 255 MCButton.getByName(RangeNavigatorButtons.name(button)).click(times); 256 } 257 258 public static boolean isRangeNavigatorButtonEnabled(RangeNavigatorButtons button) { 259 return MCButton.getByName(RangeNavigatorButtons.name(button)).isEnabled(); 260 } 261 262 public static enum RangeNavigatorButtons { 263 ZOOMIN, ZOOMOUT, BACKWARD, FORWARD, ALL; 264 265 public static String name(RangeNavigatorButtons button) { 266 String result = ""; 267 switch (button) { 268 case ZOOMIN: 269 result = "navigator.zoom.in"; 270 break; 271 case ZOOMOUT: 272 result = "navigator.zoom.out"; 273 break; 274 case BACKWARD: 275 result = "navigator.move.backward"; 276 break; 277 case FORWARD: 278 result = "navigator.move.forward"; 279 break; 280 case ALL: 281 result = "navigator.select.all"; 282 break; 283 default: 284 break; 285 } 286 return result; 287 } 288 } 289 290 }