Changed the root package from net.sf.briar to org.briarproject.

This commit is contained in:
akwizgran
2014-01-08 16:18:30 +00:00
parent dce70f487c
commit 832476412c
427 changed files with 2507 additions and 2507 deletions

View File

@@ -0,0 +1,108 @@
package org.briarproject.plugins;
import static org.briarproject.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
import java.io.IOException;
import java.util.Map;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
public abstract class DuplexClientTest extends DuplexTest {
protected ClientCallback callback = null;
protected void run() throws IOException {
assert plugin != null;
// Start the plugin
System.out.println("Starting plugin");
if(!plugin.start()) {
System.out.println("Plugin failed to start");
return;
}
try {
// Try to connect to the server
System.out.println("Creating connection");
DuplexTransportConnection d = plugin.createConnection(contactId);
if(d == null) {
System.out.println("Connection failed");
return;
} else {
System.out.println("Connection created");
receiveChallengeSendResponse(d);
}
if(!plugin.supportsInvitations()) {
System.out.println("Skipping invitation test");
return;
}
// Try to create an invitation connection
System.out.println("Creating invitation connection");
PseudoRandom r = getPseudoRandom(123);
d = plugin.createInvitationConnection(r, CONNECTION_TIMEOUT);
if(d == null) {
System.out.println("Connection failed");
return;
} else {
System.out.println("Connection created");
sendChallengeReceiveResponse(d);
}
} finally {
// Stop the plugin
System.out.println("Stopping plugin");
plugin.stop();
}
}
protected static class ClientCallback implements DuplexPluginCallback {
private TransportConfig config = null;
private TransportProperties local = null;
private Map<ContactId, TransportProperties> remote = null;
public ClientCallback(TransportConfig config, TransportProperties local,
Map<ContactId, TransportProperties> remote) {
this.config = config;
this.local = local;
this.remote = remote;
}
public TransportConfig getConfig() {
return config;
}
public TransportProperties getLocalProperties() {
return local;
}
public Map<ContactId, TransportProperties> getRemoteProperties() {
return remote;
}
public void mergeConfig(TransportConfig c) {
config = c;
}
public void mergeLocalProperties(TransportProperties p) {
local = p;
}
public int showChoice(String[] options, String... message) {
return -1;
}
public boolean showConfirmationMessage(String... message) {
return false;
}
public void showMessage(String... message) {}
public void incomingConnectionCreated(DuplexTransportConnection d) {}
public void outgoingConnectionCreated(ContactId contactId,
DuplexTransportConnection d) {}
}
}

View File

@@ -0,0 +1,111 @@
package org.briarproject.plugins;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
public abstract class DuplexServerTest extends DuplexTest {
protected ServerCallback callback = null;
protected void run() throws Exception {
assert callback != null;
assert plugin != null;
// Start the plugin
System.out.println("Starting plugin");
if(!plugin.start()) {
System.out.println("Plugin failed to start");
return;
}
try {
// Wait for a connection
System.out.println("Waiting for connection");
if(!callback.latch.await(120, SECONDS)) {
System.out.println("No connection received");
return;
}
if(!plugin.supportsInvitations()) {
System.out.println("Skipping invitation test");
return;
}
// Try to create an invitation connection
System.out.println("Creating invitation connection");
DuplexTransportConnection d = plugin.createInvitationConnection(
getPseudoRandom(123), CONNECTION_TIMEOUT);
if(d == null) {
System.out.println("Connection failed");
return;
} else {
System.out.println("Connection created");
receiveChallengeSendResponse(d);
}
} finally {
// Stop the plugin
System.out.println("Stopping plugin");
plugin.stop();
}
}
protected class ServerCallback implements DuplexPluginCallback {
private final CountDownLatch latch = new CountDownLatch(1);
private TransportConfig config;
private TransportProperties local;
private Map<ContactId, TransportProperties> remote;
public ServerCallback(TransportConfig config, TransportProperties local,
Map<ContactId, TransportProperties> remote) {
this.config = config;
this.local = local;
this.remote = remote;
}
public TransportConfig getConfig() {
return config;
}
public TransportProperties getLocalProperties() {
return local;
}
public Map<ContactId, TransportProperties> getRemoteProperties() {
return remote;
}
public void mergeConfig(TransportConfig c) {
config = c;
}
public void mergeLocalProperties(TransportProperties p) {
local = p;
}
public int showChoice(String[] options, String... message) {
return -1;
}
public boolean showConfirmationMessage(String... message) {
return false;
}
public void showMessage(String... message) {}
public void incomingConnectionCreated(DuplexTransportConnection d) {
System.out.println("Connection received");
sendChallengeReceiveResponse(d);
latch.countDown();
}
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {}
}
}

View File

@@ -0,0 +1,91 @@
package org.briarproject.plugins;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Random;
import java.util.Scanner;
import org.briarproject.api.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
abstract class DuplexTest {
protected static final String CHALLENGE = "Carrots!";
protected static final String RESPONSE = "Potatoes!";
protected final ContactId contactId = new ContactId(234);
protected DuplexPlugin plugin = null;
protected void sendChallengeReceiveResponse(DuplexTransportConnection d) {
assert plugin != null;
try {
PrintStream out = new PrintStream(d.getOutputStream());
out.println(CHALLENGE);
out.flush();
System.out.println("Sent challenge: " + CHALLENGE);
Scanner in = new Scanner(d.getInputStream());
if(in.hasNextLine()) {
String response = in.nextLine();
System.out.println("Received response: " + response);
if(RESPONSE.equals(response)) {
System.out.println("Correct response");
} else {
System.out.println("Incorrect response");
}
} else {
System.out.println("No response");
}
d.dispose(false, true);
} catch(IOException e) {
e.printStackTrace();
try {
d.dispose(true, true);
} catch(IOException e1) {
e1.printStackTrace();
}
}
}
protected void receiveChallengeSendResponse(DuplexTransportConnection d) {
assert plugin != null;
try {
Scanner in = new Scanner(d.getInputStream());
if(in.hasNextLine()) {
String challenge = in.nextLine();
System.out.println("Received challenge: " + challenge);
if(CHALLENGE.equals(challenge)) {
PrintStream out = new PrintStream(d.getOutputStream());
out.println(RESPONSE);
out.flush();
System.out.println("Sent response: " + RESPONSE);
} else {
System.out.println("Incorrect challenge");
}
} else {
System.out.println("No challenge");
}
d.dispose(false, true);
} catch(IOException e) {
e.printStackTrace();
try {
d.dispose(true, true);
} catch(IOException e1) {
e1.printStackTrace();
}
}
}
protected PseudoRandom getPseudoRandom(int seed) {
final Random random = new Random(seed);
return new PseudoRandom() {
public byte[] nextBytes(int bytes) {
byte[] b = new byte[bytes];
random.nextBytes(b);
return b;
}
};
}
}

View File

@@ -0,0 +1,10 @@
package org.briarproject.plugins;
import java.util.concurrent.Executor;
public class ImmediateExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}

View File

@@ -0,0 +1,128 @@
package org.briarproject.plugins;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginConfig;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.plugins.simplex.SimplexPlugin;
import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
import org.briarproject.api.transport.ConnectionDispatcher;
import org.briarproject.api.ui.UiCallback;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
public class PluginManagerImplTest extends BriarTestCase {
@Test
public void testStartAndStop() throws Exception {
Mockery context = new Mockery();
final Executor pluginExecutor = Executors.newCachedThreadPool();
final SimplexPluginConfig simplexPluginConfig =
context.mock(SimplexPluginConfig.class);
final DuplexPluginConfig duplexPluginConfig =
context.mock(DuplexPluginConfig.class);
final DatabaseComponent db = context.mock(DatabaseComponent.class);
final Poller poller = context.mock(Poller.class);
final ConnectionDispatcher dispatcher =
context.mock(ConnectionDispatcher.class);
final UiCallback uiCallback = context.mock(UiCallback.class);
// Two simplex plugin factories: both create plugins, one fails to start
final SimplexPluginFactory simplexFactory =
context.mock(SimplexPluginFactory.class);
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
final TransportId simplexId = new TransportId(TestUtils.getRandomId());
final long simplexLatency = 12345;
final SimplexPluginFactory simplexFailFactory =
context.mock(SimplexPluginFactory.class, "simplexFailFactory");
final SimplexPlugin simplexFailPlugin =
context.mock(SimplexPlugin.class, "simplexFailPlugin");
final TransportId simplexFailId =
new TransportId(TestUtils.getRandomId());
final long simplexFailLatency = 23456;
// Two duplex plugin factories: one creates a plugin, the other fails
final DuplexPluginFactory duplexFactory =
context.mock(DuplexPluginFactory.class);
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
final TransportId duplexId = new TransportId(TestUtils.getRandomId());
final long duplexLatency = 34567;
final DuplexPluginFactory duplexFailFactory =
context.mock(DuplexPluginFactory.class, "duplexFailFactory");
final TransportId duplexFailId =
new TransportId(TestUtils.getRandomId());
context.checking(new Expectations() {{
// First simplex plugin
oneOf(simplexPluginConfig).getFactories();
will(returnValue(Arrays.asList(simplexFactory,
simplexFailFactory)));
oneOf(simplexFactory).getId();
will(returnValue(simplexId));
oneOf(simplexFactory).createPlugin(with(any(
SimplexPluginCallback.class)));
will(returnValue(simplexPlugin)); // Created
oneOf(simplexPlugin).getMaxLatency();
will(returnValue(simplexLatency));
oneOf(db).addTransport(simplexId, simplexLatency);
will(returnValue(true));
oneOf(simplexPlugin).start();
will(returnValue(true)); // Started
// Second simplex plugin
oneOf(simplexFailFactory).getId();
will(returnValue(simplexFailId));
oneOf(simplexFailFactory).createPlugin(with(any(
SimplexPluginCallback.class)));
will(returnValue(simplexFailPlugin)); // Created
oneOf(simplexFailPlugin).getMaxLatency();
will(returnValue(simplexFailLatency));
oneOf(db).addTransport(simplexFailId, simplexFailLatency);
will(returnValue(true));
oneOf(simplexFailPlugin).start();
will(returnValue(false)); // Failed to start
// First duplex plugin
oneOf(duplexPluginConfig).getFactories();
will(returnValue(Arrays.asList(duplexFactory, duplexFailFactory)));
oneOf(duplexFactory).getId();
will(returnValue(duplexId));
oneOf(duplexFactory).createPlugin(with(any(
DuplexPluginCallback.class)));
will(returnValue(duplexPlugin)); // Created
oneOf(duplexPlugin).getMaxLatency();
will(returnValue(duplexLatency));
oneOf(db).addTransport(duplexId, duplexLatency);
will(returnValue(true));
oneOf(duplexPlugin).start();
will(returnValue(true)); // Started
// Second duplex plugin
oneOf(duplexFailFactory).getId();
will(returnValue(duplexFailId));
oneOf(duplexFailFactory).createPlugin(with(any(
DuplexPluginCallback.class)));
will(returnValue(null)); // Failed to create a plugin
// Start the poller
oneOf(poller).start(Arrays.asList(simplexPlugin, duplexPlugin));
// Stop the poller
oneOf(poller).stop();
// Stop the plugins
oneOf(simplexPlugin).stop();
oneOf(duplexPlugin).stop();
}});
PluginManagerImpl p = new PluginManagerImpl(pluginExecutor,
simplexPluginConfig, duplexPluginConfig, db, poller,
dispatcher, uiCallback);
// Two plugins should be started and stopped
assertTrue(p.start());
assertTrue(p.stop());
context.assertIsSatisfied();
}
}

View File

@@ -0,0 +1,46 @@
package org.briarproject.plugins.bluetooth;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.system.SystemClock;
import org.briarproject.plugins.DuplexClientTest;
// This is not a JUnit test - it has to be run manually while the server test
// is running on another machine
public class BluetoothClientTest extends DuplexClientTest {
private BluetoothClientTest(Executor executor, String serverAddress) {
// Store the server's Bluetooth address and UUID
TransportProperties p = new TransportProperties();
p.put("address", serverAddress);
p.put("uuid", BluetoothTest.EMPTY_UUID);
Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
// Create the plugin
callback = new ClientCallback(new TransportConfig(),
new TransportProperties(), remote);
plugin = new BluetoothPlugin(executor, new SystemClock(),
new SecureRandom(), callback, 0, 0, 0);
}
public static void main(String[] args) throws Exception {
if(args.length != 1) {
System.err.println("Please specify the server's Bluetooth address");
System.exit(1);
}
ExecutorService executor = Executors.newCachedThreadPool();
try {
new BluetoothClientTest(executor, args[0]).run();
} finally {
executor.shutdown();
}
}
}

View File

@@ -0,0 +1,37 @@
package org.briarproject.plugins.bluetooth;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.system.SystemClock;
import org.briarproject.plugins.DuplexServerTest;
// This is not a JUnit test - it has to be run manually while the client test
// is running on another machine
public class BluetoothServerTest extends DuplexServerTest {
private BluetoothServerTest(Executor executor) {
// Store the UUID
TransportProperties local = new TransportProperties();
local.put("uuid", BluetoothTest.EMPTY_UUID);
// Create the plugin
callback = new ServerCallback(new TransportConfig(), local,
Collections.singletonMap(contactId, new TransportProperties()));
plugin = new BluetoothPlugin(executor, new SystemClock(),
new SecureRandom(), callback, 0, 0, 0);
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
try {
new BluetoothServerTest(executor).run();
} finally {
executor.shutdown();
}
}
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.plugins.bluetooth;
import java.util.UUID;
class BluetoothTest {
static final String EMPTY_UUID =
UUID.nameUUIDFromBytes(new byte[0]).toString();
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.plugins.file;
import org.briarproject.BriarTestCase;
import org.junit.Test;
public class LinuxRemovableDriveFinderTest extends BriarTestCase {
@Test
public void testParseMountPoint() {
LinuxRemovableDriveFinder f = new LinuxRemovableDriveFinder();
String line = "/dev/sda3 on / type ext3"
+ " (rw,errors=remount-ro,commit=0)";
assertEquals("/", f.parseMountPoint(line));
line = "gvfs-fuse-daemon on /home/alice/.gvfs"
+ " type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=alice)";
assertEquals(null, f.parseMountPoint(line)); // Can't be parsed
line = "fusectl on /sys/fs/fuse/connections type fusectl (rw)";
assertEquals(null, f.parseMountPoint(line)); // Can't be parsed
line = "/dev/sdd1 on /media/HAZ SPACE(!) type vfat"
+ " (rw,nosuid,nodev,uhelper=udisks,uid=1000,gid=1000,"
+ "shortname=mixed,dmask=0077,utf8=1,showexec,flush)";
assertEquals("/media/HAZ SPACE(!)", f.parseMountPoint(line));
}
}

View File

@@ -0,0 +1,23 @@
package org.briarproject.plugins.file;
import org.briarproject.BriarTestCase;
import org.junit.Test;
public class MacRemovableDriveFinderTest extends BriarTestCase {
@Test
public void testParseMountPoint() {
MacRemovableDriveFinder f = new MacRemovableDriveFinder();
String line = "/dev/disk0s3 on / (local, journaled)";
assertEquals("/", f.parseMountPoint(line));
line = "devfs on /dev (local)";
assertEquals(null, f.parseMountPoint(line)); // Can't be parsed
line = "<volfs> on /.vol";
assertEquals(null, f.parseMountPoint(line)); // Can't be parsed
line = "automount -nsl [117] on /Network (automounted)";
assertEquals(null, f.parseMountPoint(line)); // Can't be parsed
line = "/dev/disk1s1 on /Volumes/HAZ SPACE(!) (local, nodev, nosuid)";
assertEquals("/Volumes/HAZ SPACE(!)", f.parseMountPoint(line));
}
}

View File

@@ -0,0 +1,95 @@
package org.briarproject.plugins.file;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.briarproject.BriarTestCase;
import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
import org.junit.Test;
public class PollingRemovableDriveMonitorTest extends BriarTestCase {
@Test
public void testOneCallbackPerFile() throws Exception {
// Create a finder that returns no files the first time, then two files
final File file1 = new File("foo");
final File file2 = new File("bar");
final RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true);
public Collection<File> findRemovableDrives() throws IOException {
if(firstCall.getAndSet(false)) return Collections.emptyList();
else return Arrays.asList(file1, file2);
}
};
// Create a callback that waits for two files
final CountDownLatch latch = new CountDownLatch(2);
final List<File> detected = new ArrayList<File>();
Callback callback = new Callback() {
public void driveInserted(File f) {
detected.add(f);
latch.countDown();
}
public void exceptionThrown(IOException e) {
fail();
}
};
// Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback);
// Wait for the monitor to detect the files
assertTrue(latch.await(10, SECONDS));
monitor.stop();
// Check that both files were detected
assertEquals(2, detected.size());
assertTrue(detected.contains(file1));
assertTrue(detected.contains(file2));
}
@Test
public void testExceptionCallback() throws Exception {
// Create a finder that throws an exception the second time it's polled
final RemovableDriveFinder finder = new RemovableDriveFinder() {
private AtomicBoolean firstCall = new AtomicBoolean(true);
public Collection<File> findRemovableDrives() throws IOException {
if(firstCall.getAndSet(false)) return Collections.emptyList();
else throw new IOException();
}
};
// Create a callback that waits for an exception
final CountDownLatch latch = new CountDownLatch(1);
Callback callback = new Callback() {
public void driveInserted(File root) {
fail();
}
public void exceptionThrown(IOException e) {
latch.countDown();
}
};
// Create the monitor and start it
final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
Executors.newCachedThreadPool(), finder, 1);
monitor.start(callback);
assertTrue(latch.await(10, SECONDS));
monitor.stop();
}
}

View File

@@ -0,0 +1,360 @@
package org.briarproject.plugins.file;
import static org.briarproject.api.transport.TransportConstants.MAX_FRAME_LENGTH;
import static org.briarproject.api.transport.TransportConstants.MIN_CONNECTION_LENGTH;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import org.briarproject.BriarTestCase;
import org.briarproject.TestFileUtils;
import org.briarproject.TestUtils;
import org.briarproject.api.ContactId;
import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
import org.briarproject.api.plugins.simplex.SimplexTransportWriter;
import org.briarproject.api.system.FileUtils;
import org.briarproject.plugins.ImmediateExecutor;
import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class RemovableDrivePluginTest extends BriarTestCase {
private final File testDir = TestUtils.getTestDirectory();
private final ContactId contactId = new ContactId(234);
private final FileUtils fileUtils = new TestFileUtils();
@Before
public void setUp() {
testDir.mkdirs();
}
@Test
public void testWriterIsNullIfNoDrivesAreFound() throws Exception {
final List<File> drives = Collections.emptyList();
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
assertNull(plugin.createWriter(contactId));
context.assertIsSatisfied();
}
@Test
public void testWriterIsNullIfNoDriveIsChosen() throws Exception {
final File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<File>();
drives.add(drive1);
drives.add(drive2);
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
oneOf(callback).showChoice(with(any(String[].class)),
with(any(String.class)));
will(returnValue(-1)); // The user cancelled the choice
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
assertNull(plugin.createWriter(contactId));
File[] files = drive1.listFiles();
assertTrue(files == null || files.length == 0);
context.assertIsSatisfied();
}
@Test
public void testWriterIsNullIfOutputDirDoesNotExist() throws Exception {
final File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<File>();
drives.add(drive1);
drives.add(drive2);
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
oneOf(callback).showChoice(with(any(String[].class)),
with(any(String.class)));
will(returnValue(0)); // The user chose drive1 but it doesn't exist
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
assertNull(plugin.createWriter(contactId));
File[] files = drive1.listFiles();
assertTrue(files == null || files.length == 0);
context.assertIsSatisfied();
}
@Test
public void testWriterIsNullIfOutputDirIsAFile() throws Exception {
final File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<File>();
drives.add(drive1);
drives.add(drive2);
// Create drive1 as a file rather than a directory
assertTrue(drive1.createNewFile());
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
oneOf(callback).showChoice(with(any(String[].class)),
with(any(String.class)));
will(returnValue(0)); // The user chose drive1 but it's not a dir
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
assertNull(plugin.createWriter(contactId));
File[] files = drive1.listFiles();
assertTrue(files == null || files.length == 0);
context.assertIsSatisfied();
}
@Test
public void testWriterIsNotNullIfOutputDirIsADir() throws Exception {
final File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<File>();
drives.add(drive1);
drives.add(drive2);
// Create drive1 as a directory
assertTrue(drive1.mkdir());
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
oneOf(callback).showChoice(with(any(String[].class)),
with(any(String.class)));
will(returnValue(0)); // The user chose drive1
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
assertNotNull(plugin.createWriter(contactId));
// The output file should exist and should be empty
File[] files = drive1.listFiles();
assertNotNull(files);
assertEquals(1, files.length);
assertEquals(0, files[0].length());
context.assertIsSatisfied();
}
@Test
public void testWritingToWriter() throws Exception {
final File drive1 = new File(testDir, "1");
final File drive2 = new File(testDir, "2");
final List<File> drives = new ArrayList<File>();
drives.add(drive1);
drives.add(drive2);
// Create drive1 as a directory
assertTrue(drive1.mkdir());
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(finder).findRemovableDrives();
will(returnValue(drives));
oneOf(callback).showChoice(with(any(String[].class)),
with(any(String.class)));
will(returnValue(0)); // The user chose drive1
oneOf(callback).showMessage(with(any(String.class)));
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
SimplexTransportWriter writer = plugin.createWriter(contactId);
assertNotNull(writer);
// The output file should exist and should be empty
File[] files = drive1.listFiles();
assertNotNull(files);
assertEquals(1, files.length);
assertEquals(0, files[0].length());
// Writing to the output stream should increase the size of the file
OutputStream out = writer.getOutputStream();
out.write(new byte[1234]);
out.flush();
out.close();
// Disposing of the writer should not delete the file
writer.dispose(false);
assertTrue(files[0].exists());
assertEquals(1234, files[0].length());
context.assertIsSatisfied();
}
@Test
public void testEmptyDriveIsIgnored() throws Exception {
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
plugin.start();
plugin.driveInserted(testDir);
context.assertIsSatisfied();
}
@Test
public void testFilenames() {
Mockery context = new Mockery();
final Executor executor = context.mock(Executor.class);
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
RemovableDrivePlugin plugin = new RemovableDrivePlugin(executor,
fileUtils, callback, finder, monitor, MAX_FRAME_LENGTH, 0);
assertFalse(plugin.isPossibleConnectionFilename("abcdefg.dat"));
assertFalse(plugin.isPossibleConnectionFilename("abcdefghi.dat"));
assertFalse(plugin.isPossibleConnectionFilename("abcdefgh_dat"));
assertFalse(plugin.isPossibleConnectionFilename("abcdefgh.rat"));
assertTrue(plugin.isPossibleConnectionFilename("abcdefgh.dat"));
assertTrue(plugin.isPossibleConnectionFilename("ABCDEFGH.DAT"));
context.assertIsSatisfied();
}
@Test
public void testReaderIsCreated() throws Exception {
Mockery context = new Mockery();
final SimplexPluginCallback callback =
context.mock(SimplexPluginCallback.class);
final RemovableDriveFinder finder =
context.mock(RemovableDriveFinder.class);
final RemovableDriveMonitor monitor =
context.mock(RemovableDriveMonitor.class);
context.checking(new Expectations() {{
oneOf(monitor).start(with(any(Callback.class)));
oneOf(callback).readerCreated(with(any(FileTransportReader.class)));
}});
RemovableDrivePlugin plugin = new RemovableDrivePlugin(
new ImmediateExecutor(), fileUtils, callback, finder, monitor,
MAX_FRAME_LENGTH, 0);
plugin.start();
File f = new File(testDir, "abcdefgh.dat");
OutputStream out = new FileOutputStream(f);
out.write(new byte[MIN_CONNECTION_LENGTH]);
out.flush();
out.close();
assertEquals(MIN_CONNECTION_LENGTH, f.length());
plugin.driveInserted(testDir);
context.assertIsSatisfied();
}
@After
public void tearDown() {
TestUtils.deleteTestDirectory(testDir);
}
}

View File

@@ -0,0 +1,100 @@
package org.briarproject.plugins.file;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.plugins.file.RemovableDriveMonitor.Callback;
import org.briarproject.util.OsUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class UnixRemovableDriveMonitorTest extends BriarTestCase {
private final File testDir = TestUtils.getTestDirectory();
@Before
public void setUp() {
testDir.mkdirs();
}
@Test
public void testNonexistentDir() throws Exception {
if(!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
System.err.println("Warning: Skipping test");
return;
}
File doesNotExist = new File(testDir, "doesNotExist");
RemovableDriveMonitor monitor = createMonitor(doesNotExist);
monitor.start(new Callback() {
public void driveInserted(File root) {
fail();
}
public void exceptionThrown(IOException e) {
fail();
}
});
monitor.stop();
}
@Test
public void testOneCallbackPerFile() throws Exception {
if(!(OsUtils.isLinux() || OsUtils.isMacLeopardOrNewer())) {
System.err.println("Warning: Skipping test");
return;
}
// 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();
}
public void exceptionThrown(IOException e) {
fail();
}
};
// Create the monitor and start it
RemovableDriveMonitor monitor = createMonitor(testDir);
monitor.start(callback);
// Create two files in the test directory
File file1 = new File(testDir, "1");
File file2 = new File(testDir, "2");
assertTrue(file1.createNewFile());
assertTrue(file2.createNewFile());
// Wait for the monitor to detect the files
assertTrue(latch.await(5, SECONDS));
monitor.stop();
// Check that both files were detected
assertEquals(2, detected.size());
assertTrue(detected.contains(file1));
assertTrue(detected.contains(file2));
}
@After
public void tearDown() {
TestUtils.deleteTestDirectory(testDir);
}
private RemovableDriveMonitor createMonitor(final File dir) {
return new UnixRemovableDriveMonitor() {
@Override
protected String[] getPathsToWatch() {
return new String[] { dir.getPath() };
}
};
}
}

View File

@@ -0,0 +1,61 @@
package org.briarproject.plugins.modem;
import org.briarproject.BriarTestCase;
import org.junit.Test;
public class CountryCodesTest extends BriarTestCase {
@Test
public void testTranslation() {
// Unrecognised country for caller
assertNull(CountryCodes.translate("02012345678", "ZZ", "GB"));
// Unrecognised country for callee
assertNull(CountryCodes.translate("02012345678", "GB", "ZZ"));
// GB to GB, callee has not included a prefix
assertEquals("02012345678",
CountryCodes.translate("2012345678", "GB", "GB"));
// GB to GB, callee has included NDD prefix
assertEquals("02012345678",
CountryCodes.translate("02012345678", "GB", "GB"));
// GB to GB, callee has included plus sign and country code
assertEquals("02012345678",
CountryCodes.translate("+442012345678", "GB", "GB"));
// GB to GB, callee has included IDD prefix and country code
assertEquals("02012345678",
CountryCodes.translate("00442012345678", "GB", "GB"));
// Russia to GB, callee has not included a prefix
assertEquals("8**10442012345678",
CountryCodes.translate("2012345678", "RU", "GB"));
// Russia to GB, callee has included NDD prefix
assertEquals("8**10442012345678",
CountryCodes.translate("02012345678", "RU", "GB"));
// Russia to GB, callee has included plus sign and country code
assertEquals("8**10442012345678",
CountryCodes.translate("+442012345678", "RU", "GB"));
// Russia to GB, callee has included IDD prefix and country code
assertEquals("8**10442012345678",
CountryCodes.translate("00442012345678", "RU", "GB"));
// Andorra to Andorra (no NDD), callee has not included a prefix
assertEquals("765432", CountryCodes.translate("765432", "AD", "AD"));
// Andorra to Andorra, callee has included plus sign and country code
assertEquals("765432",
CountryCodes.translate("+376765432", "AD", "AD"));
// Andorra to Andorra, callee has included IDD and country code
assertEquals("765432",
CountryCodes.translate("00376765432", "AD", "AD"));
// GB to Andorra (no NDD), callee has not included a prefix
assertEquals("00376765432",
CountryCodes.translate("765432", "GB", "AD"));
// GB to Andorra, callee has included plus sign and country code
assertEquals("00376765432",
CountryCodes.translate("+376765432", "GB", "AD"));
// GB to Andorra, callee has included IDD and country code
assertEquals("00376765432",
CountryCodes.translate("00376765432", "GB", "AD"));
}
}

View File

@@ -0,0 +1,288 @@
package org.briarproject.plugins.modem;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.BriarTestCase;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.hamcrest.Description;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.api.Action;
import org.jmock.api.Invocation;
import org.junit.Test;
public class ModemPluginTest extends BriarTestCase {
private static final String ISO_1336 = "GB";
private static final String NUMBER1 = "0123";
private static final String NUMBER2 = "0234";
private static final String NUMBER3 = "0345";
@Test
public void testModemCreation() throws Exception {
Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList =
context.mock(SerialPortList.class);
final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
serialPortList, null, 0, 0, 0, true);
final Modem modem = context.mock(Modem.class);
context.checking(new Expectations() {{
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo", "bar", "baz" }));
// First call to createModem() returns false
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(false));
// Second call to createModem() throws an exception
oneOf(modemFactory).createModem(plugin, "bar");
will(returnValue(modem));
oneOf(modem).start();
will(throwException(new IOException()));
// Third call to createModem() returns true
oneOf(modemFactory).createModem(plugin, "baz");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
}});
assertTrue(plugin.start());
context.assertIsSatisfied();
}
@Test
public void testCreateConnection() throws Exception {
Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList =
context.mock(SerialPortList.class);
final DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
serialPortList, callback, 0, 0, 0, true);
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER1);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
will(returnValue(remote));
oneOf(modem).dial(NUMBER1);
will(returnValue(true));
}});
assertTrue(plugin.start());
// A connection should be returned
assertNotNull(plugin.createConnection(contactId));
context.assertIsSatisfied();
}
@Test
public void testCreateConnectionWhenDialReturnsFalse() throws Exception {
Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList =
context.mock(SerialPortList.class);
final DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
serialPortList, callback, 0, 0, 0, true);
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER1);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
will(returnValue(remote));
oneOf(modem).dial(NUMBER1);
will(returnValue(false));
}});
assertTrue(plugin.start());
// No connection should be returned
assertNull(plugin.createConnection(contactId));
context.assertIsSatisfied();
}
@Test
public void testCreateConnectionWhenDialThrowsException() throws Exception {
Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList =
context.mock(SerialPortList.class);
final DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
final ModemPlugin plugin = new ModemPlugin(null, modemFactory,
serialPortList, callback, 0, 0, 0, true);
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p = new TransportProperties();
p.put("iso3166", ISO_1336);
p.put("number", NUMBER1);
ContactId contactId = new ContactId(234);
final Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
// createConnection()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
will(returnValue(remote));
oneOf(modem).dial(NUMBER1);
will(throwException(new IOException()));
// resetModem()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
}});
assertTrue(plugin.start());
// No connection should be returned
assertNull(plugin.createConnection(contactId));
context.assertIsSatisfied();
}
@Test
public void testPolling() throws Exception {
final ExecutorService pluginExecutor =
Executors.newSingleThreadExecutor();
Mockery context = new Mockery();
final ModemFactory modemFactory = context.mock(ModemFactory.class);
final SerialPortList serialPortList =
context.mock(SerialPortList.class);
final DuplexPluginCallback callback =
context.mock(DuplexPluginCallback.class);
// Disable shuffling for this test, it confuses jMock
final ModemPlugin plugin = new ModemPlugin(pluginExecutor, modemFactory,
serialPortList, callback, 0, 0, 0, false);
final Modem modem = context.mock(Modem.class);
final TransportProperties local = new TransportProperties();
local.put("iso3166", ISO_1336);
TransportProperties p1 = new TransportProperties();
p1.put("iso3166", ISO_1336);
p1.put("number", NUMBER1);
TransportProperties p2 = new TransportProperties();
p2.put("iso3166", ISO_1336);
p2.put("number", NUMBER2);
TransportProperties p3 = new TransportProperties();
p3.put("iso3166", ISO_1336);
p3.put("number", NUMBER3);
ContactId contactId1 = new ContactId(234);
ContactId contactId2 = new ContactId(345);
ContactId contactId3 = new ContactId(456);
final Map<ContactId, TransportProperties> remote =
new HashMap<ContactId, TransportProperties>();
remote.put(contactId1, p1);
remote.put(contactId2, p2);
remote.put(contactId3, p3);
final DisposeAction disposeAction = new DisposeAction();
context.checking(new Expectations() {{
// start()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
// poll()
oneOf(callback).getLocalProperties();
will(returnValue(local));
oneOf(callback).getRemoteProperties();
will(returnValue(remote));
// First call to dial() throws an exception
oneOf(modem).dial(NUMBER1);
will(throwException(new IOException()));
// resetModem()
oneOf(serialPortList).getPortNames();
will(returnValue(new String[] { "foo" }));
oneOf(modemFactory).createModem(plugin, "foo");
will(returnValue(modem));
oneOf(modem).start();
will(returnValue(true));
// Second call to dial() returns true
oneOf(modem).dial(NUMBER2);
will(returnValue(true));
// A connection is passed to the callback - dispose of it
oneOf(callback).outgoingConnectionCreated(
with(any(ContactId.class)),
with(any(DuplexTransportConnection.class)));
will(disposeAction);
oneOf(modem).hangUp();
// Third call to dial() returns false
oneOf(modem).dial(NUMBER3);
will(returnValue(false));
}});
assertTrue(plugin.start());
plugin.poll(Collections.<ContactId>emptyList());
assertTrue(disposeAction.invoked.await(5, SECONDS));
pluginExecutor.shutdown();
context.assertIsSatisfied();
}
private static class DisposeAction implements Action {
private final CountDownLatch invoked = new CountDownLatch(1);
public void describeTo(Description description) {
description.appendText("Disposes of a transport connection");
}
public Object invoke(Invocation invocation) throws Throwable {
DuplexTransportConnection conn =
(DuplexTransportConnection) invocation.getParameter(1);
conn.dispose(false, true);
invoked.countDown();
return null;
}
}
}

View File

@@ -0,0 +1,47 @@
package org.briarproject.plugins.tcp;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.SystemClock;
import org.briarproject.plugins.DuplexClientTest;
// This is not a JUnit test - it has to be run manually while the server test
// is running on another machine
public class LanTcpClientTest extends DuplexClientTest {
private LanTcpClientTest(Executor executor, String serverAddress,
String serverPort) {
// Store the server's internal address and port
TransportProperties p = new TransportProperties();
p.put("internal", serverAddress);
p.put("port", serverPort);
Map<ContactId, TransportProperties> remote =
Collections.singletonMap(contactId, p);
// Create the plugin
callback = new ClientCallback(new TransportConfig(),
new TransportProperties(), remote);
Clock clock = new SystemClock();
plugin = new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
}
public static void main(String[] args) throws Exception {
if(args.length != 2) {
System.err.println("Please specify the server's address and port");
System.exit(1);
}
ExecutorService executor = Executors.newCachedThreadPool();
try {
new LanTcpClientTest(executor, args[0], args[1]).run();
} finally {
executor.shutdown();
}
}
}

View File

@@ -0,0 +1,147 @@
package org.briarproject.plugins.tcp;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.briarproject.BriarTestCase;
import org.briarproject.api.ContactId;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.SystemClock;
import org.junit.Test;
public class LanTcpPluginTest extends BriarTestCase {
private final ContactId contactId = new ContactId(234);
@Test
public void testIncomingConnection() throws Exception {
Callback callback = new Callback();
callback.local.put("address", "127.0.0.1");
callback.local.put("port", "0");
Executor executor = Executors.newCachedThreadPool();
Clock clock = new SystemClock();
DuplexPlugin plugin =
new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
plugin.start();
// The plugin should have bound a socket and stored the port number
assertTrue(callback.propertiesLatch.await(5, SECONDS));
String host = callback.local.get("address");
assertNotNull(host);
assertEquals("127.0.0.1", host);
String portString = callback.local.get("port");
assertNotNull(portString);
int port = Integer.parseInt(portString);
assertTrue(port > 0 && port < 65536);
// The plugin should be listening on the port
InetSocketAddress addr = new InetSocketAddress(host, port);
Socket s = new Socket();
s.connect(addr, 100);
assertTrue(callback.connectionsLatch.await(5, SECONDS));
s.close();
// Stop the plugin
plugin.stop();
}
@Test
public void testOutgoingConnection() throws Exception {
Callback callback = new Callback();
Executor executor = Executors.newCachedThreadPool();
Clock clock = new SystemClock();
DuplexPlugin plugin =
new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
plugin.start();
// Listen on a local port
final ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress("127.0.0.1", 0), 10);
int port = ss.getLocalPort();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean error = new AtomicBoolean(false);
new Thread() {
@Override
public void run() {
try {
ss.accept();
latch.countDown();
} catch(IOException e) {
error.set(true);
}
}
}.start();
// Tell the plugin about the port
TransportProperties p = new TransportProperties();
p.put("address", "127.0.0.1");
p.put("port", String.valueOf(port));
callback.remote.put(contactId, p);
// Connect to the port
DuplexTransportConnection d = plugin.createConnection(contactId);
assertNotNull(d);
// Check that the connection was accepted
assertTrue(latch.await(5, SECONDS));
assertFalse(error.get());
// Clean up
d.dispose(false, true);
ss.close();
plugin.stop();
}
private static class Callback implements DuplexPluginCallback {
private final Map<ContactId, TransportProperties> remote =
new Hashtable<ContactId, TransportProperties>();
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
private final TransportProperties local = new TransportProperties();
public TransportConfig getConfig() {
return new TransportConfig();
}
public TransportProperties getLocalProperties() {
return local;
}
public Map<ContactId, TransportProperties> getRemoteProperties() {
return remote;
}
public void mergeConfig(TransportConfig c) {}
public void mergeLocalProperties(TransportProperties p) {
local.putAll(p);
propertiesLatch.countDown();
}
public int showChoice(String[] options, String... message) {
return -1;
}
public boolean showConfirmationMessage(String... message) {
return false;
}
public void showMessage(String... message) {}
public void incomingConnectionCreated(DuplexTransportConnection d) {
connectionsLatch.countDown();
}
public void outgoingConnectionCreated(ContactId c,
DuplexTransportConnection d) {}
}
}

View File

@@ -0,0 +1,34 @@
package org.briarproject.plugins.tcp;
import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.briarproject.api.TransportConfig;
import org.briarproject.api.TransportProperties;
import org.briarproject.api.system.Clock;
import org.briarproject.api.system.SystemClock;
import org.briarproject.plugins.DuplexServerTest;
// This is not a JUnit test - it has to be run manually while the client test
// is running on another machine
public class LanTcpServerTest extends DuplexServerTest {
private LanTcpServerTest(Executor executor) {
callback = new ServerCallback(new TransportConfig(),
new TransportProperties(),
Collections.singletonMap(contactId, new TransportProperties()));
Clock clock = new SystemClock();
plugin = new LanTcpPlugin(executor, clock, callback, 0, 0, 0);
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
try {
new LanTcpServerTest(executor).run();
} finally {
executor.shutdown();
}
}
}