From 1bf0fdfa8135fd1ef202b1c9032afb520b5ca16c Mon Sep 17 00:00:00 2001
From: Torsten Grote <t@grobox.de>
Date: Thu, 21 Sep 2017 17:16:42 -0300
Subject: [PATCH] Add an option to debug builds to create fake test data

---
 .../bramble/plugin/tor/TorPlugin.java         |   2 +-
 .../bramble/api/plugin/LanTcpConstants.java   |   5 +
 .../bramble/api/plugin/TorConstants.java      |   3 +
 .../bramble/util/StringUtils.java             |  10 +
 .../briarproject/bramble/test/TestUtils.java  |   7 -
 .../bramble/plugin/tcp/LanTcpPlugin.java      |   2 +-
 .../bramble/client/ClientHelperImplTest.java  |   4 +-
 .../briarproject/bramble/crypto/HashTest.java |   5 +-
 .../bramble/crypto/SignatureTest.java         |   7 +-
 .../bramble/data/BdfReaderImplTest.java       |  21 +-
 .../bramble/data/BdfWriterImplTest.java       |   8 +-
 .../briarproject/bramble/db/BasicH2Test.java  |   9 +-
 .../bramble/db/DatabaseComponentImplTest.java |   3 +-
 .../bramble/db/H2DatabaseTest.java            |   3 +-
 .../identity/IdentityManagerImplTest.java     |   8 +-
 .../TransportPropertyValidatorTest.java       |   5 +-
 .../bramble/sync/SyncIntegrationTest.java     |   3 +-
 .../sync/ValidationManagerImplTest.java       |   3 +-
 .../bramble/test/ValidatorTestCase.java       |   3 +-
 .../briar/android/AndroidComponent.java       |   6 +-
 .../android/activity/ActivityComponent.java   |   3 +
 .../android/settings/SettingsActivity.java    |  24 -
 .../android/settings/SettingsFragment.java    |  43 +-
 briar-android/src/main/res/xml/settings.xml   |   4 +
 .../briar/api/test/TestDataCreator.java       |  11 +
 .../briar/BriarCoreEagerSingletons.java       |   1 +
 .../briarproject/briar/BriarCoreModule.java   |   4 +-
 .../org/briarproject/briar/test/TestData.java |  68 +++
 .../briar/test/TestDataCreatorImpl.java       | 409 ++++++++++++++++++
 .../briarproject/briar/test/TestModule.java   |  19 +
 .../briar/blog/BlogManagerImplTest.java       |   2 +-
 .../blog/BlogManagerIntegrationTest.java      |   2 +-
 .../briar/blog/BlogPostValidatorTest.java     |   3 +-
 .../client/MessageQueueManagerImplTest.java   |   3 +-
 .../briar/forum/ForumPostValidatorTest.java   |  11 +-
 .../IntroductionIntegrationTest.java          |   3 +-
 .../IntroductionManagerImplTest.java          |   3 +-
 .../IntroductionValidatorTest.java            |  29 +-
 .../briar/introduction/MessageSenderTest.java |   3 +-
 .../messaging/MessageSizeIntegrationTest.java |   4 +-
 .../PrivateMessageValidatorTest.java          |   6 +-
 .../GroupMessageValidatorTest.java            |   2 +-
 .../GroupInvitationManagerImplTest.java       |   2 +-
 .../GroupInvitationValidatorTest.java         |   2 +-
 .../sharing/BlogSharingValidatorTest.java     |  11 +-
 .../sharing/ForumSharingIntegrationTest.java  |   2 +-
 .../sharing/ForumSharingValidatorTest.java    |  11 +-
 47 files changed, 676 insertions(+), 126 deletions(-)
 create mode 100644 briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/test/TestData.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java
 create mode 100644 briar-core/src/main/java/org/briarproject/briar/test/TestModule.java

diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
index 69eb13d5a4..9ad9f427f0 100644
--- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
+++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tor/TorPlugin.java
@@ -84,13 +84,13 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
 import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
 import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
 import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
+import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
 import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
 
 @MethodsNotNullByDefault
 @ParametersNotNullByDefault
 class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
 
-	private static final String PROP_ONION = "onion";
 	private static final String[] EVENTS = {
 			"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
 	};
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
index 9d486c4ae1..506bd75895 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/LanTcpConstants.java
@@ -4,5 +4,10 @@ public interface LanTcpConstants {
 
 	TransportId ID = new TransportId("org.briarproject.bramble.lan");
 
+	// a transport property (shared with contacts)
+	String PROP_IP_PORTS = "ipPorts";
+
+	// a local setting
 	String PREF_LAN_IP_PORTS = "ipPorts";
+
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
index 639155ac4a..8f265a95ed 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/api/plugin/TorConstants.java
@@ -4,6 +4,8 @@ public interface TorConstants {
 
 	TransportId ID = new TransportId("org.briarproject.bramble.tor");
 
+	String PROP_ONION = "onion";
+
 	int SOCKS_PORT = 59050;
 	int CONTROL_PORT = 59051;
 
@@ -16,4 +18,5 @@ public interface TorConstants {
 	int PREF_TOR_NETWORK_NEVER = 0;
 	int PREF_TOR_NETWORK_WIFI = 1;
 	int PREF_TOR_NETWORK_ALWAYS = 2;
+
 }
diff --git a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
index 4cfe34ee98..7e1556fb51 100644
--- a/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
+++ b/bramble-api/src/main/java/org/briarproject/bramble/util/StringUtils.java
@@ -8,6 +8,7 @@ import java.nio.charset.CharacterCodingException;
 import java.nio.charset.Charset;
 import java.nio.charset.CharsetDecoder;
 import java.util.Collection;
+import java.util.Random;
 import java.util.regex.Pattern;
 
 import javax.annotation.Nullable;
@@ -27,6 +28,7 @@ public class StringUtils {
 			'0', '1', '2', '3', '4', '5', '6', '7',
 			'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
 	};
+	private static final Random random = new Random();
 
 	public static boolean isNullOrEmpty(@Nullable String s) {
 		return s == null || s.length() == 0;
@@ -139,4 +141,12 @@ public class StringUtils {
 		}
 		return s.toString();
 	}
+
+	public static String getRandomString(int length) {
+		char[] c = new char[length];
+		for (int i = 0; i < length; i++)
+			c[i] = (char) ('a' + random.nextInt(26));
+		return new String(c);
+	}
+
 }
diff --git a/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java b/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java
index 9e8a1df9ac..b07f79d5fc 100644
--- a/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java
+++ b/bramble-api/src/test/java/org/briarproject/bramble/test/TestUtils.java
@@ -34,13 +34,6 @@ public class TestUtils {
 		return getRandomBytes(UniqueId.LENGTH);
 	}
 
-	public static String getRandomString(int length) {
-		char[] c = new char[length];
-		for (int i = 0; i < length; i++)
-			c[i] = (char) ('a' + random.nextInt(26));
-		return new String(c);
-	}
-
 	public static SecretKey getSecretKey() {
 		return new SecretKey(getRandomBytes(SecretKey.LENGTH));
 	}
diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
index 8819644709..c1cdb0b35f 100644
--- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
+++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java
@@ -35,6 +35,7 @@ import static java.util.logging.Level.WARNING;
 import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
 import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
 import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
+import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
 import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
 import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
 
@@ -45,7 +46,6 @@ class LanTcpPlugin extends TcpPlugin {
 			Logger.getLogger(LanTcpPlugin.class.getName());
 
 	private static final int MAX_ADDRESSES = 4;
-	private static final String PROP_IP_PORTS = "ipPorts";
 	private static final String SEPARATOR = ",";
 
 	LanTcpPlugin(Executor ioExecutor, Backoff backoff,
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java
index d0def2ad4c..f41f6a225e 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/client/ClientHelperImplTest.java
@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.sync.Message;
 import org.briarproject.bramble.api.sync.MessageFactory;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.test.BrambleTestCase;
-import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -65,7 +65,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
 			new Message(messageId, groupId, timestamp, rawMessage);
 	private final Metadata metadata = new Metadata();
 	private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
-	private final String label = TestUtils.getRandomString(5);
+	private final String label = StringUtils.getRandomString(5);
 
 	public ClientHelperImplTest() {
 		clientHelper =
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java
index bce8b720ea..dcd3177ba7 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/HashTest.java
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestSecureRandomProvider;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -15,7 +16,7 @@ public class HashTest extends BrambleTestCase {
 
 	private final CryptoComponent crypto;
 
-	private final String label = TestUtils.getRandomString(42);
+	private final String label = StringUtils.getRandomString(42);
 	private final byte[] inputBytes = TestUtils.getRandomBytes(123);
 	private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
 	private final byte[] inputBytes2 = new byte[0];
@@ -40,7 +41,7 @@ public class HashTest extends BrambleTestCase {
 
 	@Test
 	public void testDifferentLabelsProduceDifferentHashes() {
-		String label2 = TestUtils.getRandomString(42);
+		String label2 = StringUtils.getRandomString(42);
 		byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
 		byte[] hash2 =
 				crypto.hash(label2, inputBytes, inputBytes1, inputBytes2);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java
index c11444c634..4bf6017a8b 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/SignatureTest.java
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.crypto.KeyPair;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestSecureRandomProvider;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.util.Arrays;
@@ -18,7 +19,7 @@ public class SignatureTest extends BrambleTestCase {
 	private final CryptoComponent crypto;
 
 	private final byte[] publicKey, privateKey;
-	private final String label = TestUtils.getRandomString(42);
+	private final String label = StringUtils.getRandomString(42);
 	private final byte[] inputBytes = TestUtils.getRandomBytes(123);
 
 	public SignatureTest() {
@@ -64,7 +65,7 @@ public class SignatureTest extends BrambleTestCase {
 	public void testDifferentLabelsProduceDifferentSignatures()
 			throws Exception {
 		// Generate a second label
-		String label2 = TestUtils.getRandomString(42);
+		String label2 = StringUtils.getRandomString(42);
 		// Calculate the signature with different inputs
 		// the results should be different
 		byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
@@ -100,7 +101,7 @@ public class SignatureTest extends BrambleTestCase {
 	@Test
 	public void testDifferentLabelFailsVerification() throws Exception {
 		// Generate a second label
-		String label2 = TestUtils.getRandomString(42);
+		String label2 = StringUtils.getRandomString(42);
 		// calculate the signature with different label, should fail to verify
 		byte[] sig = crypto.sign(label, inputBytes, privateKey);
 		assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java
index f8e5fc070a..5e237782c0 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfReaderImplTest.java
@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.test.BrambleTestCase;
-import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
@@ -159,7 +158,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testReadString8() throws Exception {
-		String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		// "foo", the empty string, and 127 random letters
 		setContents("41" + "03" + "666F6F" + "41" + "00" +
@@ -181,7 +180,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testSkipString8() throws Exception {
-		String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		// "foo", the empty string, and 127 random letters
 		setContents("41" + "03" + "666F6F" + "41" + "00" +
@@ -194,9 +193,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testReadString16() throws Exception {
-		String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
-		String longest = TestUtils.getRandomString(Short.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Short.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		// 128 random letters and 2^15 -1 random letters
 		setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
@@ -207,7 +206,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test(expected = FormatException.class)
 	public void testReadString16ChecksMaxLength() throws Exception {
-		String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
 		// 128 random letters, twice
 		setContents("42" + "0080" + shortHex + "42" + "0080" + shortHex);
@@ -218,9 +217,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testSkipString16() throws Exception {
-		String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
-		String longest = TestUtils.getRandomString(Short.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Short.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		// 128 random letters and 2^15 - 1 random letters
 		setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
@@ -231,7 +230,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testReadString32() throws Exception {
-		String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
 		// 2^15 random letters
 		setContents("44" + "00008000" + shortHex);
@@ -241,7 +240,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test(expected = FormatException.class)
 	public void testReadString32ChecksMaxLength() throws Exception {
-		String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
 		// 2^15 random letters, twice
 		setContents("44" + "00008000" + shortHex +
@@ -253,7 +252,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
 
 	@Test
 	public void testSkipString32() throws Exception {
-		String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
 		// 2^15 random letters, twice
 		setContents("44" + "00008000" + shortHex +
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java
index c480c91c65..1737f746f3 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/data/BdfWriterImplTest.java
@@ -81,7 +81,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
 
 	@Test
 	public void testWriteString8() throws IOException {
-		String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		w.writeString("foo bar baz bam ");
 		w.writeString(longest);
@@ -93,9 +93,9 @@ public class BdfWriterImplTest extends BrambleTestCase {
 
 	@Test
 	public void testWriteString16() throws IOException {
-		String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
-		String longest = TestUtils.getRandomString(Short.MAX_VALUE);
+		String longest = StringUtils.getRandomString(Short.MAX_VALUE);
 		String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
 		w.writeString(shortest);
 		w.writeString(longest);
@@ -106,7 +106,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
 
 	@Test
 	public void testWriteString32() throws IOException {
-		String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
+		String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
 		String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
 		w.writeString(shortest);
 		// STRING_32 tag, length 2^15, UTF-8 bytes
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/BasicH2Test.java b/bramble-core/src/test/java/org/briarproject/bramble/db/BasicH2Test.java
index da5d7aecfe..f6a21e2f86 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/BasicH2Test.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/BasicH2Test.java
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
 
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -48,8 +49,8 @@ public class BasicH2Test extends BrambleTestCase {
 		createTable(connection);
 		// Generate an ID and two names
 		byte[] id = TestUtils.getRandomId();
-		String oldName = TestUtils.getRandomString(50);
-		String newName = TestUtils.getRandomString(50);
+		String oldName = StringUtils.getRandomString(50);
+		String newName = StringUtils.getRandomString(50);
 		// Insert the ID and old name into the table
 		insertRow(id, oldName);
 		// Check that the old name can be retrieved using the ID
@@ -78,8 +79,8 @@ public class BasicH2Test extends BrambleTestCase {
 		String[] newNames = new String[BATCH_SIZE];
 		for (int i = 0; i < BATCH_SIZE; i++) {
 			ids[i] = TestUtils.getRandomId();
-			oldNames[i] = TestUtils.getRandomString(50);
-			newNames[i] = TestUtils.getRandomString(50);
+			oldNames[i] = StringUtils.getRandomString(50);
+			newNames[i] = StringUtils.getRandomString(50);
 		}
 		// Insert the IDs and old names into the table as a batch
 		insertBatch(ids, oldNames);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
index 62309e2d13..680e25652e 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java
@@ -49,6 +49,7 @@ import org.briarproject.bramble.api.transport.OutgoingKeys;
 import org.briarproject.bramble.api.transport.TransportKeys;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -94,7 +95,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
 	private final Contact contact;
 
 	public DatabaseComponentImplTest() {
-		clientId = new ClientId(TestUtils.getRandomString(5));
+		clientId = new ClientId(StringUtils.getRandomString(5));
 		groupId = new GroupId(TestUtils.getRandomId());
 		byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
 		group = new Group(groupId, clientId, descriptor);
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/H2DatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/H2DatabaseTest.java
index 7bd913489a..91ab9f597e 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/db/H2DatabaseTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/db/H2DatabaseTest.java
@@ -24,6 +24,7 @@ import org.briarproject.bramble.system.SystemClock;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestDatabaseConfig;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -84,7 +85,7 @@ public class H2DatabaseTest extends BrambleTestCase {
 
 	public H2DatabaseTest() throws Exception {
 		groupId = new GroupId(TestUtils.getRandomId());
-		clientId = new ClientId(TestUtils.getRandomString(5));
+		clientId = new ClientId(StringUtils.getRandomString(5));
 		byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
 		group = new Group(groupId, clientId, descriptor);
 		AuthorId authorId = new AuthorId(TestUtils.getRandomId());
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
index fee5bc9fc1..e653546714 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/identity/IdentityManagerImplTest.java
@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.identity.IdentityManager;
 import org.briarproject.bramble.api.identity.LocalAuthor;
 import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Expectations;
 import org.junit.Test;
 
@@ -31,8 +32,9 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
 	private final Transaction txn = new Transaction(null, false);
 	private final LocalAuthor localAuthor =
 			new LocalAuthor(new AuthorId(TestUtils.getRandomId()),
-					TestUtils.getRandomString(8), TestUtils.getRandomBytes(42),
-					TestUtils.getRandomBytes(42), 0);
+					StringUtils.getRandomString(8),
+					TestUtils.getRandomBytes(42), TestUtils.getRandomBytes(42),
+					0);
 	private final Collection<LocalAuthor> localAuthors =
 			Collections.singletonList(localAuthor);
 
@@ -93,7 +95,7 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
 		assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
 
 		// add one unverified contact
-		Author author = new Author(authorId, TestUtils.getRandomString(8),
+		Author author = new Author(authorId, StringUtils.getRandomString(8),
 				TestUtils.getRandomBytes(42));
 		Contact contact =
 				new Contact(new ContactId(1), author, localAuthor.getId(),
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
index 7d48fa75df..0ffc9e7332 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/properties/TransportPropertyValidatorTest.java
@@ -14,6 +14,7 @@ import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Mockery;
 import org.junit.Test;
 
@@ -36,7 +37,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
 		bdfDictionary = new BdfDictionary();
 
 		GroupId groupId = new GroupId(TestUtils.getRandomId());
-		ClientId clientId = new ClientId(TestUtils.getRandomString(5));
+		ClientId clientId = new ClientId(StringUtils.getRandomString(5));
 		byte[] descriptor = TestUtils.getRandomBytes(12);
 		group = new Group(groupId, clientId, descriptor);
 
@@ -85,7 +86,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
 	public void testValidateLongTransportId() throws IOException {
 
 		String wrongTransportIdString =
-				TestUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
+				StringUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
 		BdfList body = BdfList.of(wrongTransportIdString, 4, bdfDictionary);
 		tpv.validateMessage(message, group, body);
 	}
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTest.java
index c19d148b1e..bc5c86a8d5 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/sync/SyncIntegrationTest.java
@@ -22,6 +22,7 @@ import org.briarproject.bramble.api.transport.StreamReaderFactory;
 import org.briarproject.bramble.api.transport.StreamWriterFactory;
 import org.briarproject.bramble.test.BrambleTestCase;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import java.io.ByteArrayInputStream;
@@ -78,7 +79,7 @@ public class SyncIntegrationTest extends BrambleTestCase {
 		headerKey = TestUtils.getSecretKey();
 		streamNumber = 123;
 		// Create a group
-		ClientId clientId = new ClientId(TestUtils.getRandomString(5));
+		ClientId clientId = new ClientId(StringUtils.getRandomString(5));
 		byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
 		Group group = groupFactory.createGroup(clientId, descriptor);
 		// Add two messages to the group
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/sync/ValidationManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/sync/ValidationManagerImplTest.java
index ed6c361de4..28af730180 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/sync/ValidationManagerImplTest.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/sync/ValidationManagerImplTest.java
@@ -23,6 +23,7 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
 import org.briarproject.bramble.test.ImmediateExecutor;
 import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Expectations;
 import org.junit.Before;
 import org.junit.Test;
@@ -51,7 +52,7 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
 	private final Executor dbExecutor = new ImmediateExecutor();
 	private final Executor validationExecutor = new ImmediateExecutor();
 	private final ClientId clientId =
-			new ClientId(TestUtils.getRandomString(5));
+			new ClientId(StringUtils.getRandomString(5));
 	private final MessageId messageId = new MessageId(TestUtils.getRandomId());
 	private final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
 	private final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/ValidatorTestCase.java b/bramble-core/src/test/java/org/briarproject/bramble/test/ValidatorTestCase.java
index 07afb2e58b..5f29d02034 100644
--- a/bramble-core/src/test/java/org/briarproject/bramble/test/ValidatorTestCase.java
+++ b/bramble-core/src/test/java/org/briarproject/bramble/test/ValidatorTestCase.java
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.Message;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.bramble.util.StringUtils;
 
 public abstract class ValidatorTestCase extends BrambleMockTestCase {
 
@@ -28,7 +29,7 @@ public abstract class ValidatorTestCase extends BrambleMockTestCase {
 	protected final Message message =
 			new Message(messageId, groupId, timestamp, raw);
 	protected final ClientId clientId =
-			new ClientId(TestUtils.getRandomString(123));
+			new ClientId(StringUtils.getRandomString(123));
 	protected final byte[] descriptor = TestUtils.getRandomBytes(123);
 	protected final Group group = new Group(groupId, clientId, descriptor);
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
index 4ad3f75b2f..25d553bbeb 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
@@ -26,7 +26,6 @@ import org.briarproject.briar.BriarCoreEagerSingletons;
 import org.briarproject.briar.BriarCoreModule;
 import org.briarproject.briar.android.reporting.BriarReportSender;
 import org.briarproject.briar.api.android.AndroidNotificationManager;
-import org.briarproject.briar.api.android.ReferenceManager;
 import org.briarproject.briar.api.android.ScreenFilterMonitor;
 import org.briarproject.briar.api.blog.BlogManager;
 import org.briarproject.briar.api.blog.BlogPostFactory;
@@ -44,6 +43,7 @@ import org.briarproject.briar.api.privategroup.PrivateGroupFactory;
 import org.briarproject.briar.api.privategroup.PrivateGroupManager;
 import org.briarproject.briar.api.privategroup.invitation.GroupInvitationFactory;
 import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
+import org.briarproject.briar.api.test.TestDataCreator;
 import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
 import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
 
@@ -73,8 +73,6 @@ public interface AndroidComponent
 
 	DatabaseConfig databaseConfig();
 
-	ReferenceManager referenceMangager();
-
 	@DatabaseExecutor
 	Executor databaseExecutor();
 
@@ -140,6 +138,8 @@ public interface AndroidComponent
 
 	Clock clock();
 
+	TestDataCreator testDataCreator();
+
 	@IoExecutor
 	Executor ioExecutor();
 
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
index 61eea88b24..0e8d460062 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
@@ -51,6 +51,7 @@ import org.briarproject.briar.android.privategroup.reveal.GroupRevealModule;
 import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
 import org.briarproject.briar.android.privategroup.reveal.RevealContactsFragment;
 import org.briarproject.briar.android.settings.SettingsActivity;
+import org.briarproject.briar.android.settings.SettingsFragment;
 import org.briarproject.briar.android.sharing.BlogInvitationActivity;
 import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
 import org.briarproject.briar.android.sharing.ForumInvitationActivity;
@@ -179,4 +180,6 @@ public interface ActivityComponent {
 
 	void inject(IntroductionMessageFragment fragment);
 
+	void inject(SettingsFragment fragment);
+
 }
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
index 022963eea3..37870a9831 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsActivity.java
@@ -4,24 +4,12 @@ import android.os.Bundle;
 import android.support.v7.app.ActionBar;
 import android.view.MenuItem;
 
-import org.briarproject.bramble.api.event.EventBus;
-import org.briarproject.bramble.api.settings.SettingsManager;
-import org.briarproject.bramble.api.system.AndroidExecutor;
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.activity.ActivityComponent;
 import org.briarproject.briar.android.activity.BriarActivity;
 
-import javax.inject.Inject;
-
 public class SettingsActivity extends BriarActivity {
 
-	@Inject
-	protected AndroidExecutor androidExecutor;
-	@Inject
-	protected SettingsManager settingsManager;
-	@Inject
-	protected EventBus eventBus;
-
 	@Override
 	public void onCreate(Bundle bundle) {
 		super.onCreate(bundle);
@@ -40,18 +28,6 @@ public class SettingsActivity extends BriarActivity {
 		component.inject(this);
 	}
 
-	public AndroidExecutor getAndroidExecutor() {
-		return androidExecutor;
-	}
-
-	public SettingsManager getSettingsManager() {
-		return settingsManager;
-	}
-
-	public EventBus getEventBus() {
-		return eventBus;
-	}
-
 	@Override
 	public boolean onOptionsItemSelected(MenuItem item) {
 		if (item.getItemId() == android.R.id.home) {
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
index ea213e3b83..d149f15f06 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/settings/SettingsFragment.java
@@ -34,9 +34,12 @@ import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.R;
 import org.briarproject.briar.android.util.UserFeedback;
 import org.briarproject.briar.android.widget.PreferenceDividerDecoration;
+import org.briarproject.briar.api.test.TestDataCreator;
 
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
+
 import static android.app.Activity.RESULT_OK;
 import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
 import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
@@ -53,6 +56,7 @@ import static java.util.logging.Level.WARNING;
 import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
 import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
 import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS;
+import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
 import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
 import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
 import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
@@ -77,7 +81,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
 			Logger.getLogger(SettingsFragment.class.getName());
 
 	private SettingsActivity listener;
-	private AndroidExecutor androidExecutor;
 	private ListPreference enableBluetooth;
 	private ListPreference torNetwork;
 	private CheckBoxPreference notifyPrivateMessages;
@@ -90,18 +93,24 @@ public class SettingsFragment extends PreferenceFragmentCompat
 	private Preference notifySound;
 
 	// Fields that are accessed from background threads must be volatile
-	private volatile SettingsManager settingsManager;
-	private volatile EventBus eventBus;
-	private volatile Settings settings;
+	volatile Settings settings;
+	@Inject
+	volatile SettingsManager settingsManager;
+	@Inject
+	volatile EventBus eventBus;
+
+	@Inject
+	AndroidExecutor androidExecutor;
+	@Inject
+	TestDataCreator testDataCreator;
 
 	@Override
 	public void onAttach(Context context) {
 		super.onAttach(context);
-
 		listener = (SettingsActivity) context;
-		androidExecutor = listener.getAndroidExecutor();
-		settingsManager = listener.getSettingsManager();
-		eventBus = listener.getEventBus();
+		// we need to inject here,
+		// because onActivityCreated() is called after onCreatePreferences()
+		listener.getActivityComponent().inject(this);
 	}
 
 	@Override
@@ -170,6 +179,23 @@ public class SettingsFragment extends PreferenceFragmentCompat
 					}
 				});
 
+		Preference testData = findPreference("pref_key_test_data");
+		if (IS_DEBUG_BUILD) {
+			testData.setOnPreferenceClickListener(
+					new Preference.OnPreferenceClickListener() {
+						@Override
+						public boolean onPreferenceClick(
+								Preference preference) {
+							LOG.info("Creating test data");
+							testDataCreator.createTestData();
+							getActivity().finish();
+							return true;
+						}
+					});
+		} else {
+			testData.setVisible(false);
+		}
+
 		loadSettings();
 	}
 
@@ -428,4 +454,5 @@ public class SettingsFragment extends PreferenceFragmentCompat
 			}
 		}
 	}
+
 }
diff --git a/briar-android/src/main/res/xml/settings.xml b/briar-android/src/main/res/xml/settings.xml
index 8891616794..dec7e21836 100644
--- a/briar-android/src/main/res/xml/settings.xml
+++ b/briar-android/src/main/res/xml/settings.xml
@@ -114,4 +114,8 @@
 
 	</PreferenceCategory>
 
+	<Preference
+		android:key="pref_key_test_data"
+		android:title="Create Test Data"/>
+
 </PreferenceScreen>
\ No newline at end of file
diff --git a/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java b/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java
new file mode 100644
index 0000000000..55b77221d2
--- /dev/null
+++ b/briar-api/src/main/java/org/briarproject/briar/api/test/TestDataCreator.java
@@ -0,0 +1,11 @@
+package org.briarproject.briar.api.test;
+
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+
+@NotNullByDefault
+public interface TestDataCreator {
+
+	/* Creates fake test data on the DatabaseExecutor */
+	void createTestData();
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java b/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
index b8980daa2d..7380afc3c5 100644
--- a/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
+++ b/briar-core/src/main/java/org/briarproject/briar/BriarCoreEagerSingletons.java
@@ -26,4 +26,5 @@ public interface BriarCoreEagerSingletons {
 	void inject(PrivateGroupModule.EagerSingletons init);
 
 	void inject(SharingModule.EagerSingletons init);
+
 }
diff --git a/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
index 99d5879aa2..ec7e1944fa 100644
--- a/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
+++ b/briar-core/src/main/java/org/briarproject/briar/BriarCoreModule.java
@@ -10,6 +10,7 @@ import org.briarproject.briar.messaging.MessagingModule;
 import org.briarproject.briar.privategroup.PrivateGroupModule;
 import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
 import org.briarproject.briar.sharing.SharingModule;
+import org.briarproject.briar.test.TestModule;
 
 import dagger.Module;
 
@@ -23,7 +24,8 @@ import dagger.Module;
 		IntroductionModule.class,
 		MessagingModule.class,
 		PrivateGroupModule.class,
-		SharingModule.class
+		SharingModule.class,
+		TestModule.class
 })
 public class BriarCoreModule {
 
diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestData.java b/briar-core/src/main/java/org/briarproject/briar/test/TestData.java
new file mode 100644
index 0000000000..9a836fdbff
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/test/TestData.java
@@ -0,0 +1,68 @@
+package org.briarproject.briar.test;
+
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
+import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+
+public interface TestData {
+
+	String AUTHOR_NAMES[] = {
+			"Thales",
+			"Pythagoras",
+			"Plato",
+			"Aristotle",
+			"Euclid",
+			"Archimedes",
+			"Hipparchus",
+			"Ptolemy",
+			"Sun Tzu",
+			"Ibrahim ibn Sinan",
+			"Muhammad Al-Karaji",
+			"Yang Hui",
+			"René Descartes",
+			"Pierre de Fermat",
+			"Blaise Pascal",
+			"Jacob Bernoulli",
+			"Christian Goldbach",
+			"Leonhard Euler",
+			"Joseph Louis Lagrange",
+			"Pierre-Simon Laplace",
+			"Joseph Fourier",
+			"Carl Friedrich Gauss",
+			"Charles Babbage",
+			"George Boole",
+			"John Venn",
+			"Gottlob Frege",
+			"Henri Poincaré",
+			"David Hilbert",
+			"Bertrand Russell",
+			"John von Neumann",
+			"Kurt Gödel",
+			"Alan Turing",
+			"Benoît Mandelbrot",
+			"John Nash",
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+			getRandomString(MAX_AUTHOR_NAME_LENGTH),
+	};
+
+	String GROUP_NAMES[] = {
+			"Private Messengers",
+			"The Darknet",
+			"Bletchley Park",
+			"Acropolis",
+			"General Discussion",
+			"The Undiscovered Country",
+			"The Place to Be",
+			"Forum Romanum",
+			getRandomString(MAX_FORUM_NAME_LENGTH),
+			getRandomString(MAX_FORUM_NAME_LENGTH),
+			getRandomString(MAX_FORUM_NAME_LENGTH),
+			getRandomString(MAX_FORUM_NAME_LENGTH),
+	};
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java
new file mode 100644
index 0000000000..bbc5e4c120
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/test/TestDataCreatorImpl.java
@@ -0,0 +1,409 @@
+package org.briarproject.briar.test;
+
+import org.briarproject.bramble.api.FormatException;
+import org.briarproject.bramble.api.client.ClientHelper;
+import org.briarproject.bramble.api.contact.Contact;
+import org.briarproject.bramble.api.contact.ContactId;
+import org.briarproject.bramble.api.contact.ContactManager;
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.KeyPair;
+import org.briarproject.bramble.api.crypto.SecretKey;
+import org.briarproject.bramble.api.data.BdfDictionary;
+import org.briarproject.bramble.api.db.DatabaseComponent;
+import org.briarproject.bramble.api.db.DbException;
+import org.briarproject.bramble.api.db.Transaction;
+import org.briarproject.bramble.api.identity.AuthorFactory;
+import org.briarproject.bramble.api.identity.IdentityManager;
+import org.briarproject.bramble.api.identity.LocalAuthor;
+import org.briarproject.bramble.api.lifecycle.IoExecutor;
+import org.briarproject.bramble.api.plugin.BluetoothConstants;
+import org.briarproject.bramble.api.plugin.LanTcpConstants;
+import org.briarproject.bramble.api.plugin.TorConstants;
+import org.briarproject.bramble.api.plugin.TransportId;
+import org.briarproject.bramble.api.properties.TransportProperties;
+import org.briarproject.bramble.api.properties.TransportPropertyManager;
+import org.briarproject.bramble.api.sync.Group;
+import org.briarproject.bramble.api.sync.GroupId;
+import org.briarproject.bramble.api.sync.MessageId;
+import org.briarproject.bramble.api.system.Clock;
+import org.briarproject.briar.api.blog.Blog;
+import org.briarproject.briar.api.blog.BlogManager;
+import org.briarproject.briar.api.blog.BlogPost;
+import org.briarproject.briar.api.blog.BlogPostFactory;
+import org.briarproject.briar.api.client.MessageTracker;
+import org.briarproject.briar.api.forum.Forum;
+import org.briarproject.briar.api.forum.ForumManager;
+import org.briarproject.briar.api.forum.ForumPost;
+import org.briarproject.briar.api.messaging.MessagingManager;
+import org.briarproject.briar.api.messaging.PrivateMessage;
+import org.briarproject.briar.api.messaging.PrivateMessageFactory;
+import org.briarproject.briar.api.test.TestDataCreator;
+
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
+import static org.briarproject.briar.test.TestData.AUTHOR_NAMES;
+import static org.briarproject.briar.test.TestData.GROUP_NAMES;
+
+public class TestDataCreatorImpl implements TestDataCreator {
+
+	private final static int NUM_CONTACTS = 20;
+	private final static int NUM_PRIVATE_MSGS = 15;
+	private final static int NUM_BLOG_POSTS = 30;
+	private final static int NUM_FORUMS = 3;
+	private final static int NUM_FORUM_POSTS = 30;
+
+	private final Logger LOG =
+			Logger.getLogger(TestDataCreatorImpl.class.getName());
+
+	private final AuthorFactory authorFactory;
+	private final Clock clock;
+	private final PrivateMessageFactory privateMessageFactory;
+	private final ClientHelper clientHelper;
+	private final MessageTracker messageTracker;
+	private final BlogPostFactory blogPostFactory;
+	private final CryptoComponent cryptoComponent;
+
+	private final DatabaseComponent db;
+	private final IdentityManager identityManager;
+	private final ContactManager contactManager;
+	private final TransportPropertyManager transportPropertyManager;
+	private final MessagingManager messagingManager;
+	private final BlogManager blogManager;
+	private final ForumManager forumManager;
+
+	@IoExecutor
+	private final Executor ioExecutor;
+
+	private final Random random = new Random();
+	private final Map<Contact, LocalAuthor> localAuthors =
+			new HashMap<Contact, LocalAuthor>();
+
+	@Inject
+	TestDataCreatorImpl(AuthorFactory authorFactory, Clock clock,
+			PrivateMessageFactory privateMessageFactory,
+			ClientHelper clientHelper, MessageTracker messageTracker,
+			BlogPostFactory blogPostFactory, CryptoComponent cryptoComponent,
+			DatabaseComponent db, IdentityManager identityManager,
+			ContactManager contactManager,
+			TransportPropertyManager transportPropertyManager,
+			MessagingManager messagingManager, BlogManager blogManager,
+			ForumManager forumManager, @IoExecutor Executor ioExecutor) {
+		this.authorFactory = authorFactory;
+		this.clock = clock;
+		this.privateMessageFactory = privateMessageFactory;
+		this.clientHelper = clientHelper;
+		this.messageTracker = messageTracker;
+		this.blogPostFactory = blogPostFactory;
+		this.cryptoComponent = cryptoComponent;
+		this.db = db;
+		this.identityManager = identityManager;
+		this.contactManager = contactManager;
+		this.transportPropertyManager = transportPropertyManager;
+		this.messagingManager = messagingManager;
+		this.blogManager = blogManager;
+		this.forumManager = forumManager;
+		this.ioExecutor = ioExecutor;
+	}
+
+	public void createTestData() {
+		ioExecutor.execute(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					createTestDataOnDbExecutor();
+				} catch (DbException e) {
+					if (LOG.isLoggable(WARNING)) {
+						LOG.log(WARNING, "Creating test data failed", e);
+					}
+				}
+			}
+		});
+	}
+
+	@IoExecutor
+	private void createTestDataOnDbExecutor() throws DbException {
+		List<Contact> contacts = createContacts();
+		createPrivateMessages(contacts);
+		createBlogPosts(contacts);
+		List<Forum> forums = createForums(contacts);
+
+		for (Forum forum : forums) {
+			createRandomForumPosts(forum, contacts);
+		}
+	}
+
+	private List<Contact> createContacts() throws DbException {
+		List<Contact> contacts = new ArrayList<Contact>(NUM_CONTACTS);
+		LocalAuthor localAuthor = identityManager.getLocalAuthor();
+		for (int i = 0; i < NUM_CONTACTS; i++) {
+			Contact contact = addRandomContact(localAuthor);
+			contacts.add(contact);
+		}
+		return contacts;
+	}
+
+	private Contact addRandomContact(LocalAuthor localAuthor)
+			throws DbException {
+
+		// prepare to add contact
+		LocalAuthor author = getRandomAuthor();
+		SecretKey secretKey = getSecretKey();
+		long timestamp = clock.currentTimeMillis();
+		boolean verified = random.nextBoolean();
+
+		// prepare transport properties
+		Map<TransportId, TransportProperties> props =
+				getRandomTransportProperties();
+
+		Contact contact;
+		Transaction txn = db.startTransaction(false);
+		try {
+			ContactId contactId = contactManager
+					.addContact(txn, author, localAuthor.getId(), secretKey,
+							timestamp, true, verified, true);
+			transportPropertyManager.addRemoteProperties(txn, contactId, props);
+			contact = db.getContact(txn, contactId);
+			db.commitTransaction(txn);
+		} finally {
+			db.endTransaction(txn);
+		}
+
+		if (LOG.isLoggable(INFO)) {
+			LOG.info("Added contact " + author.getName());
+			LOG.info("with transport properties: " + props.toString());
+		}
+		localAuthors.put(contact, author);
+		return contact;
+	}
+
+	private LocalAuthor getRandomAuthor() {
+		int i = random.nextInt(AUTHOR_NAMES.length);
+		String authorName = AUTHOR_NAMES[i];
+		KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
+		byte[] publicKey = keyPair.getPublic().getEncoded();
+		byte[] privateKey = keyPair.getPrivate().getEncoded();
+		return authorFactory
+				.createLocalAuthor(authorName, publicKey, privateKey);
+	}
+
+	private SecretKey getSecretKey() {
+		byte[] b = new byte[SecretKey.LENGTH];
+		random.nextBytes(b);
+		return new SecretKey(b);
+	}
+
+	private Map<TransportId, TransportProperties> getRandomTransportProperties() {
+		Map<TransportId, TransportProperties> props =
+				new HashMap<TransportId, TransportProperties>();
+
+		// Bluetooth
+		TransportProperties bt = new TransportProperties();
+		String btAddress = getRandomBluetoothAddress();
+		bt.put(BluetoothConstants.PROP_ADDRESS, btAddress);
+		props.put(BluetoothConstants.ID, bt);
+
+		// LAN
+		TransportProperties lan = new TransportProperties();
+		String lanAddress = getRandomLanAddress();
+		lan.put(LanTcpConstants.PROP_IP_PORTS, lanAddress);
+		props.put(LanTcpConstants.ID, lan);
+
+		// Tor
+		TransportProperties tor = new TransportProperties();
+		String torAddress = getRandomTorAddress();
+		tor.put(TorConstants.PROP_ONION, torAddress);
+		props.put(TorConstants.ID, tor);
+
+		return props;
+	}
+
+	private String getRandomBluetoothAddress() {
+		byte[] mac = new byte[6];
+		random.nextBytes(mac);
+
+		StringBuilder sb = new StringBuilder(18);
+		for (byte b : mac) {
+			if (sb.length() > 0) sb.append(":");
+			sb.append(String.format("%02x", b));
+		}
+		return sb.toString();
+	}
+
+	private String getRandomLanAddress() {
+		StringBuilder sb = new StringBuilder();
+		// address
+		for (int i = 0; i < 4; i++) {
+			if (sb.length() > 0) sb.append(".");
+			sb.append(random.nextInt(256));
+		}
+		// port
+		sb.append(":");
+		sb.append(1024 + random.nextInt(50000));
+		return sb.toString();
+	}
+
+	private String getRandomTorAddress() {
+		StringBuilder sb = new StringBuilder();
+		// address
+		for (int i = 0; i < 16; i++) {
+			if (random.nextBoolean())
+				sb.append(2 + random.nextInt(5));
+			else
+				sb.append((char) (random.nextInt(26) + 'a'));
+		}
+		return sb.toString();
+	}
+
+	private void createPrivateMessages(List<Contact> contacts)
+			throws DbException {
+		for (Contact contact : contacts) {
+			Group group = messagingManager.getContactGroup(contact);
+			for (int i = 0; i < NUM_PRIVATE_MSGS; i++) {
+				try {
+					createPrivateMessage(group.getId(), i);
+				} catch (FormatException e) {
+					throw new RuntimeException(e);
+				}
+			}
+		}
+		if (LOG.isLoggable(INFO)) {
+			LOG.info("Created " + NUM_PRIVATE_MSGS +
+					" private messages per contact.");
+		}
+	}
+
+	private void createPrivateMessage(GroupId groupId, int num)
+			throws DbException, FormatException {
+		long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
+		String body = getRandomText();
+		PrivateMessage m = privateMessageFactory
+				.createPrivateMessage(groupId, timestamp, body);
+
+		boolean local = random.nextBoolean();
+		BdfDictionary meta = new BdfDictionary();
+		meta.put("timestamp", timestamp);
+		meta.put("local", local);
+		meta.put("read", local);  // all local messages are read
+
+		Transaction txn = db.startTransaction(false);
+		try {
+			clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
+			if (local) messageTracker.trackOutgoingMessage(txn, m.getMessage());
+			else messageTracker.trackIncomingMessage(txn, m.getMessage());
+			db.commitTransaction(txn);
+		} finally {
+			db.endTransaction(txn);
+		}
+	}
+
+	private void createBlogPosts(List<Contact> contacts)
+			throws DbException {
+		for (int i = 0; i < NUM_BLOG_POSTS; i++) {
+			Contact contact = contacts.get(random.nextInt(contacts.size()));
+			LocalAuthor author = localAuthors.get(contact);
+			addBlogPost(author, i);
+		}
+		if (LOG.isLoggable(INFO)) {
+			LOG.info("Created " + NUM_BLOG_POSTS + " blog posts.");
+		}
+	}
+
+	private void addBlogPost(LocalAuthor author, int num) throws DbException {
+		Blog blog = blogManager.getPersonalBlog(author);
+		long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
+		String body = getRandomText();
+		try {
+			BlogPost blogPost = blogPostFactory
+					.createBlogPost(blog.getId(), timestamp, null, author,
+							body);
+			blogManager.addLocalPost(blogPost);
+		} catch (FormatException e) {
+			throw new RuntimeException(e);
+		} catch (GeneralSecurityException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private List<Forum> createForums(List<Contact> contacts)
+			throws DbException {
+		List<Forum> forums = new ArrayList<Forum>(NUM_FORUMS);
+		for (int i = 0; i < NUM_FORUMS; i++) {
+			// create forum
+			String name = GROUP_NAMES[random.nextInt(GROUP_NAMES.length)];
+			Forum forum = forumManager.addForum(name);
+
+			// share with all contacts
+			Transaction txn = db.startTransaction(false);
+			try {
+				for (Contact c : contacts) {
+					db.setGroupVisibility(txn, c.getId(), forum.getId(),
+							SHARED);
+				}
+				db.commitTransaction(txn);
+			} finally {
+				db.endTransaction(txn);
+			}
+			forums.add(forum);
+		}
+		if (LOG.isLoggable(INFO)) {
+			LOG.info("Created " + NUM_FORUMS + " forums with " +
+					NUM_FORUM_POSTS + " posts each.");
+		}
+		return forums;
+	}
+
+	private void createRandomForumPosts(Forum forum, List<Contact> contacts)
+			throws DbException {
+		List<ForumPost> posts = new ArrayList<ForumPost>();
+		for (int i = 0; i < NUM_FORUM_POSTS; i++) {
+			Contact contact = contacts.get(random.nextInt(contacts.size()));
+			LocalAuthor author = localAuthors.get(contact);
+			long timestamp = clock.currentTimeMillis() - i * 60 * 1000;
+			String body = getRandomText();
+			MessageId parent = null;
+			if (random.nextBoolean() && posts.size() > 0) {
+				ForumPost parentPost =
+						posts.get(random.nextInt(posts.size()));
+				parent = parentPost.getMessage().getId();
+			}
+			ForumPost post = forumManager
+					.createLocalPost(forum.getId(), body, timestamp, parent,
+							author);
+			posts.add(post);
+			forumManager.addLocalPost(post);
+			if (random.nextBoolean()) {
+				forumManager
+						.setReadFlag(forum.getId(), post.getMessage().getId(),
+								false);
+			}
+		}
+	}
+
+	private String getRandomText() {
+		int minLength = 3 + random.nextInt(500);
+		int maxWordLength = 15;
+		StringBuilder sb = new StringBuilder();
+		while (sb.length() < minLength) {
+			if (sb.length() > 0) sb.append(' ');
+			sb.append(getRandomString(random.nextInt(maxWordLength) + 1));
+		}
+		if (random.nextBoolean()) {
+			sb.append(" \uD83D\uDC96 \uD83E\uDD84 \uD83C\uDF08");
+		}
+		return sb.toString();
+	}
+
+}
diff --git a/briar-core/src/main/java/org/briarproject/briar/test/TestModule.java b/briar-core/src/main/java/org/briarproject/briar/test/TestModule.java
new file mode 100644
index 0000000000..16083a7459
--- /dev/null
+++ b/briar-core/src/main/java/org/briarproject/briar/test/TestModule.java
@@ -0,0 +1,19 @@
+package org.briarproject.briar.test;
+
+import org.briarproject.briar.api.test.TestDataCreator;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TestModule {
+
+	@Provides
+	@Singleton
+	TestDataCreator getTestDataCreator(TestDataCreatorImpl testDataCreator) {
+		return testDataCreator;
+	}
+
+}
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
index 2077a0902f..f34f37a8ec 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerImplTest.java
@@ -39,7 +39,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
 import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_ID;
 import static org.briarproject.briar.api.blog.BlogConstants.KEY_AUTHOR_NAME;
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
index 6066f40525..867db3df9e 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java
@@ -25,7 +25,7 @@ import static junit.framework.Assert.assertNotNull;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.blog.MessageType.COMMENT;
 import static org.briarproject.briar.api.blog.MessageType.POST;
 import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogPostValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogPostValidatorTest.java
index f3eb8a803d..923bd4c4a5 100644
--- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogPostValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogPostValidatorTest.java
@@ -18,6 +18,7 @@ import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.bramble.system.SystemClock;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.blog.Blog;
 import org.briarproject.briar.api.blog.BlogFactory;
 import org.briarproject.briar.test.BriarTestCase;
@@ -64,7 +65,7 @@ public class BlogPostValidatorTest extends BriarTestCase {
 	private final BlogFactory blogFactory = context.mock(BlogFactory.class);
 	private final ClientHelper clientHelper = context.mock(ClientHelper.class);
 	private final Author author;
-	private final String body = TestUtils.getRandomString(42);
+	private final String body = StringUtils.getRandomString(42);
 
 	public BlogPostValidatorTest() {
 		GroupId groupId = new GroupId(TestUtils.getRandomId());
diff --git a/briar-core/src/test/java/org/briarproject/briar/client/MessageQueueManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/client/MessageQueueManagerImplTest.java
index 19878e4ad3..9e14fdc4c7 100644
--- a/briar-core/src/test/java/org/briarproject/briar/client/MessageQueueManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/client/MessageQueueManagerImplTest.java
@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
 import org.briarproject.bramble.test.CaptureArgumentAction;
 import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.bramble.util.ByteUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.client.MessageQueueManager.IncomingQueueMessageHook;
 import org.briarproject.briar.api.client.MessageQueueManager.QueueMessageValidator;
 import org.briarproject.briar.api.client.QueueMessage;
@@ -45,7 +46,7 @@ public class MessageQueueManagerImplTest extends BriarTestCase {
 
 	private final GroupId groupId = new GroupId(TestUtils.getRandomId());
 	private final ClientId clientId =
-			new ClientId(TestUtils.getRandomString(5));
+			new ClientId(StringUtils.getRandomString(5));
 	private final byte[] descriptor = new byte[0];
 	private final Group group = new Group(groupId, clientId, descriptor);
 	private final long timestamp = System.currentTimeMillis();
diff --git a/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java
index d61a16d125..2051635da4 100644
--- a/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/forum/ForumPostValidatorTest.java
@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.sync.InvalidMessageException;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.bramble.test.ValidatorTestCase;
+import org.briarproject.bramble.util.StringUtils;
 import org.jmock.Expectations;
 import org.junit.Test;
 
@@ -30,12 +31,12 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
 
 	private final MessageId parentId = new MessageId(TestUtils.getRandomId());
 	private final String authorName =
-			TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
+			StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
 	private final byte[] authorPublicKey =
 			TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
 	private final BdfList authorList = BdfList.of(authorName, authorPublicKey);
 	private final String content =
-			TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
+			StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
 	private final byte[] signature =
 			TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
 	private final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
@@ -165,7 +166,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
 
 	@Test
 	public void testAcceptsMinLengthAuthorName() throws Exception {
-		final String shortAuthorName = TestUtils.getRandomString(1);
+		final String shortAuthorName = StringUtils.getRandomString(1);
 		BdfList shortNameAuthorList =
 				BdfList.of(shortAuthorName, authorPublicKey);
 		final Author shortNameAuthor =
@@ -190,7 +191,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongAuthorName() throws Exception {
 		String invalidAuthorName =
-				TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
+				StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH + 1);
 		BdfList invalidAuthorList =
 				BdfList.of(invalidAuthorName, authorPublicKey);
 		ForumPostValidator v = new ForumPostValidator(authorFactory,
@@ -278,7 +279,7 @@ public class ForumPostValidatorTest extends ValidatorTestCase {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongContent() throws Exception {
 		String invalidContent =
-				TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
+				StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH + 1);
 
 		context.checking(new Expectations() {{
 			oneOf(authorFactory).createAuthor(authorName, authorPublicKey);
diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
index 7a4f263f85..0db1a2b69c 100644
--- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTest.java
@@ -27,6 +27,7 @@ import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.test.TestDatabaseModule;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.client.SessionId;
 import org.briarproject.briar.api.introduction.IntroductionManager;
 import org.briarproject.briar.api.introduction.IntroductionMessage;
@@ -479,7 +480,7 @@ public class IntroductionIntegrationTest
 				new BdfEntry(TYPE, TYPE_REQUEST),
 				new BdfEntry(SESSION_ID, sessionId),
 				new BdfEntry(GROUP_ID, group.getId()),
-				new BdfEntry(NAME, TestUtils.getRandomString(42)),
+				new BdfEntry(NAME, StringUtils.getRandomString(42)),
 				new BdfEntry(PUBLIC_KEY,
 						TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH))
 		);
diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
index 20673e7a5a..0197878828 100644
--- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionManagerImplTest.java
@@ -20,6 +20,7 @@ import org.briarproject.bramble.api.sync.Message;
 import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.api.sync.MessageStatus;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.client.MessageTracker;
 import org.briarproject.briar.api.client.SessionId;
 import org.briarproject.briar.test.BriarTestCase;
@@ -81,7 +82,7 @@ public class IntroductionManagerImplTest extends BriarTestCase {
 		introducee2 =
 				new Contact(contactId2, author2, localAuthorId2, true, true);
 
-		ClientId clientId = new ClientId(TestUtils.getRandomString(5));
+		ClientId clientId = new ClientId(StringUtils.getRandomString(5));
 		introductionGroup1 = new Group(new GroupId(TestUtils.getRandomId()),
 				clientId, new byte[0]);
 		introductionGroup2 = new Group(new GroupId(TestUtils.getRandomId()),
diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java
index fd76151097..5c3af3a9ef 100644
--- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionValidatorTest.java
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.sync.MessageId;
 import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.bramble.system.SystemClock;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.client.SessionId;
 import org.briarproject.briar.test.BriarTestCase;
 import org.jmock.Mockery;
@@ -59,7 +60,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 
 	public IntroductionValidatorTest() {
 		GroupId groupId = new GroupId(TestUtils.getRandomId());
-		ClientId clientId = new ClientId(TestUtils.getRandomString(5));
+		ClientId clientId = new ClientId(StringUtils.getRandomString(5));
 		byte[] descriptor = TestUtils.getRandomBytes(12);
 		group = new Group(groupId, clientId, descriptor);
 
@@ -83,11 +84,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
 	@Test
 	public void testValidateProperIntroductionRequest() throws IOException {
 		final byte[] sessionId = TestUtils.getRandomId();
-		final String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
+		final String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
 		final byte[] publicKey =
 				TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
 		final String text =
-				TestUtils.getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
+				StringUtils.getRandomString(MAX_INTRODUCTION_MESSAGE_LENGTH);
 
 		BdfList body = BdfList.of(TYPE_REQUEST, sessionId,
 				name, publicKey, text);
@@ -144,9 +145,9 @@ public class IntroductionValidatorTest extends BriarTestCase {
 
 	private BdfDictionary getValidIntroductionRequest() throws FormatException {
 		byte[] sessionId = TestUtils.getRandomId();
-		String name = TestUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
+		String name = StringUtils.getRandomString(MAX_AUTHOR_NAME_LENGTH);
 		byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
-		String text = TestUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
+		String text = StringUtils.getRandomString(MAX_MESSAGE_BODY_LENGTH);
 
 		BdfDictionary msg = new BdfDictionary();
 		msg.put(TYPE, TYPE_REQUEST);
@@ -168,11 +169,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		byte[] sessionId = TestUtils.getRandomId();
 		long time = clock.currentTimeMillis();
 		byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
-		String transportId = TestUtils
+		String transportId = StringUtils
 				.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
 		BdfDictionary tProps = BdfDictionary.of(
-				new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
-						TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
+				new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH),
+						StringUtils.getRandomString(MAX_PROPERTY_LENGTH))
 		);
 		BdfDictionary tp = BdfDictionary.of(
 				new BdfEntry(transportId, tProps)
@@ -230,7 +231,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 			throws IOException {
 		BdfDictionary msg = getValidIntroductionResponse(true);
 		BdfDictionary tp = msg.getDictionary(TRANSPORT);
-		tp.put(TestUtils
+		tp.put(StringUtils
 				.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH), "X");
 		msg.put(TRANSPORT, tp);
 
@@ -260,11 +261,11 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		byte[] sessionId = TestUtils.getRandomId();
 		long time = clock.currentTimeMillis();
 		byte[] publicKey = TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
-		String transportId = TestUtils
+		String transportId = StringUtils
 				.getRandomString(TransportId.MAX_TRANSPORT_ID_LENGTH);
 		BdfDictionary tProps = BdfDictionary.of(
-				new BdfEntry(TestUtils.getRandomString(MAX_PROPERTY_LENGTH),
-						TestUtils.getRandomString(MAX_PROPERTY_LENGTH))
+				new BdfEntry(StringUtils.getRandomString(MAX_PROPERTY_LENGTH),
+						StringUtils.getRandomString(MAX_PROPERTY_LENGTH))
 		);
 		BdfDictionary tp = BdfDictionary.of(
 				new BdfEntry(transportId, tProps)
@@ -310,7 +311,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		BdfDictionary msg = BdfDictionary.of(
 				new BdfEntry(TYPE, TYPE_ACK),
 				new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
-				new BdfEntry("garbage", TestUtils.getRandomString(255))
+				new BdfEntry("garbage", StringUtils.getRandomString(255))
 		);
 		BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
 				msg.getString("garbage"));
@@ -357,7 +358,7 @@ public class IntroductionValidatorTest extends BriarTestCase {
 		BdfDictionary msg = BdfDictionary.of(
 				new BdfEntry(TYPE, TYPE_ABORT),
 				new BdfEntry(SESSION_ID, TestUtils.getRandomId()),
-				new BdfEntry("garbage", TestUtils.getRandomString(255))
+				new BdfEntry("garbage", StringUtils.getRandomString(255))
 		);
 		BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID),
 				msg.getString("garbage"));
diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/MessageSenderTest.java b/briar-core/src/test/java/org/briarproject/briar/introduction/MessageSenderTest.java
index 2cfe9e712e..71079dbadb 100644
--- a/briar-core/src/test/java/org/briarproject/briar/introduction/MessageSenderTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/introduction/MessageSenderTest.java
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.sync.Group;
 import org.briarproject.bramble.api.sync.GroupId;
 import org.briarproject.bramble.api.system.Clock;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.client.MessageQueueManager;
 import org.briarproject.briar.api.client.SessionId;
 import org.briarproject.briar.test.BriarTestCase;
@@ -60,7 +61,7 @@ public class MessageSenderTest extends BriarTestCase {
 		final Transaction txn = new Transaction(null, false);
 		final Group privateGroup =
 				new Group(new GroupId(TestUtils.getRandomId()),
-						new ClientId(TestUtils.getRandomString(5)),
+						new ClientId(StringUtils.getRandomString(5)),
 						new byte[0]);
 		final SessionId sessionId = new SessionId(TestUtils.getRandomId());
 		byte[] mac = TestUtils.getRandomBytes(42);
diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTest.java
index bf5f2a387c..92d4851420 100644
--- a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTest.java
@@ -65,7 +65,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 	@Test
 	public void testForumPostFitsIntoPacket() throws Exception {
 		// Create a maximum-length author
-		String authorName = TestUtils.getRandomString(
+		String authorName = StringUtils.getRandomString(
 				MAX_AUTHOR_NAME_LENGTH);
 		byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
 		PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
@@ -76,7 +76,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
 		GroupId groupId = new GroupId(getRandomId());
 		long timestamp = Long.MAX_VALUE;
 		MessageId parent = new MessageId(getRandomId());
-		String body = TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
+		String body = StringUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
 		ForumPost post = forumPostFactory.createPost(groupId,
 				timestamp, parent, author, body);
 		// Check the size of the serialised message
diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
index ef776d726e..41a52035c8 100644
--- a/briar-core/src/test/java/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/messaging/PrivateMessageValidatorTest.java
@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.BdfMessageContext;
 import org.briarproject.bramble.api.data.BdfDictionary;
 import org.briarproject.bramble.api.data.BdfList;
-import org.briarproject.bramble.test.TestUtils;
 import org.briarproject.bramble.test.ValidatorTestCase;
+import org.briarproject.bramble.util.StringUtils;
 import org.junit.Test;
 
 import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
@@ -48,7 +48,7 @@ public class PrivateMessageValidatorTest extends ValidatorTestCase {
 		PrivateMessageValidator v = new PrivateMessageValidator(clientHelper,
 				metadataEncoder, clock);
 		String invalidContent =
-				TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1);
+				StringUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH + 1);
 		v.validateMessage(message, group, BdfList.of(invalidContent));
 	}
 
@@ -57,7 +57,7 @@ public class PrivateMessageValidatorTest extends ValidatorTestCase {
 		PrivateMessageValidator v = new PrivateMessageValidator(clientHelper,
 				metadataEncoder, clock);
 		String content =
-				TestUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
+				StringUtils.getRandomString(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
 		BdfMessageContext messageContext =
 				v.validateMessage(message, group, BdfList.of(content));
 		assertExpectedContext(messageContext);
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
index a4cf4603b8..c0253840f2 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/GroupMessageValidatorTest.java
@@ -26,7 +26,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_JOIN;
 import static org.briarproject.briar.api.privategroup.GroupMessageFactory.SIGNING_LABEL_POST;
 import static org.briarproject.briar.api.privategroup.MessageType.JOIN;
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
index c197bb73c0..c0bbe0dab0 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationManagerImplTest.java
@@ -48,7 +48,7 @@ import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
 import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
 import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
 import static org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager.CLIENT_ID;
diff --git a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
index cc8f025f08..1a4377e40a 100644
--- a/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/privategroup/invitation/GroupInvitationValidatorTest.java
@@ -23,7 +23,7 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
 import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
 import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
 import static org.briarproject.bramble.test.TestUtils.getRandomId;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.GROUP_SALT_LENGTH;
 import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
 import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_NAME_LENGTH;
diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java
index 7c4c96ab26..a660dd9acb 100644
--- a/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/sharing/BlogSharingValidatorTest.java
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.api.identity.Author;
 import org.briarproject.bramble.api.identity.AuthorId;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.blog.Blog;
 import org.jmock.Expectations;
 import org.junit.Test;
@@ -19,14 +20,14 @@ import static org.briarproject.briar.sharing.MessageType.INVITE;
 public class BlogSharingValidatorTest extends SharingValidatorTest {
 
 	private final AuthorId authorId = new AuthorId(getRandomId());
-	private final String authorName = TestUtils.getRandomString(42);
+	private final String authorName = StringUtils.getRandomString(42);
 	private final byte[] publicKey =
 			TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
 	private final Author author = new Author(authorId, authorName, publicKey);
 	private final Blog blog = new Blog(group, author, false);
 	private final BdfList descriptor = BdfList.of(authorName, publicKey, false);
 	private final String content =
-			TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
+			StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
 
 	@Override
 	SharingValidator getValidator() {
@@ -88,7 +89,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
 
 	@Test
 	public void testAcceptsMinLengthBlogName() throws Exception {
-		String shortBlogName = TestUtils.getRandomString(1);
+		String shortBlogName = StringUtils.getRandomString(1);
 		BdfList validDescriptor = BdfList.of(shortBlogName, publicKey, false);
 		expectCreateBlog(shortBlogName, publicKey);
 		expectEncodeMetadata(INVITE);
@@ -101,7 +102,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongBlogName() throws Exception {
 		String invalidBlogName =
-				TestUtils.getRandomString(MAX_BLOG_NAME_LENGTH + 1);
+				StringUtils.getRandomString(MAX_BLOG_NAME_LENGTH + 1);
 		BdfList invalidDescriptor =
 				BdfList.of(invalidBlogName, publicKey, false);
 		v.validateMessage(message, group,
@@ -167,7 +168,7 @@ public class BlogSharingValidatorTest extends SharingValidatorTest {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongContent() throws Exception {
 		String invalidContent =
-				TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
+				StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
 		expectCreateBlog(authorName, publicKey);
 		v.validateMessage(message, group,
 				BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java
index 052d0e69d3..df1cdd48ff 100644
--- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingIntegrationTest.java
@@ -37,7 +37,7 @@ import java.util.Collection;
 import java.util.List;
 
 import static junit.framework.Assert.assertNotNull;
-import static org.briarproject.bramble.test.TestUtils.getRandomString;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
diff --git a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
index 038da56a94..8ede843f15 100644
--- a/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
+++ b/briar-core/src/test/java/org/briarproject/briar/sharing/ForumSharingValidatorTest.java
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException;
 import org.briarproject.bramble.api.client.BdfMessageContext;
 import org.briarproject.bramble.api.data.BdfList;
 import org.briarproject.bramble.test.TestUtils;
+import org.briarproject.bramble.util.StringUtils;
 import org.briarproject.briar.api.forum.Forum;
 import org.jmock.Expectations;
 import org.junit.Test;
@@ -16,12 +17,12 @@ import static org.briarproject.briar.sharing.MessageType.INVITE;
 public class ForumSharingValidatorTest extends SharingValidatorTest {
 
 	private final String forumName =
-			TestUtils.getRandomString(MAX_FORUM_NAME_LENGTH);
+			StringUtils.getRandomString(MAX_FORUM_NAME_LENGTH);
 	private final byte[] salt = TestUtils.getRandomBytes(FORUM_SALT_LENGTH);
 	private final Forum forum = new Forum(group, forumName, salt);
 	private final BdfList descriptor = BdfList.of(forumName, salt);
 	private final String content =
-			TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
+			StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH);
 
 	@Override
 	SharingValidator getValidator() {
@@ -83,7 +84,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
 
 	@Test
 	public void testAcceptsMinLengthForumName() throws Exception {
-		String shortForumName = TestUtils.getRandomString(1);
+		String shortForumName = StringUtils.getRandomString(1);
 		BdfList validDescriptor = BdfList.of(shortForumName, salt);
 		expectCreateForum(shortForumName);
 		expectEncodeMetadata(INVITE);
@@ -96,7 +97,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongForumName() throws Exception {
 		String invalidForumName =
-				TestUtils.getRandomString(MAX_FORUM_NAME_LENGTH + 1);
+				StringUtils.getRandomString(MAX_FORUM_NAME_LENGTH + 1);
 		BdfList invalidDescriptor = BdfList.of(invalidForumName, salt);
 		v.validateMessage(message, group,
 				BdfList.of(INVITE.getValue(), previousMsgId, invalidDescriptor,
@@ -157,7 +158,7 @@ public class ForumSharingValidatorTest extends SharingValidatorTest {
 	@Test(expected = FormatException.class)
 	public void testRejectsTooLongContent() throws Exception {
 		String invalidContent =
-				TestUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
+				StringUtils.getRandomString(MAX_INVITATION_MESSAGE_LENGTH + 1);
 		expectCreateForum(forumName);
 		v.validateMessage(message, group,
 				BdfList.of(INVITE.getValue(), previousMsgId, descriptor,
-- 
GitLab