--- /dev/null 2017-11-09 09:38:01.297999907 +0100 +++ new/test/lib/jdk/test/lib/jfr/Events.java 2018-04-09 19:08:23.344034490 +0200 @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertNotNull; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Asserts.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.EventType; +import jdk.jfr.Recording; +import jdk.jfr.SettingDescriptor; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.Asserts; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.consumer.RecordedThreadGroup; + + +/** + * Helper class to verify RecordedEvent content + */ +public class Events { + + public static EventField assertField(RecordedEvent event, String name) { + String[] partNames = name.split("\\."); + RecordedObject struct = event; + try { + for (int i=0; i valueDescriptors = struct.getFields(); + for (ValueDescriptor d : valueDescriptors) { + if (name.equals(d.getName())) { + return d; + } + } + System.out.printf("Failed struct:%s", struct.toString()); + fail(String.format("Field %s not in struct", name)); + return null; + } + + public static void hasEvents(List events) { + assertFalse(events.isEmpty(), "No events"); + } + + public static void hasEvents(RecordingFile file) { + assertTrue(file.hasMoreEvents(), "No events"); + } + + public static void assertEventThread(RecordedEvent event) { + RecordedThread eventThread = event.getThread(); + if (eventThread == null) { + System.out.printf("Failed event:%n%s%n", event.toString()); + fail("No thread in event"); + } + } + + public static void assertJavaMethod(RecordedEvent event) { + assertField(event, "method.name").notEmpty(); + assertField(event, "method.descriptor").notEmpty(); + assertField(event, "method.modifiers").atLeast(0); + assertField(event, "method.hidden"); + assertField(event, "method.type.name").notEmpty(); + assertField(event, "method.type.modifiers").atLeast(0); + } + + public static void assertEventThread(RecordedEvent event, Thread thread) { + assertThread(event.getThread(), thread); + } + + public static void assertEventThread(RecordedEvent event, String structName, Thread thread) { + assertThread(assertField(event, structName).notNull().getValue(), thread); + } + + private static void assertThread(RecordedThread eventThread, Thread thread) { + assertNotNull(eventThread, "Thread in event was null"); + assertEquals(eventThread.getJavaThreadId(), thread.getId(), "Wrong thread id"); + assertEquals(eventThread.getJavaName(), thread.getName(), "Wrong thread name"); + + ThreadGroup threadGroup = thread.getThreadGroup(); + RecordedThreadGroup eventThreadGroup = eventThread.getThreadGroup(); + assertNotNull(eventThreadGroup, "eventThreadGroup was null"); + + // Iterate and check all threadGroups + while (eventThreadGroup != null) { + final String groupName = eventThreadGroup.getName(); + if (threadGroup != null) { + assertEquals(groupName, threadGroup.getName(), "Wrong threadGroup name"); + threadGroup = threadGroup.getParent(); + } else { + assertNotNull(groupName, "threadGroup name was null"); + assertFalse(groupName.isEmpty(), "threadGroup name was empty"); + } + eventThreadGroup = eventThreadGroup.getParent(); + } + } + + public static boolean hasField(RecordedEvent event, String name) { + return event.getFields().stream().map(vd -> vd.getName()).anyMatch(s -> s.equals(name)); + } + + public static boolean isEventType(RecordedEvent event, String typeName) { + return typeName.equals(event.getEventType().getName()); + } + + + /** + * Creates a list of events from a recording. + * + * @param recording recording, not {@code null} + * @return an a list, not null + * @throws IOException if an event set could not be created due to I/O + * errors. + */ + public static List fromRecording(Recording recording) throws IOException { + return RecordingFile.readAllEvents(makeCopy(recording)); + } + + public static RecordingFile copyTo(Recording r) throws IOException { + return new RecordingFile(makeCopy(r)); + } + + private static Path makeCopy(Recording recording) throws IOException { + Path p = recording.getDestination(); + if (p == null) { + File directory = new File("."); + // FIXME: Must come up with a way to give human-readable name + // this will at least not clash when running parallel. + ProcessHandle h = ProcessHandle.current(); + p = new File(directory.getAbsolutePath(), "recording-" + recording.getId() + "-pid" + h.pid() + ".jfr").toPath(); + recording.dump(p); + } + return p; + } + + public static void hasAnnotation(ValueDescriptor field, Class annotationClass) throws Exception { + AnnotationElement a = getAnnotation(field, annotationClass); + if (a == null) { + throw new Exception("Expected " + annotationClass.getSimpleName() + " on field " + field.getName()); + } + } + + public static void assertAnnotation(ValueDescriptor field, Class annotationClass, String value) throws Exception { + AnnotationElement a = getAnnotation(field, annotationClass); + Object v = a.getValue("value"); + if (!v.equals(value)) { + throw new Exception("Expected " + annotationClass.getSimpleName() + " on field " + field.getName() + " to have value " + value + ", but got " + v); + } + } + + // candidate for moving into API + public static AnnotationElement getAnnotation(ValueDescriptor v, Class clazz) throws Exception { + for (AnnotationElement a : v.getAnnotationElements()) { + if (a.getTypeName().equals(clazz.getName())) { + return a; + } + } + + throw new Exception("Could not find annotation " + clazz.getName()); + } + + // candidate for moving into API + public static AnnotationElement getAnnotationByName(EventType t, String name) throws Exception { + for (AnnotationElement a : t.getAnnotationElements()) { + if (a.getTypeName().equals(name)) { + return a; + } + } + throw new Exception("Could not find annotation '" + name + " in type " + t.getName()); + } + + // candidate for moving into API + public static SettingDescriptor getSetting(EventType type, String name) { + for (SettingDescriptor s : type.getSettingDescriptors()) { + if (s.getName().equals(name)) { + return s; + } + } + throw new IllegalArgumentException("Could not setting with name " + name); + } + + public static void hasEvent(Recording r, String name) throws IOException { + List events = fromRecording(r); + Events.hasEvents(events); + Events.hasEvent(events, name); + } + + public static void hasEvent(List events, String name) throws IOException { + if (!containsEvent(events, name)) { + Asserts.fail("Missing event " + name + " in recording " + events.toString()); + } + } + + public static void hasNotEvent(List events, String name) throws IOException { + if (containsEvent(events, name)) { + Asserts.fail("Rercording should not contain event " + name + " " + events.toString()); + } + } + + private static boolean containsEvent(List events, String name) { + for (RecordedEvent event : events) { + if (event.getEventType().getName().equals(name)) { + return true; + } + } + return false; + } +}