Merge branch 'mailbox-integration-tests' into 'master'

First integration test for mailbox with two contacts

See merge request briar/briar!1725
This commit is contained in:
akwizgran
2022-11-07 12:58:18 +00:00
53 changed files with 800 additions and 316 deletions

View File

@@ -107,6 +107,10 @@ bridge test:
mailbox integration test: mailbox integration test:
extends: .optional_tests extends: .optional_tests
rules: rules:
- changes:
- mailbox-integration-tests/**/*
when: on_success
allow_failure: false
- if: '$CI_PIPELINE_SOURCE == "schedule"' - if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success when: on_success
- if: '$CI_COMMIT_TAG == null' - if: '$CI_COMMIT_TAG == null'

View File

@@ -9,6 +9,7 @@ import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.system.AndroidSystemModule; import org.briarproject.bramble.system.AndroidSystemModule;
import org.briarproject.bramble.system.AndroidTaskSchedulerModule; import org.briarproject.bramble.system.AndroidTaskSchedulerModule;
import org.briarproject.bramble.system.AndroidWakefulIoExecutorModule; import org.briarproject.bramble.system.AndroidWakefulIoExecutorModule;
import org.briarproject.bramble.system.DefaultThreadFactoryModule;
import dagger.Module; import dagger.Module;
@@ -18,6 +19,7 @@ import dagger.Module;
AndroidSystemModule.class, AndroidSystemModule.class,
AndroidTaskSchedulerModule.class, AndroidTaskSchedulerModule.class,
AndroidWakefulIoExecutorModule.class, AndroidWakefulIoExecutorModule.class,
DefaultThreadFactoryModule.class,
CircumventionModule.class, CircumventionModule.class,
DnsModule.class, DnsModule.class,
ReportingModule.class, ReportingModule.class,

View File

@@ -4,6 +4,7 @@ import org.briarproject.nullsafety.NotNullByDefault;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -19,9 +20,10 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize, public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize,
long keepAliveTime, TimeUnit unit, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) { RejectedExecutionHandler handler) {
super(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, super(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue,
handler); threadFactory, handler);
log = Logger.getLogger(tag); log = Logger.getLogger(tag);
} }

View File

@@ -9,6 +9,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Inject; import javax.inject.Inject;
@@ -37,31 +38,31 @@ public class CryptoExecutorModule {
private static final int MAX_EXECUTOR_THREADS = private static final int MAX_EXECUTOR_THREADS =
Math.max(1, Runtime.getRuntime().availableProcessors() - 1); Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
private final ExecutorService cryptoExecutor;
public CryptoExecutorModule() { public CryptoExecutorModule() {
// Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create a limited # of threads and keep them in the pool for 60 secs
cryptoExecutor = new TimeLoggingExecutor("CryptoExecutor", 0,
MAX_EXECUTOR_THREADS, 60, SECONDS, queue, policy);
} }
@Provides @Provides
@Singleton @Singleton
@CryptoExecutor @CryptoExecutor
ExecutorService provideCryptoExecutorService( ExecutorService provideCryptoExecutorService(
LifecycleManager lifecycleManager) { LifecycleManager lifecycleManager, ThreadFactory threadFactory) {
// Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create a limited # of threads and keep them in the pool for 60 secs
ExecutorService cryptoExecutor = new TimeLoggingExecutor(
"CryptoExecutor", 0, MAX_EXECUTOR_THREADS, 60, SECONDS, queue,
threadFactory, policy);
lifecycleManager.registerForShutdown(cryptoExecutor); lifecycleManager.registerForShutdown(cryptoExecutor);
return cryptoExecutor; return cryptoExecutor;
} }
@Provides @Provides
@CryptoExecutor @CryptoExecutor
Executor provideCryptoExecutor() { Executor provideCryptoExecutor(
@CryptoExecutor ExecutorService cryptoExecutor) {
return cryptoExecutor; return cryptoExecutor;
} }
} }

View File

@@ -9,6 +9,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Inject; import javax.inject.Inject;
@@ -28,24 +29,20 @@ public class DatabaseExecutorModule {
ExecutorService executorService; ExecutorService executorService;
} }
private final ExecutorService databaseExecutor; @Provides
@Singleton
public DatabaseExecutorModule() { @DatabaseExecutor
ExecutorService provideDatabaseExecutorService(
LifecycleManager lifecycleManager, ThreadFactory threadFactory) {
// Use an unbounded queue // Use an unbounded queue
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(); BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy(); new ThreadPoolExecutor.DiscardPolicy();
// Use a single thread and keep it in the pool for 60 secs // Use a single thread and keep it in the pool for 60 secs
databaseExecutor = new TimeLoggingExecutor("DatabaseExecutor", 0, 1, ExecutorService databaseExecutor = new TimeLoggingExecutor(
60, SECONDS, queue, policy); "DatabaseExecutor", 0, 1, 60, SECONDS, queue, threadFactory,
} policy);
@Provides
@Singleton
@DatabaseExecutor
ExecutorService provideDatabaseExecutorService(
LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(databaseExecutor); lifecycleManager.registerForShutdown(databaseExecutor);
return databaseExecutor; return databaseExecutor;
} }

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.event;
import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.event.EventExecutor;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -22,10 +23,11 @@ public class DefaultEventExecutorModule {
@Provides @Provides
@Singleton @Singleton
@EventExecutor @EventExecutor
Executor provideEventExecutor() { Executor provideEventExecutor(ThreadFactory threadFactory) {
return newSingleThreadExecutor(r -> { return newSingleThreadExecutor(r -> {
Thread t = new Thread(r); Thread t = threadFactory.newThread(r);
t.setDaemon(true); t.setDaemon(true);
t.setName(t.getName() + "-Event");
return t; return t;
}); });
} }

View File

@@ -9,6 +9,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import javax.inject.Inject; import javax.inject.Inject;
@@ -28,19 +29,6 @@ public class LifecycleModule {
Executor executor; Executor executor;
} }
private final ExecutorService ioExecutor;
public LifecycleModule() {
// The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create threads as required and keep them in the pool for 60 seconds
ioExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60, SECONDS, queue, policy);
}
@Provides @Provides
@Singleton @Singleton
ShutdownManager provideShutdownManager() { ShutdownManager provideShutdownManager() {
@@ -57,7 +45,16 @@ public class LifecycleModule {
@Provides @Provides
@Singleton @Singleton
@IoExecutor @IoExecutor
Executor provideIoExecutor(LifecycleManager lifecycleManager) { Executor provideIoExecutor(LifecycleManager lifecycleManager,
ThreadFactory threadFactory) {
// The thread pool is unbounded, so use direct handoff
BlockingQueue<Runnable> queue = new SynchronousQueue<>();
// Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy =
new ThreadPoolExecutor.DiscardPolicy();
// Create threads as required and keep them in the pool for 60 seconds
ExecutorService ioExecutor = new ThreadPoolExecutor(0,
Integer.MAX_VALUE, 60, SECONDS, queue, threadFactory, policy);
lifecycleManager.registerForShutdown(ioExecutor); lifecycleManager.registerForShutdown(ioExecutor);
return ioExecutor; return ioExecutor;
} }

View File

@@ -20,12 +20,15 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
class MailboxApiCallerImpl implements MailboxApiCaller { class MailboxApiCallerImpl implements MailboxApiCaller {
private final TaskScheduler taskScheduler; private final TaskScheduler taskScheduler;
private final MailboxConfig mailboxConfig;
private final Executor ioExecutor; private final Executor ioExecutor;
@Inject @Inject
MailboxApiCallerImpl(TaskScheduler taskScheduler, MailboxApiCallerImpl(TaskScheduler taskScheduler,
MailboxConfig mailboxConfig,
@IoExecutor Executor ioExecutor) { @IoExecutor Executor ioExecutor) {
this.taskScheduler = taskScheduler; this.taskScheduler = taskScheduler;
this.mailboxConfig = mailboxConfig;
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
} }
@@ -49,7 +52,8 @@ class MailboxApiCallerImpl implements MailboxApiCaller {
private boolean cancelled = false; private boolean cancelled = false;
@GuardedBy("lock") @GuardedBy("lock")
private long retryIntervalMs = MIN_RETRY_INTERVAL_MS; private long retryIntervalMs =
mailboxConfig.getApiCallerMinRetryInterval();
private Task(ApiCall apiCall) { private Task(ApiCall apiCall) {
this.apiCall = apiCall; this.apiCall = apiCall;
@@ -74,8 +78,9 @@ class MailboxApiCallerImpl implements MailboxApiCaller {
scheduledTask = taskScheduler.schedule(this::callApi, scheduledTask = taskScheduler.schedule(this::callApi,
ioExecutor, retryIntervalMs, MILLISECONDS); ioExecutor, retryIntervalMs, MILLISECONDS);
// Increase the retry interval each time we retry // Increase the retry interval each time we retry
retryIntervalMs = retryIntervalMs = min(
min(MAX_RETRY_INTERVAL_MS, retryIntervalMs * 2); mailboxConfig.getApiCallerMaxRetryInterval(),
retryIntervalMs * 2);
} }
} else { } else {
synchronized (lock) { synchronized (lock) {

View File

@@ -0,0 +1,24 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.plugin.Plugin;
interface MailboxConfig {
/**
* The minimum interval between API call retries in milliseconds.
*/
long getApiCallerMinRetryInterval();
/**
* The maximum interval between API call retries in milliseconds.
*/
long getApiCallerMaxRetryInterval();
/**
* How long (in milliseconds) the Tor plugin needs to be continuously
* {@link Plugin.State#ACTIVE active} before we assume our contacts can
* reach our hidden service.
*/
long getTorReachabilityPeriod();
}

View File

@@ -0,0 +1,30 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@Immutable
@NotNullByDefault
class MailboxConfigImpl implements MailboxConfig {
@Inject
MailboxConfigImpl() {
}
@Override
public long getApiCallerMinRetryInterval() {
return MailboxApiCaller.MIN_RETRY_INTERVAL_MS;
}
@Override
public long getApiCallerMaxRetryInterval() {
return MailboxApiCaller.MAX_RETRY_INTERVAL_MS;
}
@Override
public long getTorReachabilityPeriod() {
return TorReachabilityMonitor.REACHABILITY_PERIOD_MS;
}
}

View File

@@ -4,7 +4,11 @@ import dagger.Module;
import dagger.Provides; import dagger.Provides;
@Module @Module
public class UrlConverterModule { public class ModularMailboxModule {
@Provides
MailboxConfig provideMailboxConfig(MailboxConfigImpl mailboxConfig) {
return mailboxConfig;
}
@Provides @Provides
UrlConverter provideUrlConverter(UrlConverterImpl urlConverter) { UrlConverter provideUrlConverter(UrlConverterImpl urlConverter) {

View File

@@ -32,6 +32,7 @@ class TorReachabilityMonitorImpl
private final Executor ioExecutor; private final Executor ioExecutor;
private final TaskScheduler taskScheduler; private final TaskScheduler taskScheduler;
private final MailboxConfig mailboxConfig;
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final EventBus eventBus; private final EventBus eventBus;
private final Object lock = new Object(); private final Object lock = new Object();
@@ -50,10 +51,12 @@ class TorReachabilityMonitorImpl
TorReachabilityMonitorImpl( TorReachabilityMonitorImpl(
@IoExecutor Executor ioExecutor, @IoExecutor Executor ioExecutor,
TaskScheduler taskScheduler, TaskScheduler taskScheduler,
MailboxConfig mailboxConfig,
PluginManager pluginManager, PluginManager pluginManager,
EventBus eventBus) { EventBus eventBus) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.taskScheduler = taskScheduler; this.taskScheduler = taskScheduler;
this.mailboxConfig = mailboxConfig;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
this.eventBus = eventBus; this.eventBus = eventBus;
} }
@@ -110,7 +113,7 @@ class TorReachabilityMonitorImpl
synchronized (lock) { synchronized (lock) {
if (destroyed || task != null) return; if (destroyed || task != null) return;
task = taskScheduler.schedule(this::onTorReachable, ioExecutor, task = taskScheduler.schedule(this::onTorReachable, ioExecutor,
REACHABILITY_PERIOD_MS, MILLISECONDS); mailboxConfig.getTorReachabilityPeriod(), MILLISECONDS);
} }
} }

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.system.TaskScheduler;
import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -21,18 +22,15 @@ public class DefaultTaskSchedulerModule {
TaskScheduler scheduler; TaskScheduler scheduler;
} }
private final ScheduledExecutorService scheduledExecutorService; @Provides
@Singleton
public DefaultTaskSchedulerModule() { TaskScheduler provideTaskScheduler(LifecycleManager lifecycleManager,
ThreadFactory threadFactory) {
// Discard tasks that are submitted during shutdown // Discard tasks that are submitted during shutdown
RejectedExecutionHandler policy = RejectedExecutionHandler policy =
new ScheduledThreadPoolExecutor.DiscardPolicy(); new ScheduledThreadPoolExecutor.DiscardPolicy();
scheduledExecutorService = new ScheduledThreadPoolExecutor(1, policy); ScheduledExecutorService scheduledExecutorService =
} new ScheduledThreadPoolExecutor(1, threadFactory, policy);
@Provides
@Singleton
TaskScheduler provideTaskScheduler(LifecycleManager lifecycleManager) {
lifecycleManager.registerForShutdown(scheduledExecutorService); lifecycleManager.registerForShutdown(scheduledExecutorService);
return new TaskSchedulerImpl(scheduledExecutorService); return new TaskSchedulerImpl(scheduledExecutorService);
} }

View File

@@ -0,0 +1,18 @@
package org.briarproject.bramble.system;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class DefaultThreadFactoryModule {
@Provides
@Singleton
ThreadFactory provideThreadFactory() {
return Executors.defaultThreadFactory();
}
}

View File

@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -25,7 +25,7 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -21,12 +21,13 @@ public class MailboxApiCallerImplTest extends BrambleMockTestCase {
private final TaskScheduler taskScheduler = private final TaskScheduler taskScheduler =
context.mock(TaskScheduler.class); context.mock(TaskScheduler.class);
private final MailboxConfig mailboxConfig = new MailboxConfigImpl();
private final Executor ioExecutor = context.mock(Executor.class); private final Executor ioExecutor = context.mock(Executor.class);
private final ApiCall apiCall = context.mock(ApiCall.class); private final ApiCall apiCall = context.mock(ApiCall.class);
private final Cancellable scheduledTask = context.mock(Cancellable.class); private final Cancellable scheduledTask = context.mock(Cancellable.class);
private final MailboxApiCallerImpl caller = private final MailboxApiCallerImpl caller =
new MailboxApiCallerImpl(taskScheduler, ioExecutor); new MailboxApiCallerImpl(taskScheduler, mailboxConfig, ioExecutor);
@Test @Test
public void testSubmitsTaskImmediately() { public void testSubmitsTaskImmediately() {

View File

@@ -24,9 +24,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import javax.net.SocketFactory;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.MockWebServer;
@@ -34,8 +31,8 @@ import okhttp3.mockwebserver.RecordedRequest;
import okio.Buffer; import okio.Buffer;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS; import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.mailbox.MailboxTestUtils.createHttpClientProvider;
import static org.briarproject.bramble.test.TestUtils.getContactId; import static org.briarproject.bramble.test.TestUtils.getContactId;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties; import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
@@ -56,18 +53,8 @@ public class MailboxApiTest extends BrambleTestCase {
@Rule @Rule
public TemporaryFolder folder = new TemporaryFolder(); public TemporaryFolder folder = new TemporaryFolder();
private final OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
private final WeakSingletonProvider<OkHttpClient> httpClientProvider = private final WeakSingletonProvider<OkHttpClient> httpClientProvider =
new WeakSingletonProvider<OkHttpClient>() { createHttpClientProvider();
@Override
@Nonnull
public OkHttpClient createInstance() {
return client;
}
};
// We aren't using a real onion address, so use the given address verbatim // We aren't using a real onion address, so use the given address verbatim
private final UrlConverter urlConverter = onion -> onion; private final UrlConverter urlConverter = onion -> onion;
private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider, private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider,

View File

@@ -22,13 +22,12 @@ import org.jmock.Expectations;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
import static org.briarproject.bramble.test.TestUtils.getContact; import static org.briarproject.bramble.test.TestUtils.getContact;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;
@@ -59,7 +58,8 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
new MailboxAuthToken(getRandomId()); new MailboxAuthToken(getRandomId());
private final MailboxAuthToken ownerToken = private final MailboxAuthToken ownerToken =
new MailboxAuthToken(getRandomId()); new MailboxAuthToken(getRandomId());
private final String validPayload = getValidPayload(); private final String validPayload =
getQrCodePayload(onionBytes, setupToken.getBytes());
private final long time = System.currentTimeMillis(); private final long time = System.currentTimeMillis();
private final MailboxProperties setupProperties = new MailboxProperties( private final MailboxProperties setupProperties = new MailboxProperties(
onion, setupToken, new ArrayList<>()); onion, setupToken, new ArrayList<>());
@@ -194,16 +194,6 @@ public class MailboxPairingTaskImplTest extends BrambleMockTestCase {
MailboxPairingState.UnexpectedError.class)); MailboxPairingState.UnexpectedError.class));
} }
private String getValidPayload() {
byte[] payloadBytes = ByteBuffer.allocate(65)
.put((byte) 32) // 1
.put(onionBytes) // 32
.put(setupToken.getBytes()) // 32
.array();
//noinspection CharsetObjectCanBeUsed
return new String(payloadBytes, Charset.forName("ISO-8859-1"));
}
private PredicateMatcher<MailboxProperties> matches(MailboxProperties p2) { private PredicateMatcher<MailboxProperties> matches(MailboxProperties p2) {
return new PredicateMatcher<>(MailboxProperties.class, p1 -> return new PredicateMatcher<>(MailboxProperties.class, p1 ->
p1.getAuthToken().equals(p2.getAuthToken()) && p1.getAuthToken().equals(p2.getAuthToken()) &&

View File

@@ -0,0 +1,44 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.WeakSingletonProvider;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import javax.annotation.Nonnull;
import javax.net.SocketFactory;
import okhttp3.OkHttpClient;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
class MailboxTestUtils {
static String getQrCodePayload(byte[] onionBytes, byte[] setupToken) {
byte[] payloadBytes = ByteBuffer.allocate(65)
.put((byte) 32) // 1
.put(onionBytes) // 32
.put(setupToken) // 32
.array();
//noinspection CharsetObjectCanBeUsed
return new String(payloadBytes, Charset.forName("ISO-8859-1"));
}
static String getQrCodePayload(byte[] setupToken) {
return getQrCodePayload(getRandomId(), setupToken);
}
static WeakSingletonProvider<OkHttpClient> createHttpClientProvider() {
return new WeakSingletonProvider<OkHttpClient>() {
@Override
@Nonnull
public OkHttpClient createInstance() {
return new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
}
};
}
}

View File

@@ -29,6 +29,7 @@ public class TorReachabilityMonitorImplTest extends BrambleMockTestCase {
private final Executor ioExecutor = context.mock(Executor.class); private final Executor ioExecutor = context.mock(Executor.class);
private final TaskScheduler taskScheduler = private final TaskScheduler taskScheduler =
context.mock(TaskScheduler.class); context.mock(TaskScheduler.class);
private final MailboxConfig mailboxConfig = new MailboxConfigImpl();
private final PluginManager pluginManager = private final PluginManager pluginManager =
context.mock(PluginManager.class); context.mock(PluginManager.class);
private final EventBus eventBus = context.mock(EventBus.class); private final EventBus eventBus = context.mock(EventBus.class);
@@ -39,7 +40,7 @@ public class TorReachabilityMonitorImplTest extends BrambleMockTestCase {
private final TorReachabilityMonitorImpl monitor = private final TorReachabilityMonitorImpl monitor =
new TorReachabilityMonitorImpl(ioExecutor, taskScheduler, new TorReachabilityMonitorImpl(ioExecutor, taskScheduler,
pluginManager, eventBus); mailboxConfig, pluginManager, eventBus);
@Test @Test
public void testSchedulesTaskWhenStartedIfTorIsActive() { public void testSchedulesTaskWhenStartedIfTorIsActive() {

View File

@@ -9,7 +9,8 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.plugin.file.RemovableDriveManager; import org.briarproject.bramble.api.plugin.file.RemovableDriveManager;
import org.briarproject.bramble.battery.DefaultBatteryManagerModule; import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.system.DefaultThreadFactoryModule;
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule; import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule;
import org.briarproject.bramble.system.TimeTravelModule; import org.briarproject.bramble.system.TimeTravelModule;
import org.briarproject.bramble.test.TestDatabaseConfigModule; import org.briarproject.bramble.test.TestDatabaseConfigModule;
@@ -29,13 +30,14 @@ import dagger.Component;
DefaultBatteryManagerModule.class, DefaultBatteryManagerModule.class,
DefaultEventExecutorModule.class, DefaultEventExecutorModule.class,
DefaultWakefulIoExecutorModule.class, DefaultWakefulIoExecutorModule.class,
DefaultThreadFactoryModule.class,
TestDatabaseConfigModule.class, TestDatabaseConfigModule.class,
TestDnsModule.class, TestDnsModule.class,
TestFeatureFlagModule.class, TestFeatureFlagModule.class,
TestMailboxDirectoryModule.class, TestMailboxDirectoryModule.class,
RemovableDriveIntegrationTestModule.class, RemovableDriveIntegrationTestModule.class,
RemovableDriveModule.class, RemovableDriveModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestSecureRandomModule.class, TestSecureRandomModule.class,
TimeTravelModule.class, TimeTravelModule.class,
TestSocksModule.class, TestSocksModule.class,

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.sync;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -16,7 +16,7 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -11,6 +11,7 @@ import dagger.Module;
DefaultBatteryManagerModule.class, DefaultBatteryManagerModule.class,
DefaultEventExecutorModule.class, DefaultEventExecutorModule.class,
DefaultWakefulIoExecutorModule.class, DefaultWakefulIoExecutorModule.class,
TestThreadFactoryModule.class,
TestDatabaseConfigModule.class, TestDatabaseConfigModule.class,
TestFeatureFlagModule.class, TestFeatureFlagModule.class,
TestMailboxDirectoryModule.class, TestMailboxDirectoryModule.class,

View File

@@ -235,11 +235,16 @@ public abstract class BrambleIntegrationTest<C extends BrambleIntegrationTestCom
protected void awaitPendingMessageDelivery(int num) protected void awaitPendingMessageDelivery(int num)
throws TimeoutException { throws TimeoutException {
deliveryWaiter.await(TIMEOUT, num); awaitPendingMessageDelivery(num, TIMEOUT);
}
protected void awaitPendingMessageDelivery(int num, long timeout)
throws TimeoutException {
deliveryWaiter.await(timeout, num);
assertEquals("Messages delivered", num, deliveryCounter.getAndSet(0)); assertEquals("Messages delivered", num, deliveryCounter.getAndSet(0));
try { try {
messageSemaphore.tryAcquire(num, TIMEOUT, MILLISECONDS); messageSemaphore.tryAcquire(num, timeout, MILLISECONDS);
} catch (InterruptedException e) { } catch (InterruptedException e) {
LOG.info("Interrupted while waiting for messages"); LOG.info("Interrupted while waiting for messages");
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();

View File

@@ -6,7 +6,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.connection.ConnectionManager; import org.briarproject.bramble.api.connection.ConnectionManager;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -16,7 +16,7 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -0,0 +1,66 @@
package org.briarproject.bramble.test;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dagger.Module;
import dagger.Provides;
@Module
public class TestThreadFactoryModule {
@Nullable
private final String prefix;
public TestThreadFactoryModule() {
this(null);
}
public TestThreadFactoryModule(@Nullable String prefix) {
this.prefix = prefix;
}
@Provides
ThreadFactory provideThreadFactory() {
if (prefix == null) return Executors.defaultThreadFactory();
return new TestThreadFactory(prefix);
}
/**
* This class is mostly copied from
* {@link Executors#defaultThreadFactory()} only adds a given prefix.
*/
static class TestThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private TestThreadFactory(String prefix) {
SecurityManager s = System.getSecurityManager();
this.group = s != null ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
this.namePrefix =
prefix + "-p-" + poolNumber.getAndIncrement() + "-t-";
}
@Override
public Thread newThread(@Nonnull Runnable r) {
Thread t = new Thread(this.group, r,
this.namePrefix + this.threadNumber.getAndIncrement(), 0L);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != 5) {
t.setPriority(5);
}
return t;
}
}
}

View File

@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.transport.KeyManager; import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent; import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
@@ -22,7 +22,7 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.io.DnsModule; import org.briarproject.bramble.io.DnsModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.network.JavaNetworkModule; import org.briarproject.bramble.network.JavaNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule; import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.socks.SocksModule; import org.briarproject.bramble.socks.SocksModule;
@@ -14,7 +14,7 @@ import dagger.Module;
DnsModule.class, DnsModule.class,
JavaNetworkModule.class, JavaNetworkModule.class,
JavaSystemModule.class, JavaSystemModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
SocksModule.class SocksModule.class
}) })
public class BrambleJavaModule { public class BrambleJavaModule {

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.test;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.BrambleJavaModule; import org.briarproject.bramble.BrambleJavaModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.plugin.tor.BridgeTest; import org.briarproject.bramble.plugin.tor.BridgeTest;
import org.briarproject.bramble.plugin.tor.CircumventionProvider; import org.briarproject.bramble.plugin.tor.CircumventionProvider;
@@ -16,7 +16,7 @@ import dagger.Component;
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
BrambleJavaModule.class, BrambleJavaModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestTorPortsModule.class, TestTorPortsModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,
}) })

View File

@@ -3,7 +3,7 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidModule; import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.plugin.file.RemovableDriveModule; import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.system.ClockModule; import org.briarproject.bramble.system.ClockModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
@@ -28,7 +28,7 @@ import dagger.Component;
BrambleAndroidModule.class, BrambleAndroidModule.class,
BriarAccountModule.class, BriarAccountModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class ModularMailboxModule.class
}) })
public interface BriarUiTestComponent extends AndroidComponent { public interface BriarUiTestComponent extends AndroidComponent {

View File

@@ -3,7 +3,7 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidModule; import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.plugin.file.RemovableDriveModule; import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.system.ClockModule; import org.briarproject.bramble.system.ClockModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
@@ -27,7 +27,7 @@ import dagger.Component;
BrambleAndroidModule.class, BrambleAndroidModule.class,
BriarAccountModule.class, BriarAccountModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
UrlConverterModule.class ModularMailboxModule.class
}) })
public interface BriarUiTestComponent extends AndroidComponent { public interface BriarUiTestComponent extends AndroidComponent {

View File

@@ -28,7 +28,7 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager; import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.plugin.file.RemovableDriveModule; import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.plugin.tor.CircumventionProvider; import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.system.ClockModule; import org.briarproject.bramble.system.ClockModule;
@@ -102,7 +102,7 @@ import dagger.Component;
AttachmentModule.class, AttachmentModule.class,
ClockModule.class, ClockModule.class,
MediaModule.class, MediaModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
RemovableDriveModule.class RemovableDriveModule.class
}) })
public interface AndroidComponent public interface AndroidComponent

View File

@@ -4,7 +4,7 @@ import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -29,7 +29,7 @@ import dagger.Component;
BriarClientModule.class, BriarClientModule.class,
FeedModule.class, FeedModule.class,
IdentityModule.class, IdentityModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -1,7 +1,7 @@
package org.briarproject.briar.introduction; package org.briarproject.briar.introduction;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -41,7 +41,7 @@ import dagger.Component;
MessagingModule.class, MessagingModule.class,
PrivateGroupModule.class, PrivateGroupModule.class,
SharingModule.class, SharingModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -2,7 +2,7 @@ package org.briarproject.briar.messaging;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -29,7 +29,7 @@ import dagger.Component;
ForumModule.class, ForumModule.class,
IdentityModule.class, IdentityModule.class,
MessagingModule.class, MessagingModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -7,7 +7,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestPluginConfigModule; import org.briarproject.bramble.test.TestPluginConfigModule;
@@ -30,7 +30,7 @@ import dagger.Component;
BriarClientModule.class, BriarClientModule.class,
ConversationModule.class, ConversationModule.class,
MessagingModule.class, MessagingModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.mailbox.UrlConverterModule; import org.briarproject.bramble.mailbox.ModularMailboxModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent; import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
@@ -66,7 +66,7 @@ import dagger.Component;
MessagingModule.class, MessagingModule.class,
PrivateGroupModule.class, PrivateGroupModule.class,
SharingModule.class, SharingModule.class,
UrlConverterModule.class, ModularMailboxModule.class,
TestDnsModule.class, TestDnsModule.class,
TestSocksModule.class, TestSocksModule.class,
TestPluginConfigModule.class, TestPluginConfigModule.class,

View File

@@ -22,6 +22,7 @@ import org.briarproject.bramble.plugin.tor.UnixTorPluginFactory
import org.briarproject.bramble.plugin.tor.WindowsTorPluginFactory import org.briarproject.bramble.plugin.tor.WindowsTorPluginFactory
import org.briarproject.bramble.system.ClockModule import org.briarproject.bramble.system.ClockModule
import org.briarproject.bramble.system.DefaultTaskSchedulerModule import org.briarproject.bramble.system.DefaultTaskSchedulerModule
import org.briarproject.bramble.system.DefaultThreadFactoryModule
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule
import org.briarproject.bramble.system.DesktopSecureRandomModule import org.briarproject.bramble.system.DesktopSecureRandomModule
import org.briarproject.bramble.util.OsUtils.isLinux import org.briarproject.bramble.util.OsUtils.isLinux
@@ -44,6 +45,7 @@ import javax.inject.Singleton
DefaultEventExecutorModule::class, DefaultEventExecutorModule::class,
DefaultTaskSchedulerModule::class, DefaultTaskSchedulerModule::class,
DefaultWakefulIoExecutorModule::class, DefaultWakefulIoExecutorModule::class,
DefaultThreadFactoryModule::class,
DesktopSecureRandomModule::class, DesktopSecureRandomModule::class,
HeadlessBlogModule::class, HeadlessBlogModule::class,
HeadlessContactModule::class, HeadlessContactModule::class,

View File

@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory
import org.briarproject.bramble.event.DefaultEventExecutorModule import org.briarproject.bramble.event.DefaultEventExecutorModule
import org.briarproject.bramble.system.ClockModule import org.briarproject.bramble.system.ClockModule
import org.briarproject.bramble.system.DefaultTaskSchedulerModule import org.briarproject.bramble.system.DefaultTaskSchedulerModule
import org.briarproject.bramble.system.DefaultThreadFactoryModule
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule
import org.briarproject.bramble.test.TestFeatureFlagModule import org.briarproject.bramble.test.TestFeatureFlagModule
import org.briarproject.bramble.test.TestSecureRandomModule import org.briarproject.bramble.test.TestSecureRandomModule
@@ -37,6 +38,7 @@ import javax.inject.Singleton
DefaultEventExecutorModule::class, DefaultEventExecutorModule::class,
DefaultTaskSchedulerModule::class, DefaultTaskSchedulerModule::class,
DefaultWakefulIoExecutorModule::class, DefaultWakefulIoExecutorModule::class,
DefaultThreadFactoryModule::class,
TestFeatureFlagModule::class, TestFeatureFlagModule::class,
TestSecureRandomModule::class, TestSecureRandomModule::class,
HeadlessBlogModule::class, HeadlessBlogModule::class,

View File

@@ -7,14 +7,15 @@ apply from: '../dagger.gradle'
dependencies { dependencies {
testImplementation project(path: ':bramble-api', configuration: 'default') testImplementation project(path: ':bramble-api', configuration: 'default')
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'default') testImplementation project(path: ':bramble-core', configuration: 'default')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation project(path: ':mailbox-core', configuration: 'default') testImplementation project(path: ':mailbox-core', configuration: 'default')
testImplementation project(path: ':mailbox-lib', configuration: 'default') testImplementation project(path: ':mailbox-lib', configuration: 'default')
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation "junit:junit:$junit_version" testImplementation "junit:junit:$junit_version"
testImplementation "ch.qos.logback:logback-classic:1.2.11" testImplementation "ch.qos.logback:logback-classic:1.2.11"
testImplementation 'net.jodah:concurrentunit:0.4.6'
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
} }

View File

@@ -0,0 +1,221 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbCallable;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxPairingState;
import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.test.BrambleIntegrationTest;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.bramble.test.TestLogFormatter;
import org.briarproject.bramble.test.TestThreadFactoryModule;
import org.briarproject.mailbox.lib.AbstractMailbox;
import org.briarproject.mailbox.lib.TestMailbox;
import org.junit.After;
import org.junit.Before;
import java.io.File;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.briarproject.bramble.api.mailbox.MailboxAuthToken.fromString;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestComponent.Helper.injectEagerSingletons;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
import static org.briarproject.bramble.mailbox.MailboxTestUtils.getQrCodePayload;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
abstract class AbstractMailboxIntegrationTest
extends BrambleIntegrationTest<MailboxIntegrationTestComponent> {
static final String URL_BASE = "http://127.0.0.1:8000";
AbstractMailboxIntegrationTest() {
TestLogFormatter.use();
}
private final TransportId transportId = new TransportId(getRandomString(4));
private final File dir1 = new File(testDir, "alice");
private final File dir2 = new File(testDir, "bob");
private final SecretKey rootKey = getSecretKey();
MailboxIntegrationTestComponent c1, c2;
Contact contact1From2, contact2From1;
TestMailbox mailbox;
MailboxApi api = createMailboxApi();
@Before
@Override
public void setUp() throws Exception {
super.setUp();
c1 = startTestComponent(dir1, "Alice");
c2 = startTestComponent(dir2, "Bob");
mailbox = new TestMailbox(new File(testDir, "mailbox"));
mailbox.startLifecycle();
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
c1.getLifecycleManager().stopServices();
c2.getLifecycleManager().stopServices();
c1.getLifecycleManager().waitForShutdown();
c2.getLifecycleManager().waitForShutdown();
mailbox.stopLifecycle(true);
}
private MailboxIntegrationTestComponent startTestComponent(
File databaseDir, String name) throws Exception {
TestThreadFactoryModule threadFactoryModule =
new TestThreadFactoryModule(name);
TestDatabaseConfigModule dbModule =
new TestDatabaseConfigModule(databaseDir);
MailboxIntegrationTestComponent component =
DaggerMailboxIntegrationTestComponent
.builder()
.testThreadFactoryModule(threadFactoryModule)
.testDatabaseConfigModule(dbModule)
.build();
injectEagerSingletons(component);
setUp(component, name);
return component;
}
private void setUp(MailboxIntegrationTestComponent device,
String name) throws Exception {
// Add an identity for the user
IdentityManager identityManager = device.getIdentityManager();
Identity identity = identityManager.createIdentity(name);
identityManager.registerIdentity(identity);
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(getSecretKey());
lifecycleManager.waitForStartup();
addEventListener(device);
}
MailboxProperties pair(MailboxIntegrationTestComponent c,
AbstractMailbox mailbox) throws Exception {
MailboxAuthToken setupToken = fromString(mailbox.getSetupToken());
MailboxPairingTask pairingTask = c.getMailboxManager()
.startPairingTask(getQrCodePayload(setupToken.getBytes()));
CountDownLatch latch = new CountDownLatch(1);
pairingTask.addObserver((state) -> {
if (state instanceof MailboxPairingState.Paired) {
latch.countDown();
}
});
if (!latch.await(10, SECONDS)) {
fail("Timeout reached when waiting for pairing.");
}
MailboxProperties properties = c.getDatabaseComponent()
.transactionWithNullableResult(true, txn ->
c.getMailboxSettingsManager()
.getOwnMailboxProperties(txn)
);
assertNotNull(properties);
return properties;
}
void addContacts() throws Exception {
LocalAuthor author1 = c1.getIdentityManager().getLocalAuthor();
LocalAuthor author2 = c2.getIdentityManager().getLocalAuthor();
ContactId contactId2From1 =
c1.getContactManager().addContact(author2,
author1.getId(), rootKey,
c1.getClock().currentTimeMillis(),
true, true, true);
ContactId contactId1From2 =
c2.getContactManager().addContact(author1,
author2.getId(), rootKey,
c2.getClock().currentTimeMillis(),
false, true, true);
contact2From1 = c1.getContactManager().getContact(contactId2From1);
contact1From2 = c2.getContactManager().getContact(contactId1From2);
// Sync client versioning update from 1 to 2
sync1To2(1, true);
// Sync client versioning update and ack from 2 to 1
sync2To1(1, true);
// Sync second client versioning update, mailbox properties and ack
// from 1 to 2
sync1To2(2, true);
// Sync mailbox properties and ack from 2 to 1
sync2To1(1, true);
// Sync final ack from 1 to 2
ack1To2(1);
}
<T> T getFromDb(MailboxIntegrationTestComponent device,
DbCallable<T, ?> callable) throws Exception {
return device.getDatabaseComponent()
.transactionWithResult(true, callable::call);
}
MailboxProperties getMailboxProperties(
MailboxIntegrationTestComponent device, ContactId contactId)
throws DbException {
DatabaseComponent db = device.getDatabaseComponent();
MailboxUpdateWithMailbox update = (MailboxUpdateWithMailbox)
db.transactionWithNullableResult(true, txn ->
device.getMailboxUpdateManager()
.getRemoteUpdate(txn, contactId)
);
if (update == null) fail();
return update.getMailboxProperties();
}
void broadcastMessage(MailboxIntegrationTestComponent from)
throws Exception {
TransportProperties p = from.getTransportPropertyManager()
.getLocalProperties(transportId);
p.put(getRandomString(23), getRandomString(8));
from.getTransportPropertyManager().mergeLocalProperties(transportId, p);
}
void sync1To2(int num, boolean valid) throws Exception {
syncMessage(c1, c2, contact2From1.getId(), num, valid);
}
void sync2To1(int num, boolean valid) throws Exception {
syncMessage(c2, c1, contact1From2.getId(), num, valid);
}
void ack1To2(int num) throws Exception {
sendAcks(c1, c2, contact2From1.getId(), num);
}
void ack2To1(int num) throws Exception {
sendAcks(c2, c1, contact1From2.getId(), num);
}
void assertNumMessages(MailboxIntegrationTestComponent c,
ContactId contactId, int num) throws DbException {
Map<ContactId, TransportProperties> p = c.getTransportPropertyManager()
.getRemoteProperties(transportId);
assertEquals(num, p.get(contactId).size());
}
}

View File

@@ -26,7 +26,7 @@ import java.util.List;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.URL_BASE; import static org.briarproject.bramble.mailbox.AbstractMailboxIntegrationTest.URL_BASE;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi; import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getRandomId;

View File

@@ -0,0 +1,70 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.mailbox.MailboxApi.MailboxFile;
import org.junit.Test;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.retryUntilSuccessOrTimeout;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class MailboxIntegrationTest extends AbstractMailboxIntegrationTest {
private static final Logger LOG =
getLogger(MailboxIntegrationTest.class.getSimpleName());
@Test
public void testSendMessageViaMailbox() throws Exception {
addContacts();
// c1 one pairs the mailbox
MailboxProperties props1 = pair(c1, mailbox);
// Check for number of contacts on mailbox via API every 100ms.
// This should be quick and will succeed with first call.
retryUntilSuccessOrTimeout(1_000, 100, () -> {
Collection<ContactId> contacts = api.getContacts(props1);
return contacts.size() == 1;
});
// tell contact about mailbox
sync1To2(1, true);
ack2To1(1);
// contact should have received their MailboxProperties
MailboxProperties props2 =
getMailboxProperties(c2, contact1From2.getId());
assertNotNull(props2.getInboxId());
// wait until file containing mailbox properties arrived on mailbox
retryUntilSuccessOrTimeout(5_000, 500, () -> {
List<MailboxFile> files = api.getFiles(props2, props2.getInboxId());
return files.size() == 1;
});
LOG.info("Mailbox properties uploaded");
// send message and wait for it to arrive via mailbox
broadcastMessage(c1);
// we don't check for two messages now, because 2 (Bob) might have
// download the first message still in their 1st download cycle.
// wait for message to arrive
// this might require 2nd download cycle after Tor reachability period
LOG.info("Waiting for delivery of broadcast message");
awaitPendingMessageDelivery(1);
// assert that message arrived for c2
assertNumMessages(c2, contact1From2.getId(), 1);
// all files were deleted from mailbox
assertEquals(0, api.getFiles(props2, props2.getInboxId()).size());
}
}

View File

@@ -1,8 +1,8 @@
package org.briarproject.bramble.mailbox; package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -11,10 +11,9 @@ import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxUpdateManager; import org.briarproject.bramble.api.mailbox.MailboxUpdateManager;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.TestUrlConverterModule;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent; import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import org.briarproject.bramble.test.FakeTorPluginConfigModule; import org.briarproject.bramble.test.MailboxTestPluginConfigModule;
import org.briarproject.bramble.test.TestDnsModule; import org.briarproject.bramble.test.TestDnsModule;
import org.briarproject.bramble.test.TestSocksModule; import org.briarproject.bramble.test.TestSocksModule;
@@ -26,31 +25,37 @@ import dagger.Component;
@Component(modules = { @Component(modules = {
BrambleCoreIntegrationTestModule.class, BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class, BrambleCoreModule.class,
TestUrlConverterModule.class, TestModularMailboxModule.class,
FakeTorPluginConfigModule.class, MailboxTestPluginConfigModule.class,
TestSocksModule.class, TestSocksModule.class,
TestDnsModule.class, TestDnsModule.class,
}) })
interface MailboxIntegrationTestComponent extends interface MailboxIntegrationTestComponent extends
BrambleIntegrationTestComponent { BrambleIntegrationTestComponent {
DatabaseComponent getDatabaseComponent();
MailboxManager getMailboxManager();
MailboxUpdateManager getMailboxUpdateManager();
MailboxSettingsManager getMailboxSettingsManager();
LifecycleManager getLifecycleManager(); LifecycleManager getLifecycleManager();
DatabaseComponent getDatabaseComponent();
ContactManager getContactManager(); ContactManager getContactManager();
AuthorFactory getAuthorFactory();
Clock getClock(); Clock getClock();
MailboxManager getMailboxManager();
MailboxSettingsManager getMailboxSettingsManager();
MailboxUpdateManager getMailboxUpdateManager();
TransportPropertyManager getTransportPropertyManager(); TransportPropertyManager getTransportPropertyManager();
AuthorFactory getAuthorFactory(); class Helper {
static void injectEagerSingletons(
CryptoComponent getCrypto(); MailboxIntegrationTestComponent c) {
BrambleCoreIntegrationTestEagerSingletons.Helper
.injectEagerSingletons(c);
}
}
} }

View File

@@ -1,89 +1,16 @@
package org.briarproject.bramble.mailbox; package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.api.WeakSingletonProvider;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
import javax.net.SocketFactory;
import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;
import static java.lang.System.currentTimeMillis; import static java.lang.System.currentTimeMillis;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.briarproject.bramble.mailbox.MailboxTestUtils.createHttpClientProvider;
import static org.briarproject.bramble.mailbox.TestModularMailboxModule.urlConverter;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
class MailboxIntegrationTestUtils { class MailboxIntegrationTestUtils {
static final String URL_BASE = "http://127.0.0.1:8000";
static String getQrCodePayload(MailboxAuthToken setupToken) {
byte[] bytes = getQrCodeBytes(setupToken);
Charset charset = Charset.forName("ISO-8859-1");
return new String(bytes, charset);
}
private static byte[] getQrCodeBytes(MailboxAuthToken setupToken) {
byte[] hiddenServiceBytes = getHiddenServiceBytes();
byte[] setupTokenBytes = setupToken.getBytes();
return ByteBuffer.allocate(65).put((byte) 32)
.put(hiddenServiceBytes).put(setupTokenBytes).array();
}
private static byte[] getHiddenServiceBytes() {
byte[] data = new byte[32];
Arrays.fill(data, (byte) 'a');
return data;
}
private static WeakSingletonProvider<OkHttpClient> createHttpClientProvider() {
OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
return new WeakSingletonProvider<OkHttpClient>() {
@Override
@Nonnull
public OkHttpClient createInstance() {
return client;
}
};
}
static MailboxApi createMailboxApi() { static MailboxApi createMailboxApi() {
return new MailboxApiImpl(createHttpClientProvider(), return new MailboxApiImpl(createHttpClientProvider(), urlConverter);
new TestUrlConverter());
}
static MailboxIntegrationTestComponent createTestComponent(
File databaseDir) {
MailboxIntegrationTestComponent component =
DaggerMailboxIntegrationTestComponent
.builder()
.testDatabaseConfigModule(
new TestDatabaseConfigModule(databaseDir))
.build();
BrambleCoreIntegrationTestEagerSingletons.Helper
.injectEagerSingletons(component);
return component;
}
@Module
static class TestUrlConverterModule {
@Provides
UrlConverter provideUrlConverter() {
return new TestUrlConverter();
}
} }
interface Check { interface Check {
@@ -126,6 +53,7 @@ class MailboxIntegrationTestUtils {
return; return;
} }
try { try {
//noinspection BusyWait
Thread.sleep(step); Thread.sleep(step);
} catch (InterruptedException ignore) { } catch (InterruptedException ignore) {
// continue // continue

View File

@@ -6,112 +6,49 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorFactory; import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.Identity; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.mailbox.MailboxAuthToken;
import org.briarproject.bramble.api.mailbox.MailboxPairingState.Paired;
import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.mailbox.lib.TestMailbox;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch;
import static org.briarproject.bramble.api.mailbox.MailboxAuthToken.fromString;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi; import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createMailboxApi;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.createTestComponent;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.getQrCodePayload;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.retryUntilSuccessOrTimeout; import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.retryUntilSuccessOrTimeout;
import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class OwnMailboxContactListWorkerIntegrationTest public class OwnMailboxContactListWorkerIntegrationTest
extends BrambleTestCase { extends AbstractMailboxIntegrationTest {
@Rule
public TemporaryFolder mailboxDataDirectory = new TemporaryFolder();
private TestMailbox mailbox;
private final MailboxApi api = createMailboxApi(); private final MailboxApi api = createMailboxApi();
private MailboxProperties ownerProperties; private MailboxProperties ownerProperties;
private final File testDir = getTestDirectory(); private LocalAuthor localAuthor1;
private final File aliceDir = new File(testDir, "alice");
private MailboxIntegrationTestComponent component;
private Identity identity;
private final SecretKey rootKey = getSecretKey(); private final SecretKey rootKey = getSecretKey();
private final long timestamp = System.currentTimeMillis(); private final long timestamp = System.currentTimeMillis();
@Before @Before
@Override
public void setUp() throws Exception { public void setUp() throws Exception {
mailbox = new TestMailbox(mailboxDataDirectory.getRoot()); super.setUp();
mailbox.startLifecycle(); localAuthor1 = c1.getIdentityManager().getLocalAuthor();
ownerProperties = pair(c1, mailbox);
MailboxAuthToken setupToken = fromString(mailbox.getSetupToken());
component = createTestComponent(aliceDir);
identity = setUp(component, "Alice");
MailboxPairingTask pairingTask = component.getMailboxManager()
.startPairingTask(getQrCodePayload(setupToken));
CountDownLatch latch = new CountDownLatch(1);
pairingTask.addObserver((state) -> {
if (state instanceof Paired) {
latch.countDown();
}
});
latch.await();
ownerProperties = component.getDatabaseComponent()
.transactionWithNullableResult(false, txn ->
component.getMailboxSettingsManager()
.getOwnMailboxProperties(txn)
);
}
@After
public void tearDown() {
mailbox.stopLifecycle(true);
}
private Identity setUp(MailboxIntegrationTestComponent device, String name)
throws Exception {
// Add an identity for the user
IdentityManager identityManager = device.getIdentityManager();
Identity identity = identityManager.createIdentity(name);
identityManager.registerIdentity(identity);
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(getSecretKey());
lifecycleManager.waitForStartup();
// Check the initial conditions
ContactManager contactManager = device.getContactManager();
assertEquals(0, contactManager.getPendingContacts().size());
assertEquals(0, contactManager.getContacts().size());
return identity;
} }
@Test @Test
public void testUploadContacts() throws Exception { public void testUploadContacts() throws Exception {
// Check the initial conditions
ContactManager contactManager = c1.getContactManager();
assertEquals(0, contactManager.getPendingContacts().size());
assertEquals(0, contactManager.getContacts().size());
int numContactsToAdd = 5; int numContactsToAdd = 5;
List<ContactId> expectedContacts = List<ContactId> expectedContacts = createContacts(c1, numContactsToAdd);
createContacts(component, identity, numContactsToAdd);
// Check for number of contacts on mailbox via API every 100ms // Check for number of contacts on mailbox via API every 100ms
retryUntilSuccessOrTimeout(1000, 100, () -> { retryUntilSuccessOrTimeout(1000, 100, () -> {
@@ -125,15 +62,16 @@ public class OwnMailboxContactListWorkerIntegrationTest
} }
private List<ContactId> createContacts( private List<ContactId> createContacts(
MailboxIntegrationTestComponent component, Identity local, MailboxIntegrationTestComponent component, int numContacts)
int numContacts) throws DbException { throws DbException {
List<ContactId> contactIds = new ArrayList<>(); List<ContactId> contactIds = new ArrayList<>();
ContactManager contactManager = component.getContactManager(); ContactManager contactManager = component.getContactManager();
AuthorFactory authorFactory = component.getAuthorFactory(); AuthorFactory authorFactory = component.getAuthorFactory();
for (int i = 0; i < numContacts; i++) { for (int i = 0; i < numContacts; i++) {
Author remote = authorFactory.createLocalAuthor("Bob " + i); Author remote = authorFactory.createLocalAuthor("Bob " + i);
contactIds.add(contactManager.addContact(remote, local.getId(), ContactId c = contactManager.addContact(remote,
rootKey, timestamp, true, true, true)); localAuthor1.getId(), rootKey, timestamp, true, true, true);
contactIds.add(c);
} }
return contactIds; return contactIds;
} }

View File

@@ -0,0 +1,30 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@Immutable
@NotNullByDefault
class TestMailboxConfigImpl implements MailboxConfig {
@Inject
TestMailboxConfigImpl() {
}
@Override
public long getApiCallerMinRetryInterval() {
return 1000;
}
@Override
public long getApiCallerMaxRetryInterval() {
return 2000;
}
@Override
public long getTorReachabilityPeriod() {
return 10_000;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.nullsafety.NotNullByDefault;
import dagger.Module;
import dagger.Provides;
import static org.briarproject.bramble.mailbox.AbstractMailboxIntegrationTest.URL_BASE;
@Module
@NotNullByDefault
class TestModularMailboxModule {
@Provides
MailboxConfig provideMailboxConfig(TestMailboxConfigImpl mailboxConfig) {
return mailboxConfig;
}
static UrlConverter urlConverter = onion -> URL_BASE;
@Provides
UrlConverter provideUrlConverter() {
return urlConverter;
}
}

View File

@@ -1,14 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.nullsafety.NotNullByDefault;
import static org.briarproject.bramble.mailbox.MailboxIntegrationTestUtils.URL_BASE;
@NotNullByDefault
class TestUrlConverter implements UrlConverter {
@Override
public String convertOnionToBaseUrl(String onion) {
return URL_BASE;
}
}

View File

@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.plugin.ConnectionHandler; import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginException; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
@@ -21,7 +21,6 @@ import javax.annotation.Nullable;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
@NotNullByDefault @NotNullByDefault
@@ -29,9 +28,14 @@ public class FakeTorPlugin implements DuplexPlugin {
private static final Logger LOG = private static final Logger LOG =
getLogger(FakeTorPlugin.class.getName()); getLogger(FakeTorPlugin.class.getName());
private final PluginCallback callback;
private State state = INACTIVE; private State state = INACTIVE;
FakeTorPlugin(PluginCallback callback) {
this.callback = callback;
}
@Override @Override
public TransportId getId() { public TransportId getId() {
return TorConstants.ID; return TorConstants.ID;
@@ -48,15 +52,17 @@ public class FakeTorPlugin implements DuplexPlugin {
} }
@Override @Override
public void start() throws PluginException { public void start() {
LOG.info("Starting plugin"); LOG.info("Starting plugin");
state = ACTIVE; state = ACTIVE;
callback.pluginStateChanged(state);
} }
@Override @Override
public void stop() throws PluginException { public void stop() {
LOG.info("Stopping plugin"); LOG.info("Stopping plugin");
state = DISABLED; state = INACTIVE;
callback.pluginStateChanged(state);
} }
@Override @Override

View File

@@ -32,6 +32,6 @@ public class FakeTorPluginFactory implements DuplexPluginFactory {
@Nullable @Nullable
@Override @Override
public DuplexPlugin createPlugin(PluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
return new FakeTorPlugin(); return new FakeTorPlugin(callback);
} }
} }

View File

@@ -1,27 +1,56 @@
package org.briarproject.bramble.test; package org.briarproject.bramble.test;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginConfig; import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.plugin.file.MailboxPluginFactory;
import org.briarproject.nullsafety.NotNullByDefault; import org.briarproject.nullsafety.NotNullByDefault;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import static java.util.Collections.emptyList; import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap; import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
@Module @Module
public class FakeTorPluginConfigModule { public class MailboxTestPluginConfigModule {
private static final int MAX_LATENCY = 30_000; // 30 seconds
@NotNullByDefault
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
@Override
public TransportId getId() {
return SIMPLEX_TRANSPORT_ID;
}
@Override
public long getMaxLatency() {
return MAX_LATENCY;
}
@Override
@Nullable
public SimplexPlugin createPlugin(PluginCallback callback) {
return null;
}
};
@Provides @Provides
PluginConfig providePluginConfig(FakeTorPluginFactory tor) { PluginConfig providePluginConfig(FakeTorPluginFactory tor,
MailboxPluginFactory mailboxPluginFactory) {
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {
@@ -32,7 +61,7 @@ public class FakeTorPluginConfigModule {
@Override @Override
public Collection<SimplexPluginFactory> getSimplexFactories() { public Collection<SimplexPluginFactory> getSimplexFactories() {
return emptyList(); return asList(simplex, mailboxPluginFactory);
} }
@Override @Override

View File

@@ -0,0 +1,57 @@
package org.briarproject.bramble.test;
import org.briarproject.nullsafety.NotNullByDefault;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
@NotNullByDefault
public class TestLogFormatter extends SimpleFormatter {
private final Object lock = new Object();
private final DateFormat dateFormat; // Locking: lock
private final Date date; // Locking: lock
public static void use() {
LogManager.getLogManager().reset();
Logger rootLogger = LogManager.getLogManager().getLogger("");
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new TestLogFormatter());
rootLogger.addHandler(handler);
}
private TestLogFormatter() {
synchronized (lock) {
dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
date = new Date();
}
}
@Override
public String format(LogRecord rec) {
if (rec.getThrown() == null) {
String dateString;
synchronized (lock) {
date.setTime(rec.getMillis());
dateString = dateFormat.format(date);
}
return String.format("%s [%s] %s %s - %s\n",
dateString,
Thread.currentThread().getName(),
rec.getLevel().getName(),
rec.getLoggerName(),
rec.getMessage());
} else {
return super.format(rec);
}
}
}