/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cassandra.config;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.*;
import static org.springframework.util.ReflectionUtils.*;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.util.ReflectionUtils;
import com.datastax.driver.core.HostDistance;
import com.datastax.driver.core.PoolingOptions;
/**
* Unit tests for {@link PoolingOptionsFactoryBean}.
*
* @author Sumit Kumar
* @author David Webb
* @author John Blum
* @author Mark Paluch
*/
@RunWith(MockitoJUnitRunner.class)
public class PoolingOptionsFactoryBeanUnitTests {
@Mock Executor mockExecutor;
@Spy PoolingOptions poolingOptionsSpy;
private PoolingOptionsFactoryBean poolingOptionsFactoryBean;
@Before
public void setup() {
poolingOptionsFactoryBean = new PoolingOptionsFactoryBean();
}
@Test // DATACASS-176, DATACASS-298
public void getObjectReturnsNullWhenNotInitialized() throws Exception {
assertThat(poolingOptionsFactoryBean.getObject()).isNull();
}
@Test
@SuppressWarnings("unchecked")
public void getObjectTypeReturnsPoolingOptionsClassWhenNotInitialized() {
assertThat(poolingOptionsFactoryBean.getObjectType()).isEqualTo(PoolingOptions.class);
}
@Test
public void isSingletonIsTrue() {
assertThat(poolingOptionsFactoryBean.isSingleton()).isTrue();
}
@Test // DATACASS-298, DATACASS-344
public void setAndGetFactoryBeanProperties() {
poolingOptionsFactoryBean.setHeartbeatIntervalSeconds(15);
poolingOptionsFactoryBean.setIdleTimeoutSeconds(120);
poolingOptionsFactoryBean.setInitializationExecutor(mockExecutor);
poolingOptionsFactoryBean.setLocalCoreConnections(50);
poolingOptionsFactoryBean.setLocalMaxConnections(1000);
poolingOptionsFactoryBean.setLocalMaxSimultaneousRequests(200);
poolingOptionsFactoryBean.setLocalMinSimultaneousRequests(100);
poolingOptionsFactoryBean.setPoolTimeoutMilliseconds(300);
poolingOptionsFactoryBean.setRemoteCoreConnections(25);
poolingOptionsFactoryBean.setRemoteMaxConnections(250);
poolingOptionsFactoryBean.setRemoteMaxSimultaneousRequests(100);
poolingOptionsFactoryBean.setRemoteMinSimultaneousRequests(50);
assertThat(poolingOptionsFactoryBean.getHeartbeatIntervalSeconds()).isEqualTo(15);
assertThat(poolingOptionsFactoryBean.getIdleTimeoutSeconds()).isEqualTo(120);
assertThat(poolingOptionsFactoryBean.getInitializationExecutor()).isEqualTo(mockExecutor);
assertThat(poolingOptionsFactoryBean.getLocalCoreConnections()).isEqualTo(50);
assertThat(poolingOptionsFactoryBean.getLocalMaxConnections()).isEqualTo(1000);
assertThat(poolingOptionsFactoryBean.getLocalMaxSimultaneousRequests()).isEqualTo(200);
assertThat(poolingOptionsFactoryBean.getLocalMinSimultaneousRequests()).isEqualTo(100);
assertThat(poolingOptionsFactoryBean.getPoolTimeoutMilliseconds()).isEqualTo(300);
assertThat(poolingOptionsFactoryBean.getRemoteCoreConnections()).isEqualTo(25);
assertThat(poolingOptionsFactoryBean.getRemoteMaxConnections()).isEqualTo(250);
assertThat(poolingOptionsFactoryBean.getRemoteMaxSimultaneousRequests()).isEqualTo(100);
assertThat(poolingOptionsFactoryBean.getRemoteMinSimultaneousRequests()).isEqualTo(50);
}
@Test // DATACASS-298
public void afterPropertiesSetInitializesLocalPoolingOptions() throws Exception {
PoolingOptionsFactoryBean poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
PoolingOptions newPoolingOptions() {
poolingOptionsSpy.setNewConnectionThreshold(HostDistance.LOCAL, 1);
return poolingOptionsSpy;
}
};
poolingOptionsFactoryBean.setHeartbeatIntervalSeconds(60);
poolingOptionsFactoryBean.setIdleTimeoutSeconds(300);
poolingOptionsFactoryBean.setInitializationExecutor(mockExecutor);
poolingOptionsFactoryBean.setLocalCoreConnections(10);
poolingOptionsFactoryBean.setLocalMaxConnections(100);
poolingOptionsFactoryBean.setLocalMaxSimultaneousRequests(50);
poolingOptionsFactoryBean.setLocalMinSimultaneousRequests(5);
poolingOptionsFactoryBean.setPoolTimeoutMilliseconds(180);
assertThat(poolingOptionsFactoryBean.getObject()).isNull();
poolingOptionsFactoryBean.afterPropertiesSet();
assertThat(poolingOptionsFactoryBean.getObject()).isSameAs(poolingOptionsSpy);
assertThat(poolingOptionsFactoryBean.getObjectType()).isEqualTo(poolingOptionsSpy.getClass());
verify(poolingOptionsSpy).setHeartbeatIntervalSeconds(eq(60));
verify(poolingOptionsSpy).setIdleTimeoutSeconds(eq(300));
verify(poolingOptionsSpy).setInitializationExecutor(eq(mockExecutor));
verify(poolingOptionsSpy).setPoolTimeoutMillis(eq(180));
verify(poolingOptionsSpy).setCoreConnectionsPerHost(eq(HostDistance.LOCAL), eq(10));
verify(poolingOptionsSpy).setMaxConnectionsPerHost(eq(HostDistance.LOCAL), eq(100));
verify(poolingOptionsSpy).setMaxRequestsPerConnection(eq(HostDistance.LOCAL), eq(50));
verify(poolingOptionsSpy).setNewConnectionThreshold(eq(HostDistance.LOCAL), eq(5));
verify(poolingOptionsSpy, never()).setCoreConnectionsPerHost(eq(HostDistance.REMOTE), anyInt());
verify(poolingOptionsSpy, never()).setMaxConnectionsPerHost(eq(HostDistance.REMOTE), anyInt());
verify(poolingOptionsSpy, never()).setMaxRequestsPerConnection(eq(HostDistance.REMOTE), anyInt());
verify(poolingOptionsSpy, never()).setNewConnectionThreshold(eq(HostDistance.REMOTE), anyInt());
}
@Test // DATACASS-298
public void afterPropertiesSetInitializesRemotePoolingOptions() throws Exception {
PoolingOptionsFactoryBean poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
PoolingOptions newPoolingOptions() {
poolingOptionsSpy.setNewConnectionThreshold(HostDistance.REMOTE, 10);
return poolingOptionsSpy;
}
};
poolingOptionsFactoryBean.setHeartbeatIntervalSeconds(33);
poolingOptionsFactoryBean.setIdleTimeoutSeconds(112);
poolingOptionsFactoryBean.setInitializationExecutor(mockExecutor);
poolingOptionsFactoryBean.setPoolTimeoutMilliseconds(130);
poolingOptionsFactoryBean.setRemoteCoreConnections(5);
poolingOptionsFactoryBean.setRemoteMaxConnections(50);
poolingOptionsFactoryBean.setRemoteMaxSimultaneousRequests(20);
poolingOptionsFactoryBean.setRemoteMinSimultaneousRequests(5);
assertThat(poolingOptionsFactoryBean.getObject()).isNull();
poolingOptionsFactoryBean.afterPropertiesSet();
assertThat(poolingOptionsFactoryBean.getObject()).isSameAs(poolingOptionsSpy);
assertThat(poolingOptionsFactoryBean.getObjectType()).isEqualTo(poolingOptionsSpy.getClass());
verify(poolingOptionsSpy).setHeartbeatIntervalSeconds(eq(33));
verify(poolingOptionsSpy).setIdleTimeoutSeconds(eq(112));
verify(poolingOptionsSpy).setInitializationExecutor(eq(mockExecutor));
verify(poolingOptionsSpy).setPoolTimeoutMillis(eq(130));
verify(poolingOptionsSpy).setCoreConnectionsPerHost(eq(HostDistance.REMOTE), eq(5));
verify(poolingOptionsSpy).setMaxConnectionsPerHost(eq(HostDistance.REMOTE), eq(50));
verify(poolingOptionsSpy).setMaxRequestsPerConnection(eq(HostDistance.REMOTE), eq(20));
verify(poolingOptionsSpy, never()).setCoreConnectionsPerHost(eq(HostDistance.LOCAL), anyInt());
verify(poolingOptionsSpy, never()).setMaxConnectionsPerHost(eq(HostDistance.LOCAL), anyInt());
verify(poolingOptionsSpy, never()).setMaxRequestsPerConnection(eq(HostDistance.LOCAL), anyInt());
verify(poolingOptionsSpy, never()).setNewConnectionThreshold(eq(HostDistance.LOCAL), anyInt());
verify(poolingOptionsSpy, never()).setNewConnectionThreshold(eq(HostDistance.REMOTE), eq(5));
}
@Test // DATACASS-344
public void afterPropertiesSetInitializesMaxQueueSize() throws Exception {
Method setMaxQueueSize = ReflectionUtils.findMethod(PoolingOptions.class, "setMaxQueueSize", int.class);
Method getMaxQueueSize = ReflectionUtils.findMethod(PoolingOptions.class, "getMaxQueueSize");
assumeNotNull(setMaxQueueSize);
PoolingOptionsFactoryBean poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
PoolingOptions newPoolingOptions() {
return poolingOptionsSpy;
}
};
poolingOptionsFactoryBean.setMaxQueueSize(1234);
poolingOptionsFactoryBean.afterPropertiesSet();
assertThat(poolingOptionsFactoryBean.getObject()).isSameAs(poolingOptionsSpy);
assertThat(poolingOptionsFactoryBean.getObjectType()).isEqualTo(poolingOptionsSpy.getClass());
assertThat(invokeMethod(getMaxQueueSize, poolingOptionsSpy)).isEqualTo(1234);
}
/**
* This particular test case is technically an integration test since it uses an actual instance of a DataStax Java
* driver class type... {@link PoolingOptions}! The max values should be set before setting core values. Otherwise the
* core values will be compared with the default max values which is 8. Same for other min-max properties pairs. This
* test checks the same.
*/
@Test // DATACASS-176
public void afterPropertiesSetProperlySetsPoolingOptionsMaxBeforeMinProperties() throws Exception {
poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
PoolingOptions newPoolingOptions() {
return spy(super.newPoolingOptions());
}
};
poolingOptionsFactoryBean.setLocalMaxConnections(200);
poolingOptionsFactoryBean.setLocalCoreConnections(100);
poolingOptionsFactoryBean.setLocalMaxSimultaneousRequests(99);
poolingOptionsFactoryBean.setLocalMinSimultaneousRequests(97);
poolingOptionsFactoryBean.setRemoteMaxConnections(210);
poolingOptionsFactoryBean.setRemoteCoreConnections(110);
poolingOptionsFactoryBean.setRemoteMaxSimultaneousRequests(127);
poolingOptionsFactoryBean.setRemoteMinSimultaneousRequests(111);
assertThat(poolingOptionsFactoryBean.getObject()).isNull();
poolingOptionsFactoryBean.afterPropertiesSet();
PoolingOptions poolingOptions = poolingOptionsFactoryBean.getObject();
assertThat(poolingOptions).isNotNull();
assertThat(poolingOptions.getCoreConnectionsPerHost(HostDistance.LOCAL)).isEqualTo(100);
assertThat(poolingOptions.getMaxConnectionsPerHost(HostDistance.LOCAL)).isEqualTo(200);
assertThat(poolingOptions.getMaxRequestsPerConnection(HostDistance.LOCAL)).isEqualTo(99);
assertThat(poolingOptions.getNewConnectionThreshold(HostDistance.LOCAL)).isEqualTo(97);
assertThat(poolingOptions.getCoreConnectionsPerHost(HostDistance.REMOTE)).isEqualTo(110);
assertThat(poolingOptions.getMaxConnectionsPerHost(HostDistance.REMOTE)).isEqualTo(210);
assertThat(poolingOptions.getMaxRequestsPerConnection(HostDistance.REMOTE)).isEqualTo(127);
assertThat(poolingOptions.getNewConnectionThreshold(HostDistance.REMOTE)).isEqualTo(111);
verify(poolingOptions).setMaxConnectionsPerHost(eq(HostDistance.LOCAL), eq(200));
verify(poolingOptions).setCoreConnectionsPerHost(eq(HostDistance.LOCAL), eq(100));
verify(poolingOptions).setMaxRequestsPerConnection(eq(HostDistance.LOCAL), eq(99));
verify(poolingOptions).setNewConnectionThreshold(eq(HostDistance.LOCAL), eq(97));
verify(poolingOptions).setMaxConnectionsPerHost(eq(HostDistance.REMOTE), eq(210));
verify(poolingOptions).setCoreConnectionsPerHost(eq(HostDistance.REMOTE), eq(110));
verify(poolingOptions).setMaxRequestsPerConnection(eq(HostDistance.REMOTE), eq(127));
verify(poolingOptions).setNewConnectionThreshold(eq(HostDistance.REMOTE), eq(111));
}
@Test // DATACASS-176
public void newLocalHostDistancePoolingOptionsReturnsLocalHostDistancePoolingOptionsFactoryBeanSettings() {
poolingOptionsFactoryBean.setLocalCoreConnections(50);
poolingOptionsFactoryBean.setLocalMaxConnections(500);
poolingOptionsFactoryBean.setLocalMaxSimultaneousRequests(1000);
poolingOptionsFactoryBean.setLocalMinSimultaneousRequests(100);
poolingOptionsFactoryBean.setRemoteCoreConnections(20);
poolingOptionsFactoryBean.setRemoteMaxConnections(200);
poolingOptionsFactoryBean.setRemoteMaxSimultaneousRequests(400);
poolingOptionsFactoryBean.setRemoteMinSimultaneousRequests(40);
PoolingOptionsFactoryBean.HostDistancePoolingOptions poolingOptions = poolingOptionsFactoryBean
.newLocalHostDistancePoolingOptions();
assertThat(poolingOptions.getHostDistance()).isEqualTo(HostDistance.LOCAL);
assertThat(poolingOptions.getCoreConnectionsPerHost()).isEqualTo(50);
assertThat(poolingOptions.getMaxConnectionsPerHost()).isEqualTo(500);
assertThat(poolingOptions.getMaxRequestsPerConnection()).isEqualTo(1000);
assertThat(poolingOptions.getNewConnectionThreshold()).isEqualTo(100);
}
@Test // DATACASS-176
public void newLocalHostDistancePoolingOptionsReturnsRemoteHostDistancePoolingOptionsFactoryBeanSettings() {
poolingOptionsFactoryBean.setLocalCoreConnections(50);
poolingOptionsFactoryBean.setLocalMaxConnections(500);
poolingOptionsFactoryBean.setLocalMaxSimultaneousRequests(1000);
poolingOptionsFactoryBean.setLocalMinSimultaneousRequests(100);
poolingOptionsFactoryBean.setRemoteCoreConnections(20);
poolingOptionsFactoryBean.setRemoteMaxConnections(200);
poolingOptionsFactoryBean.setRemoteMaxSimultaneousRequests(400);
poolingOptionsFactoryBean.setRemoteMinSimultaneousRequests(40);
PoolingOptionsFactoryBean.HostDistancePoolingOptions poolingOptions = poolingOptionsFactoryBean
.newRemoteHostDistancePoolingOptions();
assertThat(poolingOptions.getHostDistance()).isEqualTo(HostDistance.REMOTE);
assertThat(poolingOptions.getCoreConnectionsPerHost()).isEqualTo(20);
assertThat(poolingOptions.getMaxConnectionsPerHost()).isEqualTo(200);
assertThat(poolingOptions.getMaxRequestsPerConnection()).isEqualTo(400);
assertThat(poolingOptions.getNewConnectionThreshold()).isEqualTo(40);
}
@Test // DATACASS-176
public void configureLocalHostDistancePoolingOptionsCallsConfigureWithExpectedInstance() {
final PoolingOptionsFactoryBean.HostDistancePoolingOptions mockHostDistancePoolingOptions = mock(
PoolingOptionsFactoryBean.HostDistancePoolingOptions.class);
when(mockHostDistancePoolingOptions.configure(any(PoolingOptions.class)))
.thenAnswer(invocationOnMock -> invocationOnMock.getArgument(0));
poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
protected HostDistancePoolingOptions newLocalHostDistancePoolingOptions() {
return mockHostDistancePoolingOptions;
}
};
assertThat(poolingOptionsFactoryBean.configureLocalHostDistancePoolingOptions(poolingOptionsSpy))
.isSameAs(poolingOptionsSpy);
verify(mockHostDistancePoolingOptions).configure(same(poolingOptionsSpy));
}
@Test // DATACASS-176
public void configureRemoteHostDistancePoolingOptionsCallsConfigureWithExpectedInstance() {
final PoolingOptionsFactoryBean.HostDistancePoolingOptions mockHostDistancePoolingOptions = mock(
PoolingOptionsFactoryBean.HostDistancePoolingOptions.class);
when(mockHostDistancePoolingOptions.configure(any(PoolingOptions.class)))
.thenAnswer(invocationOnMock -> invocationOnMock.getArgument(0));
poolingOptionsFactoryBean = new PoolingOptionsFactoryBean() {
@Override
protected HostDistancePoolingOptions newRemoteHostDistancePoolingOptions() {
return mockHostDistancePoolingOptions;
}
};
assertThat(poolingOptionsFactoryBean.configureRemoteHostDistancePoolingOptions(poolingOptionsSpy))
.isSameAs(poolingOptionsSpy);
verify(mockHostDistancePoolingOptions).configure(same(poolingOptionsSpy));
}
}