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 }