DATACASS-271 - Polishing.

Add author tags. Add/update license headers where needed. Remove calls to deprecated methods. Adopt pooling options after the driver update. Add hints_directory for Cassandra 3.

Reduce driver baseline to core driver 3.0.1. The DSE driver requires the core driver itself and can be added as dependency to user projects while retaining full compatibility. As of now the DSE driver is rc1 hence it requires core rc1.

Use getTimestamp for timestamp type methods as the driver aligned the method to the type. Support short, byte and time. Enable LocalDate return type and add tests for native supported types.

Change long to bigint type as long was mapped to the counter type when creating tables. Align the default to bigint as bigint is the better choice since table creation uses mostly regular tables and not counter tables. Type can be overriden using @CassandraType.

We now support setting NettyOptions on CassandraCqlClusterFactoryBean and AbstractClusterConfiguration. The cassandra driver 2.1.9 changed its default shutdown behavior by introducing a 2 second quiet period when shutting down Cluster instances. This change was retained throughout the 3.0 driver which slow the test down by an order of magnitude. Configure QueryOptions on tests to prevent delays caused by the asynchronous schema refresh.

Original pull request: #56.
Related pull request: #52.
Related ticket: DATACASS-169.
This commit is contained in:
Mark Paluch
2016-05-04 15:33:35 +02:00
committed by John Blum
parent a920b530df
commit be495728d9
45 changed files with 1269 additions and 385 deletions

View File

@@ -24,6 +24,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Configuration;
import com.datastax.driver.core.JdkSSLOptions;
import com.datastax.driver.core.PlainTextAuthProvider;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions.Compression;
@@ -257,7 +258,7 @@ public class CassandraCqlClusterFactoryBeanUnitTests {
@Test
public void shouldSetSslOptions() throws Exception {
SSLOptions sslOptions = new SSLOptions();
SSLOptions sslOptions = JdkSSLOptions.builder().build();
CassandraCqlClusterFactoryBean bean = new CassandraCqlClusterFactoryBean();
bean.setSslEnabled(true);
@@ -278,7 +279,7 @@ public class CassandraCqlClusterFactoryBeanUnitTests {
bean.setMetricsEnabled(false);
bean.afterPropertiesSet();
assertThat(getConfiguration(bean).getMetricsOptions(), is(nullValue()));
assertThat(getConfiguration(bean).getMetricsOptions().isEnabled(), is(false));
}
/**

View File

@@ -245,7 +245,7 @@ public class AbstractClusterConfigurationUnitTests {
};
Cluster cluster = getCluster(clusterConfiguration);
assertThat(getConfiguration(cluster).getMetricsOptions(), is(nullValue()));
assertThat(getConfiguration(cluster).getMetricsOptions().isEnabled(), is(false));
}
/**

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2013-2016 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
* 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,
@@ -73,7 +73,7 @@ public class CassandraExceptionTranslatorTest {
@Test
public void testInvalidConfigurationInQueryException() {
String msg = "msg";
InvalidQueryException cx = new InvalidConfigurationInQueryException(msg);
InvalidQueryException cx = new InvalidConfigurationInQueryException(null, msg);
DataAccessException dax = tx.translateExceptionIfPossible(cx);
assertNotNull(dax);
assertTrue(dax instanceof CassandraInvalidConfigurationInQueryException);

View File

@@ -27,11 +27,13 @@ import org.junit.rules.ExternalResource;
import org.springframework.cassandra.core.SessionCallback;
import org.springframework.cassandra.test.integration.support.CassandraConnectionProperties;
import org.springframework.cassandra.test.integration.support.CqlDataSet;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.dao.DataAccessException;
import org.springframework.util.Assert;
import org.springframework.util.SocketUtils;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.QueryOptions;
import com.datastax.driver.core.Session;
/**
@@ -48,6 +50,7 @@ import com.datastax.driver.core.Session;
* </pre>
*
* @author Mark Paluch
* @since 1.5
*/
public class CassandraRule extends ExternalResource {
@@ -70,7 +73,7 @@ public class CassandraRule extends ExternalResource {
* @param yamlConfigurationResource name of the configuration resource, must not be {@literal null} and not empty
*/
public CassandraRule(String yamlConfigurationResource) {
this(yamlConfigurationResource, EmbeddedCassandraServerHelper.DEFAULT_STARTUP_TIMEOUT);
this(yamlConfigurationResource, EmbeddedCassandraServerHelper.DEFAULT_STARTUP_TIMEOUT_MS);
}
/**
@@ -310,7 +313,15 @@ public class CassandraRule extends ExternalResource {
port = properties.getCassandraPort();
}
cassandraPort = port;
cluster = new Cluster.Builder().addContactPoints(hostIp).withPort(port).build();
QueryOptions queryOptions = new QueryOptions();
queryOptions.setRefreshSchemaIntervalMillis(0);
cluster = new Cluster.Builder().addContactPoints(hostIp).//
withPort(port).//
withQueryOptions(queryOptions).//
withNettyOptions(FastShutdownNettyOptions.INSTANCE).//
build();
} else {
cluster = parent.cluster;
cassandraPort = parent.cassandraPort;

View File

@@ -22,10 +22,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.cassandra.config.DatabaseDescriptor;
@@ -45,7 +42,7 @@ class EmbeddedCassandraServerHelper {
private static Logger log = LoggerFactory.getLogger(EmbeddedCassandraServerHelper.class);
public static final long DEFAULT_STARTUP_TIMEOUT = 10000;
public static final long DEFAULT_STARTUP_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(20);
public static final String DEFAULT_TMP_DIR = "target/embeddedCassandra";
private final static AtomicReference<Object> sync = new AtomicReference<Object>();

View File

@@ -15,13 +15,16 @@
*/
package org.springframework.cassandra.test.integration.config;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.config.CassandraCqlClusterFactoryBean;
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.test.util.ReflectionTestUtils;
import com.datastax.driver.core.ProtocolVersion;
@@ -29,8 +32,9 @@ import com.datastax.driver.core.ProtocolVersion;
* Unit tests for {@link CassandraCqlClusterFactoryBean}.
*
* @author Kirk Clemens
* @author Mark Paluch
*/
public class CassandraCqlClusterFactoryBeanIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest {
public class CassandraCqlClusterFactoryBeanIntegrationTests {
private CassandraCqlClusterFactoryBean cassandraCqlClusterFactoryBean;
@@ -47,27 +51,26 @@ public class CassandraCqlClusterFactoryBeanIntegrationTests extends AbstractEmbe
@Test
public void configuredProtocolVersionShouldBeSet() throws Exception {
cassandraCqlClusterFactoryBean.setProtocolVersion(ProtocolVersion.V4);
cassandraCqlClusterFactoryBean.setPort(cassandraEnvironment.getPort());
cassandraCqlClusterFactoryBean.setNettyOptions(FastShutdownNettyOptions.INSTANCE);
cassandraCqlClusterFactoryBean.setProtocolVersion(ProtocolVersion.V2);
cassandraCqlClusterFactoryBean.afterPropertiesSet();
assertEquals(ProtocolVersion.V4, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
assertEquals(ProtocolVersion.V2, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
}
@Test
public void defaultProtocolVersionShouldBeSet() throws Exception {
cassandraCqlClusterFactoryBean.setPort(cassandraEnvironment.getPort());
cassandraCqlClusterFactoryBean.afterPropertiesSet();
assertEquals(ProtocolVersion.NEWEST_SUPPORTED, getProtocolVersionEnum(cassandraCqlClusterFactoryBean));
assertThat(getProtocolVersionEnum(cassandraCqlClusterFactoryBean), is(nullValue()));
}
private ProtocolVersion getProtocolVersionEnum(CassandraCqlClusterFactoryBean cassandraCqlClusterFactoryBean)
throws Exception {
// initialize connection factory
cassandraCqlClusterFactoryBean.getObject().init();
return cassandraCqlClusterFactoryBean.getObject().getConfiguration().getProtocolOptions().getProtocolVersion();
return (ProtocolVersion) ReflectionTestUtils.getField(
cassandraCqlClusterFactoryBean.getObject().getConfiguration().getProtocolOptions(), "initialProtocolVersion");
}
}

View File

@@ -23,23 +23,24 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.config.java.AbstractCqlTemplateConfiguration;
import org.springframework.cassandra.core.CqlTemplate;
import org.springframework.cassandra.support.RandomKeySpaceName;
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.cassandra.test.integration.support.FastShutdownNettyOptions;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.Session;
/**
* Integration tests for {@link AbstractCqlTemplateConfiguration}.
*
* @author Matthews T. Adams
* @author Oliver Gierke
* @author Mark Paluch
*/
public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandraIntegrationTest {
public static final String KEYSPACE_NAME = RandomKeySpaceName.create();
@Configuration
public static class Config extends AbstractCqlTemplateConfiguration {
@@ -52,6 +53,11 @@ public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandra
protected int getPort() {
return cassandraEnvironment.getPort();
}
@Override
protected NettyOptions getNettyOptions() {
return FastShutdownNettyOptions.INSTANCE;
}
}
Session session;
@@ -59,6 +65,7 @@ public class CqlTemplateConfigIntegrationTests extends AbstractEmbeddedCassandra
@Before
public void setUp() {
this.context = new AnnotationConfigApplicationContext(Config.class);
this.session = context.getBean(Session.class);
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -24,6 +24,10 @@ import org.springframework.cassandra.core.keyspace.KeyspaceOption;
import org.springframework.cassandra.test.integration.support.AbstractTestJavaConfig;
import org.springframework.context.annotation.Configuration;
/**
* @author Matthew T. Adams
* @author Mark Paluch
*/
@Configuration
public class KeyspaceCreatingJavaConfig extends AbstractTestJavaConfig {

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2014 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -23,7 +23,11 @@ import com.datastax.driver.core.Host;
import com.datastax.driver.core.Host.StateListener;
/**
* {@link StateListener} that logs latency events and their payload. This class can be considered a test dummy and is
* suitable for mocking.
*
* @author David Webb
* @author Antoine Toulme
*/
public class TestHostStateListener implements StateListener {
@@ -31,32 +35,32 @@ public class TestHostStateListener implements StateListener {
@Override
public void onAdd(Host host) {
log.info("Host Added: " + host.getAddress());
log.info("Host Added: {}", host.getAddress());
}
@Override
public void onUp(Host host) {
log.info("Host Up: " + host.getAddress());
log.info("Host Up: {}", host.getAddress());
}
@Override
public void onDown(Host host) {
log.info("Host Down: " + host.getAddress());
log.info("Host Down: {}", host.getAddress());
}
@Override
public void onRemove(Host host) {
log.info("Host Removed: " + host.getAddress());
log.info("Host Removed: {}", host.getAddress());
}
@Override
public void onRegister(Cluster cluster) {
log.info("Cluster registered: " + cluster.getClusterName());
log.info("Cluster registered: {}", cluster.getClusterName());
}
@Override
public void onUnregister(Cluster cluster) {
log.info("Cluster unregistered: " + cluster.getClusterName());
log.info("Cluster unregistered: {}", cluster.getClusterName());
}
}

View File

@@ -1,12 +1,12 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Copyright 2013-2016 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.
@@ -24,8 +24,12 @@ import com.datastax.driver.core.LatencyTracker;
import com.datastax.driver.core.Statement;
/**
* {@link LatencyTracker} that logs latency events and their payload. This class can be considered a test dummy and is suitable for
* mocking.
*
* @author David Webb
* @author Oliver Gierke
* @author Antoine Toulme
*/
public class TestLatencyTracker implements LatencyTracker {
@@ -33,15 +37,16 @@ public class TestLatencyTracker implements LatencyTracker {
@Override
public void update(Host host, Statement statement, Exception exception, long newLatencyNanos) {
LOG.info("Latency Tracker: " + host.getAddress() + ", " + newLatencyNanos + " nanoseconds.");
}
@Override
public void onRegister(Cluster cluster) {
}
@Override
public void onUnregister(Cluster cluster) {
LOG.info("Latency Tracker update: {}, {} nanoseconds.", host.getAddress(), newLatencyNanos);
}
@Override
public void onRegister(Cluster cluster) {
LOG.info("Latency Tracker onRegister: {}", cluster);
}
@Override
public void onUnregister(Cluster cluster) {
LOG.info("Latency Tracker onUnregister: {}", cluster);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -15,6 +15,7 @@
*/
package org.springframework.cassandra.test.integration.core.cql.generator;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import org.springframework.cassandra.core.keyspace.IndexDescriptor;
@@ -26,24 +27,40 @@ import com.datastax.driver.core.TableMetadata;
/**
* @author David Webb
* @author Matthew T. Adams
* @author Antoine Toulme
*/
public class CqlIndexSpecificationAssertions {
/**
* Assert the existence of an index using the index name.
*
* @param expected
* @param keyspace
* @param session
*/
public static void assertIndex(IndexDescriptor expected, String keyspace, Session session) {
TableMetadata tableMetadata = session.getCluster().getMetadata().getKeyspace(keyspace.toLowerCase())
.getTable(expected.getTableName().toCql());
IndexMetadata imd = tableMetadata.getIndex(expected.getName().toCql());
assertEquals(expected.getName(), imd == null ? null : imd.getName());
IndexMetadata indexMetadata = tableMetadata.getIndex(expected.getName().toCql());
assertThat(indexMetadata, is(not(nullValue())));
assertThat(indexMetadata.getName(), is(equalTo(expected.getName().toCql())));
}
/**
* Assert the absence of an index using the index name.
*
* @param expected
* @param keyspace
* @param session
*/
public static void assertNoIndex(IndexDescriptor expected, String keyspace, Session session) {
TableMetadata tableMetadata = session.getCluster().getMetadata().getKeyspace(keyspace.toLowerCase())
.getTable(expected.getTableName().toCql());
IndexMetadata imd = tableMetadata.getIndex(expected.getName().toCql());
assertNull(imd);
IndexMetadata indexMetadata = tableMetadata.getIndex(expected.getName().toCql());
assertThat(indexMetadata, is(nullValue()));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -35,8 +35,9 @@ import com.datastax.driver.core.TableOptionsMetadata;
/**
* @author Matthew T. Adams
* @author Matthew T. Adams
* @author David Webb
* @author Alex Shvid
* @author Antoine Toulme
*/
public class CqlTableSpecificationAssertions {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2014 the original author or authors.
* Copyright 2013-2016 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.
@@ -18,8 +18,14 @@ package org.springframework.cassandra.test.integration.support;
import org.springframework.cassandra.config.java.AbstractSessionConfiguration;
import org.springframework.context.annotation.Configuration;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.QueryOptions;
/**
* Java-based configuration for integration tests using defaults for a smooth test run.
*
* @author Matthew T. Adams
* @author Mark Paluch
*/
@Configuration
public abstract class AbstractTestJavaConfig extends AbstractSessionConfiguration {
@@ -30,4 +36,20 @@ public abstract class AbstractTestJavaConfig extends AbstractSessionConfiguratio
protected int getPort() {
return PROPERTIES.getCassandraPort();
}
@Override
protected NettyOptions getNettyOptions() {
return FastShutdownNettyOptions.INSTANCE;
}
@Override
protected QueryOptions getQueryOptions() {
// The driver blocks otherwise up to 1 sec on schema refreshes.
// see also https://datastax-oss.atlassian.net/browse/JAVA-1120
// ideally, this issue will be resolved with Cassandra Java Driver 3.0.2
QueryOptions queryOptions = new QueryOptions();
queryOptions.setRefreshSchemaIntervalMillis(0);
return queryOptions;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2016 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.test.integration.support;
import java.util.concurrent.TimeUnit;
import com.datastax.driver.core.NettyOptions;
import io.netty.channel.EventLoopGroup;
/**
* {@link NettyOptions} to shutdown a {@link com.datastax.driver.core.Cluster} instance without wait time.
*
* @author Mark Paluch
* @since 1.5
*/
public class FastShutdownNettyOptions extends NettyOptions {
public final static FastShutdownNettyOptions INSTANCE = new FastShutdownNettyOptions();
@Override
public void onClusterClose(EventLoopGroup eventLoopGroup) {
eventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS);
}
}