package eu.dnetlib.iis.wf.collapsers;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.avro.AvroTypeException;
import org.apache.avro.generic.IndexedRecord;
import org.apache.avro.mapred.AvroKey;
import org.apache.avro.mapred.AvroValue;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.Reducer.Context;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import eu.dnetlib.iis.common.schemas.Identifier;
import eu.dnetlib.iis.importer.schemas.DocumentToProject;
/**
* @author mhorst
*
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings({"rawtypes", "unchecked"})
public class CollapserReducerTest {
@Mock
private Context context;
@Captor
private ArgumentCaptor<AvroKey<IndexedRecord>> keyCaptor;
@Captor
private ArgumentCaptor<NullWritable> valueCaptor;
private CollapserReducer reducer = new CollapserReducer();
// ------------------------------------- TESTS -----------------------------------
@Test(expected=IOException.class)
public void testSetupWithoutCollapserClass() throws Exception {
// given
Configuration conf = new Configuration();
conf.set(CollapserReducer.INPUT_SCHEMA, DocumentToProject.class.getCanonicalName());
doReturn(conf).when(context).getConfiguration();
// execute
reducer.setup(context);
}
@Test(expected=IOException.class)
public void testSetupWithoutInputSchema() throws Exception {
// given
Configuration conf = new Configuration();
conf.set(CollapserReducer.RECORD_COLLAPSER, DummyDocumentToProjectCollapser.class.getCanonicalName());
doReturn(conf).when(context).getConfiguration();
// execute
reducer.setup(context);
}
@Test(expected=AvroTypeException.class)
public void testReduceWithInvalidInputClass() throws Exception {
// given
Configuration conf = new Configuration();
conf.set(CollapserReducer.RECORD_COLLAPSER, DummyDocumentToProjectCollapser.class.getCanonicalName());
conf.set(CollapserReducer.INPUT_SCHEMA, DocumentToProject.class.getCanonicalName());
doReturn(conf).when(context).getConfiguration();
reducer.setup(context);
// execute
reducer.reduce(null, Collections.singletonList(
new AvroValue(Identifier.newBuilder().setId("id1").build())), context);
}
@Test
public void testReduce() throws Exception {
// given
Configuration conf = new Configuration();
conf.set(CollapserReducer.RECORD_COLLAPSER, DummyDocumentToProjectCollapser.class.getCanonicalName());
conf.set(CollapserReducer.INPUT_SCHEMA, DocumentToProject.class.getCanonicalName());
doReturn(conf).when(context).getConfiguration();
reducer.setup(context);
String docId1 = "docId1";
String docId2 = "docId2";
String projId1 = "projId1";
String projId2 = "projId2";
List<AvroValue<IndexedRecord>> docProjList = new ArrayList<>();
docProjList.add(buildInputRecord(docId1, projId1));
docProjList.add(buildInputRecord(docId1, projId2));
docProjList.add(buildInputRecord(docId2, projId1));
docProjList.add(buildInputRecord(docId2, projId2));
// execute
reducer.reduce(null, docProjList, context);
// assert
verify(context, times(2)).write(keyCaptor.capture(), valueCaptor.capture());
assertEquals(2, keyCaptor.getAllValues().size());
assertTrue(keyCaptor.getAllValues().get(0).datum() instanceof Identifier);
assertEquals(docId1, ((Identifier)keyCaptor.getAllValues().get(0).datum()).getId().toString());
assertTrue(keyCaptor.getAllValues().get(1).datum() instanceof Identifier);
assertEquals(docId2, ((Identifier)keyCaptor.getAllValues().get(1).datum()).getId().toString());
assertEquals(2, valueCaptor.getAllValues().size());
assertTrue(NullWritable.get() == valueCaptor.getAllValues().get(0));
assertTrue(NullWritable.get() == valueCaptor.getAllValues().get(1));
}
// ------------------------------------- PRIVATE --------------------------------
private static AvroValue buildInputRecord(String docId, String projId) {
return new AvroValue(DocumentToProject.newBuilder().setDocumentId(docId).setProjectId(projId).build());
}
}