// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.client;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.yahoo.jdisc.application.BundleInstaller;
import com.yahoo.jdisc.application.ContainerActivator;
import com.yahoo.jdisc.service.CurrentContainer;
import org.junit.Test;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Simon Thoresen Hult
*/
public class AbstractClientApplicationTestCase {
@Test
public void requireThatApplicationCanBeShutdown() throws Exception {
MyDriver driver = newDriver();
assertFalse(driver.awaitDone(100, TimeUnit.MILLISECONDS));
assertTrue(driver.awaitApp(600, TimeUnit.SECONDS));
driver.app.shutdown();
assertTrue(driver.app.isShutdown());
assertTrue(driver.close());
}
@Test
public void requireThatShutdownCanBeWaitedForWithTimeout() throws Exception {
final MyDriver driver = newDriver();
assertFalse(driver.awaitDone(100, TimeUnit.MILLISECONDS));
assertTrue(driver.awaitApp(600, TimeUnit.SECONDS));
final CountDownLatch latch = new CountDownLatch(1);
Executors.newSingleThreadExecutor().submit(new Callable() {
@Override
public Boolean call() throws Exception {
driver.app.awaitShutdown(600, TimeUnit.SECONDS);
latch.countDown();
return Boolean.TRUE;
}
});
assertFalse(latch.await(100, TimeUnit.MILLISECONDS));
driver.app.shutdown();
assertTrue(driver.close());
assertTrue(latch.await(600, TimeUnit.SECONDS));
}
@Test
public void requireThatShutdownCanBeWaitedForWithoutTimeout() throws Exception {
final MyDriver driver = newDriver();
assertFalse(driver.awaitDone(100, TimeUnit.MILLISECONDS));
assertTrue(driver.awaitApp(600, TimeUnit.SECONDS));
final CountDownLatch latch = new CountDownLatch(1);
Executors.newSingleThreadExecutor().submit(new Callable() {
@Override
public Boolean call() throws Exception {
driver.app.awaitShutdown();
latch.countDown();
return Boolean.TRUE;
}
});
assertFalse(latch.await(100, TimeUnit.MILLISECONDS));
driver.app.shutdown();
assertTrue(driver.close());
assertTrue(latch.await(600, TimeUnit.SECONDS));
}
private static MyDriver newDriver() {
final MyDriver driver = new MyDriver();
driver.done = Executors.newSingleThreadExecutor().submit(new Callable() {
@Override
public Boolean call() throws Exception {
ClientDriver.runApplication(MyApplication.class, driver);
return Boolean.TRUE;
}
});
return driver;
}
private static class MyDriver extends AbstractModule {
final CountDownLatch appLatch = new CountDownLatch(1);
Future done;
MyApplication app;
@Override
protected void configure() {
bind(MyDriver.class).toInstance(this);
}
boolean awaitApp(int timeout, TimeUnit unit) throws InterruptedException {
return appLatch.await(timeout, unit);
}
boolean awaitDone(int timeout, TimeUnit unit) throws ExecutionException, InterruptedException {
try {
done.get(timeout, unit);
return app.isTerminated();
} catch (TimeoutException e) {
return false;
}
}
boolean close() throws ExecutionException, InterruptedException {
return awaitDone(600, TimeUnit.SECONDS);
}
}
private static class MyApplication extends AbstractClientApplication {
@Inject
MyApplication(BundleInstaller bundleInstaller, ContainerActivator activator,
CurrentContainer container, MyDriver driver) {
super(bundleInstaller, activator, container);
driver.app = this;
driver.appLatch.countDown();
}
@Override
public void start() {
}
}
}