/**
*
*/
package com.stratio.deep.cassandra.cql;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.TableMetadata;
import com.stratio.deep.cassandra.config.CassandraDeepJobConfig;
import com.stratio.deep.cassandra.filter.value.EqualsInValue;
import com.stratio.deep.commons.rdd.DeepTokenRange;
import com.stratio.deep.commons.utils.Pair;
/**
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({ CassandraClientProvider.class })
public class DeepRecordReaderTest {
private final static int PAGE_SIZE_CONSTANT = 1000;
private final static String TABLE_NAME_CONSTANT = "TABLENAME";
private final static String[] INPUT_COLUMNS_CONSTANT = { "col1", "col2", "col3" };
private final static String LOCALHOST_CONSTANT = "localhost";
@Mock
private DeepTokenRange<Long, String> tokenRange;
@Mock
private CassandraDeepJobConfig<?> config;
@Mock
private Session session;
@Mock
private TableMetadata tableMetadata;
@Mock
private ColumnMetadata columnMetadata;
@Mock
private EqualsInValue equalsInValue;
@Mock
private ResultSet resultSet;
@Test
public void testEqualsInForDeepRecordReader() {
// Static stubs
PowerMockito.mockStatic(CassandraClientProvider.class);
// Stubbing
when(config.getPageSize()).thenReturn(PAGE_SIZE_CONSTANT);
when(config.getTable()).thenReturn(TABLE_NAME_CONSTANT);
when(config.getInputColumns()).thenReturn(INPUT_COLUMNS_CONSTANT);
when(config.fetchTableMetadata()).thenReturn(tableMetadata);
when(config.getEqualsInValue()).thenReturn(equalsInValue);
when(config.getPartitionerClassName()).thenReturn("org.apache.cassandra.dht.Murmur3Partitioner");
when(tokenRange.getReplicas()).thenReturn(Arrays.asList(LOCALHOST_CONSTANT));
when(tokenRange.getStartTokenAsComparable()).thenReturn(-8000000000000000000L, -7000000000000000000L,
2200000000000000000L, 2300000000000000000L, 2600000000000000000L);
when(tokenRange.getEndTokenAsComparable()).thenReturn(-7000000000000000000L, 2200000000000000000L,
2300000000000000000L, 2600000000000000000L, -8000000000000000000L);
when(CassandraClientProvider.trySessionForLocation(any(String.class), any(CassandraDeepJobConfig.class),
any(Boolean.class))).thenReturn(Pair.create(session, LOCALHOST_CONSTANT));
when(tableMetadata.getPartitionKey()).thenReturn(Arrays.asList(columnMetadata, columnMetadata));
when(tableMetadata.getClusteringColumns()).thenReturn(new ArrayList<ColumnMetadata>());
when(columnMetadata.getName()).thenReturn("col1", "col2");
when(columnMetadata.getType()).thenReturn(DataType.bigint());
when(equalsInValue.getEqualsList()).thenReturn(Arrays.asList(Pair.create("col1", (Serializable) 1L)));
when(equalsInValue.getInField()).thenReturn("col2");
when(equalsInValue.getInValues()).thenReturn(
Arrays.asList((Serializable) 1L, (Serializable) 2L, (Serializable) 3L, (Serializable) 4L,
(Serializable) 5L));
Object[] values = { 1L, Arrays.asList(1L, 4L) };
SimpleStatement stmt = new SimpleStatement(
"SELECT \"col1\",\"col2\",\"col3\" FROM \"TABLENAME\" WHERE col1 = ? AND col2 IN ?", values);
when(session.execute(any(Statement.class))).thenReturn(resultSet);
DeepRecordReader recordReader = new DeepRecordReader(config, tokenRange);
// TODO How do we check two statements are the same?
verify(session, times(1)).execute(Matchers.argThat(new StatementMatcher(stmt)));
}
class StatementMatcher extends BaseMatcher<SimpleStatement> {
private final SimpleStatement expectedStmt;
public StatementMatcher(SimpleStatement expectedStmt) {
this.expectedStmt = expectedStmt;
}
@Override
@SuppressWarnings("unchecked")
public boolean matches(Object obj) {
if (obj != null && obj instanceof SimpleStatement) {
SimpleStatement receivedStmt = (SimpleStatement) obj;
Object[] expectedValues = Whitebox.getInternalState(expectedStmt, "values");
Object[] receivedValues = Whitebox.getInternalState(receivedStmt, "values");
return matchValues(expectedValues, receivedValues);
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
*/
@Override
public void describeTo(Description description) {
description.appendText("Matches a class or subclass");
}
private boolean matchValues(Object[] expectedValues, Object[] receivedValues) {
boolean match = true;
int pointer = 0;
while (pointer < expectedValues.length && match) {
if (expectedValues[pointer] instanceof Long) {
Long expectedValue = (Long) expectedValues[pointer];
Long receivedValue = (Long) receivedValues[pointer];
match = expectedValue.equals(receivedValue);
} else if (expectedValues[pointer] instanceof List) {
List<Long> expectedValue = (List<Long>) expectedValues[pointer];
List<Long> receivedValue = (List<Long>) receivedValues[pointer];
match = expectedValue.equals(receivedValue);
} else {
match = expectedValues[pointer].equals(receivedValues[pointer]);
}
pointer++;
}
return match;
}
}
}