/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.component.integration; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.exec.OS; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import de.rcenvironment.core.component.integration.internal.ToolIntegrationFileWatcher; import de.rcenvironment.core.component.integration.internal.ToolIntegrationFileWatcherManager; import de.rcenvironment.core.utils.common.CompressingHelper; import de.rcenvironment.core.utils.common.TempFileServiceAccess; /** * Test the {@link ToolIntegrationFileWatcherManager} and the {@link ToolIntegrationFileWatcher}. * * @author Sascha Zur */ public class ToolIntegrationFileWatcherManagerTest { private static final int TEST_TIMEOUT = 10000; private static File toolDirectory = null; private final Object lockObject = new Object(); private File testDirectory; private MockToolIntegrationContext mockContext; private File integrationDir; private CountDownLatch latch; private String currentToolName; private int methodCount = 0; private ToolIntegrationFileWatcherManager manager; /** * Copy test resources to a temp dir, for a better access (copy dir to dir). */ @BeforeClass public static void setupTestDirectories() { if (toolDirectory == null) { TempFileServiceAccess.setupUnitTestEnvironment(); try { toolDirectory = TempFileServiceAccess.getInstance().createManagedTempDir(); CompressingHelper.unzip(ToolIntegrationFileWatcherManagerTest.class.getResourceAsStream("/TestTools.zip"), toolDirectory); } catch (IOException | ArchiveException e) { Assert.fail(e.getMessage()); } } } /** * Clean up temp dir. */ @AfterClass public static void cleanUpTestDirectories() { if (toolDirectory != null) { try { TempFileServiceAccess.getInstance().disposeManagedTempDirOrFile(toolDirectory); } catch (IOException e) { Assert.fail(e.getMessage()); } } } /** * Set up the environment. */ @Before public void setup() { try { testDirectory = TempFileServiceAccess.getInstance().createManagedTempDir(); } catch (IOException e) { Assert.fail("Could not set up test directory: " + e.getMessage()); } currentToolName = null; methodCount = 0; mockContext = new MockToolIntegrationContext(); integrationDir = new File(mockContext.getRootPathToToolIntegrationDirectory(), mockContext.getContextType()); ToolIntegrationService integrationServiceMock = new ToolIntegrationServiceMock(); manager = new ToolIntegrationFileWatcherManager(integrationServiceMock); manager.createWatcherForToolRootDirectory(mockContext); } /** * Clean up. */ @After public void tearDown() { manager.unregisterRootDirectory(mockContext); if (integrationDir.exists()) { integrationDir.delete(); } if (testDirectory.exists()) { try { TempFileServiceAccess.getInstance().disposeManagedTempDirOrFile(testDirectory); } catch (IOException e) { Assert.fail(e.getMessage()); } } } /** * Test if the {@link ToolIntegrationFileWatcher} works correct if a directory with a configuration is copied. */ @Test public void testCopyToolDirIntoFolder() { latch = new CountDownLatch(2); currentToolName = "TestDirectoryValidConfiguration"; try { FileUtils.copyDirectoryToDirectory(new File(toolDirectory, currentToolName), integrationDir); latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); } catch (IOException | InterruptedException e) { Assert.fail(e.getMessage()); } manager.unregister(currentToolName, mockContext); Assert.assertEquals(2, getMethodCount()); } /** * Test if the {@link ToolIntegrationFileWatcher} works correct if a directory with a configuration is copied. */ @Test public void testCopyToolDirWithDocsIntoFolder() { if (OS.isFamilyWindows()) { latch = new CountDownLatch(10); } else { latch = new CountDownLatch(2); } currentToolName = "TestDirectoryWithDocs"; try { FileUtils.copyDirectoryToDirectory(new File(toolDirectory, currentToolName), integrationDir); latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); } catch (IOException | InterruptedException e) { Assert.fail(e.getMessage()); } manager.unregister(currentToolName, mockContext); if (OS.isFamilyWindows()) { Assert.assertEquals(10, getMethodCount()); } else { Assert.assertEquals(2, getMethodCount()); } } /** * Test if the {@link ToolIntegrationFileWatcher} works correct if a directory with a configuration is copied. */ @Test public void testCopyToolDirWithEmptyDocsIntoFolder() { if (OS.isFamilyWindows()) { latch = new CountDownLatch(4); } else { latch = new CountDownLatch(2); } currentToolName = "TestDirectoryWithEmptyDocs"; try { FileUtils.copyDirectoryToDirectory(new File(toolDirectory, currentToolName), integrationDir); latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); } catch (IOException | InterruptedException e) { Assert.fail(e.getMessage()); } manager.unregister(currentToolName, mockContext); if (OS.isFamilyWindows()) { Assert.assertTrue(getMethodCount() >= 4); } else { Assert.assertEquals(2, getMethodCount()); } } /** * Test if the {@link ToolIntegrationFileWatcher} works correct if an empty directory is pasted. */ @Test public void testFillUpEmptyDirectory() { currentToolName = "Tool"; new File(integrationDir, currentToolName).mkdir(); if (OS.isFamilyWindows()) { latch = new CountDownLatch(6); } else { latch = new CountDownLatch(2); } try { FileUtils.copyFileToDirectory(new File(toolDirectory, "configuration.json"), new File(integrationDir, currentToolName)); latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS); } catch (IOException | InterruptedException e) { Assert.fail(e.getMessage()); } if (OS.isFamilyWindows()) { Assert.assertEquals(6, getMethodCount()); } else { Assert.assertEquals(2, getMethodCount()); } } /** * Test if the {@link ToolIntegrationFileWatcher} works correct if an empty directory is pasted. */ @Test public void testEmptyDirectoryPasted() { currentToolName = "Empty"; new File(integrationDir, currentToolName).mkdir(); // Since the file watcher is in another thread and there is no way of flagging if it was // triggered yet, the test waits a bit hoping that the file watcher is done. manager.unregister(currentToolName, mockContext); Assert.assertEquals(0, getMethodCount()); } public File getTempDirectory() { return testDirectory; } private String getCurrentToolName() { return currentToolName; } private int getMethodCount() { int result = 0; synchronized (lockObject) { result = methodCount; } return result; } private void increaseMethodCount() { synchronized (lockObject) { methodCount++; } } /** * Mock for {@link ToolIntegrationService} to count down if file watcher was activated. * * @author Sascha Zur */ private class ToolIntegrationServiceMock extends DefaultToolIntegrationServiceStub { private Map<String, String> toolNameToPath = new HashMap<>(); @Override public void integrateTool(Map<String, Object> configurationMap, ToolIntegrationContext context) { Assert.assertEquals(context, mockContext); increaseMethodCount(); latch.countDown(); } @Override public void putToolNameToPath(String toolName, File parentFile) { Assert.assertEquals(getCurrentToolName(), toolName); toolNameToPath.put(parentFile.getAbsolutePath(), toolName); increaseMethodCount(); latch.countDown(); } @Override public void updatePublishedComponents(ToolIntegrationContext context) { Assert.assertEquals(context, mockContext); increaseMethodCount(); latch.countDown(); } @Override public String getToolNameToPath(String path) { increaseMethodCount(); latch.countDown(); return toolNameToPath.get(path); } @Override public void removeTool(String toolName, ToolIntegrationContext context) { Assert.assertEquals(context, mockContext); increaseMethodCount(); latch.countDown(); } } /** * Mock of a {@link ToolIntegrationContext} to test the {@link ToolIntegrationFileWatcher}. * * @author Sascha Zur */ private class MockToolIntegrationContext implements ToolIntegrationContext { @Override public String getContextId() { return "Mock"; } @Override public String getContextType() { return "Mock"; } @Override public String getRootPathToToolIntegrationDirectory() { return getTempDirectory().getAbsolutePath(); } @Override public String getNameOfToolIntegrationDirectory() { return getContextType(); } @Override public String getToolDirectoryPrefix() { return ""; } @Override public String getConfigurationFilename() { return "configuration.json"; } @Override public String getImplementingComponentClassName() { return null; } @Override public String getPrefixForComponentId() { return null; } @Override public String getComponentGroupId() { return null; } @Override public String[] getDisabledIntegrationKeys() { return null; } @Override public File[] getReadOnlyPathsList() { return null; } } }