/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.vfs.watcher;
import org.junit.After;
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 java.io.File;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
import static java.io.File.createTempFile;
import static java.lang.Thread.sleep;
import static org.apache.commons.io.FileUtils.write;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link FileTreeWalker}
*/
@SuppressWarnings({"WeakerAccess", "ResultOfMethodCallIgnored"})
@RunWith(MockitoJUnitRunner.class)
public class FileTreeWalkerTest {
static final int FS_LATENCY_DELAY = 1_000;
static final String TEST_FILE_NAME = "test-file-name";
static final String TEST_FILE_CONTENT = "test-file-content";
static final String TEST_FOLDER_NAME = "test-folder-name";
@Rule
public TemporaryFolder rootFolder = new TemporaryFolder();
FileTreeWalker fileTreeWalker;
Set<Consumer<Path>> directoryCreateConsumers = new HashSet<>();
Set<Consumer<Path>> directoryUpdateConsumers = new HashSet<>();
Set<Consumer<Path>> directoryDeleteConsumers = new HashSet<>();
Set<PathMatcher> directoryExcludes = new HashSet<>();
Set<Consumer<Path>> fileCreateConsumers = new HashSet<>();
Set<Consumer<Path>> fileUpdateConsumers = new HashSet<>();
Set<Consumer<Path>> fileDeleteConsumers = new HashSet<>();
Set<PathMatcher> fileExcludes = new HashSet<>();
@Mock
Consumer<Path> fileCreatedConsumerMock;
@Mock
Consumer<Path> fileUpdateConsumerMock;
@Mock
Consumer<Path> fileDeleteConsumerMock;
@Mock
Consumer<Path> directoryCreatedConsumerMock;
@Mock
Consumer<Path> directoryUpdateConsumerMock;
@Mock
Consumer<Path> directoryDeleteConsumerMock;
@Before
public void setUp() throws Exception {
fileTreeWalker = new FileTreeWalker(rootFolder.getRoot(),
directoryUpdateConsumers,
directoryCreateConsumers,
directoryDeleteConsumers,
directoryExcludes,
fileUpdateConsumers,
fileCreateConsumers,
fileDeleteConsumers,
fileExcludes);
}
@After
public void tearDown() throws Exception {
directoryUpdateConsumers.clear();
directoryCreateConsumers.clear();
directoryDeleteConsumers.clear();
directoryExcludes.clear();
fileUpdateConsumers.clear();
fileCreateConsumers.clear();
fileDeleteConsumers.clear();
fileExcludes.clear();
}
@Test
public void shouldRunFileCreatedConsumer() throws Exception {
fileCreateConsumers.add(fileCreatedConsumerMock);
File file = rootFolder.newFile(TEST_FILE_NAME);
fileTreeWalker.walk();
verify(fileCreatedConsumerMock).accept(file.toPath());
}
@Test
public void shouldRunFileUpdateConsumer() throws Exception {
fileUpdateConsumers.add(fileUpdateConsumerMock);
File file = rootFolder.newFile(TEST_FILE_NAME);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
write(file, TEST_FILE_CONTENT);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
verify(fileUpdateConsumerMock).accept(file.toPath());
}
@Test
public void shouldRunFileDeleteConsumer() throws Exception {
fileDeleteConsumers.add(fileDeleteConsumerMock);
File file = rootFolder.newFile(TEST_FILE_NAME);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
file.delete();
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
verify(fileDeleteConsumerMock).accept(file.toPath());
}
@Test
public void shouldRunDirectoryCreatedConsumer() throws Exception {
directoryCreateConsumers.add(directoryCreatedConsumerMock);
File file = rootFolder.newFolder(TEST_FOLDER_NAME);
fileTreeWalker.walk();
verify(directoryCreatedConsumerMock).accept(file.toPath());
}
@Test
public void shouldRunDirectoryUpdateConsumer() throws Exception {
directoryUpdateConsumers.add(directoryUpdateConsumerMock);
File file = rootFolder.newFolder(TEST_FOLDER_NAME);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
createTempFile(TEST_FILE_NAME, "", file);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
verify(directoryUpdateConsumerMock).accept(file.toPath());
}
@Test
public void shouldRunDirectoryDeleteConsumer() throws Exception {
directoryDeleteConsumers.add(directoryDeleteConsumerMock);
File file = rootFolder.newFolder(TEST_FOLDER_NAME);
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
file.delete();
sleep(FS_LATENCY_DELAY);
fileTreeWalker.walk();
verify(directoryDeleteConsumerMock).accept(file.toPath());
}
@Test
public void shouldProperlySkipExcludedFile() throws Exception {
fileExcludes.add(it-> it.getFileName().toString().equals(TEST_FILE_NAME));
fileCreateConsumers.add(fileCreatedConsumerMock);
File file = rootFolder.newFile(TEST_FILE_NAME);
fileTreeWalker.walk();
verify(fileCreatedConsumerMock, never()).accept(file.toPath());
}
@Test
public void shouldProperlySkipExcludedDirectory() throws Exception {
directoryExcludes.add(it-> it.getFileName().toString().equals(TEST_FOLDER_NAME));
directoryCreateConsumers.add(directoryCreatedConsumerMock);
File file = rootFolder.newFolder(TEST_FOLDER_NAME);
fileTreeWalker.walk();
verify(directoryCreatedConsumerMock, never()).accept(file.toPath());
}
}