/*
* Syncany, www.syncany.org
* Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.syncany.tests.integration.operations;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Test;
import org.syncany.config.Logging;
import org.syncany.operations.watch.DefaultRecursiveWatcher;
import org.syncany.operations.watch.RecursiveWatcher.WatchListener;
import org.syncany.tests.unit.util.TestFileUtil;
public class RecursiveWatcherTest {
static {
Logging.init();
}
@Test
public void testWatchOneFile() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
TestFileUtil.createRandomFilesInDirectory(tempDir, 50*1024, 20);
// Test
final AtomicBoolean eventOccurred = new AtomicBoolean(false);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
eventOccurred.set(true);
}
});
// Start watcher and wait for watch service to set watch on all folders
watcher.start();
Thread.sleep(100);
// Event 1
TestFileUtil.createRandomFileInDirectory(tempDir, 10);
assertFalse(eventOccurred.get());
Thread.sleep(550);
assertTrue(eventOccurred.get());
// Stop watcher (close watches)
watcher.stop();
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
@Test
public void testWatchExistingSubfolderEvent() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
File subDir1 = new File(tempDir+"/subdir1");
// Test
final AtomicBoolean eventOccurred = new AtomicBoolean(false);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
eventOccurred.set(true);
}
});
// Create sub folder BEFORE watcher starts
subDir1.mkdir();
// Start watcher and wait for watch service to set watch on all folders
watcher.start();
Thread.sleep(100);
// Event 1
TestFileUtil.createRandomFileInDirectory(subDir1, 10);
assertFalse(eventOccurred.get());
Thread.sleep(350);
assertTrue(eventOccurred.get());
// Stop watcher (close watches)
watcher.stop();
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
@Test
public void testWatchNewSubfolderEvent() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
File subDir1 = new File(tempDir+"/subdir1");
// Test
final AtomicBoolean eventOccurred = new AtomicBoolean(false);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
eventOccurred.set(true);
}
});
// Start watcher and wait for watch service to set watch on all folders
watcher.start();
Thread.sleep(150);
// Create sub folder AFTER watcher starts
subDir1.mkdir();
Thread.sleep(370);
assertTrue(eventOccurred.get());
eventOccurred.set(false);
// Event on NEW subfolder
TestFileUtil.createRandomFileInDirectory(subDir1, 10);
assertFalse(eventOccurred.get());
Thread.sleep(350);
assertTrue(eventOccurred.get());
// Stop watcher (close watches)
watcher.stop();
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
@Test
public void testWatch100LevelsOfNewSubfolders() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
// Test
final AtomicBoolean eventOccurred = new AtomicBoolean(false);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
eventOccurred.set(true);
}
});
// Start watcher and wait for watch service to set watch on all folders
watcher.start();
Thread.sleep(100);
// Create sub folder hierarchy
File lastSubFolder = tempDir;
for (int i=0; i<100; i++) {
lastSubFolder.mkdir();
lastSubFolder = new File(lastSubFolder+"/"+i);
}
lastSubFolder.mkdir();
// Wait for settlement
Thread.sleep(350);
eventOccurred.set(false);
// Event on DEEPEST new subfolder
TestFileUtil.createRandomFileInDirectory(lastSubFolder, 10*1024);
assertFalse(eventOccurred.get());
Thread.sleep(500);
assertTrue(eventOccurred.get());
// Stop watcher (close watches)
watcher.stop();
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
@Test
public void testWatchFireOnceWhenLargeFileFinishes() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
// Test
final AtomicLong watcherEventOccurredTime = new AtomicLong(0L);
final AtomicInteger watcherEventOccurredCount = new AtomicInteger(0);
final AtomicLong fileWrittenTime = new AtomicLong(0L);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
watcherEventOccurredCount.addAndGet(1);
watcherEventOccurredTime.set(System.currentTimeMillis());
}
});
// Start watcher
watcher.start();
Thread.sleep(400); // Wait for watch service to set watch on all folders
File largeFile = new File(tempDir+"/largefile");
TestFileUtil.createRandomFile(largeFile, 50*1024*1024);
fileWrittenTime.set(System.currentTimeMillis());
// Stop watcher (close watches)
Thread.sleep(800); // Wait for the watcher to fire an event
watcher.stop();
// Test
assertNotSame(0L, watcherEventOccurredTime.get());
assertEquals(1, watcherEventOccurredCount.get());
assertNotSame(0L, fileWrittenTime.get());
assertTrue(watcherEventOccurredTime.get() >= fileWrittenTime.get());
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
@Test
public void testWatchFireEventCount() throws Exception {
// Setup
File tempDir = TestFileUtil.createTempDirectoryInSystemTemp();
// Test
final AtomicInteger watcherEventOccurredCount = new AtomicInteger(0);
DefaultRecursiveWatcher watcher = new DefaultRecursiveWatcher(Paths.get(tempDir.getAbsolutePath()), new ArrayList<Path>(), 300, new WatchListener() {
@Override
public void watchEventsOccurred() {
watcherEventOccurredCount.addAndGet(1);
}
});
// Start watcher
watcher.start();
Thread.sleep(200); // Wait for watch service to set watch on all folders
for (int i=0; i<20; i++) {
TestFileUtil.createRandomFile(new File(tempDir+"/"+i), 50*1024);
}
// Stop watcher (close watches)
Thread.sleep(400); // Wait for the watcher to fire an event
watcher.stop();
// Test
assertEquals(1, watcherEventOccurredCount.get()); // not 20!
// Tear down
TestFileUtil.deleteDirectory(tempDir);
}
}