mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Changed drive monitors to use callbacks rather than blocking.
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.api.transport.batch;
|
package net.sf.briar.api.transport.batch;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.TransportId;
|
||||||
import net.sf.briar.api.transport.TransportCallback;
|
import net.sf.briar.api.transport.TransportCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,7 +10,9 @@ import net.sf.briar.api.transport.TransportCallback;
|
|||||||
*/
|
*/
|
||||||
public interface BatchTransportCallback extends TransportCallback {
|
public interface BatchTransportCallback extends TransportCallback {
|
||||||
|
|
||||||
void readerCreated(BatchTransportReader r);
|
void readerCreated(ContactId contactId, byte[] encryptedIv,
|
||||||
|
BatchTransportReader r);
|
||||||
|
|
||||||
void writerCreated(BatchTransportWriter w);
|
void writerCreated(ContactId contactId, TransportId t, long connection,
|
||||||
|
BatchTransportWriter w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.api.transport.batch;
|
package net.sf.briar.api.transport.batch;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
@@ -23,13 +24,13 @@ public interface BatchTransportPlugin {
|
|||||||
void start(Map<String, String> localProperties,
|
void start(Map<String, String> localProperties,
|
||||||
Map<ContactId, Map<String, String>> remoteProperties,
|
Map<ContactId, Map<String, String>> remoteProperties,
|
||||||
Map<String, String> config, BatchTransportCallback c)
|
Map<String, String> config, BatchTransportCallback c)
|
||||||
throws InvalidTransportException, InvalidConfigException;
|
throws InvalidTransportException, InvalidConfigException, IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the plugin. No further connections will be passed to the callback
|
* Stops the plugin. No further connections will be passed to the callback
|
||||||
* after this method has returned.
|
* after this method has returned.
|
||||||
*/
|
*/
|
||||||
void stop();
|
void stop() throws IOException;
|
||||||
|
|
||||||
/** Updates the plugin's local transport properties. */
|
/** Updates the plugin's local transport properties. */
|
||||||
void setLocalProperties(Map<String, String> properties)
|
void setLocalProperties(Map<String, String> properties)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.api.transport.stream;
|
package net.sf.briar.api.transport.stream;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.TransportId;
|
||||||
import net.sf.briar.api.transport.TransportCallback;
|
import net.sf.briar.api.transport.TransportCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,5 +10,9 @@ import net.sf.briar.api.transport.TransportCallback;
|
|||||||
*/
|
*/
|
||||||
public interface StreamTransportCallback extends TransportCallback {
|
public interface StreamTransportCallback extends TransportCallback {
|
||||||
|
|
||||||
void connectionCreated(StreamTransportConnection c);
|
void incomingConnectionCreated(ContactId contactId, byte[] encryptedIv,
|
||||||
|
StreamTransportConnection c);
|
||||||
|
|
||||||
|
void outgoingConnectionCreated(ContactId contactId, TransportId t,
|
||||||
|
long connection, StreamTransportConnection c);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package net.sf.briar.plugins.file;
|
package net.sf.briar.plugins.file;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.db.DbException;
|
||||||
|
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||||
import net.sf.briar.api.transport.InvalidConfigException;
|
import net.sf.briar.api.transport.InvalidConfigException;
|
||||||
import net.sf.briar.api.transport.InvalidTransportException;
|
import net.sf.briar.api.transport.InvalidTransportException;
|
||||||
import net.sf.briar.api.transport.TransportConstants;
|
import net.sf.briar.api.transport.TransportConstants;
|
||||||
@@ -19,6 +22,8 @@ import org.apache.commons.io.FileSystemUtils;
|
|||||||
|
|
||||||
abstract class FilePlugin implements BatchTransportPlugin {
|
abstract class FilePlugin implements BatchTransportPlugin {
|
||||||
|
|
||||||
|
private final ConnectionRecogniser recogniser;
|
||||||
|
|
||||||
protected Map<String, String> localProperties = null;
|
protected Map<String, String> localProperties = null;
|
||||||
protected Map<ContactId, Map<String, String>> remoteProperties = null;
|
protected Map<ContactId, Map<String, String>> remoteProperties = null;
|
||||||
protected Map<String, String> config = null;
|
protected Map<String, String> config = null;
|
||||||
@@ -28,10 +33,14 @@ abstract class FilePlugin implements BatchTransportPlugin {
|
|||||||
protected abstract File chooseOutputDirectory();
|
protected abstract File chooseOutputDirectory();
|
||||||
protected abstract void writerFinished(File f);
|
protected abstract void writerFinished(File f);
|
||||||
|
|
||||||
|
FilePlugin(ConnectionRecogniser recogniser) {
|
||||||
|
this.recogniser = recogniser;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void start(Map<String, String> localProperties,
|
public synchronized void start(Map<String, String> localProperties,
|
||||||
Map<ContactId, Map<String, String>> remoteProperties,
|
Map<ContactId, Map<String, String>> remoteProperties,
|
||||||
Map<String, String> config, BatchTransportCallback callback)
|
Map<String, String> config, BatchTransportCallback callback)
|
||||||
throws InvalidTransportException, InvalidConfigException {
|
throws InvalidTransportException, InvalidConfigException, IOException {
|
||||||
if(started) throw new IllegalStateException();
|
if(started) throw new IllegalStateException();
|
||||||
started = true;
|
started = true;
|
||||||
this.localProperties = localProperties;
|
this.localProperties = localProperties;
|
||||||
@@ -40,7 +49,7 @@ abstract class FilePlugin implements BatchTransportPlugin {
|
|||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stop() {
|
public synchronized void stop() throws IOException {
|
||||||
if(!started) throw new IllegalStateException();
|
if(!started) throw new IllegalStateException();
|
||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
@@ -106,4 +115,37 @@ abstract class FilePlugin implements BatchTransportPlugin {
|
|||||||
protected long getCapacity(String path) throws IOException {
|
protected long getCapacity(String path) throws IOException {
|
||||||
return FileSystemUtils.freeSpaceKb(path) * 1024L;
|
return FileSystemUtils.freeSpaceKb(path) * 1024L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void createReaderFromFile(File f) {
|
||||||
|
if(!isPossibleConnectionFilename(f.getName())) return;
|
||||||
|
if(f.length() < TransportConstants.MIN_CONNECTION_LENGTH) return;
|
||||||
|
try {
|
||||||
|
FileInputStream in = new FileInputStream(f);
|
||||||
|
byte[] iv = new byte[TransportConstants.IV_LENGTH];
|
||||||
|
int offset = 0;
|
||||||
|
while(offset < iv.length) {
|
||||||
|
int read = in.read(iv, offset, iv.length - offset);
|
||||||
|
if(read == -1) break;
|
||||||
|
offset += read;
|
||||||
|
}
|
||||||
|
ContactId c = recogniser.acceptConnection(iv);
|
||||||
|
if(c == null) {
|
||||||
|
// Nobody there
|
||||||
|
in.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileTransportReader reader = new FileTransportReader(f, in);
|
||||||
|
callback.readerCreated(c, iv, reader);
|
||||||
|
} catch(DbException e) {
|
||||||
|
// FIXME: At least log it
|
||||||
|
return;
|
||||||
|
} catch(IOException e) {
|
||||||
|
// FIXME: At least log it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPossibleConnectionFilename(String filename) {
|
||||||
|
return filename.toLowerCase().matches("[a-z]{8}\\.dat");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.sf.briar.plugins.file;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.sf.briar.api.transport.batch.BatchTransportReader;
|
||||||
|
|
||||||
|
class FileTransportReader implements BatchTransportReader {
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
private final InputStream in;
|
||||||
|
|
||||||
|
private boolean streamInUse = false;
|
||||||
|
|
||||||
|
FileTransportReader(File file, InputStream in) {
|
||||||
|
this.file = file;
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
streamInUse = true;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() throws IOException {
|
||||||
|
if(streamInUse) in.close();
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,52 +2,39 @@ package net.sf.briar.plugins.file;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
|
class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
|
||||||
|
|
||||||
private final RemovableDriveFinder finder;
|
private final RemovableDriveFinder finder;
|
||||||
private final long pollingInterval;
|
private final long pollingInterval;
|
||||||
private final LinkedList<File> inserted;
|
private final Object pollingLock = new Object();
|
||||||
private final LinkedList<IOException> exceptions;
|
|
||||||
private final Object pollingLock;
|
|
||||||
|
|
||||||
private boolean started = false, stopped = false;
|
private volatile boolean running = false;
|
||||||
private Thread pollingThread = null;
|
private volatile Callback callback = null;
|
||||||
|
private volatile IOException exception = null;
|
||||||
|
|
||||||
public PollingRemovableDriveMonitor(RemovableDriveFinder finder,
|
public PollingRemovableDriveMonitor(RemovableDriveFinder finder,
|
||||||
long pollingInterval) {
|
long pollingInterval) {
|
||||||
this.finder = finder;
|
this.finder = finder;
|
||||||
this.pollingInterval = pollingInterval;
|
this.pollingInterval = pollingInterval;
|
||||||
inserted = new LinkedList<File>();
|
|
||||||
exceptions = new LinkedList<IOException>();
|
|
||||||
pollingLock = new Object();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start() throws IOException {
|
public synchronized void start(Callback callback) throws IOException {
|
||||||
if(started || stopped) throw new IllegalStateException();
|
if(running) throw new IllegalStateException();
|
||||||
started = true;
|
running = true;
|
||||||
pollingThread = new Thread(this);
|
this.callback = callback;
|
||||||
pollingThread.start();
|
new Thread(this).start();
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized File waitForInsertion() throws IOException {
|
|
||||||
if(!started || stopped) throw new IllegalStateException();
|
|
||||||
if(!exceptions.isEmpty()) throw exceptions.poll();
|
|
||||||
while(inserted.isEmpty()) {
|
|
||||||
try {
|
|
||||||
wait();
|
|
||||||
} catch(InterruptedException ignored) {}
|
|
||||||
if(!exceptions.isEmpty()) throw exceptions.poll();
|
|
||||||
}
|
|
||||||
return inserted.poll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stop() throws IOException {
|
public synchronized void stop() throws IOException {
|
||||||
if(!started || stopped) throw new IllegalStateException();
|
if(!running) throw new IllegalStateException();
|
||||||
if(!exceptions.isEmpty()) throw exceptions.poll();
|
running = false;
|
||||||
stopped = true;
|
if(exception != null) {
|
||||||
|
IOException e = exception;
|
||||||
|
exception = null;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
synchronized(pollingLock) {
|
synchronized(pollingLock) {
|
||||||
pollingLock.notifyAll();
|
pollingLock.notifyAll();
|
||||||
}
|
}
|
||||||
@@ -56,34 +43,21 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
List<File> drives = finder.findRemovableDrives();
|
List<File> drives = finder.findRemovableDrives();
|
||||||
while(true) {
|
while(running) {
|
||||||
synchronized(this) {
|
|
||||||
if(stopped) return;
|
|
||||||
}
|
|
||||||
synchronized(pollingLock) {
|
synchronized(pollingLock) {
|
||||||
try {
|
try {
|
||||||
pollingLock.wait(pollingInterval);
|
pollingLock.wait(pollingInterval);
|
||||||
} catch(InterruptedException ignored) {}
|
} catch(InterruptedException ignored) {}
|
||||||
}
|
}
|
||||||
synchronized(this) {
|
if(!running) return;
|
||||||
if(stopped) return;
|
|
||||||
}
|
|
||||||
List<File> newDrives = finder.findRemovableDrives();
|
List<File> newDrives = finder.findRemovableDrives();
|
||||||
for(File f : newDrives) {
|
for(File f : newDrives) {
|
||||||
if(!drives.contains(f)) {
|
if(!drives.contains(f)) callback.driveInserted(f);
|
||||||
synchronized(this) {
|
|
||||||
inserted.add(f);
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
drives = newDrives;
|
drives = newDrives;
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
synchronized(this) {
|
exception = e;
|
||||||
exceptions.add(e);
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import java.io.IOException;
|
|||||||
|
|
||||||
interface RemovableDriveMonitor {
|
interface RemovableDriveMonitor {
|
||||||
|
|
||||||
void start() throws IOException;
|
void start(Callback c) throws IOException;
|
||||||
|
|
||||||
File waitForInsertion() throws IOException;
|
|
||||||
|
|
||||||
void stop() throws IOException;
|
void stop() throws IOException;
|
||||||
|
|
||||||
|
interface Callback {
|
||||||
|
|
||||||
|
void driveInserted(File f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,25 +3,51 @@ package net.sf.briar.plugins.file;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.TransportId;
|
import net.sf.briar.api.TransportId;
|
||||||
|
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||||
|
import net.sf.briar.api.transport.InvalidConfigException;
|
||||||
|
import net.sf.briar.api.transport.InvalidTransportException;
|
||||||
|
import net.sf.briar.api.transport.batch.BatchTransportCallback;
|
||||||
|
|
||||||
class RemovableDrivePlugin extends FilePlugin {
|
class RemovableDrivePlugin extends FilePlugin
|
||||||
|
implements RemovableDriveMonitor.Callback {
|
||||||
|
|
||||||
public static final int TRANSPORT_ID = 0;
|
public static final int TRANSPORT_ID = 0;
|
||||||
|
|
||||||
private static final TransportId id = new TransportId(TRANSPORT_ID);
|
private static final TransportId id = new TransportId(TRANSPORT_ID);
|
||||||
|
|
||||||
private final RemovableDriveFinder finder;
|
private final RemovableDriveFinder finder;
|
||||||
|
private final RemovableDriveMonitor monitor;
|
||||||
|
|
||||||
RemovableDrivePlugin(RemovableDriveFinder finder) {
|
RemovableDrivePlugin(ConnectionRecogniser recogniser,
|
||||||
|
RemovableDriveFinder finder, RemovableDriveMonitor monitor) {
|
||||||
|
super(recogniser);
|
||||||
this.finder = finder;
|
this.finder = finder;
|
||||||
|
this.monitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Map<String, String> localProperties,
|
||||||
|
Map<ContactId, Map<String, String>> remoteProperties,
|
||||||
|
Map<String, String> config, BatchTransportCallback callback)
|
||||||
|
throws InvalidTransportException, InvalidConfigException, IOException {
|
||||||
|
super.start(localProperties, remoteProperties, config, callback);
|
||||||
|
monitor.start(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() throws IOException {
|
||||||
|
super.stop();
|
||||||
|
monitor.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected File chooseOutputDirectory() {
|
protected File chooseOutputDirectory() {
|
||||||
try {
|
try {
|
||||||
@@ -43,4 +69,9 @@ class RemovableDrivePlugin extends FilePlugin {
|
|||||||
protected void writerFinished(File f) {
|
protected void writerFinished(File f) {
|
||||||
callback.showMessage("REMOVABLE_DRIVE_WRITE_FINISHED");
|
callback.showMessage("REMOVABLE_DRIVE_WRITE_FINISHED");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void driveInserted(File root) {
|
||||||
|
File[] files = root.listFiles();
|
||||||
|
if(files != null) for(File f : files) createReaderFromFile(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.sf.briar.plugins.file;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.contentobjects.jnotify.JNotify;
|
import net.contentobjects.jnotify.JNotify;
|
||||||
@@ -13,15 +12,16 @@ abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
|
|||||||
JNotifyListener {
|
JNotifyListener {
|
||||||
|
|
||||||
private final List<Integer> watches = new ArrayList<Integer>();
|
private final List<Integer> watches = new ArrayList<Integer>();
|
||||||
private final LinkedList<File> inserted = new LinkedList<File>();
|
|
||||||
|
|
||||||
private boolean started = false, stopped = false;
|
private boolean started = false;
|
||||||
|
private Callback callback = null;
|
||||||
|
|
||||||
protected abstract String[] getPathsToWatch();
|
protected abstract String[] getPathsToWatch();
|
||||||
|
|
||||||
public synchronized void start() throws IOException {
|
public synchronized void start(Callback callback) throws IOException {
|
||||||
if(started || stopped) throw new IllegalStateException();
|
if(started) throw new IllegalStateException();
|
||||||
started = true;
|
started = true;
|
||||||
|
this.callback = callback;
|
||||||
int mask = JNotify.FILE_CREATED;
|
int mask = JNotify.FILE_CREATED;
|
||||||
for(String path : getPathsToWatch()) {
|
for(String path : getPathsToWatch()) {
|
||||||
if(new File(path).exists())
|
if(new File(path).exists())
|
||||||
@@ -29,26 +29,18 @@ JNotifyListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized File waitForInsertion() throws IOException {
|
|
||||||
if(!started || stopped) throw new IllegalStateException();
|
|
||||||
while(inserted.isEmpty()) {
|
|
||||||
try {
|
|
||||||
wait();
|
|
||||||
} catch(InterruptedException ignored) {}
|
|
||||||
}
|
|
||||||
return inserted.poll();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void stop() throws IOException {
|
public synchronized void stop() throws IOException {
|
||||||
if(!started || stopped) throw new IllegalStateException();
|
if(!started) throw new IllegalStateException();
|
||||||
stopped = true;
|
started = false;
|
||||||
|
callback = null;
|
||||||
for(Integer w : watches) JNotify.removeWatch(w);
|
for(Integer w : watches) JNotify.removeWatch(w);
|
||||||
|
watches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fileCreated(int wd, String rootPath, String name) {
|
public void fileCreated(int wd, String rootPath, String name) {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
inserted.add(new File(rootPath + "/" + name));
|
if(!started) throw new IllegalStateException();
|
||||||
notifyAll();
|
callback.driveInserted(new File(rootPath + "/" + name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback;
|
||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -18,15 +20,13 @@ public class PollingRemovableDriveMonitorTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneCallbackPerFile() throws Exception {
|
public void testOneCallbackPerFile() throws Exception {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
final List<File> detected = new ArrayList<File>();
|
|
||||||
final File file1 = new File("foo");
|
final File file1 = new File("foo");
|
||||||
final File file2 = new File("bar");
|
final File file2 = new File("bar");
|
||||||
|
// Create a finder that returns no files the first time, then two files
|
||||||
final List<File> noDrives = Collections.emptyList();
|
final List<File> noDrives = Collections.emptyList();
|
||||||
final List<File> twoDrives = new ArrayList<File>();
|
final List<File> twoDrives = new ArrayList<File>();
|
||||||
twoDrives.add(file1);
|
twoDrives.add(file1);
|
||||||
twoDrives.add(file2);
|
twoDrives.add(file2);
|
||||||
// Create a finder that returns no files the first time, then two files
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
@@ -36,24 +36,21 @@ public class PollingRemovableDriveMonitorTest extends TestCase {
|
|||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(twoDrives));
|
will(returnValue(twoDrives));
|
||||||
}});
|
}});
|
||||||
// Create a monitor that will wait for two files before stopping
|
// Create a callback that will wait for two files before stopping
|
||||||
|
final List<File> detected = new ArrayList<File>();
|
||||||
|
final CountDownLatch latch = new CountDownLatch(2);
|
||||||
|
final Callback callback = new Callback() {
|
||||||
|
public void driveInserted(File f) {
|
||||||
|
detected.add(f);
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Create the monitor and start it
|
||||||
final RemovableDriveMonitor monitor =
|
final RemovableDriveMonitor monitor =
|
||||||
new PollingRemovableDriveMonitor(finder, 10);
|
new PollingRemovableDriveMonitor(finder, 10);
|
||||||
monitor.start();
|
monitor.start(callback);
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
detected.add(monitor.waitForInsertion());
|
|
||||||
detected.add(monitor.waitForInsertion());
|
|
||||||
latch.countDown();
|
|
||||||
} catch(IOException e) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
// Wait for the monitor to detect the files
|
// Wait for the monitor to detect the files
|
||||||
assertTrue(latch.await(2, TimeUnit.SECONDS));
|
assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
// Check that both files were detected
|
// Check that both files were detected
|
||||||
assertEquals(2, detected.size());
|
assertEquals(2, detected.size());
|
||||||
@@ -63,32 +60,6 @@ public class PollingRemovableDriveMonitorTest extends TestCase {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExceptionRethrownWhenWaiting() throws Exception {
|
|
||||||
final List<File> noDrives = Collections.emptyList();
|
|
||||||
// Create a finder that throws an exception the second time it's polled
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
final RemovableDriveFinder finder =
|
|
||||||
context.mock(RemovableDriveFinder.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(finder).findRemovableDrives();
|
|
||||||
will(returnValue(noDrives));
|
|
||||||
oneOf(finder).findRemovableDrives();
|
|
||||||
will(throwException(new IOException()));
|
|
||||||
}});
|
|
||||||
// The monitor should rethrow the exception when it waits
|
|
||||||
final RemovableDriveMonitor monitor =
|
|
||||||
new PollingRemovableDriveMonitor(finder, 10);
|
|
||||||
monitor.start();
|
|
||||||
try {
|
|
||||||
monitor.waitForInsertion();
|
|
||||||
fail();
|
|
||||||
} catch(IOException expected) {}
|
|
||||||
// The exception shouldn't be thrown again
|
|
||||||
monitor.stop();
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExceptionRethrownWhenStopping() throws Exception {
|
public void testExceptionRethrownWhenStopping() throws Exception {
|
||||||
final List<File> noDrives = Collections.emptyList();
|
final List<File> noDrives = Collections.emptyList();
|
||||||
@@ -102,11 +73,12 @@ public class PollingRemovableDriveMonitorTest extends TestCase {
|
|||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(throwException(new IOException()));
|
will(throwException(new IOException()));
|
||||||
}});
|
}});
|
||||||
// The monitor should rethrow the exception when it stops
|
// Create the monitor, start it, and give it some time to run
|
||||||
final RemovableDriveMonitor monitor =
|
final RemovableDriveMonitor monitor =
|
||||||
new PollingRemovableDriveMonitor(finder, 10);
|
new PollingRemovableDriveMonitor(finder, 10);
|
||||||
monitor.start();
|
monitor.start(null);
|
||||||
Thread.sleep(50);
|
Thread.sleep(50);
|
||||||
|
// The monitor should rethrow the exception when it stops
|
||||||
try {
|
try {
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
fail();
|
fail();
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import java.util.List;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.transport.ConnectionRecogniser;
|
||||||
import net.sf.briar.api.transport.batch.BatchTransportCallback;
|
import net.sf.briar.api.transport.batch.BatchTransportCallback;
|
||||||
import net.sf.briar.api.transport.batch.BatchTransportWriter;
|
import net.sf.briar.api.transport.batch.BatchTransportWriter;
|
||||||
|
import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback;
|
||||||
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
@@ -31,9 +33,14 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetId() {
|
public void testGetId() {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
|
|
||||||
assertEquals(RemovableDrivePlugin.TRANSPORT_ID,
|
assertEquals(RemovableDrivePlugin.TRANSPORT_ID,
|
||||||
plugin.getId().getInt());
|
plugin.getId().getInt());
|
||||||
@@ -46,15 +53,23 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
final List<File> drives = Collections.emptyList();
|
final List<File> drives = Collections.emptyList();
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
assertNull(plugin.createWriter(contactId));
|
assertNull(plugin.createWriter(contactId));
|
||||||
@@ -71,18 +86,26 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
drives.add(drive2);
|
drives.add(drive2);
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
oneOf(callback).showChoice(with(any(String.class)),
|
oneOf(callback).showChoice(with(any(String.class)),
|
||||||
with(any(String[].class)));
|
with(any(String[].class)));
|
||||||
will(returnValue(-1)); // The user cancelled the choice
|
will(returnValue(-1)); // The user cancelled the choice
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
assertNull(plugin.createWriter(contactId));
|
assertNull(plugin.createWriter(contactId));
|
||||||
@@ -101,18 +124,26 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
drives.add(drive2);
|
drives.add(drive2);
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
oneOf(callback).showChoice(with(any(String.class)),
|
oneOf(callback).showChoice(with(any(String.class)),
|
||||||
with(any(String[].class)));
|
with(any(String[].class)));
|
||||||
will(returnValue(0)); // The user chose drive1 but it doesn't exist
|
will(returnValue(0)); // The user chose drive1 but it doesn't exist
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
assertNull(plugin.createWriter(contactId));
|
assertNull(plugin.createWriter(contactId));
|
||||||
@@ -133,18 +164,26 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
assertTrue(drive1.createNewFile());
|
assertTrue(drive1.createNewFile());
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
oneOf(callback).showChoice(with(any(String.class)),
|
oneOf(callback).showChoice(with(any(String.class)),
|
||||||
with(any(String[].class)));
|
with(any(String[].class)));
|
||||||
will(returnValue(0)); // The user chose drive1 but it's not a dir
|
will(returnValue(0)); // The user chose drive1 but it's not a dir
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
assertNull(plugin.createWriter(contactId));
|
assertNull(plugin.createWriter(contactId));
|
||||||
@@ -165,18 +204,26 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
assertTrue(drive1.mkdir());
|
assertTrue(drive1.mkdir());
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
oneOf(callback).showChoice(with(any(String.class)),
|
oneOf(callback).showChoice(with(any(String.class)),
|
||||||
with(any(String[].class)));
|
with(any(String[].class)));
|
||||||
will(returnValue(0)); // The user chose drive1
|
will(returnValue(0)); // The user chose drive1
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
assertNotNull(plugin.createWriter(contactId));
|
assertNotNull(plugin.createWriter(contactId));
|
||||||
@@ -200,11 +247,17 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
assertTrue(drive1.mkdir());
|
assertTrue(drive1.mkdir());
|
||||||
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
|
final ConnectionRecogniser recogniser =
|
||||||
|
context.mock(ConnectionRecogniser.class);
|
||||||
final RemovableDriveFinder finder =
|
final RemovableDriveFinder finder =
|
||||||
context.mock(RemovableDriveFinder.class);
|
context.mock(RemovableDriveFinder.class);
|
||||||
|
final RemovableDriveMonitor monitor =
|
||||||
|
context.mock(RemovableDriveMonitor.class);
|
||||||
final BatchTransportCallback callback =
|
final BatchTransportCallback callback =
|
||||||
context.mock(BatchTransportCallback.class);
|
context.mock(BatchTransportCallback.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(monitor).start(with(any(Callback.class)));
|
||||||
oneOf(finder).findRemovableDrives();
|
oneOf(finder).findRemovableDrives();
|
||||||
will(returnValue(drives));
|
will(returnValue(drives));
|
||||||
oneOf(callback).showChoice(with(any(String.class)),
|
oneOf(callback).showChoice(with(any(String.class)),
|
||||||
@@ -212,7 +265,9 @@ public class RemovableDrivePluginTest extends TestCase {
|
|||||||
will(returnValue(0)); // The user chose drive1
|
will(returnValue(0)); // The user chose drive1
|
||||||
oneOf(callback).showMessage(with(any(String.class)));
|
oneOf(callback).showMessage(with(any(String.class)));
|
||||||
}});
|
}});
|
||||||
RemovableDrivePlugin plugin = new RemovableDrivePlugin(finder);
|
|
||||||
|
RemovableDrivePlugin plugin = new RemovableDrivePlugin(recogniser,
|
||||||
|
finder, monitor);
|
||||||
plugin.start(null, null, null, callback);
|
plugin.start(null, null, null, callback);
|
||||||
|
|
||||||
BatchTransportWriter writer = plugin.createWriter(contactId);
|
BatchTransportWriter writer = plugin.createWriter(contactId);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package net.sf.briar.plugins.file;
|
package net.sf.briar.plugins.file;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
@@ -9,6 +8,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
|
import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -27,36 +27,31 @@ public class UnixRemovableDriveMonitorTest extends TestCase {
|
|||||||
public void testNonexistentDir() throws Exception {
|
public void testNonexistentDir() throws Exception {
|
||||||
File doesNotExist = new File(testDir, "doesNotExist");
|
File doesNotExist = new File(testDir, "doesNotExist");
|
||||||
RemovableDriveMonitor monitor = createMonitor(doesNotExist);
|
RemovableDriveMonitor monitor = createMonitor(doesNotExist);
|
||||||
monitor.start();
|
monitor.start(null);
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneCallbackPerFile() throws Exception {
|
public void testOneCallbackPerFile() throws Exception {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
// Create a callback that will wait for two files before stopping
|
||||||
final List<File> detected = new ArrayList<File>();
|
final List<File> detected = new ArrayList<File>();
|
||||||
// Create a monitor that will wait for two files before stopping
|
final CountDownLatch latch = new CountDownLatch(2);
|
||||||
final RemovableDriveMonitor monitor = createMonitor(testDir);
|
final Callback callback = new Callback() {
|
||||||
monitor.start();
|
public void driveInserted(File f) {
|
||||||
new Thread() {
|
detected.add(f);
|
||||||
@Override
|
latch.countDown();
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
detected.add(monitor.waitForInsertion());
|
|
||||||
detected.add(monitor.waitForInsertion());
|
|
||||||
latch.countDown();
|
|
||||||
} catch(IOException e) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.start();
|
};
|
||||||
|
// Create the monitor and start it
|
||||||
|
RemovableDriveMonitor monitor = createMonitor(testDir);
|
||||||
|
monitor.start(callback);
|
||||||
// Create two files in the test directory
|
// Create two files in the test directory
|
||||||
File file1 = new File(testDir, "1");
|
File file1 = new File(testDir, "1");
|
||||||
File file2 = new File(testDir, "2");
|
File file2 = new File(testDir, "2");
|
||||||
assertTrue(file1.createNewFile());
|
assertTrue(file1.createNewFile());
|
||||||
assertTrue(file2.createNewFile());
|
assertTrue(file2.createNewFile());
|
||||||
// Wait for the monitor to detect the files
|
// Wait for the monitor to detect the files
|
||||||
assertTrue(latch.await(2, TimeUnit.SECONDS));
|
assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
// Check that both files were detected
|
// Check that both files were detected
|
||||||
assertEquals(2, detected.size());
|
assertEquals(2, detected.size());
|
||||||
|
|||||||
Reference in New Issue
Block a user