package netflix.karyon.transport.tcp;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.netflix.governator.guice.LifecycleInjector;
import com.netflix.governator.lifecycle.LifecycleManager;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.MessageToMessageCodec;
import io.reactivex.netty.RxNetty;
import io.reactivex.netty.channel.ConnectionHandler;
import io.reactivex.netty.channel.ObservableConnection;
import io.reactivex.netty.pipeline.PipelineConfigurator;
import io.reactivex.netty.server.RxServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import rx.Observable;
import rx.functions.Func1;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
/**
* @author Tomasz Bak
*/
public class KaryonTcpModuleTest {
private static final Key<Map<String, RxServer>> RX_SERVERS_KEY = Key.get(new TypeLiteral<Map<String, RxServer>>() {
});
private static final String SERVER_MESSAGE = "Hello";
private Injector injector;
private LifecycleManager lifecycleManager;
private RxServer server;
@Before
public void setUp() throws Exception {
injector = LifecycleInjector.bootstrap(TestableTcpModule.class);
lifecycleManager = injector.getInstance(LifecycleManager.class);
lifecycleManager.start();
server = injector.getInstance(RX_SERVERS_KEY).values().iterator().next();
}
@After
public void tearDown() throws Exception {
if (lifecycleManager != null) {
lifecycleManager.close();
}
}
@Test
public void testGovernatedTcpServer() throws Exception {
String message = RxNetty.createTcpClient("localhost", server.getServerPort()).connect()
.flatMap(new Func1<ObservableConnection<ByteBuf, ByteBuf>, Observable<String>>() {
@Override
public Observable<String> call(ObservableConnection<ByteBuf, ByteBuf> connection) {
return connection.getInput().map(new Func1<ByteBuf, String>() {
@Override
public String call(ByteBuf byteBuf) {
return byteBuf.toString(Charset.defaultCharset());
}
});
}
}).single().toBlocking().toFuture().get(60, TimeUnit.SECONDS);
assertEquals("Invalid message received from server", SERVER_MESSAGE, message);
}
public static class TestableTcpModule extends KaryonTcpModule<String, String> {
public TestableTcpModule() {
super("testTcpModule", String.class, String.class);
}
@Override
protected void configureServer() {
bindPipelineConfigurator().to(StringCodecPipelineConfigurator.class);
bindConnectionHandler().to(TestableConnectionHandler.class);
server().port(0);
}
}
private static class TestableConnectionHandler implements ConnectionHandler<String, String> {
@Override
public Observable<Void> handle(ObservableConnection<String, String> connection) {
return connection.writeAndFlush(SERVER_MESSAGE);
}
}
public static class StringCodecPipelineConfigurator implements PipelineConfigurator<ByteBuf, String> {
@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
pipeline.addLast(new MessageToMessageCodec<ByteBuf, String>() {
@Override
protected void encode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception {
out.add(Unpooled.copiedBuffer(msg, Charset.defaultCharset()));
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(msg.toString(Charset.defaultCharset()));
}
});
}
}
}