package eu.dnetlib.iis.wf.referenceextraction; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.avro.Schema; import org.apache.hadoop.conf.Configuration; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import eu.dnetlib.iis.common.java.PortBindings; import eu.dnetlib.iis.common.java.io.CloseableIterator; import eu.dnetlib.iis.common.java.io.FileSystemPath; import eu.dnetlib.iis.common.java.io.JsonStreamReader; import eu.dnetlib.iis.common.java.porttype.AnyPortType; import eu.dnetlib.iis.common.java.porttype.AvroPortType; import eu.dnetlib.iis.common.java.porttype.PortType; import eu.dnetlib.iis.importer.schemas.Project; /** * {@link AbstractDBBuilder} test class. * @author mhorst * */ @RunWith(MockitoJUnitRunner.class) public class DBBuilderTest { private static final Schema SCHEMA_PROJECT = Project.SCHEMA$; private static final String PORT_NAME_INPUT = "input"; private static final String PORT_NAME_OUTPUT = "output"; private final PortBindings portBindings = new PortBindings(new HashMap<>(), new HashMap<>()); private final Configuration conf = null; private final Map<String, String> parameters = null; private File outputFile; private Project firstProject = buildProject("id1", "text1"); private Project secondProject = buildProject("id2", "text2"); private List<Project> projects; private AbstractDBBuilder<Project> dbBuilder; @Rule public TemporaryFolder testFolder = new TemporaryFolder(); @Mock private FileSystemFacade fileSystemFacade; @Mock private Process process; @Before public void initializeBuilder() { projects = Arrays.asList(new Project[] {firstProject, secondProject}); outputFile = new File(testFolder.getRoot(),"tmpfile"); dbBuilder = new AbstractDBBuilder<Project>( (conf) -> { return fileSystemFacade; }, SCHEMA_PROJECT, PORT_NAME_INPUT, PORT_NAME_OUTPUT) { @Override protected ProcessExecutionContext initializeProcess(Map<String, String> parameters) throws IOException { return new ProcessExecutionContext(process, outputFile); } @Override protected CloseableIterator<Project> getInputRecordsIterator(FileSystemPath fileSystemPath) throws IOException { return new CloseableIterator<Project>() { final Iterator<Project> it = projects.iterator(); @Override public boolean hasNext() { return it.hasNext(); } @Override public Project next() { return it.next(); } @Override public void close() throws IOException { // does nothing } }; } }; } @Test public void testNonZeroExitValue() throws Exception { // given ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String errorMessage = "custom error message related to non zero exit value"; doReturn(outputStream).when(fileSystemFacade).create(any()); doReturn(null).when(fileSystemFacade).getFileSystem(); doReturn(new FileOutputStream(outputFile)).when(process).getOutputStream(); doReturn(1).when(process).exitValue(); doReturn(new ByteArrayInputStream(errorMessage.getBytes("utf8"))).when(process).getErrorStream(); try { // execute dbBuilder.run(portBindings, conf, parameters); fail("exception was expected!"); } catch (RuntimeException e) { // assert assertTrue(e.getMessage().contains(errorMessage)); assertEquals(0, outputStream.size()); } } @Test public void testException() throws Exception { // given ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String errorMessage = "custom error message after exception"; Throwable exception = new RuntimeException(errorMessage); doReturn(outputStream).when(fileSystemFacade).create(any()); doReturn(null).when(fileSystemFacade).getFileSystem(); doReturn(new FileOutputStream(outputFile)).when(process).getOutputStream(); doReturn(0).when(process).exitValue(); doThrow(exception).when(process).waitFor(); doReturn(new ByteArrayInputStream(errorMessage.getBytes("utf8"))).when(process).getErrorStream(); try { // execute dbBuilder.run(portBindings, conf, parameters); fail("exception was expected!"); } catch (IOException e) { // assert assertTrue(e.getMessage().contains(errorMessage)); assertTrue(exception == e.getCause()); assertEquals(0, outputStream.size()); } } @Test public void testEmptyInput() throws Exception { // given ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); projects = Collections.emptyList(); doReturn(outputStream).when(fileSystemFacade).create(any()); doReturn(null).when(fileSystemFacade).getFileSystem(); doReturn(new FileOutputStream(outputFile)).when(process).getOutputStream(); doReturn(0).when(process).exitValue(); dbBuilder.run(portBindings, conf, parameters); assertEquals(0, outputStream.size()); } @Test public void test() throws Exception { // given ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); doReturn(outputStream).when(fileSystemFacade).create(any()); doReturn(null).when(fileSystemFacade).getFileSystem(); doReturn(0).when(process).exitValue(); doReturn(new FileOutputStream(outputFile)).when(process).getOutputStream(); // execute dbBuilder.run(portBindings, conf, parameters); // assert try (JsonStreamReader<Project> reader = new JsonStreamReader<Project>( Project.SCHEMA$, new ByteArrayInputStream(outputStream.toByteArray()), Project.class)) { assertTrue(reader.hasNext()); Project receivedProject = reader.next(); assertEquals(firstProject, receivedProject); assertTrue(reader.hasNext()); receivedProject = reader.next(); assertEquals(secondProject, receivedProject); assertFalse(reader.hasNext()); } } @Test public void testGetInputPorts() throws Exception { // execute Map<String, PortType> result = dbBuilder.getInputPorts(); // assert assertNotNull(result); assertNotNull(result.get(PORT_NAME_INPUT)); assertTrue(result.get(PORT_NAME_INPUT) instanceof AvroPortType); assertTrue(SCHEMA_PROJECT == ((AvroPortType)result.get(PORT_NAME_INPUT)).getSchema()); } @Test public void testGetOutputPorts() throws Exception { // execute Map<String, PortType> result = dbBuilder.getOutputPorts(); // assert assertNotNull(result); assertNotNull(result.get(PORT_NAME_OUTPUT)); assertTrue(result.get(PORT_NAME_OUTPUT) instanceof AnyPortType); } // --------------------------------- PRIVATE ----------------------------------------- private Project buildProject(String id, String jsonExtraInfo) { return Project.newBuilder().setId(id).setJsonextrainfo(jsonExtraInfo).build(); } }