Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ private Boolean initEventClass(ResolvedJavaType eventType) throws RuntimeExcepti
eventType.initialize();

if (JavaVersionUtil.JAVA_SPEC < 22) {
// It is crucial that mirror events are registered before the actual events.
/*
* It is crucial that mirror events are registered before the actual events.
* Starting with JDK 22, this is no longer necessary because
* MetadataRepository.register(...) handles that directly, see code that uses
* MirrorEvents.find(...).
*/
Class<? extends jdk.jfr.Event> mirrorEventClass = mirrorEventMapping.get(newEventClass.getName());
if (mirrorEventClass != null) {
registerMirror.invoke(null, mirrorEventClass);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,22 +86,22 @@ protected static Configuration getDefaultConfiguration() throws Throwable {
return Configuration.getConfiguration("default");
}

protected static void checkRecording(EventValidator validator, Path path, JfrRecordingState state) throws Throwable {
protected static void checkRecording(EventValidator validator, Path path, JfrRecordingState state, boolean validateTestedEventsOnly) throws Throwable {
JfrFileParser parser = new JfrFileParser(path);
parser.verify();

List<RecordedEvent> events = getEvents(path, state.testedEvents);
List<RecordedEvent> events = getEvents(path, state.testedEvents, validateTestedEventsOnly);
checkEvents(events, state.testedEvents);
if (validator != null) {
validator.validate(events);
}
}

private static List<RecordedEvent> getEvents(Path path, String[] testedEvents) throws IOException {
private static List<RecordedEvent> getEvents(Path path, String[] testedEvents, boolean validateTestedEventsOnly) throws IOException {
/* Only return events that are in the list of tested events. */
ArrayList<RecordedEvent> result = new ArrayList<>();
for (RecordedEvent event : RecordingFile.readAllEvents(path)) {
if (isTestedEvent(event, testedEvents)) {
if (!validateTestedEventsOnly || isTestedEvent(event, testedEvents)) {
result.add(event);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ protected Recording startRecording(String[] events) throws Throwable {
return startRecording(events, config, null, createTempJfrFile());
}

protected Recording startRecording(String[] events, Configuration config) throws Throwable {
return startRecording(events, config, null, createTempJfrFile());
}

protected Recording startRecording(String[] events, Configuration config, Map<String, String> settings) throws Throwable {
return startRecording(events, config, settings, createTempJfrFile());
}
Expand Down Expand Up @@ -95,10 +99,14 @@ private static void enableEvents(Recording recording, String[] events) {
}

public void stopRecording(Recording recording, EventValidator validator) throws Throwable {
stopRecording(recording, validator, true);
}

public void stopRecording(Recording recording, EventValidator validator, boolean validateTestedEventsOnly) throws Throwable {
recording.stop();
recording.close();

JfrRecordingState state = recordingStates.get(recording);
checkRecording(validator, recording.getDestination(), state);
checkRecording(validator, recording.getDestination(), state, validateTestedEventsOnly);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,16 @@ protected RecordingStream startStream(String[] events) throws Throwable {
}

protected void stopStream(RecordingStream stream, EventValidator validator) throws Throwable {
stopStream(stream, validator, true);
}

protected void stopStream(RecordingStream stream, EventValidator validator, boolean validateTestedEventsOnly) throws Throwable {
Path jfrFile = createTempJfrFile();
stream.dump(jfrFile);
closeStream(stream);

JfrStreamState state = streamStates.get(stream);
checkRecording(validator, jfrFile, state);
checkRecording(validator, jfrFile, state, validateTestedEventsOnly);
}

private void startStream(RecordingStream stream) throws InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2023, Red Hat Inc. 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 com.oracle.svm.test.jfr;

import static org.junit.Assert.assertTrue;

import java.util.List;

import org.junit.Test;

import jdk.jfr.EventType;
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;

/**
* This test checks that JFR mirror events have been set up correctly. If mirror events have not
* been set up correctly, then mirrored events will have incorrect metadata. This test verifies that
* metadata.
*/
public class TestMirrorEvents extends JfrRecordingTest {

@Test
public void test() throws Throwable {
String[] events = new String[]{"jdk.ThreadSleep", "jdk.VirtualThreadStart", "jdk.VirtualThreadEnd"};
Recording recording = startRecording(events);

Runnable eventEmitter = () -> {
try {
Thread.sleep(100);
} catch (Exception e) {
throw new RuntimeException(e);
}
};

VirtualStressor.execute(1, eventEmitter);

stopRecording(recording, TestMirrorEvents::validateEvents);
}

/**
* If the mirror event metadata is incorrect, we will see events with the wrong event name, e.g.
* "jdk.internal.event.ThreadSleepEvent" instead of "jdk.ThreadSleep".
*/
private static void validateEvents(List<RecordedEvent> unfilteredEvents) {
boolean foundSleepEvent = false;
boolean foundVthreadStartEvent = false;
boolean foundVthreadEndEvent = false;

for (RecordedEvent event : unfilteredEvents) {
EventType eventType = event.getEventType();
if (eventType.getName().equals("jdk.ThreadSleep") && eventType.getCategoryNames().contains("Java Application") && eventType.getLabel().equals("Java Thread Sleep")) {
foundSleepEvent = true;
}
if (eventType.getName().equals("jdk.VirtualThreadStart") && eventType.getCategoryNames().contains("Java Application") && eventType.getLabel().equals("Virtual Thread Start")) {
foundVthreadStartEvent = true;
}
if (eventType.getName().equals("jdk.VirtualThreadEnd") && eventType.getCategoryNames().contains("Java Application") && eventType.getLabel().equals("Virtual Thread End")) {
foundVthreadEndEvent = true;
}
}

assertTrue(foundSleepEvent);
assertTrue(foundVthreadStartEvent);
assertTrue(foundVthreadEndEvent);
}
}