blob: faae878a43deeceb06783bf1859a66d099a87a6b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.io.monitor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Iterator;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.CanReadFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.junit.jupiter.api.Test;
/**
* {@link FileAlterationObserver} Test Case.
*/
public class FileAlterationObserverTest extends AbstractMonitorTest {
/**
* Constructs a new instance.
*/
public FileAlterationObserverTest() {
listener = new CollectionFileListener(true);
}
/**
* Call {@link FileAlterationObserver#checkAndNotify()}.
*/
protected void checkAndNotify() {
observer.checkAndNotify();
}
/**
* Test add/remove listeners.
*/
@Test
public void testAddRemoveListeners() {
final FileAlterationObserver observer = new FileAlterationObserver("/foo");
// Null Listener
observer.addListener(null);
assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[1]");
observer.removeListener(null);
assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[2]");
// Add Listener
final FileAlterationListenerAdaptor listener = new FileAlterationListenerAdaptor();
observer.addListener(listener);
final Iterator<FileAlterationListener> it = observer.getListeners().iterator();
assertTrue(it.hasNext(), "Listeners[3]");
assertEquals(listener, it.next(), "Added");
assertFalse(it.hasNext(), "Listeners[4]");
// Remove Listener
observer.removeListener(listener);
assertFalse(observer.getListeners().iterator().hasNext(), "Listeners[5]");
}
/**
* Test checkAndNotify() method
* @throws Exception
*/
@Test
public void testDirectory() throws Exception {
checkAndNotify();
checkCollectionsEmpty("A");
final File testDirA = new File(testDir, "test-dir-A");
final File testDirB = new File(testDir, "test-dir-B");
final File testDirC = new File(testDir, "test-dir-C");
testDirA.mkdir();
testDirB.mkdir();
testDirC.mkdir();
final File testDirAFile1 = touch(new File(testDirA, "A-file1.java"));
final File testDirAFile2 = touch(new File(testDirA, "A-file2.txt")); // filter should ignore this
final File testDirAFile3 = touch(new File(testDirA, "A-file3.java"));
File testDirAFile4 = touch(new File(testDirA, "A-file4.java"));
final File testDirBFile1 = touch(new File(testDirB, "B-file1.java"));
checkAndNotify();
checkCollectionSizes("B", 3, 0, 0, 4, 0, 0);
assertTrue(listener.getCreatedDirectories().contains(testDirA), "B testDirA");
assertTrue(listener.getCreatedDirectories().contains(testDirB), "B testDirB");
assertTrue(listener.getCreatedDirectories().contains(testDirC), "B testDirC");
assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1");
assertFalse(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2");
assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3");
assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4");
assertTrue(listener.getCreatedFiles().contains(testDirBFile1), "B testDirBFile1");
checkAndNotify();
checkCollectionsEmpty("C");
testDirAFile4 = touch(testDirAFile4);
FileUtils.deleteDirectory(testDirB);
checkAndNotify();
checkCollectionSizes("D", 0, 0, 1, 0, 1, 1);
assertTrue(listener.getDeletedDirectories().contains(testDirB), "D testDirB");
assertTrue(listener.getChangedFiles().contains(testDirAFile4), "D testDirAFile4");
assertTrue(listener.getDeletedFiles().contains(testDirBFile1), "D testDirBFile1");
FileUtils.deleteDirectory(testDir);
checkAndNotify();
checkCollectionSizes("E", 0, 0, 2, 0, 0, 3);
assertTrue(listener.getDeletedDirectories().contains(testDirA), "E testDirA");
assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "E testDirAFile1");
assertFalse(listener.getDeletedFiles().contains(testDirAFile2), "E testDirAFile2");
assertTrue(listener.getDeletedFiles().contains(testDirAFile3), "E testDirAFile3");
assertTrue(listener.getDeletedFiles().contains(testDirAFile4), "E testDirAFile4");
testDir.mkdir();
checkAndNotify();
checkCollectionsEmpty("F");
checkAndNotify();
checkCollectionsEmpty("G");
}
/**
* Test checkAndNotify() creating
* @throws IOException if an I/O error occurs.
*/
@Test
public void testFileCreate() throws IOException {
checkAndNotify();
checkCollectionsEmpty("A");
File testDirA = new File(testDir, "test-dir-A");
testDirA.mkdir();
testDir = touch(testDir);
testDirA = touch(testDirA);
File testDirAFile1 = new File(testDirA, "A-file1.java");
final File testDirAFile2 = touch(new File(testDirA, "A-file2.java"));
File testDirAFile3 = new File(testDirA, "A-file3.java");
final File testDirAFile4 = touch(new File(testDirA, "A-file4.java"));
File testDirAFile5 = new File(testDirA, "A-file5.java");
checkAndNotify();
checkCollectionSizes("B", 1, 0, 0, 2, 0, 0);
assertFalse(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1");
assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2");
assertFalse(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3");
assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4");
assertFalse(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5");
assertFalse(testDirAFile1.exists(), "B testDirAFile1 exists");
assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists");
assertFalse(testDirAFile3.exists(), "B testDirAFile3 exists");
assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists");
assertFalse(testDirAFile5.exists(), "B testDirAFile5 exists");
checkAndNotify();
checkCollectionsEmpty("C");
// Create file with name < first entry
testDirAFile1 = touch(testDirAFile1);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("D", 0, 1, 0, 1, 0, 0);
assertTrue(testDirAFile1.exists(), "D testDirAFile1 exists");
assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "D testDirAFile1");
// Create file with name between 2 entries
testDirAFile3 = touch(testDirAFile3);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("E", 0, 1, 0, 1, 0, 0);
assertTrue(testDirAFile3.exists(), "E testDirAFile3 exists");
assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "E testDirAFile3");
// Create file with name > last entry
testDirAFile5 = touch(testDirAFile5);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("F", 0, 1, 0, 1, 0, 0);
assertTrue(testDirAFile5.exists(), "F testDirAFile5 exists");
assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "F testDirAFile5");
}
/**
* Test checkAndNotify() deleting
* @throws IOException if an I/O error occurs.
*/
@Test
public void testFileDelete() throws IOException {
checkAndNotify();
checkCollectionsEmpty("A");
File testDirA = new File(testDir, "test-dir-A");
testDirA.mkdir();
testDir = touch(testDir);
testDirA = touch(testDirA);
final File testDirAFile1 = touch(new File(testDirA, "A-file1.java"));
final File testDirAFile2 = touch(new File(testDirA, "A-file2.java"));
final File testDirAFile3 = touch(new File(testDirA, "A-file3.java"));
final File testDirAFile4 = touch(new File(testDirA, "A-file4.java"));
final File testDirAFile5 = touch(new File(testDirA, "A-file5.java"));
assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists");
assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists");
assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists");
assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists");
assertTrue(testDirAFile5.exists(), "B testDirAFile5 exists");
checkAndNotify();
checkCollectionSizes("B", 1, 0, 0, 5, 0, 0);
assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1");
assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2");
assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3");
assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4");
assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5");
checkAndNotify();
checkCollectionsEmpty("C");
// Delete first entry
FileUtils.deleteQuietly(testDirAFile1);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("D", 0, 1, 0, 0, 0, 1);
assertFalse(testDirAFile1.exists(), "D testDirAFile1 exists");
assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "D testDirAFile1");
// Delete file with name between 2 entries
FileUtils.deleteQuietly(testDirAFile3);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("E", 0, 1, 0, 0, 0, 1);
assertFalse(testDirAFile3.exists(), "E testDirAFile3 exists");
assertTrue(listener.getDeletedFiles().contains(testDirAFile3), "E testDirAFile3");
// Delete last entry
FileUtils.deleteQuietly(testDirAFile5);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("F", 0, 1, 0, 0, 0, 1);
assertFalse(testDirAFile5.exists(), "F testDirAFile5 exists");
assertTrue(listener.getDeletedFiles().contains(testDirAFile5), "F testDirAFile5");
}
/**
* Test checkAndNotify() creating
* @throws IOException if an I/O error occurs.
*/
@Test
public void testFileUpdate() throws IOException {
checkAndNotify();
checkCollectionsEmpty("A");
File testDirA = new File(testDir, "test-dir-A");
testDirA.mkdir();
testDir = touch(testDir);
testDirA = touch(testDirA);
File testDirAFile1 = touch(new File(testDirA, "A-file1.java"));
final File testDirAFile2 = touch(new File(testDirA, "A-file2.java"));
File testDirAFile3 = touch(new File(testDirA, "A-file3.java"));
final File testDirAFile4 = touch(new File(testDirA, "A-file4.java"));
File testDirAFile5 = touch(new File(testDirA, "A-file5.java"));
checkAndNotify();
checkCollectionSizes("B", 1, 0, 0, 5, 0, 0);
assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "B testDirAFile1");
assertTrue(listener.getCreatedFiles().contains(testDirAFile2), "B testDirAFile2");
assertTrue(listener.getCreatedFiles().contains(testDirAFile3), "B testDirAFile3");
assertTrue(listener.getCreatedFiles().contains(testDirAFile4), "B testDirAFile4");
assertTrue(listener.getCreatedFiles().contains(testDirAFile5), "B testDirAFile5");
assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists");
assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists");
assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists");
assertTrue(testDirAFile4.exists(), "B testDirAFile4 exists");
assertTrue(testDirAFile5.exists(), "B testDirAFile5 exists");
checkAndNotify();
checkCollectionsEmpty("C");
// Update first entry
testDirAFile1 = touch(testDirAFile1);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("D", 0, 1, 0, 0, 1, 0);
assertTrue(listener.getChangedFiles().contains(testDirAFile1), "D testDirAFile1");
// Update file with name between 2 entries
testDirAFile3 = touch(testDirAFile3);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("E", 0, 1, 0, 0, 1, 0);
assertTrue(listener.getChangedFiles().contains(testDirAFile3), "E testDirAFile3");
// Update last entry
testDirAFile5 = touch(testDirAFile5);
testDirA = touch(testDirA);
checkAndNotify();
checkCollectionSizes("F", 0, 1, 0, 0, 1, 0);
assertTrue(listener.getChangedFiles().contains(testDirAFile5), "F testDirAFile5");
}
/**
* Test checkAndNotify() method
* @throws IOException if an I/O error occurs.
*/
@Test
public void testObserveSingleFile() throws IOException {
final File testDirA = new File(testDir, "test-dir-A");
File testDirAFile1 = new File(testDirA, "A-file1.java");
testDirA.mkdir();
final FileFilter nameFilter = FileFilterUtils.nameFileFilter(testDirAFile1.getName());
createObserver(testDirA, nameFilter);
checkAndNotify();
checkCollectionsEmpty("A");
assertFalse(testDirAFile1.exists(), "A testDirAFile1 exists");
// Create
testDirAFile1 = touch(testDirAFile1);
File testDirAFile2 = touch(new File(testDirA, "A-file2.txt")); /* filter should ignore */
File testDirAFile3 = touch(new File(testDirA, "A-file3.java")); /* filter should ignore */
assertTrue(testDirAFile1.exists(), "B testDirAFile1 exists");
assertTrue(testDirAFile2.exists(), "B testDirAFile2 exists");
assertTrue(testDirAFile3.exists(), "B testDirAFile3 exists");
checkAndNotify();
checkCollectionSizes("C", 0, 0, 0, 1, 0, 0);
assertTrue(listener.getCreatedFiles().contains(testDirAFile1), "C created");
assertFalse(listener.getCreatedFiles().contains(testDirAFile2), "C created");
assertFalse(listener.getCreatedFiles().contains(testDirAFile3), "C created");
// Modify
testDirAFile1 = touch(testDirAFile1);
testDirAFile2 = touch(testDirAFile2);
testDirAFile3 = touch(testDirAFile3);
checkAndNotify();
checkCollectionSizes("D", 0, 0, 0, 0, 1, 0);
assertTrue(listener.getChangedFiles().contains(testDirAFile1), "D changed");
assertFalse(listener.getChangedFiles().contains(testDirAFile2), "D changed");
assertFalse(listener.getChangedFiles().contains(testDirAFile3), "D changed");
// Delete
FileUtils.deleteQuietly(testDirAFile1);
FileUtils.deleteQuietly(testDirAFile2);
FileUtils.deleteQuietly(testDirAFile3);
assertFalse(testDirAFile1.exists(), "E testDirAFile1 exists");
assertFalse(testDirAFile2.exists(), "E testDirAFile2 exists");
assertFalse(testDirAFile3.exists(), "E testDirAFile3 exists");
checkAndNotify();
checkCollectionSizes("E", 0, 0, 0, 0, 0, 1);
assertTrue(listener.getDeletedFiles().contains(testDirAFile1), "E deleted");
assertFalse(listener.getDeletedFiles().contains(testDirAFile2), "E deleted");
assertFalse(listener.getDeletedFiles().contains(testDirAFile3), "E deleted");
}
/**
* Test toString().
*/
@Test
public void testToString() {
final File file = new File("/foo");
FileAlterationObserver observer = new FileAlterationObserver(file);
assertEquals("FileAlterationObserver[file='" + file.getPath() + "', true, listeners=0]", observer.toString());
observer = new FileAlterationObserver(file, CanReadFileFilter.CAN_READ);
assertEquals("FileAlterationObserver[file='" + file.getPath() + "', CanReadFileFilter, listeners=0]", observer.toString());
assertEquals(file, observer.getDirectory());
}
}