package org.jooby.memcached; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.isA; import java.util.Arrays; import org.jooby.Env; import org.jooby.internal.memcached.MemcachedClientProvider; 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.google.inject.binder.AnnotatedBindingBuilder; import com.google.inject.binder.ScopedBindingBuilder; import com.typesafe.config.Config; import com.typesafe.config.ConfigValueFactory; import javaslang.control.Try.CheckedRunnable; import net.spy.memcached.ConnectionFactoryBuilder; import net.spy.memcached.ConnectionFactoryBuilder.Locator; import net.spy.memcached.ConnectionFactoryBuilder.Protocol; import net.spy.memcached.FailureMode; import net.spy.memcached.MemcachedClient; import net.spy.memcached.auth.AuthDescriptor; import net.spy.memcached.metrics.MetricType; @RunWith(PowerMockRunner.class) @PrepareForTest({SpyMemcached.class, ConnectionFactoryBuilder.class }) public class SpyMemcachedTest { private Block cfb = unit -> { ConnectionFactoryBuilder cfb = unit.mockConstructor(ConnectionFactoryBuilder.class); unit.registerMock(ConnectionFactoryBuilder.class, cfb); }; private Block defprops = unit -> { ConnectionFactoryBuilder cfb = unit.get(ConnectionFactoryBuilder.class); expect(cfb.setAuthWaitTime(1000L)).andReturn(cfb); expect(cfb.setDaemon(false)).andReturn(cfb); expect(cfb.setFailureMode(FailureMode.Redistribute)).andReturn(cfb); expect(cfb.setLocatorType(Locator.ARRAY_MOD)).andReturn(cfb); expect(cfb.setMaxReconnectDelay(30)).andReturn(cfb); expect(cfb.setProtocol(Protocol.TEXT)).andReturn(cfb); }; private Block fullprops = unit -> { ConnectionFactoryBuilder cfb = unit.get(ConnectionFactoryBuilder.class); expect(cfb.setAuthWaitTime(1000L)).andReturn(cfb); expect(cfb.setDaemon(false)).andReturn(cfb); expect(cfb.setFailureMode(FailureMode.Redistribute)).andReturn(cfb); expect(cfb.setLocatorType(Locator.ARRAY_MOD)).andReturn(cfb); expect(cfb.setMaxReconnectDelay(30)).andReturn(cfb); expect(cfb.setProtocol(Protocol.TEXT)).andReturn(cfb); expect(cfb.setEnableMetrics(MetricType.OFF)).andReturn(cfb); expect(cfb.setOpQueueMaxBlockTime(1000L)).andReturn(cfb); expect(cfb.setOpTimeout(1000L)).andReturn(cfb); expect(cfb.setReadBufferSize(100)).andReturn(cfb); expect(cfb.setShouldOptimize(true)).andReturn(cfb); expect(cfb.setTimeoutExceptionThreshold(10)).andReturn(cfb); expect(cfb.setUseNagleAlgorithm(true)).andReturn(cfb); }; @SuppressWarnings("unchecked") private Block bind = unit -> { ScopedBindingBuilder sbbMC = unit.mock(ScopedBindingBuilder.class); sbbMC.asEagerSingleton(); AnnotatedBindingBuilder<MemcachedClient> abbMC = unit.mock(AnnotatedBindingBuilder.class); expect(abbMC.toProvider(isA(MemcachedClientProvider.class))).andReturn(sbbMC); Binder binder = unit.get(Binder.class); expect(binder.bind(MemcachedClient.class)).andReturn(abbMC); }; 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 config = new SpyMemcached().config() .withValue("memcached.server", ConfigValueFactory.fromAnyRef("localhost:11211")); new MockUnit(Env.class, Binder.class) .expect(cfb) .expect(defprops) .expect(bind) .expect(onStop) .run(unit -> { new SpyMemcached() .configure(unit.get(Env.class), config, unit.get(Binder.class)); }, unit -> { unit.captured(CheckedRunnable.class).iterator().next().run(); }); } @Test public void fullprops() throws Exception { Config config = new SpyMemcached().config() .withValue("memcached.server", ConfigValueFactory.fromAnyRef("localhost:11211")) .withValue("memcached.enableMetrics", ConfigValueFactory.fromAnyRef("off")) .withValue("memcached.opQueueMaxBlockTime", ConfigValueFactory.fromAnyRef("1s")) .withValue("memcached.opTimeout", ConfigValueFactory.fromAnyRef("1s")) .withValue("memcached.readBufferSize", ConfigValueFactory.fromAnyRef(100)) .withValue("memcached.shouldOptimize", ConfigValueFactory.fromAnyRef(true)) .withValue("memcached.timeoutExceptionThreshold", ConfigValueFactory.fromAnyRef(10)) .withValue("memcached.useNagleAlgorithm", ConfigValueFactory.fromAnyRef(true)); new MockUnit(Env.class, Binder.class) .expect(cfb) .expect(fullprops) .expect(bind) .expect(onStop) .run(unit -> { new SpyMemcached() .configure(unit.get(Env.class), config, unit.get(Binder.class)); }); } @Test(expected = IllegalArgumentException.class) public void enumErr() throws Exception { Config config = new SpyMemcached().config() .withValue("memcached.server", ConfigValueFactory.fromAnyRef("localhost:11211")) .withValue("memcached.enableMetrics", ConfigValueFactory.fromAnyRef("invalid")); new MockUnit(Env.class, Binder.class) .expect(cfb) .expect(defprops) .expect(bind) .run(unit -> { new SpyMemcached() .configure(unit.get(Env.class), config, unit.get(Binder.class)); }); } @Test public void configureServers() throws Exception { Config config = new SpyMemcached().config() .withValue("memcached.server", ConfigValueFactory.fromAnyRef(Arrays.asList("localhost:11211", "localhost:11212"))); new MockUnit(Env.class, Binder.class) .expect(cfb) .expect(defprops) .expect(bind) .expect(onStop) .run(unit -> { new SpyMemcached() .configure(unit.get(Env.class), config, unit.get(Binder.class)); }); } @Test public void configurer() throws Exception { Config config = new SpyMemcached().config() .withValue("memcached.server", ConfigValueFactory.fromAnyRef(Arrays.asList("localhost:11211", "localhost:11212"))); new MockUnit(Env.class, Binder.class, AuthDescriptor.class) .expect(cfb) .expect(defprops) .expect(unit -> { ConnectionFactoryBuilder cfb = unit.get(ConnectionFactoryBuilder.class); expect(cfb.setAuthDescriptor(unit.get(AuthDescriptor.class))).andReturn(cfb); }) .expect(bind) .expect(onStop) .run(unit -> { new SpyMemcached() .doWith(builder -> { builder.setAuthDescriptor(unit.get(AuthDescriptor.class)); }) .configure(unit.get(Env.class), config, unit.get(Binder.class)); }); } }