From b90197448840d3b5b68295e3c0588f12264ebded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= Date: Thu, 15 Apr 2021 10:56:08 +0200 Subject: [PATCH] Start work on an integration test --- .../recover/OwnerReturnShardViewModel.java | 17 ++- .../recovery/CustodianTaskImpl.java | 1 + .../recovery/ReturnShardTaskImpl.java | 8 +- .../recovery/SecretOwnerTaskImpl.java | 12 +- .../recovery/ReturnShardIntegrationTest.java | 120 ++++++++++++++++++ .../ReturnShardIntegrationTestComponent.java | 50 ++++++++ 6 files changed, 193 insertions(+), 15 deletions(-) create mode 100644 briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java create mode 100644 briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTestComponent.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java index 28be28d61..ea8f5b9dd 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java @@ -6,7 +6,6 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.util.DisplayMetrics; -import org.briarproject.bramble.api.Pair; import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.AndroidExecutor; @@ -16,16 +15,13 @@ import org.briarproject.briar.android.viewmodel.MutableLiveEvent; import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; import java.net.InetAddress; -import java.net.InterfaceAddress; import java.net.UnknownHostException; import java.nio.charset.Charset; -import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; import javax.inject.Inject; -import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; @@ -36,7 +32,8 @@ import static java.util.logging.Level.INFO; import static java.util.logging.Logger.getLogger; @NotNullByDefault -class OwnerReturnShardViewModel extends AndroidViewModel implements SecretOwnerTask.Observer { +class OwnerReturnShardViewModel extends AndroidViewModel + implements SecretOwnerTask.Observer { private static final Logger LOG = getLogger(OwnerReturnShardViewModel.class.getName()); @@ -123,6 +120,8 @@ class OwnerReturnShardViewModel extends AndroidViewModel implements SecretOwnerT @UiThread private void startListening() { ioExecutor.execute(() -> { + task.cancel(); + // wait until really cancelled task.start(this, getWifiIpv4Address()); }); // KeyAgreementTask oldTask = task; @@ -142,8 +141,6 @@ class OwnerReturnShardViewModel extends AndroidViewModel implements SecretOwnerT } - - /** * Set to true in onPostResume() and false in onPause(). This prevents the * QR code fragment from being shown if onRequestPermissionsResult() is @@ -175,9 +172,11 @@ class OwnerReturnShardViewModel extends AndroidViewModel implements SecretOwnerT public void onStateChanged(SecretOwnerTask.State state) { this.state.postValue(state); if (state instanceof SecretOwnerTask.State.Listening) { - DisplayMetrics dm = getApplication().getResources().getDisplayMetrics(); + DisplayMetrics dm = + getApplication().getResources().getDisplayMetrics(); ioExecutor.execute(() -> { - byte[] payloadBytes = ((SecretOwnerTask.State.Listening) state).getLocalPayload(); + byte[] payloadBytes = ((SecretOwnerTask.State.Listening) state) + .getLocalPayload(); if (LOG.isLoggable(INFO)) { LOG.info("Local payload is " + payloadBytes.length + " bytes"); diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/CustodianTaskImpl.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/CustodianTaskImpl.java index 0ec820543..3bfff6cb7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/CustodianTaskImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/CustodianTaskImpl.java @@ -97,6 +97,7 @@ public class CustodianTaskImpl extends ReturnShardTaskImpl private void connectAndSendShard() { observer.onStateChanged(new CustodianTask.State.SendingShard()); try { + LOG.info("Connecting to secret owner " + remoteSocketAddress); socket.connect(remoteSocketAddress, TIMEOUT); LOG.info("Connected to secret owner " + remoteSocketAddress); diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/ReturnShardTaskImpl.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/ReturnShardTaskImpl.java index ac961adc0..d86e2e2e7 100644 --- a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/ReturnShardTaskImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/ReturnShardTaskImpl.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.SecretKey; +import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; @@ -35,7 +36,8 @@ public class ReturnShardTaskImpl { return nonce; } - void deriveSharedSecret(AgreementPublicKey remotePublicKey, byte[] context) throws + void deriveSharedSecret(AgreementPublicKey remotePublicKey, byte[] context) + throws GeneralSecurityException { sharedSecret = crypto.deriveSharedSecret("ShardReturn", remotePublicKey, @@ -60,9 +62,9 @@ public class ReturnShardTaskImpl { byte[] read(InputStream inputStream, int length) throws IOException { + DataInputStream dis = new DataInputStream(inputStream); byte[] output = new byte[length]; - int bytesRead = inputStream.read(output); - if (bytesRead < 0) throw new IOException("Cannot read from socket"); + dis.readFully(output); return output; } } diff --git a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/SecretOwnerTaskImpl.java b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/SecretOwnerTaskImpl.java index e4d501369..9d865869e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/SecretOwnerTaskImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/socialbackup/recovery/SecretOwnerTaskImpl.java @@ -5,14 +5,13 @@ import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.crypto.AgreementPublicKey; import org.briarproject.bramble.api.crypto.AuthenticatedCipher; import org.briarproject.bramble.api.crypto.CryptoComponent; -import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; +import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; @@ -64,8 +63,10 @@ public class SecretOwnerTaskImpl extends ReturnShardTaskImpl // Start listening on socketAddress try { + LOG.info("Binding socket"); serverSocket = new ServerSocket(); serverSocket.bind(socketAddress); + LOG.info("Binding socket done"); } catch (IOException e) { LOG.warning( "IO Error when listening on local socket" + e.getMessage()); @@ -80,18 +81,22 @@ public class SecretOwnerTaskImpl extends ReturnShardTaskImpl payloadList.add(localKeyPair.getPublic().getEncoded()); payloadList.add(socketAddress.getAddress().getAddress()); payloadList.add(socketAddress.getPort()); + LOG.info("changing state to listening"); observer.onStateChanged( new State.Listening(clientHelper.toByteArray(payloadList))); + LOG.info("changing state to listening done"); } catch (FormatException e) { LOG.warning("Error encoding QR code"); observer.onStateChanged(new State.Failure()); return; } + LOG.info("receiving payload"); receivePayload(); } private void receivePayload() { try { + LOG.info("Accepting connections"); socket = serverSocket.accept(); LOG.info("Client connected"); observer.onStateChanged(new State.ReceivingShard()); @@ -125,7 +130,8 @@ public class SecretOwnerTaskImpl extends ReturnShardTaskImpl // StreamWriter streamWriter = streamWriterFactory.createContactExchangeStreamWriter(socket.getOutputStream(), sharedSecret); // OutputStream outputStream = streamWriter.getOutputStream(); - OutputStream outputStream = socket.getOutputStream(); + DataOutputStream outputStream = + new DataOutputStream(socket.getOutputStream()); byte[] ackNonce = generateNonce(); outputStream.write(ackNonce); diff --git a/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java new file mode 100644 index 000000000..3b0e0eff1 --- /dev/null +++ b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTest.java @@ -0,0 +1,120 @@ +package org.briarproject.briar.socialbackup.recovery; + +import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.test.BrambleTestCase; +import org.briarproject.bramble.test.TestDatabaseConfigModule; +import org.briarproject.briar.api.socialbackup.recovery.CustodianTask; +import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.net.InetAddress; + +import static junit.framework.TestCase.fail; +import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; +import static org.briarproject.bramble.test.TestUtils.getTestDirectory; +import static org.junit.Assert.assertTrue; + +public class ReturnShardIntegrationTest extends BrambleTestCase { + + private final File testDir = getTestDirectory(); + private final File ownerDir = new File(testDir, "owner"); + private final File custodianDir = new File(testDir, "custodian"); + + private ReturnShardIntegrationTestComponent owner, custodian; + + @Before + public void setUp() throws Exception { + assertTrue(testDir.mkdirs()); + // Create the devices + owner = DaggerReturnShardIntegrationTestComponent.builder() + .testDatabaseConfigModule( + new TestDatabaseConfigModule(ownerDir)).build(); + BrambleCoreIntegrationTestEagerSingletons.Helper + .injectEagerSingletons(owner); + custodian = DaggerReturnShardIntegrationTestComponent.builder() + .testDatabaseConfigModule(new TestDatabaseConfigModule( + custodianDir)) + .build(); + BrambleCoreIntegrationTestEagerSingletons.Helper + .injectEagerSingletons(custodian); + } + + @Test + public void testReturnShard() { + SecretOwnerTask secretOwnerTask = owner.getSecretOwnerTask(); + CustodianTask custodianTask = custodian.getCustodianTask(); + + SecretOwnerTask.Observer ownerObserver = + state -> { + if (state instanceof SecretOwnerTask.State.Listening) { + SecretOwnerTask.State.Listening listening = + (SecretOwnerTask.State.Listening) state; + byte[] payload = listening.getLocalPayload(); + System.out.println(payload.length); + tansferQrCode(custodianTask, payload); + } else if (state instanceof SecretOwnerTask.State.Failure) { + System.out.println("owner state: failure"); + fail(); + } else { + System.out.println( + "owner: " + state.getClass().getSimpleName()); + } + }; + + CustodianTask.Observer custodianObserver = + state -> System.out.println( + "custodian: " + state.getClass().getSimpleName()); + + owner.getIoExecutor().execute(() -> { + try { + secretOwnerTask + .start(ownerObserver, InetAddress.getLocalHost()); + } catch (Exception e) { + fail(); + } + }); + + custodian.getIoExecutor().execute(() -> { + try { + custodianTask.start(custodianObserver); + } catch (Exception e) { + fail(); + } + }); + } + + private void tansferQrCode(CustodianTask custodianTask, byte[] payload) { + System.out.println("Calling qrCodeDecoded in executor()"); + custodian.getIoExecutor().execute(() -> { + try { + System.out.println("Calling qrCodeDecoded()"); + Thread.sleep(500); + custodianTask.qrCodeDecoded(payload); + System.out.println("qrCodeDecoded() done"); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + }); + } + + private void tearDown(ReturnShardIntegrationTestComponent device) + throws Exception { + // Stop the lifecycle manager + LifecycleManager lifecycleManager = device.getLifecycleManager(); + lifecycleManager.stopServices(); + lifecycleManager.waitForShutdown(); + } + + @After + public void tearDown() throws Exception { + tearDown(owner); + tearDown(custodian); + deleteTestDirectory(testDir); + } + +} diff --git a/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTestComponent.java new file mode 100644 index 000000000..d282194be --- /dev/null +++ b/briar-core/src/test/java/org/briarproject/briar/socialbackup/recovery/ReturnShardIntegrationTestComponent.java @@ -0,0 +1,50 @@ +package org.briarproject.briar.socialbackup.recovery; + +import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; +import org.briarproject.bramble.BrambleCoreModule; +import org.briarproject.bramble.api.connection.ConnectionManager; +import org.briarproject.bramble.api.contact.ContactExchangeManager; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.lifecycle.IoExecutor; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule; +import org.briarproject.briar.api.socialbackup.recovery.CustodianTask; +import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; +import org.briarproject.briar.socialbackup.SocialBackupModule; + +import java.util.concurrent.Executor; + +import javax.inject.Singleton; + +import dagger.Component; + +@Singleton +@Component(modules = { + BrambleCoreIntegrationTestModule.class, + BrambleCoreModule.class, + SocialBackupModule.class +}) +interface ReturnShardIntegrationTestComponent + extends BrambleCoreIntegrationTestEagerSingletons { + + ConnectionManager getConnectionManager(); + + ContactExchangeManager getContactExchangeManager(); + + ContactManager getContactManager(); + + EventBus getEventBus(); + + IdentityManager getIdentityManager(); + + @IoExecutor + Executor getIoExecutor(); + + LifecycleManager getLifecycleManager(); + + SecretOwnerTask getSecretOwnerTask(); + + CustodianTask getCustodianTask(); +}