/*
* Copyright (c) 2012-2015 Savoir Technologies, Inc.
*
* 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 com.savoirtech.hecate.cql3.dao.def;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.savoirtech.hecate.cql3.dao.PojoDao;
import com.savoirtech.hecate.cql3.entities.NestedPojo;
import com.savoirtech.hecate.cql3.entities.SimplePojo;
import com.savoirtech.hecate.cql3.persistence.PojoQuery;
import com.savoirtech.hecate.cql3.persistence.PojoQueryResult;
import com.savoirtech.hecate.cql3.persistence.def.DefaultPersistenceContext;
import com.savoirtech.hecate.cql3.test.CassandraTestCase;
import org.junit.Ignore;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
public class DefaultPojoDaoTest extends CassandraTestCase {
//----------------------------------------------------------------------------------------------------------------------
// Other Methods
//----------------------------------------------------------------------------------------------------------------------
@Test(expected = UncheckedExecutionException.class)
public void testWhenNotLoggedIntoKeyspace() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(getCluster().newSession());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("Nope");
dao.save(pojo);
}
@Test
public void testDelete() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo);
assertNotNull(dao.findByKey(pojo.getId()));
dao.delete(pojo.getId());
assertNull(dao.findByKey(pojo.getId()));
}
@Test
public void testDeleteAsync() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo);
assertNotNull(dao.findByKey(pojo.getId()));
awaitFuture(dao.deleteAsync(pojo.getId()));
assertNull(dao.findByKey(pojo.getId()));
}
private <T> T awaitFuture(ListenableFuture<T> future) throws InterruptedException, ExecutionException {
final LatchedFutureCallback<T> callback = new LatchedFutureCallback<T>();
Futures.addCallback(future, callback);
callback.latch.await();
return future.get();
}
@Test
public void testDeleteWithNestedPojos() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final PojoDao<String, NestedPojo> nestedPojoDao = factory.createPojoDao(NestedPojo.class);
final SimplePojo pojo = new SimplePojo();
final NestedPojo nestedPojo = new NestedPojo();
pojo.setNestedPojo(nestedPojo);
pojo.setPojoArray(new NestedPojo[]{nestedPojo});
pojo.setPojoList(Arrays.asList(nestedPojo));
Map<String, NestedPojo> pojoMap = new HashMap<>();
pojoMap.put("one", nestedPojo);
pojo.setPojoMap(pojoMap);
pojo.setPojoSet(Collections.singleton(nestedPojo));
pojo.setName("name");
dao.save(pojo);
assertNotNull(dao.findByKey(pojo.getId()));
assertNotNull(nestedPojoDao.findByKey(nestedPojo.getId()));
dao.delete(pojo.getId());
assertNull(dao.findByKey(pojo.getId()));
assertNull(nestedPojoDao.findByKey(nestedPojo.getId()));
}
@Test
public void testFindByIndexedField() {
DefaultPersistenceContext context = new DefaultPersistenceContext(connect());
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(context);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("Duke");
dao.save(pojo);
final PojoQuery<SimplePojo> query = context.find(SimplePojo.class).eq("name").build();
SimplePojo found = query.execute("Duke").one();
assertNotNull(found);
}
@Test
public void testFindByKeyAsync() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo);
assertNotNull(awaitFuture(dao.findByKeyAsync(pojo.getId())));
}
@Test
public void testFindByKeys() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo1 = new SimplePojo();
pojo1.setName("name1");
dao.save(pojo1);
final SimplePojo pojo2 = new SimplePojo();
pojo2.setName("name2");
dao.save(pojo2);
List<SimplePojo> results = dao.findByKeys(Arrays.asList(pojo1.getId(), pojo2.getId()));
assertEquals(2, results.size());
assertTrue(results.contains(pojo1));
assertTrue(results.contains(pojo2));
}
@Test
public void testFindByKeysAsync() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo1 = new SimplePojo();
pojo1.setName("name1");
dao.save(pojo1);
final SimplePojo pojo2 = new SimplePojo();
pojo2.setName("name2");
dao.save(pojo2);
List<SimplePojo> results = awaitFuture(dao.findByKeysAsync(Arrays.asList(pojo1.getId(), pojo2.getId())));
assertEquals(2, results.size());
assertTrue(results.contains(pojo1));
assertTrue(results.contains(pojo2));
}
@Test
public void testListWithMultiple() {
final Session session = connect();
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(session);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo1 = new SimplePojo();
pojo1.setName("pojo1");
dao.save(pojo1);
final SimplePojo pojo2 = new SimplePojo();
pojo2.setName("pojo2");
dao.save(pojo2);
DefaultPersistenceContext context = new DefaultPersistenceContext(session);
PojoQueryResult<SimplePojo> result = context.find(SimplePojo.class).build().execute();
final List<SimplePojo> pojos = result.list();
assertNotSame(pojos.get(0), pojos.get(1));
assertNotEquals(pojos.get(0), pojos.get(1));
}
@Test
public void testSave() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found);
assertEquals("name", found.getName());
assertEquals(pojo.getId(), found.getId());
}
@Test
public void testSaveAsync() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
awaitFuture(dao.saveAsync(pojo));
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found);
assertEquals("name", found.getName());
assertEquals(pojo.getId(), found.getId());
}
@Test
public void testSaveWithCustomTableName() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class, "BOB");
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found);
assertEquals("name", found.getName());
assertEquals(pojo.getId(), found.getId());
}
@Test
public void testSaveWithTtl() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
dao.save(pojo, 90600);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found);
assertEquals("name", found.getName());
assertEquals(pojo.getId(), found.getId());
ResultSet resultSet = connect().execute("SELECT TTL (name) from simpletons");
for (Row row : resultSet) {
assertTrue(row.getInt(0) <= 90600);
}
}
@Test
public void testSaveWithTtlAsync() throws Exception {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("name");
awaitFuture(dao.saveAsync(pojo, 90600));
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found);
assertEquals("name", found.getName());
assertEquals(pojo.getId(), found.getId());
ResultSet resultSet = connect().execute("SELECT TTL (name) from simpletons");
for (Row row : resultSet) {
assertTrue(row.getInt(0) <= 90600);
}
}
@Test
public void testSearchingByEnumField() {
DefaultPersistenceContext context = new DefaultPersistenceContext(connect());
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(context);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setNums(SimplePojo.Nums.Three);
dao.save(pojo);
final PojoQuery<SimplePojo> query = context.find(SimplePojo.class).eq("nums").build();
SimplePojo found = query.execute(SimplePojo.Nums.Three).one();
assertNotNull(found);
}
@Test
public void testSelectAll() {
DefaultPersistenceContext context = new DefaultPersistenceContext(connect());
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(context);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("Duke");
dao.save(pojo);
final PojoQuery<SimplePojo> query = context.find(SimplePojo.class).build();
SimplePojo found = query.execute().one();
assertNotNull(found);
}
@Test
public void testWithArrayField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setInts(new int[]{1, 2, 3});
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertArrayEquals(pojo.getInts(), found.getInts());
}
@Test
public void testWithEnumField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setNums(SimplePojo.Nums.Three);
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertEquals(SimplePojo.Nums.Three, found.getNums());
}
@Test
public void testWithInjectedParameters() {
DefaultPersistenceContext context = new DefaultPersistenceContext(connect());
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(context);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("Duke");
dao.save(pojo);
final PojoQuery<SimplePojo> query = context.find(SimplePojo.class).eq("name", "Duke").build();
SimplePojo found = query.execute().one();
assertNotNull(found);
}
@Test
public void testWithListField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setListOfStrings(Arrays.asList("one", "two", "three"));
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getListOfStrings());
assertEquals(3, found.getListOfStrings().size());
assertEquals("one", found.getListOfStrings().get(0));
assertEquals("two", found.getListOfStrings().get(1));
assertEquals("three", found.getListOfStrings().get(2));
}
@Test
public void testWithMapField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
Map<Integer, String> mapOfStrings = new HashMap<>();
mapOfStrings.put(1, "one");
mapOfStrings.put(2, "two");
mapOfStrings.put(3, "three");
pojo.setMapOfStrings(mapOfStrings);
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getMapOfStrings());
assertEquals(3, found.getMapOfStrings().size());
assertEquals("one", found.getMapOfStrings().get(1));
assertEquals("two", found.getMapOfStrings().get(2));
assertEquals("three", found.getMapOfStrings().get(3));
}
@Test
@Ignore("Need to figure this out (allow filtering required for anded queries)")
public void testWithMixedParameters() {
DefaultPersistenceContext context = new DefaultPersistenceContext(connect());
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(context);
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("Nums");
pojo.setNums(SimplePojo.Nums.Three);
dao.save(pojo);
final PojoQuery<SimplePojo> query = context.find(SimplePojo.class).eq("nums").eq("name", "Duke").build();
SimplePojo found = query.execute(SimplePojo.Nums.Three).one();
assertNotNull(found);
}
@Test
public void testWithNestedArrayField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setPojoArray(new NestedPojo[]{new NestedPojo()});
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertArrayEquals(pojo.getPojoArray(), found.getPojoArray());
}
@Test
public void testWithNestedPojoField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setNestedPojo(new NestedPojo());
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertEquals(pojo.getNestedPojo(), found.getNestedPojo());
}
@Test
public void testWithPojoListField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setPojoList(Arrays.asList(new NestedPojo(), new NestedPojo()));
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getPojoList());
assertEquals(2, found.getPojoList().size());
assertEquals(pojo.getPojoList().get(0), found.getPojoList().get(0));
assertEquals(pojo.getPojoList().get(1), found.getPojoList().get(1));
}
@Test
public void testWithPojoMapField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
Map<String, NestedPojo> pojoMap = new HashMap<>();
final NestedPojo nested1 = new NestedPojo();
final NestedPojo nested2 = new NestedPojo();
pojoMap.put("one", nested1);
pojoMap.put("two", nested2);
pojo.setPojoMap(pojoMap);
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getPojoMap());
assertEquals(2, found.getPojoMap().size());
assertEquals(nested1, found.getPojoMap().get("one"));
assertEquals(nested2, found.getPojoMap().get("two"));
}
@Test
public void testWithPojoMapFieldTtl() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setName("NAME");
Map<String, NestedPojo> pojoMap = new HashMap<>();
final NestedPojo nested1 = new NestedPojo();
nested1.setData("DATA");
final NestedPojo nested2 = new NestedPojo();
nested2.setData("DATA");
pojoMap.put("one", nested1);
pojoMap.put("two", nested2);
pojo.setPojoMap(pojoMap);
dao.save(pojo, 96000);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getPojoMap());
assertEquals(2, found.getPojoMap().size());
assertEquals(nested1, found.getPojoMap().get("one"));
assertEquals(nested2, found.getPojoMap().get("two"));
ResultSet resultSet2 = connect().execute("SELECT TTL (name) from simpletons");
for (Row row : resultSet2) {
System.out.println(row);
assertTrue(row.getInt(0) <= 96000);
}
ResultSet resultSet = connect().execute("SELECT TTL (data) from nestedpojo");
for (Row row : resultSet) {
System.out.println(row);
assertTrue(row.getInt(0) <= 96000 && row.getInt(0) > 0);
}
}
@Test
public void testWithPojoSetField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
final NestedPojo nested1 = new NestedPojo();
final NestedPojo nested2 = new NestedPojo();
pojo.setPojoSet(Sets.newHashSet(nested1, nested2));
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getPojoSet());
assertEquals(2, found.getPojoSet().size());
assertTrue(found.getPojoSet().contains(nested1));
assertTrue(found.getPojoSet().contains(nested2));
}
@Test
public void testWithSetField() {
DefaultPojoDaoFactory factory = new DefaultPojoDaoFactory(connect());
final PojoDao<String, SimplePojo> dao = factory.createPojoDao(SimplePojo.class);
final SimplePojo pojo = new SimplePojo();
pojo.setSetOfStrings(Sets.newHashSet("one", "two", "three"));
dao.save(pojo);
final SimplePojo found = dao.findByKey(pojo.getId());
assertNotNull(found.getSetOfStrings());
assertEquals(3, found.getSetOfStrings().size());
assertTrue(found.getSetOfStrings().contains("one"));
assertTrue(found.getSetOfStrings().contains("two"));
assertTrue(found.getSetOfStrings().contains("three"));
}
//----------------------------------------------------------------------------------------------------------------------
// Inner Classes
//----------------------------------------------------------------------------------------------------------------------
private static class LatchedFutureCallback<T> implements FutureCallback<T> {
private final CountDownLatch latch = new CountDownLatch(1);
@Override
public void onSuccess(T result) {
latch.countDown();
}
@Override
public void onFailure(Throwable t) {
latch.countDown();
}
}
}