DATACASS-144: done; rebased all branch commits
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package org.springframework.cassandra.test.integration;
|
||||
|
||||
import org.springframework.cassandra.core.CqlOperations;
|
||||
import org.springframework.cassandra.core.CqlTemplate;
|
||||
|
||||
public class AbstractCqlTemplateIntegrationTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
protected CqlOperations t;
|
||||
|
||||
{
|
||||
t = new CqlTemplate(SESSION);
|
||||
}
|
||||
|
||||
public AbstractCqlTemplateIntegrationTest() {}
|
||||
|
||||
public AbstractCqlTemplateIntegrationTest(String keyspace) {
|
||||
super(keyspace);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import com.datastax.driver.core.Host.StateListener;
|
||||
|
||||
/**
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public class TestHostStateListener implements StateListener {
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.datastax.driver.core.LatencyTracker;
|
||||
|
||||
/**
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public class TestLatencyTracker implements LatencyTracker {
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = "classpath:/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml")
|
||||
@ContextConfiguration(
|
||||
locations = "classpath:/org/springframework/cassandra/test/integration/config/xml/XmlConfigTest-context.xml")
|
||||
public class XmlConfigTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
public static final String KEYSPACE = "xmlconfigtest";
|
||||
|
||||
@@ -93,23 +93,23 @@ public class CqlTableSpecificationAssertions {
|
||||
|
||||
switch (tableOption) {
|
||||
|
||||
case BLOOM_FILTER_FP_CHANCE:
|
||||
case READ_REPAIR_CHANCE:
|
||||
case DCLOCAL_READ_REPAIR_CHANCE:
|
||||
assertEquals((Double) expected, (Double) actual, DELTA);
|
||||
return;
|
||||
case BLOOM_FILTER_FP_CHANCE:
|
||||
case READ_REPAIR_CHANCE:
|
||||
case DCLOCAL_READ_REPAIR_CHANCE:
|
||||
assertEquals((Double) expected, (Double) actual, DELTA);
|
||||
return;
|
||||
|
||||
case CACHING:
|
||||
assertEquals(((String) expected).toUpperCase(), ((String) actual).toUpperCase());
|
||||
return;
|
||||
case CACHING:
|
||||
assertEquals(((String) expected).toUpperCase(), ((String) actual).toUpperCase());
|
||||
return;
|
||||
|
||||
case COMPACTION:
|
||||
assertCompaction((Map<String, Object>) expected, (Map<String, String>) actual);
|
||||
return;
|
||||
case COMPACTION:
|
||||
assertCompaction((Map<String, Object>) expected, (Map<String, String>) actual);
|
||||
return;
|
||||
|
||||
case COMPRESSION:
|
||||
assertCompression((Map<String, Object>) expected, (Map<String, String>) actual);
|
||||
return;
|
||||
case COMPRESSION:
|
||||
assertCompression((Map<String, Object>) expected, (Map<String, String>) actual);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info(actual.getClass().getName());
|
||||
@@ -137,26 +137,26 @@ public class CqlTableSpecificationAssertions {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getOptionFor(TableOption option, Class<?> type, Options options) {
|
||||
switch (option) {
|
||||
case BLOOM_FILTER_FP_CHANCE:
|
||||
return (T) (Double) options.getBloomFilterFalsePositiveChance();
|
||||
case CACHING:
|
||||
return (T) CqlStringUtils.singleQuote(options.getCaching());
|
||||
case COMMENT:
|
||||
return (T) CqlStringUtils.singleQuote(options.getComment());
|
||||
case COMPACTION:
|
||||
return (T) options.getCompaction();
|
||||
case COMPACT_STORAGE:
|
||||
throw new Error(); // TODO: figure out
|
||||
case COMPRESSION:
|
||||
return (T) options.getCompression();
|
||||
case DCLOCAL_READ_REPAIR_CHANCE:
|
||||
return (T) (Double) options.getLocalReadRepairChance();
|
||||
case GC_GRACE_SECONDS:
|
||||
return (T) new Long(options.getGcGraceInSeconds());
|
||||
case READ_REPAIR_CHANCE:
|
||||
return (T) (Double) options.getReadRepairChance();
|
||||
case REPLICATE_ON_WRITE:
|
||||
return (T) (Boolean) options.getReplicateOnWrite();
|
||||
case BLOOM_FILTER_FP_CHANCE:
|
||||
return (T) (Double) options.getBloomFilterFalsePositiveChance();
|
||||
case CACHING:
|
||||
return (T) CqlStringUtils.singleQuote(options.getCaching());
|
||||
case COMMENT:
|
||||
return (T) CqlStringUtils.singleQuote(options.getComment());
|
||||
case COMPACTION:
|
||||
return (T) options.getCompaction();
|
||||
case COMPACT_STORAGE:
|
||||
throw new Error(); // TODO: figure out
|
||||
case COMPRESSION:
|
||||
return (T) options.getCompression();
|
||||
case DCLOCAL_READ_REPAIR_CHANCE:
|
||||
return (T) (Double) options.getLocalReadRepairChance();
|
||||
case GC_GRACE_SECONDS:
|
||||
return (T) new Long(options.getGcGraceInSeconds());
|
||||
case READ_REPAIR_CHANCE:
|
||||
return (T) (Double) options.getReadRepairChance();
|
||||
case REPLICATE_ON_WRITE:
|
||||
return (T) (Boolean) options.getReplicateOnWrite();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public class CreateIndexCqlGeneratorIntegrationTests {
|
||||
* Integration test base class that knows how to do everything except instantiate the concrete unit test type T.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <T> The concrete unit test class to which this integration test corresponds.
|
||||
*/
|
||||
public static abstract class Base<T extends CreateIndexTest> extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
@@ -34,7 +34,6 @@ public class CreateTableCqlGeneratorIntegrationTests {
|
||||
* Integration test base class that knows how to do everything except instantiate the concrete unit test type T.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <T> The concrete unit test class to which this integration test corresponds.
|
||||
*/
|
||||
public static abstract class Base<T extends CreateTableTest> extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
@@ -39,4 +39,4 @@ public class FunkyIdentifierIntegrationTest extends AbstractKeyspaceCreatingInte
|
||||
.partitionKeyColumn(name, DataType.text())).toCql());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.cassandra.test.integration.core.template;
|
||||
* Test POJO
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public class Book {
|
||||
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
*/
|
||||
package org.springframework.cassandra.test.integration.core.template;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cassandra.core.AsynchronousQueryListener;
|
||||
import org.springframework.cassandra.test.unit.support.TestListener;
|
||||
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
import com.datastax.driver.core.Row;
|
||||
@@ -26,18 +25,17 @@ import com.datastax.driver.core.Row;
|
||||
* Test Implementation of the {@link AsynchronousQueryListener}
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public class BookListener implements AsynchronousQueryListener {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(BookListener.class);
|
||||
public class BookListener extends TestListener implements AsynchronousQueryListener {
|
||||
|
||||
private Book book;
|
||||
private boolean done;
|
||||
|
||||
@Override
|
||||
public void onQueryComplete(ResultSetFuture rsf) {
|
||||
log.info("QueryCompleted");
|
||||
countDown();
|
||||
|
||||
Row row;
|
||||
try {
|
||||
row = rsf.get().one();
|
||||
@@ -51,8 +49,6 @@ public class BookListener implements AsynchronousQueryListener {
|
||||
book.setPages(row.getInt("pages"));
|
||||
|
||||
done = true;
|
||||
log.info("DONE");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,7 +73,6 @@ import static org.junit.Assert.assertTrue;
|
||||
* Unit Tests for CqlTemplate
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
@@ -106,12 +105,8 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
@Before
|
||||
public void setupTemplate() {
|
||||
|
||||
log.info("Running setupTemplate()");
|
||||
|
||||
if (cqlTemplate == null) {
|
||||
|
||||
log.info("null Template ... Initialzing DB test CQL");
|
||||
|
||||
// CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet(
|
||||
// "cassandraOperationsTest-cql-dataload.cql", keyspace), CASSANDRA_CONFIG, CASSANDRA_HOST,
|
||||
// CASSANDRA_NATIVE_PORT);
|
||||
@@ -130,10 +125,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
* running.
|
||||
*/
|
||||
assertNotNull(ring);
|
||||
|
||||
for (RingMember h : ring) {
|
||||
log.info("ringTest Host -> " + h.address);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -424,7 +415,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryAsynchronouslyWithListener() {
|
||||
public void queryAsynchronouslyWithListener() throws InterruptedException {
|
||||
|
||||
QueryOptions options = new QueryOptions();
|
||||
options.setConsistencyLevel(ConsistencyLevel.ONE);
|
||||
@@ -433,25 +424,15 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
final String isbn = "999999999";
|
||||
|
||||
BookListener listener = new BookListener();
|
||||
|
||||
cqlTemplate.queryAsynchronously("select * from book where isbn='" + isbn + "'", listener);
|
||||
|
||||
// TODO Use better multi threading devices here.
|
||||
while (!listener.isDone()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException muted) {
|
||||
}
|
||||
}
|
||||
listener.await();
|
||||
|
||||
Book book2 = getBook(isbn);
|
||||
|
||||
assertBook(listener.getBook(), book2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryAsynchronouslyWithListenerAndExecutor() {
|
||||
public void queryAsynchronouslyWithListenerAndExecutor() throws InterruptedException {
|
||||
|
||||
QueryOptions options = new QueryOptions();
|
||||
options.setConsistencyLevel(ConsistencyLevel.ONE);
|
||||
@@ -468,23 +449,14 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
command.run();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Use better multi threading devices here.
|
||||
while (!listener.isDone()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException muted) {
|
||||
}
|
||||
}
|
||||
listener.await();
|
||||
|
||||
Book book2 = getBook(isbn);
|
||||
|
||||
assertBook(listener.getBook(), book2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryAsynchronouslyWithListenerAndExecutorAndOptions() {
|
||||
public void queryAsynchronouslyWithListenerAndExecutorAndOptions() throws InterruptedException {
|
||||
|
||||
QueryOptions options = new QueryOptions();
|
||||
options.setConsistencyLevel(ConsistencyLevel.ONE);
|
||||
@@ -501,19 +473,10 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
command.run();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO Use better multi threading devices here.
|
||||
while (!listener.isDone()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException muted) {
|
||||
}
|
||||
}
|
||||
listener.await();
|
||||
|
||||
Book book2 = getBook(isbn);
|
||||
|
||||
assertBook(listener.getBook(), book2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -589,7 +552,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
}
|
||||
});
|
||||
|
||||
log.debug("Size of Book List -> " + books.size());
|
||||
assertEquals(books.size(), 3);
|
||||
assertBook(books.get(0), getBook(books.get(0).getIsbn()));
|
||||
assertBook(books.get(1), getBook(books.get(1).getIsbn()));
|
||||
@@ -617,7 +579,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
}
|
||||
});
|
||||
|
||||
log.debug("Size of Book List -> " + books.size());
|
||||
assertEquals(books.size(), 3);
|
||||
assertBook(books.get(0), getBook(books.get(0).getIsbn()));
|
||||
assertBook(books.get(1), getBook(books.get(1).getIsbn()));
|
||||
@@ -725,8 +686,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
Map<String, Object> rsMap = cqlTemplate.queryForMap("select * from book where isbn in ('" + ISBN_NINES + "')");
|
||||
|
||||
log.debug(rsMap.toString());
|
||||
|
||||
Book b1 = objectToBook(rsMap.get("isbn"), rsMap.get("title"), rsMap.get("author"), rsMap.get("pages"));
|
||||
|
||||
Book b2 = getBook(ISBN_NINES);
|
||||
@@ -746,8 +705,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
Map<String, Object> rsMap = cqlTemplate.processMap(rs);
|
||||
|
||||
log.debug("Size of Book List -> " + rsMap.size());
|
||||
|
||||
Book b1 = objectToBook(rsMap.get("isbn"), rsMap.get("title"), rsMap.get("author"), rsMap.get("pages"));
|
||||
|
||||
Book b2 = getBook(ISBN_NINES);
|
||||
@@ -765,8 +722,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
List<String> titles = cqlTemplate.queryForList("select title from book where isbn in ('1234','2345','3456')",
|
||||
String.class);
|
||||
|
||||
log.debug(titles.toString());
|
||||
|
||||
assertNotNull(titles);
|
||||
assertEquals(titles.size(), 3);
|
||||
|
||||
@@ -786,8 +741,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
List<String> titles = cqlTemplate.processList(rs, String.class);
|
||||
|
||||
log.debug(titles.toString());
|
||||
|
||||
assertNotNull(titles);
|
||||
assertEquals(titles.size(), 3);
|
||||
}
|
||||
@@ -801,8 +754,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
List<Map<String, Object>> results = cqlTemplate
|
||||
.queryForListOfMap("select * from book where isbn in ('1234','2345','3456')");
|
||||
|
||||
log.debug(results.toString());
|
||||
|
||||
assertEquals(results.size(), 3);
|
||||
|
||||
}
|
||||
@@ -821,8 +772,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
List<Map<String, Object>> results = cqlTemplate.processListOfMap(rs);
|
||||
|
||||
log.debug(results.toString());
|
||||
|
||||
assertEquals(results.size(), 3);
|
||||
|
||||
}
|
||||
@@ -981,8 +930,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
}
|
||||
});
|
||||
|
||||
log.debug("Size of all Books -> " + books.size());
|
||||
|
||||
assertTrue(books.size() > 0);
|
||||
}
|
||||
|
||||
@@ -1004,10 +951,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
@Override
|
||||
public void processRow(Row row) throws DriverException {
|
||||
|
||||
Book b = rowToBook(row);
|
||||
|
||||
log.debug("Title -> " + b.getTitle());
|
||||
|
||||
rowToBook(row);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1034,8 +978,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
}
|
||||
});
|
||||
|
||||
log.debug("Size of all Books -> " + books.size());
|
||||
|
||||
assertTrue(books.size() > 0);
|
||||
}
|
||||
|
||||
@@ -1073,8 +1015,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
Book b2 = getBook(isbn);
|
||||
|
||||
log.debug("Book list Size -> " + books.size());
|
||||
|
||||
assertEquals(books.size(), 1);
|
||||
assertBook(books.get(0), b2);
|
||||
}
|
||||
@@ -1144,8 +1084,6 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
@Test
|
||||
public void insertAndTruncateQueryObjectTest() {
|
||||
|
||||
log.info("Starting Insert and Truncate Query Object Test");
|
||||
|
||||
String tableName = "truncate_test";
|
||||
|
||||
CreateTableSpecification createTableSpec = new CreateTableSpecification();
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import org.springframework.cassandra.test.integration.AbstractCqlTemplateIntegrationTest;
|
||||
|
||||
public abstract class AbstractAsynchronousTest extends AbstractCqlTemplateIntegrationTest {}
|
||||
@@ -0,0 +1,388 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.cassandra.core.keyspace.CreateTableSpecification.createTable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cassandra.core.AsynchronousQueryListener;
|
||||
import org.springframework.cassandra.core.ConsistencyLevel;
|
||||
import org.springframework.cassandra.core.Cancellable;
|
||||
import org.springframework.cassandra.core.QueryForListOfMapListener;
|
||||
import org.springframework.cassandra.core.QueryForMapListener;
|
||||
import org.springframework.cassandra.core.QueryForObjectListener;
|
||||
import org.springframework.cassandra.core.QueryOptions;
|
||||
import org.springframework.cassandra.core.RetryPolicy;
|
||||
import org.springframework.cassandra.support.exception.CassandraInsufficientReplicasAvailableException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
public class AsynchronousTest extends AbstractAsynchronousTest {
|
||||
|
||||
public static final String TABLE = "book";
|
||||
|
||||
public static String cql(Book book, String... columns) {
|
||||
if (columns == null || columns.length == 0) {
|
||||
columns = new String[] { "title", "isbn" };
|
||||
}
|
||||
return String.format("select %s from %s where title = '%s' and isbn = '%s'",
|
||||
StringUtils.arrayToCommaDelimitedString(columns), TABLE, book.title, book.isbn);
|
||||
}
|
||||
|
||||
public static String cql(String[] titles) {
|
||||
String[] quoted = new String[titles.length];
|
||||
System.arraycopy(titles, 0, quoted, 0, titles.length);
|
||||
for (int i = 0; i < quoted.length; i++) {
|
||||
quoted[i] = "'" + quoted[i] + "'";
|
||||
}
|
||||
|
||||
return String
|
||||
.format("select * from %s where title in (%s)", TABLE, StringUtils.arrayToCommaDelimitedString(quoted));
|
||||
}
|
||||
|
||||
public static Select select(String isbn) {
|
||||
Select select = QueryBuilder.select("isbn", "title").from(TABLE);
|
||||
select.where(QueryBuilder.eq("isbn", isbn));
|
||||
return select;
|
||||
}
|
||||
|
||||
public static final Comparator<Book> BOOK_COMPARATOR = new Comparator<Book>() {
|
||||
@Override
|
||||
public int compare(Book l, Book r) {
|
||||
return l.isbn.compareTo(r.isbn);
|
||||
}
|
||||
};
|
||||
|
||||
public static void assertMapEquals(Map<?, ?> expected, Map<?, ?> actual) {
|
||||
for (Object key : expected.keySet()) {
|
||||
assertTrue(actual.containsKey(key));
|
||||
assertEquals(expected.get(key), actual.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
void ensureTableExists() {
|
||||
t.execute(createTable(TABLE).ifNotExists().partitionKeyColumn("title", DataType.ascii())
|
||||
.clusteredKeyColumn("isbn", DataType.ascii()));
|
||||
}
|
||||
|
||||
Book[] insert(int n) {
|
||||
Book[] books = new Book[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
Book b = books[i] = Book.random();
|
||||
t.execute(String.format("insert into %s (isbn, title) values ('%s', '%s')", TABLE, b.isbn, b.title));
|
||||
}
|
||||
return books;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeEach() {
|
||||
ensureTableExists();
|
||||
t.truncate(TABLE);
|
||||
}
|
||||
|
||||
void assertBook(Book expected, Book actual) {
|
||||
assertEquals(expected.isbn, actual.isbn);
|
||||
assertEquals(expected.title, actual.title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that test {@link AsynchronousQueryListener} should create an anonymous subclass of this class then call
|
||||
* either {@link #test()} or {@link #test(int)}
|
||||
*/
|
||||
abstract class AsynchronousQueryListenerTestTemplate {
|
||||
|
||||
/**
|
||||
* Subclass must perform the asynchronous query using the given data and listener and set <code>this.expected</code>
|
||||
* to the appropriate value before returning.
|
||||
*/
|
||||
abstract void doAsyncQuery(Book b, BasicListener listener);
|
||||
|
||||
void test() throws InterruptedException {
|
||||
Book expected = insert(1)[0];
|
||||
BasicListener listener = new BasicListener();
|
||||
doAsyncQuery(expected, listener);
|
||||
listener.await();
|
||||
Row r = t.getResultSetUninterruptibly(listener.rsf).one();
|
||||
Book actual = new Book(r.getString(0), r.getString(1));
|
||||
assertBook(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that test {@link QueryForObjectListener} should create an anonymous subclass of this class then call either
|
||||
* {@link #test()} or {@link #test(int)}
|
||||
*/
|
||||
abstract class QueryForObjectListenerTestTemplate<T> {
|
||||
|
||||
/**
|
||||
* Subclass must perform the asynchronous query using the given data and listener and set <code>this.expected</code>
|
||||
* to the appropriate value before returning.
|
||||
*/
|
||||
abstract void doAsyncQuery(Book b, QueryForObjectListener<T> listener);
|
||||
|
||||
T expected; // subclass should set this value in doAsyncQuery
|
||||
|
||||
void test() throws Exception {
|
||||
Book book = insert(1)[0];
|
||||
ObjectListener<T> listener = new ObjectListener<T>();
|
||||
doAsyncQuery(book, listener);
|
||||
listener.await();
|
||||
if (listener.exception != null) {
|
||||
throw listener.exception;
|
||||
}
|
||||
assertEquals(expected, listener.result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that test {@link QueryForMapListener} should create an anonymous subclass of this class then call either
|
||||
* {@link #test()} or {@link #test(int)}
|
||||
*/
|
||||
abstract class QueryForMapListenerTestTemplate {
|
||||
|
||||
/**
|
||||
* Subclass must perform the asynchronous query using the given data and listener and set <code>this.expected</code>
|
||||
* to the appropriate value before returning.
|
||||
*/
|
||||
abstract void doAsyncQuery(Book b, QueryForMapListener listener);
|
||||
|
||||
Map<String, Object> expected; // subclass should set this value in doAsyncQuery
|
||||
|
||||
void test() throws Exception {
|
||||
Book book = insert(1)[0];
|
||||
MapListener listener = new MapListener();
|
||||
doAsyncQuery(book, listener);
|
||||
listener.await();
|
||||
if (listener.exception != null) {
|
||||
throw listener.exception;
|
||||
}
|
||||
assertMapEquals(expected, listener.result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that test {@link QueryForMapListener} should create an anonymous subclass of this class then call either
|
||||
* {@link #test()} or {@link #test(int)}
|
||||
*/
|
||||
abstract class QueryForListListenerTestTemplate {
|
||||
|
||||
/**
|
||||
* Subclass must perform the asynchronous query using the given data and listener and set <code>this.expected</code>
|
||||
* to the appropriate value before returning.
|
||||
*/
|
||||
abstract void doAsyncQuery(Book[] books, QueryForListOfMapListener listener);
|
||||
|
||||
List<Map<String, Object>> expected; // subclass should set this value in doAsyncQuery
|
||||
|
||||
void test(int n) throws Exception {
|
||||
Book[] books = insert(n);
|
||||
ListOfMapListener listener = new ListOfMapListener();
|
||||
Arrays.sort(books, BOOK_COMPARATOR);
|
||||
doAsyncQuery(books, listener);
|
||||
listener.await();
|
||||
if (listener.exception != null) {
|
||||
throw listener.exception;
|
||||
}
|
||||
|
||||
for (int i = 0; i < expected.size(); i++) {
|
||||
assertMapEquals(expected.get(i), listener.result.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = CancellationException.class)
|
||||
public void testString_AsynchronousQueryListener_Cancelled() throws InterruptedException {
|
||||
new AsynchronousQueryListenerTestTemplate() {
|
||||
@Override
|
||||
void doAsyncQuery(Book b, BasicListener listener) {
|
||||
Cancellable qc = t.queryAsynchronously(cql(b), listener);
|
||||
qc.cancel();
|
||||
}
|
||||
}.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_AsynchronousQueryListener() throws InterruptedException {
|
||||
new AsynchronousQueryListenerTestTemplate() {
|
||||
@Override
|
||||
void doAsyncQuery(Book b, BasicListener listener) {
|
||||
t.queryAsynchronously(cql(b), listener);
|
||||
}
|
||||
}.test();
|
||||
}
|
||||
|
||||
public void testString_AsynchronousQueryListener_QueryOptions(final ConsistencyLevel cl) throws InterruptedException {
|
||||
new AsynchronousQueryListenerTestTemplate() {
|
||||
@Override
|
||||
void doAsyncQuery(Book b, BasicListener listener) {
|
||||
t.queryAsynchronously(cql(b), listener, new QueryOptions(cl, RetryPolicy.LOGGING));
|
||||
}
|
||||
}.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_AsynchronousQueryListener_QueryOptionsWithConsistencyLevel1() throws InterruptedException {
|
||||
testString_AsynchronousQueryListener_QueryOptions(ConsistencyLevel.ONE);
|
||||
}
|
||||
|
||||
@Test(expected = CassandraInsufficientReplicasAvailableException.class)
|
||||
public void testString_AsynchronousQueryListener_QueryOptionsWithConsistencyLevel2() throws InterruptedException {
|
||||
testString_AsynchronousQueryListener_QueryOptions(ConsistencyLevel.TWO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelect_AsynchronousQueryListener() throws InterruptedException {
|
||||
new AsynchronousQueryListenerTestTemplate() {
|
||||
@Override
|
||||
void doAsyncQuery(Book b, BasicListener listener) {
|
||||
t.queryAsynchronously(cql(b), listener);
|
||||
}
|
||||
}.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForObjectListener() throws Exception {
|
||||
new QueryForObjectListenerTestTemplate<String>() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book b, QueryForObjectListener<String> listener) {
|
||||
t.queryForObjectAsynchronously(cql(b, "title"), String.class, listener);
|
||||
expected = b.title;
|
||||
}
|
||||
|
||||
}.test();
|
||||
}
|
||||
|
||||
public void testString_QueryForObjectListener_QueryOptions(final ConsistencyLevel cl) throws Exception {
|
||||
new QueryForObjectListenerTestTemplate<String>() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book b, QueryForObjectListener<String> listener) {
|
||||
QueryOptions opts = new QueryOptions(cl, RetryPolicy.LOGGING);
|
||||
t.queryForObjectAsynchronously(cql(b, "title"), String.class, listener, opts);
|
||||
expected = b.title;
|
||||
}
|
||||
|
||||
}.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForObjectListener_QueryOptionsWithConsistencyLevel() throws Exception {
|
||||
testString_QueryForObjectListener_QueryOptions(ConsistencyLevel.ONE);
|
||||
}
|
||||
|
||||
@Test(expected = CassandraInsufficientReplicasAvailableException.class)
|
||||
public void testString_QueryForObjectListener_QueryOptionsWithConsistencyLevel2() throws Exception {
|
||||
testString_QueryForObjectListener_QueryOptions(ConsistencyLevel.TWO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForMapListener() throws Exception {
|
||||
new QueryForMapListenerTestTemplate() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book b, QueryForMapListener listener) {
|
||||
t.queryForMapAsynchronously(cql(b), listener);
|
||||
expected = new HashMap<String, Object>();
|
||||
expected.put("isbn", b.isbn);
|
||||
expected.put("title", b.title);
|
||||
}
|
||||
|
||||
}.test();
|
||||
}
|
||||
|
||||
public void testString_QueryForMapListener_QueryOptions(final ConsistencyLevel cl) throws Exception {
|
||||
new QueryForMapListenerTestTemplate() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book b, QueryForMapListener listener) {
|
||||
QueryOptions opts = new QueryOptions(cl, RetryPolicy.LOGGING);
|
||||
t.queryForMapAsynchronously(cql(b), listener, opts);
|
||||
expected = new HashMap<String, Object>();
|
||||
expected.put("isbn", b.isbn);
|
||||
expected.put("title", b.title);
|
||||
}
|
||||
|
||||
}.test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForMapListener_QueryOptionsWithConsistencyLevel1() throws Exception {
|
||||
testString_QueryForMapListener_QueryOptions(ConsistencyLevel.ONE);
|
||||
}
|
||||
|
||||
@Test(expected = CassandraInsufficientReplicasAvailableException.class)
|
||||
public void testString_QueryForMapListener_QueryOptionsWithConsistencyLevel2() throws Exception {
|
||||
testString_QueryForMapListener_QueryOptions(ConsistencyLevel.TWO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForListListener() throws Exception {
|
||||
new QueryForListListenerTestTemplate() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book[] books, QueryForListOfMapListener listener) {
|
||||
|
||||
String[] titles = new String[books.length];
|
||||
expected = new ArrayList<Map<String, Object>>(books.length);
|
||||
for (int i = 0; i < books.length; i++) {
|
||||
Book b = books[i];
|
||||
titles[i] = b.title;
|
||||
HashMap<String, Object> row = new HashMap<String, Object>(2);
|
||||
row.put("title", b.title);
|
||||
row.put("isbn", b.isbn);
|
||||
expected.add(row);
|
||||
}
|
||||
|
||||
t.queryForListOfMapAsynchronously(cql(titles), listener);
|
||||
}
|
||||
|
||||
}.test(2);
|
||||
}
|
||||
|
||||
public void testString_QueryForListListener_QueryOptions(final ConsistencyLevel cl) throws Exception {
|
||||
new QueryForListListenerTestTemplate() {
|
||||
|
||||
@Override
|
||||
void doAsyncQuery(Book[] books, QueryForListOfMapListener listener) {
|
||||
|
||||
String[] titles = new String[books.length];
|
||||
expected = new ArrayList<Map<String, Object>>(books.length);
|
||||
for (int i = 0; i < books.length; i++) {
|
||||
Book b = books[i];
|
||||
titles[i] = b.title;
|
||||
HashMap<String, Object> row = new HashMap<String, Object>(2);
|
||||
row.put("title", b.title);
|
||||
row.put("isbn", b.isbn);
|
||||
expected.add(row);
|
||||
}
|
||||
|
||||
t.queryForListOfMapAsynchronously(cql(titles), listener, new QueryOptions(cl, RetryPolicy.LOGGING));
|
||||
}
|
||||
|
||||
}.test(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testString_QueryForListListener_QueryOptionsWithConsistencyLevel1() throws Exception {
|
||||
testString_QueryForListListener_QueryOptions(ConsistencyLevel.ONE);
|
||||
}
|
||||
|
||||
@Test(expected = CassandraInsufficientReplicasAvailableException.class)
|
||||
public void testString_QueryForListListener_QueryOptionsWithConsistencyLevel2() throws Exception {
|
||||
testString_QueryForListListener_QueryOptions(ConsistencyLevel.TWO);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import org.springframework.cassandra.core.AsynchronousQueryListener;
|
||||
import org.springframework.cassandra.test.unit.support.TestListener;
|
||||
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
|
||||
class BasicListener extends TestListener implements AsynchronousQueryListener {
|
||||
|
||||
ResultSetFuture rsf;
|
||||
|
||||
@Override
|
||||
public void onQueryComplete(ResultSetFuture rsf) {
|
||||
countDown();
|
||||
this.rsf = rsf;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Book {
|
||||
|
||||
public static final String uuid() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public static Book random() {
|
||||
return new Book(uuid(), uuid());
|
||||
}
|
||||
|
||||
public Book() {}
|
||||
|
||||
public Book(String title, String isbn) {
|
||||
this.isbn = isbn;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String isbn;
|
||||
public String title;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cassandra.core.QueryForListListener;
|
||||
import org.springframework.cassandra.test.unit.support.TestListener;
|
||||
|
||||
public class ListListener<T> extends TestListener implements QueryForListListener<T> {
|
||||
|
||||
Exception exception;
|
||||
List<T> result;
|
||||
|
||||
@Override
|
||||
public void onQueryComplete(List<T> results) {
|
||||
countDown();
|
||||
this.result = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Exception x) {
|
||||
countDown();
|
||||
this.exception = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cassandra.core.QueryForListOfMapListener;
|
||||
|
||||
public class ListOfMapListener extends ListListener<Map<String, Object>> implements QueryForListOfMapListener {}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cassandra.core.QueryForMapListener;
|
||||
import org.springframework.cassandra.test.unit.support.TestListener;
|
||||
|
||||
public class MapListener extends TestListener implements QueryForMapListener {
|
||||
|
||||
Map<String, Object> result;
|
||||
Exception exception;
|
||||
|
||||
@Override
|
||||
public void onQueryComplete(Map<String, Object> results) {
|
||||
countDown();
|
||||
this.result = results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Exception x) {
|
||||
countDown();
|
||||
this.exception = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.springframework.cassandra.test.integration.core.template.async;
|
||||
|
||||
import org.springframework.cassandra.core.QueryForObjectListener;
|
||||
import org.springframework.cassandra.test.unit.support.TestListener;
|
||||
|
||||
class ObjectListener<T> extends TestListener implements QueryForObjectListener<T> {
|
||||
|
||||
T result;
|
||||
Exception exception;
|
||||
|
||||
@Override
|
||||
public void onQueryComplete(T result) {
|
||||
countDown();
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(Exception x) {
|
||||
countDown();
|
||||
this.exception = x;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,4 @@
|
||||
*/
|
||||
package org.springframework.cassandra.test.unit.core.cql;
|
||||
|
||||
|
||||
public class CqlStringUtilsTest {
|
||||
}
|
||||
public class CqlStringUtilsTest {}
|
||||
|
||||
@@ -54,8 +54,7 @@ public class AlterKeyspaceCqlGeneratorTests {
|
||||
* Convenient base class that other test classes can use so as not to repeat the generics declarations.
|
||||
*/
|
||||
public static abstract class AlterKeyspaceTest extends
|
||||
KeyspaceOperationCqlGeneratorTest<AlterKeyspaceSpecification, AlterKeyspaceCqlGenerator> {
|
||||
}
|
||||
KeyspaceOperationCqlGeneratorTest<AlterKeyspaceSpecification, AlterKeyspaceCqlGenerator> {}
|
||||
|
||||
public static class CompleteTest extends AlterKeyspaceTest {
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@ public class AlterTableCqlGeneratorTests {
|
||||
* Convenient base class that other test classes can use so as not to repeat the generics declarations.
|
||||
*/
|
||||
public static abstract class AlterTableTest extends
|
||||
TableOperationCqlGeneratorTest<AlterTableSpecification, AlterTableCqlGenerator> {
|
||||
}
|
||||
TableOperationCqlGeneratorTest<AlterTableSpecification, AlterTableCqlGenerator> {}
|
||||
|
||||
public static class BasicTest extends AlterTableTest {
|
||||
|
||||
@@ -95,7 +94,6 @@ public class AlterTableCqlGeneratorTests {
|
||||
* Fully test all available create table options
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public static class MultipleOptionsTest extends AlterTableTest {
|
||||
|
||||
|
||||
@@ -167,7 +167,6 @@ public class CreateTableCqlGeneratorTests {
|
||||
* Test just the Read Repair Chance
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public static class ReadRepairChanceTest extends CreateTableTest {
|
||||
|
||||
@@ -203,7 +202,6 @@ public class CreateTableCqlGeneratorTests {
|
||||
* Fully test all available create table options
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
*/
|
||||
public static class MultipleOptionsTest extends CreateTableTest {
|
||||
|
||||
|
||||
@@ -34,8 +34,7 @@ public class DropIndexCqlGeneratorTests {
|
||||
* Convenient base class that other test classes can use so as not to repeat the generics declarations.
|
||||
*/
|
||||
public static abstract class DropIndexTest extends
|
||||
IndexOperationCqlGeneratorTest<DropIndexSpecification, DropIndexCqlGenerator> {
|
||||
}
|
||||
IndexOperationCqlGeneratorTest<DropIndexSpecification, DropIndexCqlGenerator> {}
|
||||
|
||||
public static class BasicTest extends DropIndexTest {
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ public class DropKeyspaceCqlGeneratorTests {
|
||||
* Convenient base class that other test classes can use so as not to repeat the generics declarations.
|
||||
*/
|
||||
public static abstract class DropTableTest extends
|
||||
KeyspaceOperationCqlGeneratorTest<DropKeyspaceSpecification, DropKeyspaceCqlGenerator> {
|
||||
}
|
||||
KeyspaceOperationCqlGeneratorTest<DropKeyspaceSpecification, DropKeyspaceCqlGenerator> {}
|
||||
|
||||
public static class BasicTest extends DropTableTest {
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ public class DropTableCqlGeneratorTests {
|
||||
* Convenient base class that other test classes can use so as not to repeat the generics declarations.
|
||||
*/
|
||||
public static abstract class DropTableTest extends
|
||||
TableOperationCqlGeneratorTest<DropTableSpecification, DropTableCqlGenerator> {
|
||||
}
|
||||
TableOperationCqlGeneratorTest<DropTableSpecification, DropTableCqlGenerator> {}
|
||||
|
||||
public static class BasicTest extends DropTableTest {
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.cassandra.core.keyspace.IndexNameSpecification;
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
* @author David Webb
|
||||
*
|
||||
* @param <S> The type of the {@link IndexNameSpecification}
|
||||
* @param <G> The type of the {@link IndexNameCqlGenerator}
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.cassandra.core.keyspace.TableNameSpecification;
|
||||
* need for encapsulation, and it makes for easier reuse in other tests like integration tests (hint hint).
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <S> The type of the {@link TableNameSpecification}
|
||||
* @param <G> The type of the {@link TableNameCqlGenerator}
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.cassandra.core.keyspace.TableNameSpecification;
|
||||
* need for encapsulation, and it makes for easier reuse in other tests like integration tests (hint hint).
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <S> The type of the {@link TableNameSpecification}
|
||||
* @param <G> The type of the {@link TableNameCqlGenerator}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.springframework.cassandra.test.unit.support;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Convenient listener base class that includes a {@link CountDownLatch} in order to test asynchronous behavior.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public class TestListener {
|
||||
|
||||
protected CountDownLatch latch;
|
||||
|
||||
public TestListener() {
|
||||
this(1);
|
||||
}
|
||||
|
||||
public TestListener(int latchCount) {
|
||||
latch = new CountDownLatch(latchCount);
|
||||
}
|
||||
|
||||
public void await() throws InterruptedException {
|
||||
latch.await();
|
||||
}
|
||||
|
||||
public void await(long ms) throws InterruptedException {
|
||||
latch.await(ms, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void countDown() {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user