|
@@ -19,15 +19,36 @@ package org.apache.hadoop.yarn.server.nodemanager.containermanager.loghandler;
|
|
|
|
|
|
import static org.mockito.Matchers.any;
|
|
|
import static org.mockito.Matchers.eq;
|
|
|
+import static org.mockito.Matchers.isA;
|
|
|
+import static org.mockito.Mockito.doReturn;
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.spy;
|
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
|
|
import java.io.File;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.NotSerializableException;
|
|
|
+import java.io.ObjectInputStream;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.apache.commons.lang.builder.EqualsBuilder;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
+import org.apache.hadoop.fs.AbstractFileSystem;
|
|
|
+import org.apache.hadoop.fs.FileContext;
|
|
|
+import org.apache.hadoop.fs.FileStatus;
|
|
|
import org.apache.hadoop.fs.Path;
|
|
|
+import org.apache.hadoop.fs.UnsupportedFileSystemException;
|
|
|
+import org.apache.hadoop.fs.permission.FsPermission;
|
|
|
+import org.apache.hadoop.security.AccessControlException;
|
|
|
+import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
|
|
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
|
|
import org.apache.hadoop.yarn.api.records.ContainerId;
|
|
@@ -45,25 +66,52 @@ import org.apache.hadoop.yarn.server.nodemanager.containermanager.loghandler.eve
|
|
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.loghandler.event.LogHandlerAppStartedEvent;
|
|
|
import org.apache.hadoop.yarn.server.nodemanager.containermanager.loghandler.event.LogHandlerContainerFinishedEvent;
|
|
|
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
|
|
|
+import org.junit.After;
|
|
|
+import org.junit.Before;
|
|
|
import org.junit.Test;
|
|
|
+import org.mockito.ArgumentMatcher;
|
|
|
+import org.mockito.Mockito;
|
|
|
import org.mockito.exceptions.verification.WantedButNotInvoked;
|
|
|
+import org.mockito.internal.matchers.VarargMatcher;
|
|
|
|
|
|
public class TestNonAggregatingLogHandler {
|
|
|
+
|
|
|
+ DeletionService mockDelService;
|
|
|
+ Configuration conf;
|
|
|
+ DrainDispatcher dispatcher;
|
|
|
+ EventHandler<ApplicationEvent> appEventHandler;
|
|
|
+ String user = "testuser";
|
|
|
+ ApplicationId appId;
|
|
|
+ ApplicationAttemptId appAttemptId;
|
|
|
+ ContainerId container11;
|
|
|
+ LocalDirsHandlerService dirsHandler;
|
|
|
+
|
|
|
+ @Before
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ public void setup() {
|
|
|
+ mockDelService = mock(DeletionService.class);
|
|
|
+ conf = new YarnConfiguration();
|
|
|
+ dispatcher = createDispatcher(conf);
|
|
|
+ appEventHandler = mock(EventHandler.class);
|
|
|
+ dispatcher.register(ApplicationEventType.class, appEventHandler);
|
|
|
+ appId = BuilderUtils.newApplicationId(1234, 1);
|
|
|
+ appAttemptId = BuilderUtils.newApplicationAttemptId(appId, 1);
|
|
|
+ container11 = BuilderUtils.newContainerId(appAttemptId, 1);
|
|
|
+ dirsHandler = new LocalDirsHandlerService();
|
|
|
+ }
|
|
|
+
|
|
|
+ @After
|
|
|
+ public void tearDown() throws IOException {
|
|
|
+ dirsHandler.stop();
|
|
|
+ dirsHandler.close();
|
|
|
+ dispatcher.await();
|
|
|
+ dispatcher.stop();
|
|
|
+ dispatcher.close();
|
|
|
+ }
|
|
|
|
|
|
@Test
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- public void testLogDeletion() {
|
|
|
- DeletionService delService = mock(DeletionService.class);
|
|
|
- Configuration conf = new YarnConfiguration();
|
|
|
- String user = "testuser";
|
|
|
-
|
|
|
- File[] localLogDirs = new File[2];
|
|
|
- localLogDirs[0] =
|
|
|
- new File("target", this.getClass().getName() + "-localLogDir0")
|
|
|
- .getAbsoluteFile();
|
|
|
- localLogDirs[1] =
|
|
|
- new File("target", this.getClass().getName() + "-localLogDir1")
|
|
|
- .getAbsoluteFile();
|
|
|
+ public void testLogDeletion() throws IOException {
|
|
|
+ File[] localLogDirs = getLocalLogDirFiles(this.getClass().getName(), 2);
|
|
|
String localLogDirsString =
|
|
|
localLogDirs[0].getAbsolutePath() + ","
|
|
|
+ localLogDirs[1].getAbsolutePath();
|
|
@@ -72,72 +120,50 @@ public class TestNonAggregatingLogHandler {
|
|
|
conf.setBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, false);
|
|
|
conf.setLong(YarnConfiguration.NM_LOG_RETAIN_SECONDS, 0l);
|
|
|
|
|
|
- DrainDispatcher dispatcher = createDispatcher(conf);
|
|
|
- EventHandler<ApplicationEvent> appEventHandler = mock(EventHandler.class);
|
|
|
- dispatcher.register(ApplicationEventType.class, appEventHandler);
|
|
|
-
|
|
|
- LocalDirsHandlerService dirsHandler = new LocalDirsHandlerService();
|
|
|
dirsHandler.init(conf);
|
|
|
|
|
|
- ApplicationId appId1 = BuilderUtils.newApplicationId(1234, 1);
|
|
|
- ApplicationAttemptId appAttemptId1 =
|
|
|
- BuilderUtils.newApplicationAttemptId(appId1, 1);
|
|
|
- ContainerId container11 = BuilderUtils.newContainerId(appAttemptId1, 1);
|
|
|
+ NonAggregatingLogHandler rawLogHandler =
|
|
|
+ new NonAggregatingLogHandler(dispatcher, mockDelService, dirsHandler);
|
|
|
+ NonAggregatingLogHandler logHandler = spy(rawLogHandler);
|
|
|
+ AbstractFileSystem spylfs =
|
|
|
+ spy(FileContext.getLocalFSFileContext().getDefaultFileSystem());
|
|
|
+ FileContext lfs = FileContext.getFileContext(spylfs, conf);
|
|
|
+ doReturn(lfs).when(logHandler)
|
|
|
+ .getLocalFileContext(isA(Configuration.class));
|
|
|
+ FsPermission defaultPermission =
|
|
|
+ FsPermission.getDirDefault().applyUMask(lfs.getUMask());
|
|
|
+ final FileStatus fs =
|
|
|
+ new FileStatus(0, true, 1, 0, System.currentTimeMillis(), 0,
|
|
|
+ defaultPermission, "", "",
|
|
|
+ new Path(localLogDirs[0].getAbsolutePath()));
|
|
|
+ doReturn(fs).when(spylfs).getFileStatus(isA(Path.class));
|
|
|
|
|
|
- NonAggregatingLogHandler logHandler =
|
|
|
- new NonAggregatingLogHandler(dispatcher, delService, dirsHandler);
|
|
|
logHandler.init(conf);
|
|
|
logHandler.start();
|
|
|
|
|
|
- logHandler.handle(new LogHandlerAppStartedEvent(appId1, user, null,
|
|
|
+ logHandler.handle(new LogHandlerAppStartedEvent(appId, user, null,
|
|
|
ContainerLogsRetentionPolicy.ALL_CONTAINERS, null));
|
|
|
|
|
|
logHandler.handle(new LogHandlerContainerFinishedEvent(container11, 0));
|
|
|
|
|
|
- logHandler.handle(new LogHandlerAppFinishedEvent(appId1));
|
|
|
+ logHandler.handle(new LogHandlerAppFinishedEvent(appId));
|
|
|
|
|
|
Path[] localAppLogDirs = new Path[2];
|
|
|
localAppLogDirs[0] =
|
|
|
- new Path(localLogDirs[0].getAbsolutePath(), appId1.toString());
|
|
|
+ new Path(localLogDirs[0].getAbsolutePath(), appId.toString());
|
|
|
localAppLogDirs[1] =
|
|
|
- new Path(localLogDirs[1].getAbsolutePath(), appId1.toString());
|
|
|
+ new Path(localLogDirs[1].getAbsolutePath(), appId.toString());
|
|
|
|
|
|
- // 5 seconds for the delete which is a separate thread.
|
|
|
- long verifyStartTime = System.currentTimeMillis();
|
|
|
- WantedButNotInvoked notInvokedException = null;
|
|
|
- boolean matched = false;
|
|
|
- while (!matched && System.currentTimeMillis() < verifyStartTime + 5000l) {
|
|
|
- try {
|
|
|
- verify(delService).delete(eq(user), (Path) eq(null),
|
|
|
- eq(localAppLogDirs[0]), eq(localAppLogDirs[1]));
|
|
|
- matched = true;
|
|
|
- } catch (WantedButNotInvoked e) {
|
|
|
- notInvokedException = e;
|
|
|
- try {
|
|
|
- Thread.sleep(50l);
|
|
|
- } catch (InterruptedException i) {
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (!matched) {
|
|
|
- throw notInvokedException;
|
|
|
+ testDeletionServiceCall(mockDelService, user, 5000, localAppLogDirs);
|
|
|
+ logHandler.close();
|
|
|
+ for (int i = 0; i < localLogDirs.length; i++) {
|
|
|
+ FileUtils.deleteDirectory(localLogDirs[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- public void testDelayedDelete() {
|
|
|
- DeletionService delService = mock(DeletionService.class);
|
|
|
- Configuration conf = new YarnConfiguration();
|
|
|
- String user = "testuser";
|
|
|
-
|
|
|
- File[] localLogDirs = new File[2];
|
|
|
- localLogDirs[0] =
|
|
|
- new File("target", this.getClass().getName() + "-localLogDir0")
|
|
|
- .getAbsoluteFile();
|
|
|
- localLogDirs[1] =
|
|
|
- new File("target", this.getClass().getName() + "-localLogDir1")
|
|
|
- .getAbsoluteFile();
|
|
|
+ public void testDelayedDelete() throws IOException {
|
|
|
+ File[] localLogDirs = getLocalLogDirFiles(this.getClass().getName(), 2);
|
|
|
String localLogDirsString =
|
|
|
localLogDirs[0].getAbsolutePath() + ","
|
|
|
+ localLogDirs[1].getAbsolutePath();
|
|
@@ -148,42 +174,36 @@ public class TestNonAggregatingLogHandler {
|
|
|
conf.setLong(YarnConfiguration.NM_LOG_RETAIN_SECONDS,
|
|
|
YarnConfiguration.DEFAULT_NM_LOG_RETAIN_SECONDS);
|
|
|
|
|
|
- DrainDispatcher dispatcher = createDispatcher(conf);
|
|
|
- EventHandler<ApplicationEvent> appEventHandler = mock(EventHandler.class);
|
|
|
- dispatcher.register(ApplicationEventType.class, appEventHandler);
|
|
|
-
|
|
|
- LocalDirsHandlerService dirsHandler = new LocalDirsHandlerService();
|
|
|
dirsHandler.init(conf);
|
|
|
|
|
|
- ApplicationId appId1 = BuilderUtils.newApplicationId(1234, 1);
|
|
|
- ApplicationAttemptId appAttemptId1 =
|
|
|
- BuilderUtils.newApplicationAttemptId(appId1, 1);
|
|
|
- ContainerId container11 = BuilderUtils.newContainerId(appAttemptId1, 1);
|
|
|
-
|
|
|
NonAggregatingLogHandler logHandler =
|
|
|
- new NonAggregatingLogHandlerWithMockExecutor(dispatcher, delService,
|
|
|
+ new NonAggregatingLogHandlerWithMockExecutor(dispatcher, mockDelService,
|
|
|
dirsHandler);
|
|
|
logHandler.init(conf);
|
|
|
logHandler.start();
|
|
|
|
|
|
- logHandler.handle(new LogHandlerAppStartedEvent(appId1, user, null,
|
|
|
+ logHandler.handle(new LogHandlerAppStartedEvent(appId, user, null,
|
|
|
ContainerLogsRetentionPolicy.ALL_CONTAINERS, null));
|
|
|
|
|
|
logHandler.handle(new LogHandlerContainerFinishedEvent(container11, 0));
|
|
|
|
|
|
- logHandler.handle(new LogHandlerAppFinishedEvent(appId1));
|
|
|
+ logHandler.handle(new LogHandlerAppFinishedEvent(appId));
|
|
|
|
|
|
Path[] localAppLogDirs = new Path[2];
|
|
|
localAppLogDirs[0] =
|
|
|
- new Path(localLogDirs[0].getAbsolutePath(), appId1.toString());
|
|
|
+ new Path(localLogDirs[0].getAbsolutePath(), appId.toString());
|
|
|
localAppLogDirs[1] =
|
|
|
- new Path(localLogDirs[1].getAbsolutePath(), appId1.toString());
|
|
|
+ new Path(localLogDirs[1].getAbsolutePath(), appId.toString());
|
|
|
|
|
|
ScheduledThreadPoolExecutor mockSched =
|
|
|
((NonAggregatingLogHandlerWithMockExecutor) logHandler).mockSched;
|
|
|
|
|
|
verify(mockSched).schedule(any(Runnable.class), eq(10800l),
|
|
|
eq(TimeUnit.SECONDS));
|
|
|
+ logHandler.close();
|
|
|
+ for (int i = 0; i < localLogDirs.length; i++) {
|
|
|
+ FileUtils.deleteDirectory(localLogDirs[i]);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -202,25 +222,25 @@ public class TestNonAggregatingLogHandler {
|
|
|
verify(logHandler.mockSched)
|
|
|
.awaitTermination(eq(10l), eq(TimeUnit.SECONDS));
|
|
|
verify(logHandler.mockSched).shutdownNow();
|
|
|
+ logHandler.close();
|
|
|
+ aggregatingLogHandler.close();
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testHandlingApplicationFinishedEvent() {
|
|
|
- Configuration conf = new Configuration();
|
|
|
- LocalDirsHandlerService dirsService = new LocalDirsHandlerService();
|
|
|
+ public void testHandlingApplicationFinishedEvent() throws IOException {
|
|
|
DeletionService delService = new DeletionService(null);
|
|
|
NonAggregatingLogHandler aggregatingLogHandler =
|
|
|
new NonAggregatingLogHandler(new InlineDispatcher(),
|
|
|
delService,
|
|
|
- dirsService);
|
|
|
+ dirsHandler);
|
|
|
|
|
|
- dirsService.init(conf);
|
|
|
- dirsService.start();
|
|
|
+ dirsHandler.init(conf);
|
|
|
+ dirsHandler.start();
|
|
|
delService.init(conf);
|
|
|
delService.start();
|
|
|
aggregatingLogHandler.init(conf);
|
|
|
aggregatingLogHandler.start();
|
|
|
- ApplicationId appId = BuilderUtils.newApplicationId(1234, 1);
|
|
|
+
|
|
|
// It should NOT throw RejectedExecutionException
|
|
|
aggregatingLogHandler.handle(new LogHandlerAppFinishedEvent(appId));
|
|
|
aggregatingLogHandler.stop();
|
|
@@ -228,6 +248,7 @@ public class TestNonAggregatingLogHandler {
|
|
|
// It should NOT throw RejectedExecutionException after stopping
|
|
|
// handler service.
|
|
|
aggregatingLogHandler.handle(new LogHandlerAppFinishedEvent(appId));
|
|
|
+ aggregatingLogHandler.close();
|
|
|
}
|
|
|
|
|
|
private class NonAggregatingLogHandlerWithMockExecutor extends
|
|
@@ -255,4 +276,201 @@ public class TestNonAggregatingLogHandler {
|
|
|
dispatcher.start();
|
|
|
return dispatcher;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Test to ensure that we handle the cleanup of directories that may not have
|
|
|
+ * the application log dirs we're trying to delete or may have other problems.
|
|
|
+ * Test creates 7 log dirs, and fails the directory check for 4 of them and
|
|
|
+ * then checks to ensure we tried to delete only the ones that passed the
|
|
|
+ * check.
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ public void testFailedDirLogDeletion() throws Exception {
|
|
|
+
|
|
|
+ File[] localLogDirs = getLocalLogDirFiles(this.getClass().getName(), 7);
|
|
|
+ final List<String> localLogDirPaths =
|
|
|
+ new ArrayList<String>(localLogDirs.length);
|
|
|
+ for (int i = 0; i < localLogDirs.length; i++) {
|
|
|
+ localLogDirPaths.add(localLogDirs[i].getAbsolutePath());
|
|
|
+ }
|
|
|
+
|
|
|
+ String localLogDirsString = StringUtils.join(localLogDirPaths, ",");
|
|
|
+
|
|
|
+ conf.set(YarnConfiguration.NM_LOG_DIRS, localLogDirsString);
|
|
|
+ conf.setBoolean(YarnConfiguration.LOG_AGGREGATION_ENABLED, false);
|
|
|
+ conf.setLong(YarnConfiguration.NM_LOG_RETAIN_SECONDS, 0l);
|
|
|
+
|
|
|
+ LocalDirsHandlerService mockDirsHandler = mock(LocalDirsHandlerService.class);
|
|
|
+
|
|
|
+ NonAggregatingLogHandler rawLogHandler =
|
|
|
+ new NonAggregatingLogHandler(dispatcher, mockDelService, mockDirsHandler);
|
|
|
+ NonAggregatingLogHandler logHandler = spy(rawLogHandler);
|
|
|
+ AbstractFileSystem spylfs =
|
|
|
+ spy(FileContext.getLocalFSFileContext().getDefaultFileSystem());
|
|
|
+ FileContext lfs = FileContext.getFileContext(spylfs, conf);
|
|
|
+ doReturn(lfs).when(logHandler)
|
|
|
+ .getLocalFileContext(isA(Configuration.class));
|
|
|
+ logHandler.init(conf);
|
|
|
+ logHandler.start();
|
|
|
+ runMockedFailedDirs(logHandler, appId, user, mockDelService,
|
|
|
+ mockDirsHandler, conf, spylfs, lfs, localLogDirs);
|
|
|
+ logHandler.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to run a log handler with directories failing the getFileStatus
|
|
|
+ * call. The function accepts the log handler, setup the mocks to fail with
|
|
|
+ * specific exceptions and ensures the deletion service has the correct calls.
|
|
|
+ *
|
|
|
+ * @param logHandler the logHandler implementation to test
|
|
|
+ *
|
|
|
+ * @param appId the application id that we wish when sending events to the log
|
|
|
+ * handler
|
|
|
+ *
|
|
|
+ * @param user the user name to use
|
|
|
+ *
|
|
|
+ * @param mockDelService a mock of the DeletionService which we will verify
|
|
|
+ * the delete calls against
|
|
|
+ *
|
|
|
+ * @param dirsHandler a spy or mock on the LocalDirsHandler service used to
|
|
|
+ * when creating the logHandler. It needs to be a spy so that we can intercept
|
|
|
+ * the getAllLogDirs() call.
|
|
|
+ *
|
|
|
+ * @param conf the configuration used
|
|
|
+ *
|
|
|
+ * @param spylfs a spy on the AbstractFileSystem object used when creating lfs
|
|
|
+ *
|
|
|
+ * @param lfs the FileContext object to be used to mock the getFileStatus()
|
|
|
+ * calls
|
|
|
+ *
|
|
|
+ * @param localLogDirs list of the log dirs to run the test against, must have
|
|
|
+ * at least 7 entries
|
|
|
+ */
|
|
|
+ public static void runMockedFailedDirs(LogHandler logHandler,
|
|
|
+ ApplicationId appId, String user, DeletionService mockDelService,
|
|
|
+ LocalDirsHandlerService dirsHandler, Configuration conf,
|
|
|
+ AbstractFileSystem spylfs, FileContext lfs, File[] localLogDirs)
|
|
|
+ throws Exception {
|
|
|
+ Map<ApplicationAccessType, String> appAcls = new HashMap<ApplicationAccessType, String>();
|
|
|
+ if (localLogDirs.length < 7) {
|
|
|
+ throw new IllegalArgumentException(
|
|
|
+ "Argument localLogDirs must be at least of length 7");
|
|
|
+ }
|
|
|
+ Path[] localAppLogDirPaths = new Path[localLogDirs.length];
|
|
|
+ for (int i = 0; i < localAppLogDirPaths.length; i++) {
|
|
|
+ localAppLogDirPaths[i] =
|
|
|
+ new Path(localLogDirs[i].getAbsolutePath(), appId.toString());
|
|
|
+ }
|
|
|
+ final List<String> localLogDirPaths =
|
|
|
+ new ArrayList<String>(localLogDirs.length);
|
|
|
+ for (int i = 0; i < localLogDirs.length; i++) {
|
|
|
+ localLogDirPaths.add(localLogDirs[i].getAbsolutePath());
|
|
|
+ }
|
|
|
+
|
|
|
+ // setup mocks
|
|
|
+ FsPermission defaultPermission =
|
|
|
+ FsPermission.getDirDefault().applyUMask(lfs.getUMask());
|
|
|
+ final FileStatus fs =
|
|
|
+ new FileStatus(0, true, 1, 0, System.currentTimeMillis(), 0,
|
|
|
+ defaultPermission, "", "",
|
|
|
+ new Path(localLogDirs[0].getAbsolutePath()));
|
|
|
+ doReturn(fs).when(spylfs).getFileStatus(isA(Path.class));
|
|
|
+ doReturn(localLogDirPaths).when(dirsHandler).getLogDirsForCleanup();
|
|
|
+
|
|
|
+ logHandler.handle(new LogHandlerAppStartedEvent(appId, user, null,
|
|
|
+ ContainerLogsRetentionPolicy.ALL_CONTAINERS, appAcls));
|
|
|
+
|
|
|
+ // test case where some dirs have the log dir to delete
|
|
|
+ // mock some dirs throwing various exceptions
|
|
|
+ // verify deletion happens only on the others
|
|
|
+ Mockito.doThrow(new FileNotFoundException()).when(spylfs)
|
|
|
+ .getFileStatus(eq(localAppLogDirPaths[0]));
|
|
|
+ doReturn(fs).when(spylfs).getFileStatus(eq(localAppLogDirPaths[1]));
|
|
|
+ Mockito.doThrow(new AccessControlException()).when(spylfs)
|
|
|
+ .getFileStatus(eq(localAppLogDirPaths[2]));
|
|
|
+ doReturn(fs).when(spylfs).getFileStatus(eq(localAppLogDirPaths[3]));
|
|
|
+ Mockito.doThrow(new IOException()).when(spylfs)
|
|
|
+ .getFileStatus(eq(localAppLogDirPaths[4]));
|
|
|
+ Mockito.doThrow(new UnsupportedFileSystemException("test")).when(spylfs)
|
|
|
+ .getFileStatus(eq(localAppLogDirPaths[5]));
|
|
|
+ doReturn(fs).when(spylfs).getFileStatus(eq(localAppLogDirPaths[6]));
|
|
|
+
|
|
|
+ logHandler.handle(new LogHandlerAppFinishedEvent(appId));
|
|
|
+
|
|
|
+ testDeletionServiceCall(mockDelService, user, 5000, localAppLogDirPaths[1],
|
|
|
+ localAppLogDirPaths[3], localAppLogDirPaths[6]);
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ static class DeletePathsMatcher extends ArgumentMatcher<Path[]> implements
|
|
|
+ VarargMatcher {
|
|
|
+
|
|
|
+ // to get rid of serialization warning
|
|
|
+ static final long serialVersionUID = 0;
|
|
|
+
|
|
|
+ private transient Path[] matchPaths;
|
|
|
+
|
|
|
+ DeletePathsMatcher(Path... matchPaths) {
|
|
|
+ this.matchPaths = matchPaths;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean matches(Object varargs) {
|
|
|
+ return new EqualsBuilder().append(matchPaths, varargs).isEquals();
|
|
|
+ }
|
|
|
+
|
|
|
+ // function to get rid of FindBugs warning
|
|
|
+ private void readObject(ObjectInputStream os) throws NotSerializableException {
|
|
|
+ throw new NotSerializableException(this.getClass().getName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Function to verify that the DeletionService object received the right
|
|
|
+ * requests.
|
|
|
+ *
|
|
|
+ * @param delService the DeletionService mock which we verify against
|
|
|
+ *
|
|
|
+ * @param user the user name to use when verifying the deletion
|
|
|
+ *
|
|
|
+ * @param timeout amount in milliseconds to wait before we decide the calls
|
|
|
+ * didn't come through
|
|
|
+ *
|
|
|
+ * @param matchPaths the paths to match in the delete calls
|
|
|
+ *
|
|
|
+ * @throws WantedButNotInvoked if the calls could not be verified
|
|
|
+ */
|
|
|
+ static void testDeletionServiceCall(DeletionService delService, String user,
|
|
|
+ long timeout, Path... matchPaths) {
|
|
|
+
|
|
|
+ long verifyStartTime = System.currentTimeMillis();
|
|
|
+ WantedButNotInvoked notInvokedException = null;
|
|
|
+ boolean matched = false;
|
|
|
+ while (!matched && System.currentTimeMillis() < verifyStartTime + timeout) {
|
|
|
+ try {
|
|
|
+ verify(delService).delete(eq(user), (Path) eq(null),
|
|
|
+ Mockito.argThat(new DeletePathsMatcher(matchPaths)));
|
|
|
+ matched = true;
|
|
|
+ } catch (WantedButNotInvoked e) {
|
|
|
+ notInvokedException = e;
|
|
|
+ try {
|
|
|
+ Thread.sleep(50l);
|
|
|
+ } catch (InterruptedException i) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!matched) {
|
|
|
+ throw notInvokedException;
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static File[] getLocalLogDirFiles(String name, int number) {
|
|
|
+ File[] dirs = new File[number];
|
|
|
+ for (int i = 0; i < dirs.length; i++) {
|
|
|
+ dirs[i] = new File("target", name + "-localLogDir" + i).getAbsoluteFile();
|
|
|
+ }
|
|
|
+ return dirs;
|
|
|
+ }
|
|
|
}
|