// Copyright © 2011-2014, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
package fi.jumi.launcher.remote;
import fi.jumi.actors.*;
import fi.jumi.actors.eventizers.Event;
import fi.jumi.actors.queue.MessageSender;
import fi.jumi.core.api.*;
import fi.jumi.core.config.*;
import fi.jumi.core.events.RequestListenerEventizer;
import fi.jumi.core.events.suiteListener.*;
import fi.jumi.core.ipc.api.RequestListener;
import fi.jumi.core.network.NetworkConnection;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
public class RemoteSuiteLauncher implements SuiteLauncher, DaemonListener {
private final ActorThread currentThread;
private final ActorRef<DaemonSummoner> daemonSummoner;
private SuiteConfiguration suiteConfiguration;
private MessageSender<Event<SuiteListener>> suiteListener;
private RequestListener daemon;
private final SuiteState suiteState = new SuiteState();
public RemoteSuiteLauncher(ActorThread currentThread, ActorRef<DaemonSummoner> daemonSummoner) {
this.currentThread = currentThread;
this.daemonSummoner = daemonSummoner;
}
@Override
public void runTests(SuiteConfiguration suiteConfiguration,
DaemonConfiguration daemonConfiguration,
MessageSender<Event<SuiteListener>> suiteListener) {
this.suiteConfiguration = suiteConfiguration;
this.suiteListener = suiteListener;
daemonSummoner.tell().connectToDaemon(suiteConfiguration, daemonConfiguration, self());
}
@Override
public void shutdownDaemon() {
if (daemon == null) {
throw new IllegalStateException("cannot shutdown; daemon not connected");
}
daemon.shutdown();
}
@Override
public void onConnected(NetworkConnection connection, MessageSender<Event<RequestListener>> daemon) {
this.daemon = new RequestListenerEventizer().newFrontend(daemon);
this.daemon.runTests(suiteConfiguration);
}
@Override
public void onMessage(Event<SuiteListener> message) {
suiteListener.send(message);
message.fireOn(suiteState);
}
@Override
public void onDisconnected() {
if (suiteState.inProgress) {
suiteListener.send(new OnInternalErrorEvent("The test runner daemon process disconnected or died unexpectedly",
StackTrace.from(new Exception("disconnected"))));
suiteListener.send(new OnSuiteFinishedEvent());
}
// TODO: Should we reconnect or something? For now let's defer implementing this, because
// this feature might not be needed if we switch to communicating over memory-mapped files.
}
// actor helpers
private ActorRef<DaemonListener> self() {
return currentThread.bindActor(DaemonListener.class, this);
}
@NotThreadSafe
private static class SuiteState extends NullSuiteListener {
public boolean inProgress = false;
@Override
public void onSuiteStarted() {
inProgress = true;
}
@Override
public void onSuiteFinished() {
inProgress = false;
}
}
}