// 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() { } } }