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 THREADS, 60 MEMORY, 61 LOCK_INSTANCES, 62 FILE_IO, 63 SOCKET_IO, 64 METHOD_PROFILING, 65 EXCEPTIONS, 66 THREAD_DUMPS, 67 JVM_INTERNALS, 68 GARBAGE_COLLECTIONS, 69 GC_CONFIG, 70 COMPILATIONS, 71 CODE_CACHE, 72 CLASS_LOADING, 73 VM_OPERATIONS, 74 ALLOCATIONS, 75 ENVIRONMENT, 76 PROCESSES, 77 ENVIRONMENT_VARIABLES, 78 SYSTEM_PROPS, 79 RECORDING; 80 81 public static String[] text(Tabs tab) { 82 String[] tabText = {""}; 83 switch (tab) { 84 case JVM_INTERNALS: 85 tabText = new String[] {"JVM Internals"}; 86 break; 87 case SYSTEM_PROPS: 88 tabText = new String[] {"Environment", "System Properties"}; 89 break; 90 case RECORDING: 91 tabText = new String[] {"Environment", "Recording"}; 92 break; 93 case GARBAGE_COLLECTIONS: 94 tabText = new String[] {"JVM Internals", "Garbage Collections"}; 95 break; 96 case GC_CONFIG: 97 tabText = new String[] {"JVM Internals", "GC Configuration"}; 98 break; 99 case ALLOCATIONS: 100 tabText = new String[] {"JVM Internals", "TLAB Allocations"}; 101 break; 102 case THREADS: 103 tabText = new String[] {"Java Application", "Threads"}; 104 break; 105 case MEMORY: 106 tabText = new String[] {"Java Application", "Memory"}; 107 break; 108 case METHOD_PROFILING: 109 tabText = new String[] {"Java Application", "Method Profiling"}; 110 break; 111 case JAVA_APPLICATION: 112 tabText = new String[] {"Java Application"}; 113 break; 114 case EXCEPTIONS: 115 tabText = new String[] {"Java Application", "Exceptions"}; 116 break; 117 case COMPILATIONS: 118 tabText = new String[] {"JVM Internals", "Compilations"}; 119 break; 120 case CODE_CACHE: 121 tabText = new String[] {"JVM Internals", "Compilations", "Code Cache"}; 122 break; 123 case CLASS_LOADING: 124 tabText = new String[] {"JVM Internals", "Class Loading"}; 125 break; 126 case VM_OPERATIONS: 127 tabText = new String[] {"JVM Internals", "VM Operations"}; 128 break; 129 case THREAD_DUMPS: 130 tabText = new String[] {"Java Application", "Thread Dumps"}; 131 break; 132 case LOCK_INSTANCES: 133 tabText = new String[] {"Java Application", "Lock Instances"}; 134 break; 135 case FILE_IO: 136 tabText = new String[] {"Java Application", "File I/O"}; 137 break; 138 case SOCKET_IO: 139 tabText = new String[] {"Java Application", "Socket I/O"}; 140 break; 141 case ENVIRONMENT: 142 tabText = new String[] {"Environment"}; 143 break; 144 case PROCESSES: 145 tabText = new String[] {"Environment", "Processes"}; 146 break; 147 case ENVIRONMENT_VARIABLES: 148 tabText = new String[] {"Environment", "Environment Variables"}; 149 break; 150 default: 151 break; 152 153 } 154 return tabText; 155 } 156 } 157 158 /** 159 * Opens the file in Mission Control, waits for the editor to show up and the system to become idle (all 160 * rendering and rule calculation done) 161 * 162 * @param file 163 * a file representing a flight recording 164 */ 165 public static void openJfr(File file) { 166 openJfr(file, true); 167 } 168 169 /** 170 * Opens the file in Mission Control, optionally waits for the editor to show up and the system to become 171 * idle (all rendering and rule calculation done) 172 * 173 * @param file 174 * a file representing a flight recording 175 * @param waitForEditor 176 * {@code true} if supposed to wait for the editor before returning. Otherwise 177 * will return immediately 178 */ 179 public static void openJfr(File file, boolean waitForEditor) { 180 openJfr(file, true, waitForEditor); 181 } 182 183 /** 184 * Opens the file in Mission Control, waits for the editor to show up and the system to become idle (all 185 * rendering and rule calculation done) 186 * 187 * @param file 188 * a file representing a flight recording 189 * @param handlePotentialDecompressionDialog 190 * {@code true} if a (potential) decompression dialog should be handled by 191 * clicking the Yes button. Otherwise won't check for the dialog 192 * @param waitForEditor 193 * {@code true} if supposed to wait for the editor before returning. Otherwise 194 * will return immediately 195 */ 196 public static void openJfr(File file, boolean handlePotentialDecompressionDialog, boolean waitForEditor) { 197 TestHelper.openJfr(file.getAbsolutePath()); 198 199 if (handlePotentialDecompressionDialog) { 200 String dialogText = org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages.FILE_OPENER_ZIPPED_FILE_TEXT; 201 MCDialog decompressDialog = MCDialog.getByDialogTitleAndText( 202 org.openjdk.jmc.flightrecorder.ui.messages.internal.Messages.FILE_OPENER_ZIPPED_FILE_TITLE, 203 dialogText.replace("{0}", file.getName()).substring(0, dialogText.indexOf("{1}"))); 204 if (decompressDialog != null) { 205 decompressDialog.clickButton(Labels.YES); 206 } 207 } 208 209 if (waitForEditor) { 210 Assert.assertTrue("Could not find JFR editor for file \"" + file.getName() + "\"", 211 waitForSubstringMatchedEditor(30000, file.getName())); 212 } 213 } 214 215 /** 216 * Switches to the Recording tab, parses the event settings table and returns an 217 * EventSettingsData object 218 * 219 * @return an EventSettingsData object with the settings of the currently opened recording 220 */ 221 public static EventSettingsData parseEventSettingsTable() { 222 JfrNavigator.selectTab(Tabs.RECORDING); 223 focusSectionByTitle("Event Settings", false); 224 MCTable settingsTable = getTables(false).get(0); 225 // Turning on the "End Time" column (if not already visible) 226 Integer index = settingsTable.getColumnIndex(END_TIME_COLUMN_HEADER); 227 if (index == null || index == -1) { 228 // ensuring that one (any) table item is focused before trying to context choose 229 settingsTable.click(); 230 settingsTable.contextChoose("Visible Columns", END_TIME_COLUMN_HEADER); 231 } 232 233 EventSettingsData settings = new EventSettingsData(); 234 List<TableRow> tableData = settingsTable.getRows(); 235 236 for (TableRow row : tableData) { 237 String eventName = row.getText(SETTING_FOR_COLUMN_HEADER); 238 String name = row.getText(SETTING_NAME_COLUMN_HEADER).replaceAll("[\\p{Z}]", " "); 239 String value = row.getText(SETTING_VALUE_COULMN_HEADER).replaceAll("[\\p{Z}]", " "); 240 String eventEndtime = row.getText(END_TIME_COLUMN_HEADER).replaceAll("[\\p{Z}]", " "); 241 settings.add(eventName, eventEndtime, name, value); 242 } 243 return settings; 244 } 245 246 public static String getRangeNavigatorStartTime() { 247 return MCLabel.getByName("navigator.start.time").getText(); 248 } 249 250 public static String getRangeNavigatorEndTime() { 251 return MCLabel.getByName("navigator.end.time").getText(); 252 } 253 254 public static void clickRangeNavigatorButton(RangeNavigatorButtons button) { 255 clickRangeNavigatorButton(button, 1); 256 } 257 258 public static void clickRangeNavigatorButton(RangeNavigatorButtons button, int times) { 259 MCButton.getByName(RangeNavigatorButtons.name(button)).click(times); 260 } 261 262 public static boolean isRangeNavigatorButtonEnabled(RangeNavigatorButtons button) { 263 return MCButton.getByName(RangeNavigatorButtons.name(button)).isEnabled(); 264 } 265 266 public static enum RangeNavigatorButtons { 267 ZOOMIN, ZOOMOUT, BACKWARD, FORWARD, ALL; 268 269 public static String name(RangeNavigatorButtons button) { 270 String result = ""; 271 switch (button) { 272 case ZOOMIN: 273 result = "navigator.zoom.in"; 274 break; 275 case ZOOMOUT: 276 result = "navigator.zoom.out"; 277 break; 278 case BACKWARD: 279 result = "navigator.move.backward"; 280 break; 281 case FORWARD: 282 result = "navigator.move.forward"; 283 break; 284 case ALL: 285 result = "navigator.select.all"; 286 break; 287 default: 288 break; 289 } 290 return result; 291 } 292 } 293 294 }