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 }