Skip to content

Commit

Permalink
Print stack trace for timed-out tests (of timed-out thread)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiaso committed Apr 26, 2023
1 parent 3411536 commit 1eff7b6
Showing 1 changed file with 44 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/*
* Copyright (c) 2010-2017 BSI Business Systems Integration AG.
* Copyright (c) 2010-2023 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
Expand All @@ -17,6 +17,7 @@
import org.eclipse.scout.rt.platform.job.Jobs;
import org.eclipse.scout.rt.platform.transaction.TransactionScope;
import org.eclipse.scout.rt.platform.util.Assertions;
import org.eclipse.scout.rt.platform.util.concurrent.IRunnable;
import org.eclipse.scout.rt.platform.util.concurrent.ThreadInterruptedError;
import org.eclipse.scout.rt.platform.util.concurrent.TimedOutError;
import org.eclipse.scout.rt.testing.platform.runner.SafeStatementInvoker;
Expand Down Expand Up @@ -49,18 +50,58 @@ public TimeoutRunContextStatement(final Statement next, final long timeoutMillis
@Override
public void evaluate() throws Throwable {
final SafeStatementInvoker invoker = new SafeStatementInvoker(m_next);
class TimeoutFutureRunnable implements IRunnable {

final IFuture<Void> future = Jobs.schedule(invoker, Jobs.newInput()
protected Thread m_thread;

@Override
public void run() throws Exception {
try {
m_thread = Thread.currentThread();
invoker.run();
}
finally {
m_thread = null;
}
}

public StackTraceElement[] getStackTrace() {
Thread t = m_thread;
if (t != null) {
return t.getStackTrace();
}
return new StackTraceElement[0];
}
}
final TimeoutFutureRunnable runnable = new TimeoutFutureRunnable();

final IFuture<Void> future = Jobs.schedule(runnable, Jobs.newInput()
.withRunContext(RunContext.CURRENT.get().copy().withTransactionScope(TransactionScope.REQUIRES_NEW)) // Run in new TX, because the same TX is not allowed to be used by multiple threads.
.withName("Running test with support for JUnit timeout"));
try {
future.awaitDone(m_timeoutMillis, TimeUnit.MILLISECONDS);
}
catch (ThreadInterruptedError | TimedOutError e) { // NOSONAR
StackTraceElement[] stackTrace = runnable.getStackTrace();

This comment has been minimized.

Copy link
@matthiaso

matthiaso May 11, 2023

Author Member

Does this really still work if future is already timed out?

future.cancel(true);
printStackTrace(stackTrace);
throw new TestTimedOutException(m_timeoutMillis, TimeUnit.MILLISECONDS); // JUnit timeout exception
}

invoker.throwOnError();
}

protected void printStackTrace(StackTraceElement[] stackTrace) {
StringBuilder trace = new StringBuilder();
for (StackTraceElement traceElement : stackTrace) {
if (trace.length() != 0) {
trace.append('\n');
}
trace.append("\tat ");
trace.append(traceElement);
}
if (trace.length() > 0) {
System.err.println("Test timed out at " + trace);
}
}
}

0 comments on commit 1eff7b6

Please sign in to comment.