/*
* Copyright 2010 Henry Coles
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
*/
package org.pitest.mutationtest.execute;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.pitest.extension.common.TestUnitDecorator;
import org.pitest.functional.SideEffect;
import org.pitest.mutationtest.TimeoutLengthStrategy;
import org.pitest.testapi.ResultCollector;
import org.pitest.testapi.TestUnit;
import org.pitest.util.Unchecked;
public final class MutationTimeoutDecorator extends TestUnitDecorator {
private final TimeoutLengthStrategy timeOutStrategy;
private final SideEffect timeOutSideEffect;
private final long executionTime;
public MutationTimeoutDecorator(final TestUnit child,
final SideEffect timeOutSideEffect,
final TimeoutLengthStrategy timeStrategy, final long executionTime) {
super(child);
this.timeOutSideEffect = timeOutSideEffect;
this.executionTime = executionTime;
this.timeOutStrategy = timeStrategy;
}
@Override
public void execute(final ClassLoader loader, final ResultCollector rc) {
final long maxTime = this.timeOutStrategy
.getAllowedTime(this.executionTime);
final FutureTask<?> future = createFutureForChildTestUnit(loader, rc);
executeFutureWithTimeOut(maxTime, future, rc);
if (!future.isDone()) {
this.timeOutSideEffect.apply();
}
}
private void executeFutureWithTimeOut(final long maxTime,
final FutureTask<?> future, final ResultCollector rc) {
try {
future.get(maxTime, TimeUnit.MILLISECONDS);
} catch (final TimeoutException ex) {
// swallow
} catch (final InterruptedException e) {
// swallow
} catch (final ExecutionException e) {
throw Unchecked.translateCheckedException(e);
}
}
private FutureTask<?> createFutureForChildTestUnit(final ClassLoader loader,
final ResultCollector rc) {
final FutureTask<?> future = new FutureTask<Object>(createRunnable(loader,
rc), null);
final Thread thread = new Thread(future);
thread.setDaemon(true);
thread.setName("mutationTestThread");
thread.start();
return future;
}
private Runnable createRunnable(final ClassLoader loader,
final ResultCollector rc) {
return new Runnable() {
@Override
public void run() {
try {
child().execute(loader, rc);
} catch (final Throwable ex) {
rc.notifyEnd(child().getDescription(), ex);
}
}
};
}
}