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.testlibrary.jfr; 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.testlibrary.Asserts; 51 import jdk.testlibrary.jfr.CommonHelper; 52 import jdk.testlibrary.jfr.Events; 53 54 public class JmxHelper { 55 56 public static RecordingInfo getJmxRecording(long recId) { 57 for (RecordingInfo r : getFlighteRecorderMXBean().getRecordings()) { 58 if (r.getId() == recId) { 59 return r; 60 } 61 } 62 Asserts.fail("No RecordingInfo with id " + recId); 63 return null; 64 } 65 66 public static Recording getJavaRecording(long recId) { 67 for (Recording r : FlightRecorder.getFlightRecorder().getRecordings()) { 68 if (r.getId() == recId) { 69 return r; 70 } 71 } 72 Asserts.fail("No Recording with id " + recId); 73 return null; 74 } 75 76 public static void verifyState(long recId, RecordingState state, List<RecordingInfo> recordings) { 77 RecordingInfo r = verifyExists(recId, recordings); 78 verifyState(r, state); 79 } 80 81 public static void verifyState(RecordingInfo recording, RecordingState state) { 82 final String actual = recording.getState().toString(); 83 final String expected = state.toString(); 84 Asserts.assertEquals(actual, expected, "Wrong state"); 85 } 86 87 public static void verifyState(long recId, RecordingState state, FlightRecorderMXBean bean) throws Exception { 88 FlightRecorder jfr = FlightRecorder.getFlightRecorder(); 89 Recording recording = CommonHelper.verifyExists(recId, jfr.getRecordings()); 90 CommonHelper.verifyRecordingState(recording, state); 91 verifyState(recId, state, bean.getRecordings()); 92 } 93 94 public static void verifyNotExists(long recId, List<RecordingInfo> recordings) { 95 for (RecordingInfo r : recordings) { 96 if (recId == r.getId()) { 97 logRecordingInfos(recordings); 98 Asserts.fail("Recording should not exist, id=" + recId); 99 } 100 } 101 } 102 103 public static RecordingInfo verifyExists(long recId, List<RecordingInfo> recordings) { 104 for (RecordingInfo r : recordings) { 105 if (recId == r.getId()) { 106 return r; 107 } 108 } 109 logRecordingInfos(recordings); 110 Asserts.fail("Recording not found, id=" + recId); 111 return null; 112 } 113 114 115 public static void logRecordingInfos(List<RecordingInfo> recordings) { 116 System.out.println("RecordingInfos:"); 117 for (RecordingInfo r : recordings) { 118 System.out.println(asString(r)); 119 } 120 } 121 122 public static void logRecordings(List<Recording> recordings) { 123 System.out.println("Recordings:"); 124 for (Recording r : recordings) { 125 System.out.println(asString(r)); 126 } 127 } 128 129 static File dump(long streamId, FlightRecorderMXBean bean) throws IOException { 130 File f = File.createTempFile("stream_" + streamId + "_", ".jfr", new File(".")); 131 try (FileOutputStream fos = new FileOutputStream(f); BufferedOutputStream bos = new BufferedOutputStream(fos)) { 132 while (true) { 133 byte[] data = bean.readStream(streamId); 134 if (data == null) { 135 bos.flush(); 136 return f; 137 } 138 bos.write(data); 139 } 140 } 141 } 142 143 public static List<RecordedEvent> parseStream(long streamId, FlightRecorderMXBean bean) throws Exception { 144 File dumpFile = dump(streamId, bean); 145 System.out.println("data.length=" + dumpFile.length()); 146 List<RecordedEvent> events = new ArrayList<>(); 147 for (RecordedEvent event : RecordingFile.readAllEvents(dumpFile.toPath())) { 148 System.out.println("EVENT:" + event); 149 events.add(event); 150 } 151 return events; 152 } 153 154 public static void verifyEquals(RecordingInfo ri, Recording r) { 155 String destination = r.getDestination() != null ? r.getDestination().toString() : null; 156 long maxAge = r.getMaxAge() != null ? r.getMaxAge().getSeconds() : 0; 157 long duration = r.getDuration() != null ? r.getDuration().getSeconds() : 0; 158 159 Asserts.assertEquals(destination, ri.getDestination(), "Wrong destination"); 160 Asserts.assertEquals(r.getDumpOnExit(), ri.getDumpOnExit(), "Wrong dumpOnExit"); 161 Asserts.assertEquals(duration, ri.getDuration(), "Wrong duration"); 162 Asserts.assertEquals(r.getId(), ri.getId(), "Wrong id"); 163 Asserts.assertEquals(maxAge, ri.getMaxAge(), "Wrong maxAge"); 164 Asserts.assertEquals(r.getMaxSize(), ri.getMaxSize(), "Wrong maxSize"); 165 Asserts.assertEquals(r.getName(), ri.getName(), "Wrong name"); 166 Asserts.assertEquals(r.getSize(), ri.getSize(), "Wrong size"); 167 Asserts.assertEquals(toEpochMillis(r.getStartTime()), ri.getStartTime(), "Wrong startTime"); 168 Asserts.assertEquals(r.getState().toString(), ri.getState(), "Wrong state"); 169 Asserts.assertEquals(toEpochMillis(r.getStopTime()), ri.getStopTime(), "Wrong stopTime"); 170 171 verifyMapEquals(r.getSettings(), ri.getSettings()); 172 } 173 174 public static String asString(RecordingInfo r) { 175 StringBuffer sb = new StringBuffer(); 176 sb.append(String.format("RecordingInfo:%n")); 177 sb.append(String.format("destination=%s%n", r.getDestination())); 178 sb.append(String.format("dumpOnExit=%b%n", r.getDumpOnExit())); 179 sb.append(String.format("duration=%d%n", r.getDuration())); 180 sb.append(String.format("id=%d%n", r.getId())); 181 sb.append(String.format("maxAge=%d%n", r.getMaxAge())); 182 sb.append(String.format("maxSize=%d%n", r.getMaxSize())); 183 sb.append(String.format("getName=%s%n", r.getName())); 184 sb.append(String.format("size=%d%n", r.getSize())); 185 sb.append(String.format("startTime=%d%n", r.getStartTime())); 186 sb.append(String.format("state=%s%n", r.getState())); 187 sb.append(String.format("stopTime=%d%n", r.getStopTime())); 188 return sb.toString(); 189 } 190 191 public static String asString(Recording r) { 192 StringBuffer sb = new StringBuffer(); 193 sb.append(String.format("Recording:%n")); 194 sb.append(String.format("destination=%s%n", r.getDestination())); 195 sb.append(String.format("dumpOnExit=%b%n", r.getDumpOnExit())); 196 sb.append(String.format("duration=%d%n", r.getDuration().getSeconds())); 197 sb.append(String.format("id=%d%n", r.getId())); 198 sb.append(String.format("maxAge=%d%n", r.getMaxAge().getSeconds())); 199 sb.append(String.format("maxSize=%d%n", r.getMaxSize())); 200 sb.append(String.format("getName=%s%n", r.getName())); 201 sb.append(String.format("size=%d%n", r.getSize())); 202 sb.append(String.format("startTime=%d%n", toEpochMillis(r.getStartTime()))); 203 sb.append(String.format("state=%s%n", r.getState())); 204 sb.append(String.format("stopTime=%d%n", toEpochMillis(r.getStopTime()))); 205 return sb.toString(); 206 } 207 208 public static void verifyMapEquals(Map<String, String> a, Map<String, String> b) { 209 try { 210 Asserts.assertEquals(a.size(), b.size(), "Wrong number of keys"); 211 for (String key : a.keySet()) { 212 Asserts.assertTrue(a.containsKey(key), "Missing key " + key); 213 Asserts.assertEquals(a.get(key), b.get(key), "Wrong values for key " + key); 214 //System.out.printf("equal: %s=%s%n", key, a.get(key)); 215 } 216 } catch (Exception e) { 217 System.out.println("Error: " + e.getMessage()); 218 logMap("a", a); 219 logMap("b", b); 220 throw e; 221 } 222 } 223 224 public static void logMap(String name, Map<String, String> map) { 225 for (String key : map.keySet()) { 226 System.out.printf("map %s: %s=%s%n", name, key, map.get(key)); 227 } 228 } 229 230 private static long toEpochMillis(Instant instant) { 231 return instant != null ? instant.toEpochMilli() : 0; 232 } 233 234 public static void verifyEventSettingsEqual(EventType javaType, EventTypeInfo jmxType) { 235 Map<String, SettingDescriptor> javaSettings = new HashMap<>(); 236 for (SettingDescriptor settingDescriptor : javaType.getSettingDescriptors()) { 237 javaSettings.put(settingDescriptor.getName(), settingDescriptor); 238 } 239 Asserts.assertFalse(javaSettings.isEmpty(), "No ValueDescriptor for EventType " + javaType.getName()); 240 241 for (SettingDescriptorInfo jmxSetting : jmxType.getSettingDescriptors()) { 242 final String name = jmxSetting.getName(); 243 System.out.printf("SettingDescriptorInfo: %s#%s=%s%n", jmxType.getName(), name, jmxSetting.getDefaultValue()); 244 SettingDescriptor javaSetting = javaSettings.remove(name); 245 Asserts.assertNotNull(javaSetting, "No Setting for name " + name); 246 Asserts.assertEquals(jmxSetting.getDefaultValue(), Events.getSetting(javaType, name).getDefaultValue(), "Wrong default value"); 247 Asserts.assertEquals(jmxSetting.getDescription(), javaSetting.getDescription(), "Wrong description"); 248 Asserts.assertEquals(jmxSetting.getLabel(), javaSetting.getLabel(), "Wrong label"); 249 Asserts.assertEquals(jmxSetting.getName(), javaSetting.getName(), "Wrong name"); 250 Asserts.assertEquals(jmxSetting.getTypeName(), javaSetting.getTypeName(), "Wrong type name"); 251 Asserts.assertEquals(jmxSetting.getContentType(), javaSetting.getContentType()); 252 } 253 254 // Verify that all Settings have been matched. 255 if (!javaSettings.isEmpty()) { 256 for (String name : javaSettings.keySet()) { 257 System.out.println("Missing setting" + name + " in EventTypeInfo for " + javaType.getName()); 258 } 259 System.out.println(); 260 System.out.println(javaType.getName() + " Java API"); 261 System.out.println("==============="); 262 for (SettingDescriptor v : javaType.getSettingDescriptors()) { 263 System.out.println(" - " + v.getName()); 264 } 265 System.out.println(); 266 System.out.println(jmxType.getName() + " JMX API"); 267 System.out.println("==============="); 268 for (SettingDescriptorInfo v : jmxType.getSettingDescriptors()) { 269 System.out.println(" - " + v.getName()); 270 } 271 272 Asserts.fail("Missing setting"); 273 } 274 } 275 276 277 public static FlightRecorderMXBean getFlighteRecorderMXBean() { 278 return ManagementFactory.getPlatformMXBean(FlightRecorderMXBean.class); 279 } 280 281 }