1 /* 2 * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.jmx; 27 28 import java.io.BufferedOutputStream; 29 import java.io.File; 30 import java.io.FileOutputStream; 31 import java.io.IOException; 32 import java.lang.management.ManagementFactory; 33 import java.time.Instant; 34 import java.util.ArrayList; 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 39 import jdk.jfr.EventType; 40 import jdk.jfr.FlightRecorder; 41 import jdk.jfr.Recording; 42 import jdk.jfr.RecordingState; 43 import jdk.jfr.SettingDescriptor; 44 import jdk.jfr.consumer.RecordedEvent; 45 import jdk.jfr.consumer.RecordingFile; 46 import jdk.management.jfr.EventTypeInfo; 47 import jdk.management.jfr.FlightRecorderMXBean; 48 import jdk.management.jfr.RecordingInfo; 49 import jdk.management.jfr.SettingDescriptorInfo; 50 import jdk.test.lib.Asserts; 51 import jdk.test.lib.Utils; 52 import jdk.test.lib.jfr.CommonHelper; 53 import jdk.test.lib.jfr.Events; 54 55 public class JmxHelper { 56 57 public static RecordingInfo getJmxRecording(long recId) { 58 for (RecordingInfo r : getFlighteRecorderMXBean().getRecordings()) { 59 if (r.getId() == recId) { 60 return r; 61 } 62 } 63 Asserts.fail("No RecordingInfo with id " + recId); 64 return null; 65 } 66 67 public static Recording getJavaRecording(long recId) { 68 for (Recording r : FlightRecorder.getFlightRecorder().getRecordings()) { 69 if (r.getId() == recId) { 70 return r; 71 } 72 } 73 Asserts.fail("No Recording with id " + recId); 74 return null; 75 } 76 77 public static void verifyState(long recId, RecordingState state, List<RecordingInfo> recordings) { 78 RecordingInfo r = verifyExists(recId, recordings); 79 verifyState(r, state); 80 } 81 82 public static void verifyState(RecordingInfo recording, RecordingState state) { 83 final String actual = recording.getState().toString(); 84 final String expected = state.toString(); 85 Asserts.assertEquals(actual, expected, "Wrong state"); 86 } 87 88 public static void verifyState(long recId, RecordingState state, FlightRecorderMXBean bean) throws Exception { 89 FlightRecorder jfr = FlightRecorder.getFlightRecorder(); 90 Recording recording = CommonHelper.verifyExists(recId, jfr.getRecordings()); 91 CommonHelper.verifyRecordingState(recording, state); 92 verifyState(recId, state, bean.getRecordings()); 93 } 94 95 public static void verifyNotExists(long recId, List<RecordingInfo> recordings) { 96 for (RecordingInfo r : recordings) { 97 if (recId == r.getId()) { 98 logRecordingInfos(recordings); 99 Asserts.fail("Recording should not exist, id=" + recId); 100 } 101 } 102 } 103 104 public static RecordingInfo verifyExists(long recId, List<RecordingInfo> recordings) { 105 for (RecordingInfo r : recordings) { 106 if (recId == r.getId()) { 107 return r; 108 } 109 } 110 logRecordingInfos(recordings); 111 Asserts.fail("Recording not found, id=" + recId); 112 return null; 113 } 114 115 116 public static void logRecordingInfos(List<RecordingInfo> recordings) { 117 System.out.println("RecordingInfos:"); 118 for (RecordingInfo r : recordings) { 119 System.out.println(asString(r)); 120 } 121 } 122 123 public static void logRecordings(List<Recording> recordings) { 124 System.out.println("Recordings:"); 125 for (Recording r : recordings) { 126 System.out.println(asString(r)); 127 } 128 } 129 130 static File dump(long streamId, FlightRecorderMXBean bean) throws IOException { 131 File f = Utils.createTempFile("stream_" + streamId + "_", ".jfr").toFile(); 132 try (FileOutputStream fos = new FileOutputStream(f); BufferedOutputStream bos = new BufferedOutputStream(fos)) { 133 while (true) { 134 byte[] data = bean.readStream(streamId); 135 if (data == null) { 136 bos.flush(); 137 return f; 138 } 139 bos.write(data); 140 } 141 } 142 } 143 144 public static List<RecordedEvent> parseStream(long streamId, FlightRecorderMXBean bean) throws Exception { 145 File dumpFile = dump(streamId, bean); 146 System.out.println("data.length=" + dumpFile.length()); 147 List<RecordedEvent> events = new ArrayList<>(); 148 for (RecordedEvent event : RecordingFile.readAllEvents(dumpFile.toPath())) { 149 System.out.println("EVENT:" + event); 150 events.add(event); 151 } 152 return events; 153 } 154 155 public static void verifyEquals(RecordingInfo ri, Recording r) { 156 String destination = r.getDestination() != null ? r.getDestination().toString() : null; 157 long maxAge = r.getMaxAge() != null ? r.getMaxAge().getSeconds() : 0; 158 long duration = r.getDuration() != null ? r.getDuration().getSeconds() : 0; 159 160 Asserts.assertEquals(destination, ri.getDestination(), "Wrong destination"); 161 Asserts.assertEquals(r.getDumpOnExit(), ri.getDumpOnExit(), "Wrong dumpOnExit"); 162 Asserts.assertEquals(duration, ri.getDuration(), "Wrong duration"); 163 Asserts.assertEquals(r.getId(), ri.getId(), "Wrong id"); 164 Asserts.assertEquals(maxAge, ri.getMaxAge(), "Wrong maxAge"); 165 Asserts.assertEquals(r.getMaxSize(), ri.getMaxSize(), "Wrong maxSize"); 166 Asserts.assertEquals(r.getName(), ri.getName(), "Wrong name"); 167 Asserts.assertEquals(r.getSize(), ri.getSize(), "Wrong size"); 168 Asserts.assertEquals(toEpochMillis(r.getStartTime()), ri.getStartTime(), "Wrong startTime"); 169 Asserts.assertEquals(r.getState().toString(), ri.getState(), "Wrong state"); 170 Asserts.assertEquals(toEpochMillis(r.getStopTime()), ri.getStopTime(), "Wrong stopTime"); 171 172 verifyMapEquals(r.getSettings(), ri.getSettings()); 173 } 174 175 public static String asString(RecordingInfo r) { 176 StringBuffer sb = new StringBuffer(); 177 sb.append(String.format("RecordingInfo:%n")); 178 sb.append(String.format("destination=%s%n", r.getDestination())); 179 sb.append(String.format("dumpOnExit=%b%n", r.getDumpOnExit())); 180 sb.append(String.format("duration=%d%n", r.getDuration())); 181 sb.append(String.format("id=%d%n", r.getId())); 182 sb.append(String.format("maxAge=%d%n", r.getMaxAge())); 183 sb.append(String.format("maxSize=%d%n", r.getMaxSize())); 184 sb.append(String.format("getName=%s%n", r.getName())); 185 sb.append(String.format("size=%d%n", r.getSize())); 186 sb.append(String.format("startTime=%d%n", r.getStartTime())); 187 sb.append(String.format("state=%s%n", r.getState())); 188 sb.append(String.format("stopTime=%d%n", r.getStopTime())); 189 return sb.toString(); 190 } 191 192 public static String asString(Recording r) { 193 StringBuffer sb = new StringBuffer(); 194 sb.append(String.format("Recording:%n")); 195 sb.append(String.format("destination=%s%n", r.getDestination())); 196 sb.append(String.format("dumpOnExit=%b%n", r.getDumpOnExit())); 197 sb.append(String.format("duration=%d%n", r.getDuration().getSeconds())); 198 sb.append(String.format("id=%d%n", r.getId())); 199 sb.append(String.format("maxAge=%d%n", r.getMaxAge().getSeconds())); 200 sb.append(String.format("maxSize=%d%n", r.getMaxSize())); 201 sb.append(String.format("getName=%s%n", r.getName())); 202 sb.append(String.format("size=%d%n", r.getSize())); 203 sb.append(String.format("startTime=%d%n", toEpochMillis(r.getStartTime()))); 204 sb.append(String.format("state=%s%n", r.getState())); 205 sb.append(String.format("stopTime=%d%n", toEpochMillis(r.getStopTime()))); 206 return sb.toString(); 207 } 208 209 public static void verifyMapEquals(Map<String, String> a, Map<String, String> b) { 210 try { 211 Asserts.assertEquals(a.size(), b.size(), "Wrong number of keys"); 212 for (String key : a.keySet()) { 213 Asserts.assertTrue(a.containsKey(key), "Missing key " + key); 214 Asserts.assertEquals(a.get(key), b.get(key), "Wrong values for key " + key); 215 //System.out.printf("equal: %s=%s%n", key, a.get(key)); 216 } 217 } catch (Exception e) { 218 System.out.println("Error: " + e.getMessage()); 219 logMap("a", a); 220 logMap("b", b); 221 throw e; 222 } 223 } 224 225 public static void logMap(String name, Map<String, String> map) { 226 for (String key : map.keySet()) { 227 System.out.printf("map %s: %s=%s%n", name, key, map.get(key)); 228 } 229 } 230 231 private static long toEpochMillis(Instant instant) { 232 return instant != null ? instant.toEpochMilli() : 0; 233 } 234 235 public static void verifyEventSettingsEqual(EventType javaType, EventTypeInfo jmxType) { 236 Map<String, SettingDescriptor> javaSettings = new HashMap<>(); 237 for (SettingDescriptor settingDescriptor : javaType.getSettingDescriptors()) { 238 javaSettings.put(settingDescriptor.getName(), settingDescriptor); 239 } 240 Asserts.assertFalse(javaSettings.isEmpty(), "No ValueDescriptor for EventType " + javaType.getName()); 241 242 for (SettingDescriptorInfo jmxSetting : jmxType.getSettingDescriptors()) { 243 final String name = jmxSetting.getName(); 244 System.out.printf("SettingDescriptorInfo: %s#%s=%s%n", jmxType.getName(), name, jmxSetting.getDefaultValue()); 245 SettingDescriptor javaSetting = javaSettings.remove(name); 246 Asserts.assertNotNull(javaSetting, "No Setting for name " + name); 247 Asserts.assertEquals(jmxSetting.getDefaultValue(), Events.getSetting(javaType, name).getDefaultValue(), "Wrong default value"); 248 Asserts.assertEquals(jmxSetting.getDescription(), javaSetting.getDescription(), "Wrong description"); 249 Asserts.assertEquals(jmxSetting.getLabel(), javaSetting.getLabel(), "Wrong label"); 250 Asserts.assertEquals(jmxSetting.getName(), javaSetting.getName(), "Wrong name"); 251 Asserts.assertEquals(jmxSetting.getTypeName(), javaSetting.getTypeName(), "Wrong type name"); 252 Asserts.assertEquals(jmxSetting.getContentType(), javaSetting.getContentType()); 253 } 254 255 // Verify that all Settings have been matched. 256 if (!javaSettings.isEmpty()) { 257 for (String name : javaSettings.keySet()) { 258 System.out.println("Missing setting" + name + " in EventTypeInfo for " + javaType.getName()); 259 } 260 System.out.println(); 261 System.out.println(javaType.getName() + " Java API"); 262 System.out.println("==============="); 263 for (SettingDescriptor v : javaType.getSettingDescriptors()) { 264 System.out.println(" - " + v.getName()); 265 } 266 System.out.println(); 267 System.out.println(jmxType.getName() + " JMX API"); 268 System.out.println("==============="); 269 for (SettingDescriptorInfo v : jmxType.getSettingDescriptors()) { 270 System.out.println(" - " + v.getName()); 271 } 272 273 Asserts.fail("Missing setting"); 274 } 275 } 276 277 278 public static FlightRecorderMXBean getFlighteRecorderMXBean() { 279 return ManagementFactory.getPlatformMXBean(FlightRecorderMXBean.class); 280 } 281 282 }