/* * Copyright 2013 eBuddy B.V. * * 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.ebuddy.cassandra.dao; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.collections.KeyValue; import org.apache.commons.collections.keyvalue.DefaultKeyValue; import org.apache.commons.lang3.ObjectUtils; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.ebuddy.cassandra.dao.mapper.ColumnMapper; import me.prettyprint.cassandra.model.ExecutingKeyspace; import me.prettyprint.cassandra.model.ExecutionResult; import me.prettyprint.cassandra.model.KeyspaceOperationCallback; import me.prettyprint.cassandra.serializers.StringSerializer; import me.prettyprint.hector.api.beans.ColumnSlice; import me.prettyprint.hector.api.beans.HColumn; import me.prettyprint.hector.api.beans.Row; import me.prettyprint.hector.api.beans.Rows; import me.prettyprint.hector.api.exceptions.HectorTransportException; import me.prettyprint.hector.api.factory.HFactory; import me.prettyprint.hector.api.mutation.Mutator; /** * Test for ColumnFamilyDaoTemplate. * @author Eric Zoerner <a href="mailto:ezoerner@ebuddy.com">ezoerner@ebuddy.com</a> */ @SuppressWarnings({"unchecked", "rawtypes"}) public class ColumnFamilyTemplateTest { private final String columnFamily = "TestColumnFamily"; private final String rowKey = "testKey"; private final String columnName = "testColumnName"; private final List<String> columnNames = Arrays.asList("columnName1", "columnName2"); private final String columnValue = "testColumnValue"; private final List<String> columnValues = Arrays.asList("columnValue1", "columnValue2"); @Mock private ExecutionResult executionResult; @Mock private KeyspaceTemplate.HectorBatchContext txnContext; @Mock private Mutator<String> mutator; @Captor private ArgumentCaptor<ColumnMapper<String,String,String>> mapperCaptor; private ColumnFamilyOperations<String,String,String> columnFamilyTestDao; @BeforeMethod(alwaysRun = true) public void setUp() throws Exception { MockitoAnnotations.initMocks(this); ExecutingKeyspace keyspace = mock(ExecutingKeyspace.class); when(keyspace.doExecute(any(KeyspaceOperationCallback.class))).thenReturn(executionResult); columnFamilyTestDao = new ColumnFamilyTemplate<String,String,String>(keyspace, columnFamily, StringSerializer.get(), StringSerializer.get(), StringSerializer.get()); when(txnContext.getMutator()).thenReturn(mutator); } @Test(groups = {"unit"}) public void testReadColumnValue() throws Exception { HColumn<String,String> column = mock(HColumn.class); String columnValue = "testColumnValue"; when(column.getValue()).thenReturn(columnValue); when(executionResult.get()).thenReturn(column); //========================= String value = columnFamilyTestDao.readColumnValue(rowKey, columnName); //========================= assertEquals(value, columnValue); } @Test(groups = {"unit"}, expectedExceptions = HectorTransportException.class) public void testReadColumnValueTranslateHectorException() throws Exception { when(executionResult.get()).thenThrow(new HectorTransportException("test hector exception")); columnFamilyTestDao.readColumnValue(rowKey, columnName); } @Test(groups = {"unit"}) public void testReadColumnsAsMap() throws Exception { Map<String, String> testResultMap = new HashMap<String,String>(); testResultMap.put(columnNames.get(0), columnValues.get(0)); testResultMap.put(columnNames.get(1), columnValues.get(1)); ColumnSlice columnSlice = mock(ColumnSlice.class); HColumn column1 = mock(HColumn.class); HColumn column2 = mock(HColumn.class); when(column1.getName()).thenReturn(columnNames.get(0)); when(column1.getValue()).thenReturn(columnValues.get(0)); when(column2.getName()).thenReturn(columnNames.get(1)); when(column2.getValue()).thenReturn(columnValues.get(1)); when(columnSlice.getColumns()).thenReturn(Arrays.asList(column1, column2)); when(executionResult.get()).thenReturn(columnSlice); //========================= Map actualResult = columnFamilyTestDao.readColumnsAsMap(rowKey); //========================= assertEquals(actualResult, testResultMap); } @Test(groups = {"unit"}) public void testReadColumns() throws Exception { Map<String, String> testResultMap = new HashMap<String,String>(); testResultMap.put(columnNames.get(0), columnValues.get(0)); testResultMap.put(columnNames.get(1), columnValues.get(1)); ColumnSlice columnSlice = mock(ColumnSlice.class); HColumn column1 = mock(HColumn.class); HColumn column2 = mock(HColumn.class); when(column1.getName()).thenReturn(columnNames.get(0)); when(column1.getValue()).thenReturn(columnValues.get(0)); when(column2.getName()).thenReturn(columnNames.get(1)); when(column2.getValue()).thenReturn(columnValues.get(1)); when(columnSlice.getColumns()).thenReturn(Arrays.asList(column1, column2)); when(executionResult.get()).thenReturn(columnSlice); //========================= List<KeyValue> actualResult = columnFamilyTestDao.readColumns(rowKey, new ColumnMapper<KeyValue,String,String>() { @Override public KeyValue mapColumn(String columnName, String columnValue) { return new DefaultKeyValue(columnName, columnValue); } }); //========================= Map<String,String> resultMap = new HashMap<String,String>(); for (KeyValue kv : actualResult) { resultMap.put((String)kv.getKey(), (String)kv.getValue()); } assertEquals(resultMap, testResultMap); } @Test(groups = {"unit"}) public void testBasicMultiGetAsMap() throws Exception { Rows<String,String,String> resultRows = mock(Rows.class); Row<String,String,String> row1 = mock(Row.class); Row<String,String,String> row2 = mock(Row.class); when(row1.getKey()).thenReturn("row1Key"); when(row2.getKey()).thenReturn("row2Key"); ColumnSlice columnSlice1 = mock(ColumnSlice.class); HColumn column1 = mock(HColumn.class); HColumn column2 = mock(HColumn.class); when(column1.getName()).thenReturn(columnNames.get(0)); when(column1.getValue()).thenReturn(columnValues.get(0)); when(column2.getName()).thenReturn(columnNames.get(1)); when(column2.getValue()).thenReturn(columnValues.get(1)); when(columnSlice1.getColumns()).thenReturn(Arrays.asList(column1, column2)); when(row1.getColumnSlice()).thenReturn(columnSlice1); when(row2.getColumnSlice()).thenReturn(columnSlice1); Iterator<Row<String,String,String>> iterator = Arrays.asList(row1,row2).iterator(); when(resultRows.iterator()).thenReturn(iterator); when(executionResult.get()).thenReturn(resultRows); Iterable<String> rowKeys = Arrays.asList("key1", "key2"); Map<String,String> oneRowMap = new HashMap<String,String>(); oneRowMap.put("columnName1", "columnValue1"); oneRowMap.put("columnName2", "columnValue2"); Map<String,Map<String,String>> expectedResultMap = new HashMap<String,Map<String,String>>(); expectedResultMap.put("row1Key", oneRowMap); expectedResultMap.put("row2Key", oneRowMap); //========================= Map<String,Map<String,String>> resultMap = columnFamilyTestDao.multiGetAsMap(rowKeys); //========================= assertNotNull(resultMap); assertEquals(resultMap, expectedResultMap); } @Test(groups = {"unit"}, expectedExceptions = HectorTransportException.class) public void testReadColumnsAsMapTranslateHectorException() throws Exception { when(executionResult.get()).thenThrow(new HectorTransportException("test hector exception")); columnFamilyTestDao.readColumnsAsMap(rowKey); } @Test(groups = {"unit"}) public void testWriteColumn() throws Exception { String propertyValue = columnValue; //========================= columnFamilyTestDao.writeColumn(rowKey, columnName, propertyValue, txnContext); //========================= HColumn<String,String> column = HFactory.createColumn(columnName, columnValue, StringSerializer.get(), StringSerializer.get()); ArgumentCaptor<HColumn> columnCaptor = ArgumentCaptor.forClass(HColumn.class); verify(mutator).addInsertion(eq(rowKey), eq(columnFamily), columnCaptor.capture()); HColumn actualColumn = columnCaptor.getValue(); assertTrue(areColumnsEqual(actualColumn, column)); } @Test(groups = {"unit"}, expectedExceptions = HectorTransportException.class) public void testWriteColumnTranslateHectorException() throws Exception { when(mutator.addInsertion(eq(rowKey), eq(columnFamily), any(HColumn.class))). thenThrow(new HectorTransportException("test hector exception")); String propertyValue = columnValue; //========================= columnFamilyTestDao.writeColumn(rowKey, columnName, propertyValue, txnContext); //========================= } @Test(groups = {"unit"}) public void testWriteColumns() throws Exception { Map<String,String> properties = new HashMap<String,String>(); Iterator<String> itr = columnValues.iterator(); for (String columnName : columnNames) { properties.put(columnName, itr.next()); } //========================= columnFamilyTestDao.writeColumns(rowKey, properties, txnContext); //========================= HColumn column1 = HFactory.createColumn(columnNames.get(0), columnValues.get(0), StringSerializer.get(), StringSerializer.get()); HColumn column2 = HFactory.createColumn(columnNames.get(1), columnValues.get(1), StringSerializer.get(), StringSerializer.get()); ArgumentCaptor<HColumn> columnCaptor = ArgumentCaptor.forClass(HColumn.class); verify(mutator, times(2)).addInsertion(eq(rowKey), eq(columnFamily), columnCaptor.capture()); List<HColumn> actualColumns = columnCaptor.getAllValues(); assertTrue(areColumnsEqual(actualColumns.get(0), column1)); assertTrue(areColumnsEqual(actualColumns.get(1), column2)); } @Test(groups = {"unit"}, expectedExceptions = HectorTransportException.class) public void testWriteColumnsTranslateHectorException() throws Exception { when(mutator.addInsertion(eq(rowKey), eq(columnFamily), any(HColumn.class))).thenThrow(new HectorTransportException( "test hector exception")); Map<String,String> properties = new HashMap<String,String>(); Iterator<String> itr = columnValues.iterator(); for (String columnName : columnNames) { properties.put(columnName, itr.next()); } //========================= columnFamilyTestDao.writeColumns(rowKey, properties, txnContext); //========================= } @Test(groups = {"unit"}) public void shouldDeleteColumnSlice() throws Exception { ColumnFamilyOperations<String,String,String> spy = spy(columnFamilyTestDao); doReturn(Arrays.asList("a", "b", "c")).when(spy).readColumns(eq(rowKey), eq("start"), eq( "finish"), eq(Integer.MAX_VALUE), eq(false), mapperCaptor.capture()); //========================= spy.deleteColumns(rowKey, "start", "finish", txnContext); //========================= verify(mutator).addDeletion(rowKey, columnFamily, "a", StringSerializer.get()); verify(mutator).addDeletion(rowKey, columnFamily, "a", StringSerializer.get()); verify(mutator).addDeletion(rowKey, columnFamily, "a", StringSerializer.get()); verify(mutator, never()).execute(); } private boolean areColumnsEqual(HColumn column1, HColumn column2) { return column1 == column2 || column2 != null && column1 != null && column1.getClass() == column2.getClass() && ObjectUtils.equals(column1.getName(), column2.getName()) && ObjectUtils.equals(column1.getValue(), column2.getValue()); } }