diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6e6e62d9630d25a977003cda3f49cbe8c55ca837
--- /dev/null
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
@@ -0,0 +1,88 @@
+package net.sf.briar.plugins.bluetooth;
+
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.TreeMap;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.transport.stream.StreamTransportCallback;
+import net.sf.briar.api.transport.stream.StreamTransportConnection;
+import net.sf.briar.plugins.ImmediateExecutor;
+
+// This is not a JUnit test - it has to be run manually while the server test
+// is running on another machine
+public class BluetoothClientTest {
+
+	public static final String RESPONSE = "Carrots!";
+
+	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);
+		}
+		ContactId contactId = new ContactId(0);
+		Map<String, String> localProperties = Collections.emptyMap();
+		Map<ContactId, Map<String, String>> remoteProperties =
+			new HashMap<ContactId, Map<String, String>>();
+		Map<String, String> config = Collections.emptyMap();
+		StreamTransportCallback callback = new ClientCallback();
+		// Store the server's Bluetooth address and UUID
+		Map<String, String> properties = new TreeMap<String, String>();
+		properties.put("address", args[0]);
+		properties.put("uuid", BluetoothServerTest.UUID);
+		remoteProperties.put(contactId, properties);
+		// Create the plugin
+		BluetoothPlugin plugin =
+			new BluetoothPlugin(new ImmediateExecutor(), 0L);
+		// Start the plugin
+		System.out.println("Starting plugin");
+		plugin.start(localProperties, remoteProperties, config, callback);
+		// Try to connect to the server
+		System.out.println("Creating connection");
+		StreamTransportConnection conn = plugin.createConnection(contactId);
+		if(conn == null) {
+			System.out.println("Connection failed");
+		} else {
+			System.out.println("Connection created");
+			Scanner in = new Scanner(conn.getInputStream());
+			String challenge = in.nextLine();
+			System.out.println("Received challenge: " + challenge);
+			if(BluetoothServerTest.CHALLENGE.equals(challenge)) {
+				PrintStream out = new PrintStream(conn.getOutputStream());
+				out.println(RESPONSE);
+				System.out.println("Sent response: " + RESPONSE);
+			} else {
+				System.out.println("Incorrect challenge");
+			}
+			conn.dispose(true);
+		}
+		// Stop the plugin
+		System.out.println("Stopping plugin");
+		plugin.stop();
+	}
+
+	private static class ClientCallback implements StreamTransportCallback {
+
+		public void setLocalProperties(Map<String, String> properties) {}
+
+		public void setConfig(Map<String, String> config) {}
+
+		public void showMessage(String... message) {}
+
+		public boolean showConfirmationMessage(String... message) {
+			return false;
+		}
+
+		public int showChoice(String[] choices, String... message) {
+			return -1;
+		}
+
+		public void incomingConnectionCreated(StreamTransportConnection c) {}
+
+		public void outgoingConnectionCreated(ContactId contactId,
+				StreamTransportConnection c) {}
+	}
+}
diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a990f4b95360573f84958d04c1e5d72f0cfe4b9
--- /dev/null
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
@@ -0,0 +1,88 @@
+package net.sf.briar.plugins.bluetooth;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.TreeMap;
+
+import net.sf.briar.api.ContactId;
+import net.sf.briar.api.transport.stream.StreamTransportCallback;
+import net.sf.briar.api.transport.stream.StreamTransportConnection;
+import net.sf.briar.plugins.ImmediateExecutor;
+
+//This is not a JUnit test - it has to be run manually while the server test
+//is running on another machine
+public class BluetoothServerTest {
+
+	public static final String UUID = "CABBA6E5CABBA6E5CABBA6E5CABBA6E5";
+	public static final String CHALLENGE = "Potatoes!";
+
+	public static void main(String[] args) throws Exception {
+		Map<String, String> localProperties = Collections.emptyMap();
+		Map<ContactId, Map<String, String>> remoteProperties =
+			Collections.emptyMap();
+		Map<String, String> config = new TreeMap<String, String>();
+		StreamTransportCallback callback = new ServerCallback();
+		// Store the UUID
+		config.put("uuid", UUID);
+		// Create the plugin
+		BluetoothPlugin plugin =
+			new BluetoothPlugin(new ImmediateExecutor(), 0L);
+		// Start the plugin
+		System.out.println("Starting plugin");
+		plugin.start(localProperties, remoteProperties, config, callback);
+		// Wait for a connection
+		System.out.println("Waiting for connection");
+		synchronized(callback) {
+			callback.wait();
+		}
+		// Stop the plugin
+		System.out.println("Stopping plugin");
+		plugin.stop();
+	}
+
+	private static class ServerCallback implements StreamTransportCallback {
+
+		public void setLocalProperties(Map<String, String> properties) {}
+
+		public void setConfig(Map<String, String> config) {}
+
+		public void showMessage(String... message) {}
+
+		public boolean showConfirmationMessage(String... message) {
+			return false;
+		}
+
+		public int showChoice(String[] choices, String... message) {
+			return -1;
+		}
+
+		public void incomingConnectionCreated(StreamTransportConnection conn) {
+			System.out.println("Connection received");
+			try {
+				PrintStream out = new PrintStream(conn.getOutputStream());
+				out.println(CHALLENGE);
+				System.out.println("Sent challenge: " + CHALLENGE);
+				Scanner in = new Scanner(conn.getInputStream());
+				String response = in.nextLine();
+				System.out.println("Received response: " + response);
+				if(BluetoothClientTest.RESPONSE.equals(response)) {
+					System.out.println("Correct response");
+				} else {
+					System.out.println("Incorrect response");
+				}
+				conn.dispose(true);
+			} catch(IOException e) {
+				e.printStackTrace();
+			}
+			synchronized(this) {
+				notifyAll();
+			}
+		}
+
+		public void outgoingConnectionCreated(ContactId contactId,
+				StreamTransportConnection c) {}
+	}
+}