Skip to content

Commit

Permalink
Fix process handling
Browse files Browse the repository at this point in the history
  • Loading branch information
laeubi committed Feb 27, 2024
1 parent 8676e14 commit d3deebc
Show file tree
Hide file tree
Showing 5 changed files with 467 additions and 503 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
Expand Down Expand Up @@ -49,32 +50,41 @@ public class MavenBuildConnectionProcess implements IProcess {

private List<MavenBuildListener> buildListeners = new CopyOnWriteArrayList<>();

private AtomicBoolean terminated = new AtomicBoolean();

public MavenBuildConnectionProcess(ILaunch launch) {
this.launch = launch;
launch.addProcess(this);
attributes.put(IProcess.ATTR_PROCESS_TYPE, "m2e-build-endpoint");
fireEvent(new DebugEvent(this, DebugEvent.CREATE));
}

public <T> T getAdapter(Class<T> adapter) {
return null;
}

public boolean canTerminate() {
return true;
return !isTerminated();
}

public boolean isTerminated() {
return connection == null || connection.isReadCompleted();
return terminated.get() || connection == null;
}

public void terminate() throws DebugException {
if(connection != null) {
try {
connection.close();
} catch(IOException ex) {
throw new DebugException(Status.error("Terminate failed", ex));
public void terminate() {
if(terminated.compareAndSet(false, true)) {
if(connection != null) {
try {
connection.close();
} catch(IOException ex) {
}
connection = null;
}
for(MavenBuildListener mavenBuildListener : buildListeners) {
mavenBuildListener.close();
}
connection = null;
buildListeners.clear();
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
}
}

Expand All @@ -93,6 +103,7 @@ public IStreamsProxy getStreamsProxy() {
@Override
public void setAttribute(String key, String value) {
attributes.put(key, value);
fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
}

@Override
Expand Down Expand Up @@ -144,11 +155,7 @@ public void onTestEvent(MavenTestEvent mavenTestEvent) {
}

public void close() {
for(MavenBuildListener mavenBuildListener : buildListeners) {
mavenBuildListener.close();
}
buildListeners.clear();
launch.removeProcess(MavenBuildConnectionProcess.this);
MavenBuildConnectionProcess.this.terminate();
}
});
}
Expand All @@ -157,4 +164,11 @@ String getMavenVMArguments() throws IOException {
return connection.getMavenVMArguments();
}

private void fireEvent(DebugEvent event) {
DebugPlugin manager = DebugPlugin.getDefault();
if(manager != null) {
manager.fireDebugEventSet(new DebugEvent[] {event});
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.Optional;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchesListener2;
Expand All @@ -36,35 +35,32 @@ public class MavenBuildProjectDataConnection {
static {
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(new ILaunchesListener2() {
public void launchesRemoved(ILaunch[] launches) {
Arrays.stream(launches).flatMap(launch -> getConnection(launch).stream()).forEach(con -> {
try {
con.terminate();
} catch(DebugException ex) {
//ignore
}
});
cleanupConnections(launches);
}

public void launchesTerminated(ILaunch[] launches) {
launchesRemoved(launches);
cleanupConnections(launches);
}

public void launchesAdded(ILaunch[] launches) { // ignore
}

public void launchesChanged(ILaunch[] launches) { // ignore
}

private void cleanupConnections(ILaunch[] launches) {
Arrays.stream(launches).flatMap(launch -> getConnection(launch).stream()).forEach(con -> {
con.terminate();
});
}
});
}

static void openListenerConnection(ILaunch launch, VMArguments arguments) {
try {
if(MavenLaunchUtils.getMavenRuntime(launch.getLaunchConfiguration()) instanceof MavenEmbeddedRuntime) {
getConnection(launch).ifPresent(existing -> {
try {
existing.terminate();
} catch(DebugException ex) {
}
existing.terminate();
throw new IllegalStateException(
"Maven bridge already created for launch of" + launch.getLaunchConfiguration().getName());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,14 @@
import org.xml.sax.SAXException;

import org.eclipse.debug.core.ILaunch;
import org.eclipse.unittest.internal.junitXmlReport.TestRunHandler;
import org.eclipse.unittest.launcher.ITestRunnerClient;
import org.eclipse.unittest.model.ITestCaseElement;
import org.eclipse.unittest.model.ITestElement;
import org.eclipse.unittest.model.ITestElement.FailureTrace;
import org.eclipse.unittest.model.ITestElement.Result;
import org.eclipse.unittest.model.ITestRunSession;
import org.eclipse.unittest.model.ITestSuiteElement;

import org.apache.maven.execution.ExecutionEvent.Type;

import org.eclipse.m2e.internal.launch.MavenBuildProjectDataConnection;
import org.eclipse.m2e.internal.launch.testing.copied.TestRunHandler;
import org.eclipse.m2e.internal.maven.listener.MavenBuildListener;
import org.eclipse.m2e.internal.maven.listener.MavenProjectBuildData;
import org.eclipse.m2e.internal.maven.listener.MavenTestEvent;
Expand All @@ -63,6 +59,7 @@ public MavenTestRunnerClient(ITestRunSession session) {
}

public void startMonitoring() {
System.out.println("---- start monitoring ---");
MavenBuildProjectDataConnection.getConnection(session.getLaunch())
.ifPresent(con -> con.addMavenBuildListener(this));

Expand All @@ -78,6 +75,7 @@ public void stopTest() {
}

public void stopMonitoring() {
System.out.println("---- stop Monitoring ----\r\n");
MavenBuildProjectDataConnection.getConnection(session.getLaunch())
.ifPresent(con -> con.removeMavenBuildListener(this));
}
Expand All @@ -93,74 +91,58 @@ public void projectStarted(MavenProjectBuildData data) {
this.projectData.set(data);
}

boolean started;

public void onTestEvent(MavenTestEvent mavenTestEvent) {
System.out.println("MavenTestRunnerClient.onTestEvent()");
if(mavenTestEvent.getType() == Type.MojoSucceeded || mavenTestEvent.getType() == Type.MojoFailed) {
MavenProjectBuildData buildData = projectData.get();
// Display.getDefault().execute(() -> {

//in any case look for the tests...
Path reportDirectory = mavenTestEvent.getReportDirectory();
if(Files.isDirectory(reportDirectory)) {
SAXParser parser = getParser();
if(parser == null) {
return;
}
ensureStarted();
ITestSuiteElement projectSuite = getProjectSuite(buildData);
try (Stream<Path> list = Files.list(reportDirectory)) {
Iterator<Path> iterator = list.iterator();
while(iterator.hasNext()) {
Path path = iterator.next();
System.out.println("Scan result file " + path);
ITestRunSession importedSession = parseFile(path, parser);
if(importedSession != null) {
ITestSuiteElement project = getProjectSuite();
ITestSuiteElement file = session.newTestSuite(path.toString(), path.getFileName().toString(), null,
project, path.getFileName().toString(), null);
for(ITestElement element : importedSession.getChildren()) {
importTestElement(element, file);
}
}
parseFile(path, parser, projectSuite);
}
} catch(IOException ex) {
}
}
// });
}
}

/**
* @param element
* @param file
*/
private void importTestElement(ITestElement element, ITestSuiteElement parent) {
if(element instanceof ITestCaseElement testcase) {
ITestCaseElement importedTestCase = session.newTestCase(parent.getId() + "." + testcase.getId(),
testcase.getTestName(), parent, testcase.getDisplayName(), testcase.getData());
session.notifyTestStarted(importedTestCase);
FailureTrace failureTrace = testcase.getFailureTrace();
if(failureTrace == null) {
session.notifyTestEnded(importedTestCase, testcase.isIgnored());
} else {
session.notifyTestFailed(importedTestCase, Result.ERROR/*TODO how do we know?*/, false /*TODO how do we know?*/,
failureTrace);
}
} else if(element instanceof ITestSuiteElement suite) {
ITestSuiteElement importedTestSuite = session.newTestSuite(parent.getId() + "." + suite.getId(),
suite.getTestName(), null, parent, suite.getDisplayName(), suite.getData());
session.notifyTestStarted(importedTestSuite);
for(ITestElement child : suite.getChildren()) {
importTestElement(child, importedTestSuite);
}
session.notifyTestEnded(importedTestSuite, false);
private synchronized void ensureStarted() {
if(!started) {
session.notifyTestSessionStarted(null);
started = true;
}
}

/**
* @return
*/
private ITestSuiteElement getProjectSuite() {
return projectElementMap.computeIfAbsent(projectData.get(), data -> {
private ITestSuiteElement getProjectSuite(MavenProjectBuildData buildData) {
return projectElementMap.computeIfAbsent(buildData, data -> {
Path basedir = data.projectBasedir;
return session.newTestSuite(basedir.toString(), basedir.getFileName().toString(), null, null,
data.groupId + ":" + data.artifactId, null);
ITestSuiteElement suite = session.newTestSuite(System.currentTimeMillis() + basedir.toString(),
basedir.getFileName().toString(), null, null, data.groupId + ":" + data.artifactId, null);
session.notifyTestStarted(suite);
return suite;
});
}

@SuppressWarnings("restriction")
private SAXParser getParser() {
try {
return org.eclipse.core.internal.runtime.XmlProcessorFactory.createSAXParserWithErrorOnDOCTYPE();
Expand All @@ -170,20 +152,19 @@ private SAXParser getParser() {
return null;
}

private ITestRunSession parseFile(Path path, SAXParser parser) {
//TODO Currently NOT working as this is internal API that is not exported!
final TestRunHandler handler = new TestRunHandler();
private void parseFile(Path path, SAXParser parser, ITestSuiteElement parent) {
final TestRunHandler handler = new TestRunHandler(session, parent);
try {
parser.parse(Files.newInputStream(path), handler);
return handler.getTestRunSession();
} catch(SAXException | IOException ex) {
//can't read then...
return null;
}
}

public void close() {
// nothing to do yet...
if(started) {
session.notifyTestSessionCompleted(null);
}
}

}
Loading

0 comments on commit d3deebc

Please sign in to comment.