package netflix.ocelli.rxnetty.internal; import io.reactivex.netty.channel.Connection; import io.reactivex.netty.client.ConnectionFactory; import io.reactivex.netty.client.ConnectionObservable; import io.reactivex.netty.client.ConnectionProvider; import io.reactivex.netty.protocol.tcp.client.events.TcpClientEventListener; import netflix.ocelli.Instance; import netflix.ocelli.rxnetty.FailureListener; import netflix.ocelli.rxnetty.internal.AbstractLoadBalancer.LoadBalancingProvider; import org.junit.Rule; import org.junit.Test; import org.mockito.verification.VerificationMode; import rx.Observable; import rx.functions.Func1; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; import static org.mockito.Mockito.*; public class LoadBalancingProviderTest { @Rule public final LoadBalancerRule loadBalancerRule = new LoadBalancerRule(); @Test(timeout = 60000) public void testRoundRobin() throws Exception { List<Instance<SocketAddress>> hosts = loadBalancerRule.setupDefault(); assertThat("Unexpected hosts found.", hosts, hasSize(2)); AbstractLoadBalancer<String, String> loadBalancer = loadBalancerRule.getLoadBalancer(); ConnectionFactory<String, String> cfMock = loadBalancerRule.newConnectionFactoryMock(); Observable<Instance<ConnectionProvider<String, String>>> providers = loadBalancerRule.getHostsAsConnectionProviders(cfMock); LoadBalancingProvider lbProvider = newLoadBalancingProvider(loadBalancer, cfMock, providers); @SuppressWarnings("unchecked") ConnectionObservable<String, String> connectionObservable = lbProvider.nextConnection(); assertNextConnection(hosts.get(0).getValue(), cfMock, connectionObservable, times(1)); assertNextConnection(hosts.get(1).getValue(), cfMock, connectionObservable, times(1)); assertNextConnection(hosts.get(0).getValue(), cfMock, connectionObservable, times(2) /*Invoked once above with same host*/); } @Test(timeout = 60000) public void testListenerSubscription() throws Exception { final AtomicBoolean listenerCalled = new AtomicBoolean(); final TcpClientEventListener listener = new TcpClientEventListener() { @Override public void onConnectionCloseStart() { listenerCalled.set(true); } }; InetSocketAddress host = new InetSocketAddress(0); loadBalancerRule.setup(new Func1<FailureListener, TcpClientEventListener>() { @Override public TcpClientEventListener call(FailureListener failureListener) { return listener; } }, host); AbstractLoadBalancer<String, String> loadBalancer = loadBalancerRule.getLoadBalancer(); ConnectionFactory<String, String> cfMock = loadBalancerRule.newConnectionFactoryMock(); Observable<Instance<ConnectionProvider<String, String>>> providers = loadBalancerRule.getHostsAsConnectionProviders(cfMock); LoadBalancingProvider lbProvider = newLoadBalancingProvider(loadBalancer, cfMock, providers); @SuppressWarnings("unchecked") ConnectionObservable<String, String> connectionObservable = lbProvider.nextConnection(); Connection<String, String> c = assertNextConnection(host, cfMock, connectionObservable, times(1)); c.closeNow(); assertThat("Listener not called.", listenerCalled.get(), is(true)); } protected Connection<String, String> assertNextConnection(SocketAddress host, ConnectionFactory<String, String> cfMock, ConnectionObservable<String, String> connectionObservable, VerificationMode verificationMode) { Connection<String, String> c = loadBalancerRule.connect(connectionObservable); verify(cfMock, verificationMode).newConnection(host); return c; } protected LoadBalancingProvider newLoadBalancingProvider(AbstractLoadBalancer<String, String> loadBalancer, ConnectionFactory<String, String> cfMock, Observable<Instance<ConnectionProvider<String, String>>> providers) { LoadBalancingProvider lbProvider = loadBalancer.new LoadBalancingProvider(cfMock, providers); return lbProvider; } }