/**
* Copyright 2011, Big Switch Networks, Inc.
* Originally created by David Erickson, Stanford University
*
* 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 net.floodlightcontroller.storage.tests;
import static org.easymock.EasyMock.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.floodlightcontroller.restserver.RestApiServer;
import net.floodlightcontroller.storage.CompoundPredicate;
import net.floodlightcontroller.storage.IStorageExceptionHandler;
import net.floodlightcontroller.storage.IPredicate;
import net.floodlightcontroller.storage.IQuery;
import net.floodlightcontroller.storage.IResultSet;
import net.floodlightcontroller.storage.IRowMapper;
import net.floodlightcontroller.storage.IStorageSourceListener;
import net.floodlightcontroller.storage.NullValueStorageException;
import net.floodlightcontroller.storage.OperatorPredicate;
import net.floodlightcontroller.storage.RowOrdering;
import net.floodlightcontroller.storage.nosql.NoSqlStorageSource;
import net.floodlightcontroller.test.FloodlightTestCase;
import org.junit.Test;
public abstract class StorageTest extends FloodlightTestCase {
protected NoSqlStorageSource storageSource;
protected RestApiServer restApi;
protected String PERSON_TABLE_NAME = "Person";
protected String PERSON_SSN = "SSN";
protected String PERSON_FIRST_NAME = "FirstName";
protected String PERSON_LAST_NAME = "LastName";
protected String PERSON_AGE = "Age";
protected String PERSON_REGISTERED = "Registered";
protected String[] PERSON_COLUMN_LIST = {PERSON_SSN, PERSON_FIRST_NAME, PERSON_LAST_NAME, PERSON_AGE, PERSON_REGISTERED};
class Person {
private String ssn;
private String firstName;
private String lastName;
int age;
boolean registered;
public Person(String ssn, String firstName, String lastName, int age, boolean registered) {
this.ssn = ssn;
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.registered = registered;
}
public String getSSN() {
return ssn;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public boolean isRegistered() {
return registered;
}
}
class PersonRowMapper implements IRowMapper {
public Object mapRow(IResultSet resultSet) {
String ssn = resultSet.getString(PERSON_SSN);
String firstName = resultSet.getString(PERSON_FIRST_NAME);
String lastName = resultSet.getString(PERSON_LAST_NAME);
int age = resultSet.getInt(PERSON_AGE);
boolean registered = resultSet.getBoolean(PERSON_REGISTERED);
return new Person(ssn, firstName, lastName, age, registered);
}
}
Object[][] PERSON_INIT_DATA = {
{"111-11-1111", "John", "Smith", 40, true},
{"222-22-2222", "Jim", "White", 24, false},
{"333-33-3333", "Lisa", "Jones", 27, true},
{"444-44-4444", "Susan", "Jones", 14, false},
{"555-55-5555", "Jose", "Garcia", 31, true},
{"666-66-6666", "Abigail", "Johnson", 35, false},
{"777-77-7777", "Bjorn", "Borg", 55, true},
{"888-88-8888", "John", "McEnroe", 53, false}
};
Map<String,Object> createPersonRowValues(Object[] personData) {
Map<String,Object> rowValues = new HashMap<String,Object>();
for (int i = 0; i < PERSON_COLUMN_LIST.length; i++) {
rowValues.put(PERSON_COLUMN_LIST[i], personData[i]);
}
return rowValues;
}
public void insertPerson(Object[] personData) {
Map<String,Object> rowValues = createPersonRowValues(personData);
storageSource.insertRow(PERSON_TABLE_NAME, rowValues);
}
public void initPersons() {
for (Object[] row: PERSON_INIT_DATA) {
insertPerson(row);
}
}
public void setUp() throws Exception {
super.setUp();
Set<String> indexedColumnNames = new HashSet<String>();
indexedColumnNames.add(PERSON_LAST_NAME);
storageSource.setExceptionHandler(null);
storageSource.createTable(PERSON_TABLE_NAME, indexedColumnNames);
storageSource.setTablePrimaryKeyName(PERSON_TABLE_NAME, PERSON_SSN);
initPersons();
}
public void checkExpectedResults(IResultSet resultSet, String[] columnNameList, Object[][] expectedRowList) {
boolean nextResult;
for (Object[] expectedRow: expectedRowList) {
nextResult = resultSet.next();
assertEquals(nextResult,true);
assertEquals(expectedRow.length, columnNameList.length);
for (int i = 0; i < expectedRow.length; i++) {
Object expectedObject = expectedRow[i];
String columnName = columnNameList[i];
if (expectedObject instanceof Boolean)
assertEquals(((Boolean)expectedObject).booleanValue(), resultSet.getBoolean(columnName));
else if (expectedObject instanceof Byte)
assertEquals(((Byte)expectedObject).byteValue(), resultSet.getByte(columnName));
else if (expectedObject instanceof Short)
assertEquals(((Short)expectedObject).shortValue(), resultSet.getShort(columnName));
else if (expectedObject instanceof Integer)
assertEquals(((Integer)expectedObject).intValue(), resultSet.getInt(columnName));
else if (expectedObject instanceof Long)
assertEquals(((Long)expectedObject).longValue(), resultSet.getLong(columnName));
else if (expectedObject instanceof Float)
assertEquals(((Float)expectedObject).floatValue(), resultSet.getFloat(columnName), 0.00001);
else if (expectedObject instanceof Double)
assertEquals(((Double)expectedObject).doubleValue(), resultSet.getDouble(columnName), 0.00001);
else if (expectedObject instanceof byte[])
assertEquals((byte[])expectedObject, resultSet.getByteArray(columnName));
else if (expectedObject instanceof String)
assertEquals((String)expectedObject, resultSet.getString(columnName));
else
assertTrue("Unexpected column value type", false);
}
}
nextResult = resultSet.next();
assertEquals(nextResult,false);
resultSet.close();
}
@Test
public void testInsertRows() {
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, PERSON_INIT_DATA);
}
@Test
public void testOperatorQuery() {
Object[][] expectedResults = {
{"John", "Smith", 40},
{"Jim", "White", 24},
};
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME,PERSON_AGE};
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, columnList,
new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.GTE, "Sm"),
new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, columnList, expectedResults);
}
@Test
public void testAndQuery() {
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME};
Object[][] expectedResults = {
{"Lisa", "Jones"},
{"Susan", "Jones"},
{"Jose", "Garcia"},
{"Abigail", "Johnson"},
{"John", "McEnroe"}
};
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, columnList,
new CompoundPredicate(CompoundPredicate.Operator.AND, false,
new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.GTE, "G"),
new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.LT, "N")
),
new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, columnList, expectedResults);
}
@Test
public void testOrQuery() {
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME, PERSON_AGE};
Object[][] expectedResults = {
{"John", "Smith", 40},
{"Lisa", "Jones", 27},
{"Abigail", "Johnson", 35},
{"Bjorn", "Borg", 55},
{"John", "McEnroe", 53}
};
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, columnList,
new CompoundPredicate(CompoundPredicate.Operator.OR, false,
new OperatorPredicate(PERSON_AGE, OperatorPredicate.Operator.GTE, 35),
new OperatorPredicate(PERSON_FIRST_NAME, OperatorPredicate.Operator.EQ, "Lisa")
),
new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, columnList, expectedResults);
}
@Test
public void testCreateQuery() {
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME};
Object[][] expectedResults = {
{"Lisa", "Jones"},
{"Susan", "Jones"}
};
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.EQ, "Jones");
IQuery query = storageSource.createQuery(PERSON_TABLE_NAME, columnList, predicate, new RowOrdering(PERSON_SSN));
IResultSet resultSet = storageSource.executeQuery(query);
checkExpectedResults(resultSet, columnList, expectedResults);
}
@Test
public void testQueryParameters() {
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME, PERSON_AGE};
Object[][] expectedResults = {
{"John", "Smith", 40},
{"Bjorn", "Borg", 55},
{"John", "McEnroe", 53}
};
IPredicate predicate = new OperatorPredicate(PERSON_AGE, OperatorPredicate.Operator.GTE, "?MinimumAge?");
IQuery query = storageSource.createQuery(PERSON_TABLE_NAME, columnList, predicate, new RowOrdering(PERSON_SSN));
query.setParameter("MinimumAge", 40);
IResultSet resultSet = storageSource.executeQuery(query);
checkExpectedResults(resultSet, columnList, expectedResults);
}
private void checkPerson(Person person, Object[] expectedValues) {
assertEquals(person.getSSN(), expectedValues[0]);
assertEquals(person.getFirstName(), expectedValues[1]);
assertEquals(person.getLastName(), expectedValues[2]);
assertEquals(person.getAge(), expectedValues[3]);
assertEquals(person.isRegistered(), expectedValues[4]);
}
@Test
public void testRowMapper() {
Object[][] expectedResults = {
PERSON_INIT_DATA[2],
PERSON_INIT_DATA[3]
};
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.EQ, "Jones");
IRowMapper rowMapper = new PersonRowMapper();
Object[] personList = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, new RowOrdering(PERSON_SSN), rowMapper);
assertEquals(personList.length, 2);
for (int i = 0; i < personList.length; i++)
checkPerson((Person)personList[i], expectedResults[i]);
}
@Test
public void testDeleteRowsDirect() {
storageSource.deleteRow(PERSON_TABLE_NAME, "111-11-1111");
storageSource.deleteRow(PERSON_TABLE_NAME, "222-22-2222");
storageSource.deleteRow(PERSON_TABLE_NAME, "333-33-3333");
storageSource.deleteRow(PERSON_TABLE_NAME, "444-44-4444");
Object[][] expectedResults = {
{"555-55-5555", "Jose", "Garcia", 31, true},
{"666-66-6666", "Abigail", "Johnson", 35, false},
{"777-77-7777", "Bjorn", "Borg", 55, true},
{"888-88-8888", "John", "McEnroe", 53, false}
};
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedResults);
}
@Test
public void testDeleteRowsFromResultSet() {
Object[][] expectedResults = {
{"555-55-5555", "Jose", "Garcia", 31, true},
{"666-66-6666", "Abigail", "Johnson", 35, false},
{"777-77-7777", "Bjorn", "Borg", 55, true},
{"888-88-8888", "John", "McEnroe", 53, false}
};
// Query once to delete the rows
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, null, new RowOrdering(PERSON_SSN));
for (int i = 0; i < 4; i++) {
resultSet.next();
resultSet.deleteRow();
}
resultSet.save();
resultSet.close();
// Now query again to verify that the rows were deleted
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedResults);
}
@Test
public void testDeleteMatchingRows() {
Object[][] expectedResults = {
{"111-11-1111", "John", "Smith", 40, true},
{"777-77-7777", "Bjorn", "Borg", 55, true},
{"888-88-8888", "John", "McEnroe", 53, false}
};
storageSource.deleteMatchingRows(PERSON_TABLE_NAME, new OperatorPredicate(PERSON_AGE, OperatorPredicate.Operator.LT, 40));
// Now query again to verify that the rows were deleted
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedResults);
storageSource.deleteMatchingRows(PERSON_TABLE_NAME, null);
// Now query again to verify that all rows were deleted
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, new Object[0][]);
}
@Test
public void testUpdateRowsDirect() {
Object[][] expectedResults = {
{"777-77-7777", "Tennis", "Borg", 60, true},
{"888-88-8888", "Tennis", "McEnroe", 60, false}
};
Map<String,Object> updateValues = new HashMap<String,Object>();
updateValues.put(PERSON_FIRST_NAME, "Tennis");
updateValues.put(PERSON_AGE, 60);
IPredicate predicate = new OperatorPredicate(PERSON_AGE, OperatorPredicate.Operator.GT, 50);
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, new RowOrdering(PERSON_SSN));
while (resultSet.next()) {
String key = resultSet.getString(PERSON_SSN);
storageSource.updateRow(PERSON_TABLE_NAME, key, updateValues);
}
resultSet.close();
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, predicate, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedResults);
}
@Test
public void testUpdateRowsFromResultSet() {
Object[][] expectedResults = {
{"777-77-7777", "Tennis", "Borg", 60, true},
{"888-88-8888", "Tennis", "McEnroe", 60, false}
};
IPredicate predicate = new OperatorPredicate(PERSON_AGE, OperatorPredicate.Operator.GT, 50);
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, null);
while (resultSet.next()) {
resultSet.setString(PERSON_FIRST_NAME, "Tennis");
resultSet.setInt(PERSON_AGE, 60);
}
resultSet.save();
resultSet.close();
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, PERSON_COLUMN_LIST, predicate, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedResults);
}
@Test
public void testNullValues() {
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.EQ, "Jones");
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, new RowOrdering(PERSON_SSN));
while (resultSet.next()) {
resultSet.setNull(PERSON_FIRST_NAME);
resultSet.setIntegerObject(PERSON_AGE, null);
}
resultSet.save();
resultSet.close();
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, new RowOrdering(PERSON_SSN));
int count = 0;
while (resultSet.next()) {
boolean checkNull = resultSet.isNull(PERSON_FIRST_NAME);
assertTrue(checkNull);
String s = resultSet.getString(PERSON_FIRST_NAME);
assertEquals(s, null);
checkNull = resultSet.isNull(PERSON_AGE);
assertTrue(checkNull);
Integer intObj = resultSet.getIntegerObject(PERSON_AGE);
assertEquals(intObj, null);
Short shortObj = resultSet.getShortObject(PERSON_AGE);
assertEquals(shortObj, null);
boolean excThrown = false;
try {
resultSet.getInt(PERSON_AGE);
}
catch (NullValueStorageException exc) {
excThrown = true;
}
assertTrue(excThrown);
count++;
}
resultSet.close();
assertEquals(count, 2);
predicate = new OperatorPredicate(PERSON_FIRST_NAME, OperatorPredicate.Operator.EQ, null);
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, predicate, new RowOrdering(PERSON_SSN));
count = 0;
while (resultSet.next()) {
boolean checkNull = resultSet.isNull(PERSON_FIRST_NAME);
assertTrue(checkNull);
count++;
checkNull = resultSet.isNull(PERSON_AGE);
assertTrue(checkNull);
}
resultSet.close();
assertEquals(count, 2);
}
@Test
public void testInsertNotification() {
// Set up the listener and record the expected notification
IStorageSourceListener mockListener = createNiceMock(IStorageSourceListener.class);
Set<Object> expectedKeys = new HashSet<Object>();
expectedKeys.add("999-99-9999");
mockListener.rowsModified(PERSON_TABLE_NAME, expectedKeys);
replay(mockListener);
// Now try it for real
storageSource.addListener(PERSON_TABLE_NAME, mockListener);
// Create a new person, which should trigger the listener
Object[] newPerson = {"999-99-9999", "Serena", "Williams", 22, true};
insertPerson(newPerson);
verify(mockListener);
}
@Test
public void testUpdateNotification() {
// Set up the listener and record the expected notification
IStorageSourceListener mockListener = createNiceMock(IStorageSourceListener.class);
Set<Object> expectedKeys = new HashSet<Object>();
expectedKeys.add("111-11-1111");
mockListener.rowsModified(PERSON_TABLE_NAME, expectedKeys);
replay(mockListener);
// Now try it for real
storageSource.addListener(PERSON_TABLE_NAME, mockListener);
// Create a new person, which should trigger the listener
Map<String,Object> updateValues = new HashMap<String,Object>();
updateValues.put(PERSON_FIRST_NAME, "Tennis");
storageSource.updateRow(PERSON_TABLE_NAME, "111-11-1111", updateValues);
verify(mockListener);
}
@Test
public void testDeleteNotification() {
IStorageSourceListener mockListener = createNiceMock(IStorageSourceListener.class);
Set<Object> expectedKeys = new HashSet<Object>();
expectedKeys.add("111-11-1111");
mockListener.rowsDeleted(PERSON_TABLE_NAME, expectedKeys);
replay(mockListener);
// Now try it for real
storageSource.addListener(PERSON_TABLE_NAME, mockListener);
// Create a new person, which should trigger the listener
storageSource.deleteRow(PERSON_TABLE_NAME, "111-11-1111");
verify(mockListener);
}
public void waitForFuture(Future<?> future) {
try
{
future.get(10, TimeUnit.SECONDS);
}
catch (InterruptedException exc)
{
fail("Async storage operation interrupted");
}
catch (ExecutionException exc) {
fail("Async storage operation failed");
}
catch (TimeoutException exc) {
fail("Async storage operation timed out");
}
}
@Test
public void testAsyncQuery1() {
Object[][] expectedResults = {
{"John", "Smith", 40},
{"Jim", "White", 24},
};
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME,PERSON_AGE};
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.GTE, "Sm");
IQuery query = storageSource.createQuery(PERSON_TABLE_NAME, columnList, predicate, new RowOrdering(PERSON_SSN));
Future<IResultSet> future = storageSource.executeQueryAsync(query);
waitForFuture(future);
try {
IResultSet resultSet = future.get();
checkExpectedResults(resultSet, columnList, expectedResults);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncQuery2() {
Object[][] expectedResults = {
{"John", "Smith", 40},
{"Jim", "White", 24},
};
String[] columnList = {PERSON_FIRST_NAME,PERSON_LAST_NAME,PERSON_AGE};
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.GTE, "Sm");
Future<IResultSet> future = storageSource.executeQueryAsync(PERSON_TABLE_NAME,
columnList, predicate, new RowOrdering(PERSON_SSN));
waitForFuture(future);
try {
IResultSet resultSet = future.get();
checkExpectedResults(resultSet, columnList, expectedResults);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncQuery3() {
Object[][] expectedResults = {
PERSON_INIT_DATA[2],
PERSON_INIT_DATA[3]
};
IPredicate predicate = new OperatorPredicate(PERSON_LAST_NAME, OperatorPredicate.Operator.EQ, "Jones");
IRowMapper rowMapper = new PersonRowMapper();
Future<Object[]> future = storageSource.executeQueryAsync(PERSON_TABLE_NAME,
null, predicate, new RowOrdering(PERSON_SSN), rowMapper);
waitForFuture(future);
try {
Object[] personList = future.get();
assertEquals(personList.length, 2);
for (int i = 0; i < personList.length; i++)
checkPerson((Person)personList[i], expectedResults[i]);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncException() {
class TestExceptionHandler implements IStorageExceptionHandler {
public int exceptionCount = 0;
@Override
public void handleException(Exception exception) {
exceptionCount++;
}
}
TestExceptionHandler exceptionHandler = new TestExceptionHandler();
storageSource.setExceptionHandler(exceptionHandler);
// Use an invalid table name, which should cause the storage API call to throw
// an exception, which should then be converted to an ExecutionException.
Future<IResultSet> future = storageSource.executeQueryAsync("InvalidTableName",
null, null, null);
try {
future.get(10, TimeUnit.SECONDS);
fail("Expected ExecutionException was not thrown");
}
catch (ExecutionException e) {
assertTrue(true);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
assertEquals(exceptionHandler.exceptionCount, 1);
}
@Test
public void testAsyncInsertRow() {
Object[][] newPersonInfo = {{"999-99-9999", "Ellen", "Wilson", 40, true}};
Map<String,Object> rowValues = createPersonRowValues(newPersonInfo[0]);
Future<?> future = storageSource.insertRowAsync(PERSON_TABLE_NAME, rowValues);
waitForFuture(future);
try {
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
Object[][] expectedPersons = Arrays.copyOf(PERSON_INIT_DATA, PERSON_INIT_DATA.length + newPersonInfo.length);
System.arraycopy(newPersonInfo, 0, expectedPersons, PERSON_INIT_DATA.length, newPersonInfo.length);
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncUpdateRow() {
Map<String,Object> updateValues = new HashMap<String,Object>();
updateValues.put(PERSON_SSN, "777-77-7777");
updateValues.put(PERSON_FIRST_NAME, "Tennis");
updateValues.put(PERSON_AGE, 60);
Future<?> future = storageSource.updateRowAsync(PERSON_TABLE_NAME, updateValues);
waitForFuture(future);
try {
IResultSet resultSet = storageSource.getRow(PERSON_TABLE_NAME, "777-77-7777");
Object[][] expectedPersons = {{"777-77-7777", "Tennis", "Borg", 60, true}};
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncUpdateRow2() {
Map<String,Object> updateValues = new HashMap<String,Object>();
updateValues.put(PERSON_FIRST_NAME, "Tennis");
updateValues.put(PERSON_AGE, 60);
Future<?> future = storageSource.updateRowAsync(PERSON_TABLE_NAME, "777-77-7777", updateValues);
waitForFuture(future);
try {
IResultSet resultSet = storageSource.getRow(PERSON_TABLE_NAME, "777-77-7777");
Object[][] expectedPersons = {{"777-77-7777", "Tennis", "Borg", 60, true}};
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncUpdateMatchingRows() {
Map<String,Object> updateValues = new HashMap<String,Object>();
updateValues.put(PERSON_FIRST_NAME, "Tennis");
updateValues.put(PERSON_AGE, 60);
IPredicate predicate = new OperatorPredicate(PERSON_SSN, OperatorPredicate.Operator.EQ, "777-77-7777");
Future<?> future = storageSource.updateMatchingRowsAsync(PERSON_TABLE_NAME, predicate, updateValues);
waitForFuture(future);
try {
IResultSet resultSet = storageSource.getRow(PERSON_TABLE_NAME, "777-77-7777");
Object[][] expectedPersons = {{"777-77-7777", "Tennis", "Borg", 60, true}};
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncDeleteRow() {
Future<?> future = storageSource.deleteRowAsync(PERSON_TABLE_NAME, "111-11-1111");
waitForFuture(future);
try {
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
Object[][] expectedPersons = Arrays.copyOfRange(PERSON_INIT_DATA, 1, PERSON_INIT_DATA.length);
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncDeleteMatchingRows() {
Future<?> future = storageSource.deleteMatchingRowsAsync(PERSON_TABLE_NAME, null);
waitForFuture(future);
try {
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, new Object[0][]);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
@Test
public void testAsyncSave() {
// Get a result set and make some changes to it
IResultSet resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
resultSet.next();
resultSet.deleteRow();
resultSet.next();
resultSet.setString(PERSON_FIRST_NAME, "John");
Future<?> future = storageSource.saveAsync(resultSet);
waitForFuture(future);
try {
resultSet = storageSource.executeQuery(PERSON_TABLE_NAME, null, null, new RowOrdering(PERSON_SSN));
Object[][] expectedPersons = Arrays.copyOfRange(PERSON_INIT_DATA, 1, PERSON_INIT_DATA.length);
expectedPersons[0][1] = "John";
checkExpectedResults(resultSet, PERSON_COLUMN_LIST, expectedPersons);
}
catch (Exception e) {
fail("Exception thrown in async storage operation: " + e.toString());
}
}
}