package org.jooby.rx; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.junit.Assert.assertEquals; import java.util.Collections; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ForkJoinPool; import java.util.function.Function; import org.jooby.Deferred; import org.jooby.Env; import org.jooby.Route; import org.jooby.Router; import org.jooby.exec.Exec; import org.jooby.test.MockUnit; import org.jooby.test.MockUnit.Block; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.inject.Binder; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; import com.typesafe.config.ConfigValueFactory; import javaslang.control.Try.CheckedRunnable; import rx.plugins.RxJavaPlugins; import rx.plugins.RxJavaSchedulersHook; import rx.schedulers.Schedulers; @RunWith(PowerMockRunner.class) @PrepareForTest({Rx.class, Exec.class, Executors.class, ForkJoinPool.class, Thread.class, System.class, RxJavaPlugins.class, Schedulers.class }) public class RxTest { private Block onStop = unit -> { Env env = unit.get(Env.class); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); }; @Test public void configure() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.router()).andReturn(routes); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); }) .expect(onStop) .run(unit -> { new Rx().configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); }); } @SuppressWarnings({"rawtypes", "unchecked" }) @Test public void withObservableAdapter() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); rx.Observable<String> value = rx.Observable.just("1"); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class, Function.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.router()).andReturn(routes); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); }) .expect(onStop) .expect(unit -> { Function adapter = unit.get(Function.class); expect(adapter.apply(value)).andReturn(value); }) .run(unit -> { new Rx() .withObservable(unit.get(Function.class)) .configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); Deferred deferred = (Deferred) unit.captured(Route.Mapper.class).get(0).map(value); deferred.handler(null, (r, x) -> { }); }); } @SuppressWarnings({"rawtypes", "unchecked" }) @Test public void withSingleAdapter() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); rx.Single<String> value = rx.Single.just("1"); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class, Function.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.router()).andReturn(routes); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); }) .expect(onStop) .expect(unit -> { Function adapter = unit.get(Function.class); expect(adapter.apply(value)).andReturn(value); }) .run(unit -> { new Rx() .withSingle(unit.get(Function.class)) .configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); Deferred deferred = (Deferred) unit.captured(Route.Mapper.class).get(0).map(value); deferred.handler(null, (r, x) -> { }); }); } @SuppressWarnings({"rawtypes", "unchecked" }) @Test public void withCompletableAdapter() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); rx.Completable value = rx.Completable.complete(); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class, Function.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.router()).andReturn(routes); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); }) .expect(onStop) .expect(unit -> { Function adapter = unit.get(Function.class); expect(adapter.apply(value)).andReturn(value); }) .run(unit -> { new Rx() .withCompletable(unit.get(Function.class)) .configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); Deferred deferred = (Deferred) unit.captured(Route.Mapper.class).get(0).map(value); deferred.handler(null, (r, x) -> { }); }); } @Test public void shutdownError() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); expectLastCall().andThrow(new IllegalStateException("intentional err")); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); expect(env.router()).andReturn(routes); }) .expect(onStop) .run(unit -> { new Rx().configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); }); } @Test public void shouldNotBreakOnExistingHook() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); expectLastCall().andThrow(new IllegalStateException("Hook present")); expect(plugins.getSchedulersHook()) .andReturn(new ExecSchedulerHook(Collections.emptyMap())); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); expect(env.router()).andReturn(routes); }) .expect(onStop) .run(unit -> { new Rx().configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); }); } @Test(expected = IllegalStateException.class) public void shouldBreakOnDiffHook() throws Exception { Config conf = ConfigFactory.empty() .withValue("rx.foo", ConfigValueFactory.fromAnyRef("bar")); new MockUnit(Env.class, Binder.class, ExecutorService.class, Router.class) .expect(unit -> { unit.mockStatic(Schedulers.class); Schedulers.shutdown(); }) .expect(unit -> { unit.mockStatic(System.class); expect(System.setProperty("rx.foo", "bar")).andReturn(null); }) .expect(unit -> { RxJavaPlugins plugins = unit.mock(RxJavaPlugins.class); plugins.registerSchedulersHook(isA(RxJavaSchedulersHook.class)); expectLastCall().andThrow(new IllegalStateException("Hook present")); expect(plugins.getSchedulersHook()).andReturn(unit.mock(RxJavaSchedulersHook.class)); unit.mockStatic(RxJavaPlugins.class); expect(RxJavaPlugins.getInstance()).andReturn(plugins); }) .expect(unit -> { Router routes = unit.get(Router.class); expect(routes.map(unit.capture(Route.Mapper.class))).andReturn(routes); Env env = unit.get(Env.class); expect(env.onStop(unit.capture(CheckedRunnable.class))).andReturn(env); expect(env.router()).andReturn(routes); }) .expect(onStop) .run(unit -> { new Rx().configure(unit.get(Env.class), conf, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).get(1).run(); }); } @Test public void config() throws Exception { assertEquals(ConfigFactory.parseResources(Rx.class, "rx.conf"), new Rx().config()); } }