From 83e0b30e2ac1afe0333e2d9dfcf488ea0d063f5a Mon Sep 17 00:00:00 2001 From: David Webb Date: Mon, 26 Jan 2015 10:34:51 -0500 Subject: [PATCH] DATACASS-197: Reconsider usage of ingestions for general CQL test cases Task-Url: https://jira.spring.io/browse/DATACASS-197 --- .../core/template/CQLOperationsTest.java | 134 ++++++++++++++---- 1 file changed, 105 insertions(+), 29 deletions(-) diff --git a/spring-cql/src/test/java/org/springframework/cassandra/test/integration/core/template/CQLOperationsTest.java b/spring-cql/src/test/java/org/springframework/cassandra/test/integration/core/template/CQLOperationsTest.java index ffcf3d951..47b74ec46 100644 --- a/spring-cql/src/test/java/org/springframework/cassandra/test/integration/core/template/CQLOperationsTest.java +++ b/spring-cql/src/test/java/org/springframework/cassandra/test/integration/core/template/CQLOperationsTest.java @@ -15,7 +15,9 @@ */ package org.springframework.cassandra.test.integration.core.template; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.util.Collection; import java.util.LinkedList; @@ -75,6 +77,8 @@ import com.datastax.driver.core.querybuilder.Truncate; */ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { + private static final String BOOK_INSERT = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + private static Logger log = LoggerFactory.getLogger(CQLOperationsTest.class); private CqlOperations cqlTemplate; @@ -90,7 +94,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { /** * This loads any test specific Cassandra objects */ - @Rule + @Rule public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet( "cassandraOperationsTest-cql-dataload.cql", this.keyspace), CASSANDRA_CONFIG, CASSANDRA_HOST, CASSANDRA_NATIVE_PORT); @@ -149,7 +153,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { WriteOptions options = new WriteOptions(); options.setTtl(360); - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + String cql = BOOK_INSERT; List> values = new LinkedList>(); @@ -160,26 +164,33 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { cqlTemplate.ingest(cql, values, options); // Assert that the rows were inserted into Cassandra - Book b1 = getBook((String) o1[0]); - Book b2 = getBook((String) o2[0]); - Book b3 = getBook((String) o3[0]); + Book b1 = getBookWithRetry((String) o1[0]); + Book b2 = getBookWithRetry((String) o2[0]); + Book b3 = getBookWithRetry((String) o3[0]); assertBook(b1, objectToBook(o1)); assertBook(b2, objectToBook(o2)); assertBook(b3, objectToBook(o3)); } - @Test - public void ingestionTestObjectArray() { + /** + * Insert some Books needed to next test steps. + */ + private void insertTestObjectArray() { - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + String cql = BOOK_INSERT; Object[][] values = new Object[3][]; values[0] = o1; values[1] = o2; values[2] = o3; - cqlTemplate.ingest(cql, values); + PreparedStatement pstmt = this.session.prepare(cql); + BoundStatement binder = null; + for (Object[] o : values) { + binder = pstmt.bind(o); + cqlTemplate.execute(binder); + } // Assert that the rows were inserted into Cassandra Book b1 = getBook("1234"); @@ -191,6 +202,29 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { assertBook(b3, objectToBook(o3)); } + @Test + public void ingestTestObjectArray() { + + String cql = BOOK_INSERT; + + Object[][] values = new Object[3][]; + values[0] = o1; + values[1] = o2; + values[2] = o3; + + cqlTemplate.ingest(cql, values); + + // Assert that the rows were inserted into Cassandra + Book b1 = getBookWithRetry((String) o1[0]); + Book b2 = getBookWithRetry((String) o2[0]); + Book b3 = getBookWithRetry((String) o3[0]); + + assertBook(b1, objectToBook(o1)); + assertBook(b2, objectToBook(o2)); + assertBook(b3, objectToBook(o3)); + + } + /** * This is an implementation of RowIterator for the purposes of testing passing your own Impl to CqlTemplate * @@ -227,7 +261,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void ingestionTestRowIterator() { - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + String cql = BOOK_INSERT; final Object[][] v = new Object[3][]; v[0] = o1; @@ -238,9 +272,9 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { cqlTemplate.ingest(cql, ri); // Assert that the rows were inserted into Cassandra - Book b1 = getBook("1234"); - Book b2 = getBook("2345"); - Book b3 = getBook("3456"); + Book b1 = getBookWithRetry((String) o1[0]); + Book b2 = getBookWithRetry((String) o2[0]); + Book b3 = getBookWithRetry((String) o3[0]); assertBook(b1, objectToBook(o1)); assertBook(b2, objectToBook(o2)); @@ -261,7 +295,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Override public Object doInSession(Session s) throws DataAccessException { - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + String cql = BOOK_INSERT; PreparedStatement ps = s.prepare(cql); BoundStatement bs = ps.bind(isbn, title, author, pages); @@ -525,7 +559,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void queryTestCqlStringRowMapper() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); List books = cqlTemplate.query("select * from book where isbn in ('1234','2345','3456')", new RowMapper() { @@ -547,7 +581,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void processTestResultSetRowMapper() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); ResultSetFuture rsf = cqlTemplate.queryAsynchronously("select * from book where isbn in ('1234','2345','3456')"); @@ -594,7 +628,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void queryForObjectTestCqlStringRowMapperNotOneRowReturned() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); @SuppressWarnings("unused") Book book = cqlTemplate.queryForObject("select * from book where isbn in ('1234','2345','3456')", @@ -611,7 +645,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void processOneTestResultSetRowMapper() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); ResultSetFuture rsf = cqlTemplate.queryAsynchronously("select * from book where isbn in ('" + ISBN_NINES + "')"); @@ -702,7 +736,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void queryForListTestCqlStringType() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); List titles = cqlTemplate.queryForList("select title from book where isbn in ('1234','2345','3456')", String.class); @@ -716,7 +750,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void processListTestResultSetType() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); ResultSetFuture rsf = cqlTemplate.queryAsynchronously("select * from book where isbn in ('1234','2345','3456')"); @@ -734,7 +768,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void queryForListOfMapCqlString() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); List> results = cqlTemplate .queryForListOfMap("select * from book where isbn in ('1234','2345','3456')"); @@ -747,7 +781,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public void processListOfMapTestResultSet() { // Insert our 3 test books. - ingestionTestObjectArray(); + insertTestObjectArray(); ResultSetFuture rsf = cqlTemplate.queryAsynchronously("select * from book where isbn in ('1234','2345','3456')"); @@ -764,7 +798,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void executeTestCqlStringPreparedStatementCallback() { - String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + String cql = BOOK_INSERT; BoundStatement statement = cqlTemplate.execute(cql, new PreparedStatementCallback() { @@ -782,7 +816,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void executeTestPreparedStatementCreatorPreparedStatementCallback() { - final String cql = "insert into book (isbn, title, author, pages) values (?, ?, ?, ?)"; + final String cql = BOOK_INSERT; BoundStatement statement = cqlTemplate.execute(new PreparedStatementCreator() { @@ -890,7 +924,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void queryTestPreparedStatementCreatorResultSetExtractor() { - ingestionTestObjectArray(); + insertTestObjectArray(); final String cql = "select * from book"; @@ -921,7 +955,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void queryTestPreparedStatementCreatorRowCallbackHandler() { - ingestionTestObjectArray(); + insertTestObjectArray(); final String cql = "select * from book"; @@ -945,7 +979,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { @Test public void queryTestPreparedStatementCreatorRowMapper() { - ingestionTestObjectArray(); + insertTestObjectArray(); final String cql = "select * from book"; @@ -1147,7 +1181,7 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { * @param isbn * @return */ - public Book getBook(final String isbn) { + private Book getBook(final String isbn) { Book b = cqlTemplate.query("select * from book where isbn = ?", new PreparedStatementBinder() { @@ -1161,6 +1195,9 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { public Book extractData(ResultSet rs) throws DriverException, DataAccessException { Book b = new Book(); Row r = rs.one(); + if (r == null) { + return null; + } b.setIsbn(r.getString("isbn")); b.setTitle(r.getString("title")); b.setAuthor(r.getString("author")); @@ -1173,6 +1210,45 @@ public class CQLOperationsTest extends AbstractKeyspaceCreatingIntegrationTest { } + /** + * Get a Book from Cassandra for assertions, if the Book is not retruned then retry as needed. This is used for + * assertions after asynchronous insert/ingest to give the datastore time to catch up with the tests. + * + * @param isbn + * @param retryMillis + * @param numRetries + * @return + */ + private Book getBookWithRetry(final String isbn, final long retryMillis, final int numRetries) { + + Book b = getBook(isbn); + + for (int i = 1; i <= numRetries && b == null; i++) { + log.info(String.format("SLEEP - Trying to get Book after Async Call Waiting [%s]ms, Retry [%s]", retryMillis, i)); + try { + Thread.sleep(retryMillis); + } catch (InterruptedException e) { + throw new IllegalStateException("Failed to sleep for query retry", e); + } + b = getBook(isbn); + } + + return b; + } + + /** + * Get a Book from Cassandra for assertions, if the Book is not retruned then retry as needed. This is used for + * assertions after asynchronous insert/ingest to give the datastore time to catch up with the tests. + * + * Defaults to 5 retries @ 200ms intervals + * + * @param isbn + * @return + */ + private Book getBookWithRetry(final String isbn) { + return getBookWithRetry(isbn, 200, 5); + } + /** * For testing a HostMapper Implementation */