package eu.dnetlib.iis.common.cache; import static eu.dnetlib.iis.common.WorkflowRuntimeParameters.OOZIE_ACTION_OUTPUT_FILENAME; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; 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.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import eu.dnetlib.iis.common.FsShellPermissions; import eu.dnetlib.iis.common.java.PortBindings; /** * {@link CacheMetadataManagingProcess} test class. * * @author mhorst * */ @RunWith(MockitoJUnitRunner.class) public class CacheMetadataManagingProcessTest { private final PortBindings portBindings = null; private final Configuration conf = null; private final String irrelevantCacheDir = "irrelevantCacheDir"; @Captor ArgumentCaptor<FsShellPermissions.Op> changePermissionsOp; @Captor ArgumentCaptor<Boolean> changePermissionsRecursive; @Captor ArgumentCaptor<String> changePermissionsGroup; @Captor ArgumentCaptor<String> changePermissionsPath; @Rule public TemporaryFolder testFolder = new TemporaryFolder(); @Mock private FileSystemFacade fsFacade; private FileSystemFacadeFactory fsFacadeFactory = new FileSystemFacadeFactory() { @Override public FileSystemFacade create(Configuration conf) throws IOException { return fsFacade; } }; private CacheMetadataManagingProcess process = new CacheMetadataManagingProcess(fsFacadeFactory); @Before public void initEnv() { System.setProperty(OOZIE_ACTION_OUTPUT_FILENAME, testFolder.getRoot().getAbsolutePath() + File.separatorChar + "test.properties"); } //------------------------ TESTS -------------------------- @Test(expected=RuntimeException.class) public void testInvalidMode() throws Exception { process.run(portBindings, conf, setParams("unknown", null)); } @Test(expected=RuntimeException.class) public void testReadCurrentIdWithoutDir() throws Exception { process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_READ_CURRENT_ID, null)); } @Test() public void testReadCurrentIdNonExistingDir() throws Exception { // given doReturn(false).when(fsFacade).exists(any()); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_READ_CURRENT_ID, irrelevantCacheDir)); // verify verifyStoredCacheId("$UNDEFINED$"); } @Test() public void testReadCurrentId() throws Exception { // given String cacheId = "000021"; doReturn(true).when(fsFacade).exists(any()); doReturn(new ByteArrayInputStream(buildCacheJson(cacheId).getBytes())).when(fsFacade).open(any()); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_READ_CURRENT_ID, irrelevantCacheDir)); // verify verifyStoredCacheId(cacheId); } @Test(expected=RuntimeException.class) public void testGenerateNewIdWithoutDir() throws Exception { process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_GENERATE_NEW_ID, null)); } @Test() public void testGenerateNewIdNonExistingDir() throws Exception { // given doReturn(false).when(fsFacade).exists(any()); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_GENERATE_NEW_ID, irrelevantCacheDir)); // verify verifyStoredCacheId("000001"); } @Test() public void testGenerateNewId() throws Exception { // given doReturn(true).when(fsFacade).exists(any()); doReturn(new ByteArrayInputStream(buildCacheJson("000021").getBytes())).when(fsFacade).open(any()); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_GENERATE_NEW_ID, irrelevantCacheDir)); // verify verifyStoredCacheId("000022"); } @Test(expected=RuntimeException.class) public void testWriteIdWithoutDir() throws Exception { String cacheId = "123456"; process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_WRITE_ID, null, cacheId)); } @Test(expected=RuntimeException.class) public void testWriteIdWithoutId() throws Exception { process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_WRITE_ID, irrelevantCacheDir, null)); } @Test() public void testWriteIdNonExistingDir() throws Exception { // given String cacheId = "123456"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); Path path = new Path(irrelevantCacheDir, CacheMetadataManagingProcess.DEFAULT_METAFILE_NAME); doReturn(false).when(fsFacade).exists(any()); doReturn(bos).when(fsFacade).create( new Path(irrelevantCacheDir, CacheMetadataManagingProcess.DEFAULT_METAFILE_NAME), true); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_WRITE_ID, irrelevantCacheDir, cacheId)); // verify verify(fsFacade).changePermissions(any(), changePermissionsOp.capture(), changePermissionsRecursive.capture(), changePermissionsGroup.capture(), changePermissionsPath.capture()); assertEquals(FsShellPermissions.Op.CHMOD, changePermissionsOp.getValue()); assertEquals(false, changePermissionsRecursive.getValue()); assertEquals("0666", changePermissionsGroup.getValue()); assertEquals(path.toString(), changePermissionsPath.getValue()); assertEquals(buildCacheJson(cacheId), bos.toString("utf8")); } @Test() public void tesWriteId() throws Exception { // given String cacheId = "123456"; ByteArrayOutputStream bos = new ByteArrayOutputStream(); Path path = new Path(irrelevantCacheDir, CacheMetadataManagingProcess.DEFAULT_METAFILE_NAME); doReturn(true).when(fsFacade).exists(any()); doReturn(new ByteArrayInputStream(buildCacheJson("654321").getBytes())).when(fsFacade).open(any()); doReturn(bos).when(fsFacade).create(path, true); // execute process.run(portBindings, conf, setParams(CacheMetadataManagingProcess.MODE_WRITE_ID, irrelevantCacheDir, cacheId)); // verify verify(fsFacade).changePermissions(any(), changePermissionsOp.capture(), changePermissionsRecursive.capture(), changePermissionsGroup.capture(), changePermissionsPath.capture()); assertEquals(FsShellPermissions.Op.CHMOD, changePermissionsOp.getValue()); assertEquals(false, changePermissionsRecursive.getValue()); assertEquals("0666", changePermissionsGroup.getValue()); assertEquals(path.toString(), changePermissionsPath.getValue()); assertEquals(buildCacheJson(cacheId), bos.toString("utf8")); } // ----------------------- PRIVATE ---------------------------- private void verifyStoredCacheId(String expectedId) throws FileNotFoundException, IOException { Properties properties = getStoredProperties(); assertNotNull(properties); assertEquals(1, properties.size()); assertEquals(expectedId, properties.get(CacheMetadataManagingProcess.OUTPUT_PROPERTY_CACHE_ID)); } private String buildCacheJson(String cacheId) { return "{\"currentCacheId\":\""+cacheId+"\"}"; } private Properties getStoredProperties() throws FileNotFoundException, IOException { Properties properties = new Properties(); properties.load(new FileInputStream(System.getProperty(OOZIE_ACTION_OUTPUT_FILENAME))); return properties; } private static Map<String, String> setParams(String mode, String cacheDir) { return setParams(mode, cacheDir, null); } private static Map<String, String> setParams(String mode, String cacheDir, String id) { Map<String, String> parameters = new HashMap<>(); if (mode != null) { setParam(parameters, CacheMetadataManagingProcess.PARAM_MODE, mode); } if (cacheDir != null) { setParam(parameters, CacheMetadataManagingProcess.PARAM_CACHE_DIR, cacheDir); } if (id != null) { setParam(parameters, CacheMetadataManagingProcess.PARAM_ID, id); } return parameters; } private static Map<String, String> setParam(Map<String, String> parameters, String key, String value) { parameters.put(key, value); return parameters; } }