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

Add MailboxIntegrationTest against a real mailbox instance

See merge request briar/briar!1575
This commit is contained in:
akwizgran
2022-01-18 14:46:38 +00:00
6 changed files with 177 additions and 39 deletions

View File

@@ -62,7 +62,7 @@ android test:
when: on_failure when: on_failure
rules: rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"' - if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success when: manual
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes: changes:
- briar-android/**/* - briar-android/**/*
@@ -85,35 +85,43 @@ test_reproducible:
.optional_tests: .optional_tests:
stage: optional_tests stage: optional_tests
before_script: extends: .base-test
- set -e
- export GRADLE_USER_HOME=$PWD/.gradle
cache:
key: "$CI_COMMIT_REF_SLUG"
paths:
- .gradle/wrapper
- .gradle/caches
script:
- OPTIONAL_TESTS=org.briarproject.bramble.plugin.tor.BridgeTest ./gradlew --info bramble-java:test --tests BridgeTest
after_script:
# these file change every time but should not be cached
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
bridge test: bridge test:
extends: .optional_tests extends: .optional_tests
rules: rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"' - if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success when: on_success
allow_failure: true allow_failure: false
- if: '$CI_COMMIT_TAG == null' - if: '$CI_COMMIT_TAG == null'
when: manual when: manual
allow_failure: true allow_failure: true
script:
- OPTIONAL_TESTS=org.briarproject.bramble.plugin.tor.BridgeTest ./gradlew --info bramble-java:test --tests BridgeTest
mailbox integration test:
extends: .optional_tests
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
allow_failure: false
- if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: false
script:
# start mailbox
- cd /opt && git clone --depth 1 https://code.briarproject.org/briar/briar-mailbox.git briar-mailbox
- cd briar-mailbox
- mkdir -p /root/.local/share # create directory that mailbox (currently) expects to exist
- ./gradlew run --args="--debug --setup-token 54686973206973206120736574757020746f6b656e20666f722042726961722e" &
# run mailbox integration test once mailbox has started
- cd "$CI_PROJECT_DIR"
- bramble-core/src/test/bash/wait-for-mailbox.sh
- OPTIONAL_TESTS=org.briarproject.bramble.mailbox.MailboxIntegrationTest ./gradlew --info bramble-core:test --tests MailboxIntegrationTest
pre_release_tests: pre_release_tests:
extends: .optional_tests extends: .optional_tests
script:
- OPTIONAL_TESTS=org.briarproject.bramble.plugin.tor.BridgeTest ./gradlew --info bramble-java:test --tests BridgeTest
only: only:
- tags - tags

View File

@@ -43,20 +43,20 @@ interface MailboxApi {
/** /**
* Deletes a contact from the mailbox. * Deletes a contact from the mailbox.
* This should get called after a contact was removed from Briar. * This should get called after a contact was removed from Briar.
*/
void deleteContact(MailboxProperties properties, ContactId contactId)
throws IOException, ApiException;
/**
* Gets a list of {@link ContactId}s from the mailbox.
* These are the contacts that the mailbox already knows about.
* *
* @throws TolerableFailureException if response code is 404 * @throws TolerableFailureException if response code is 404
* (contact probably was already deleted). * (contact probably was already deleted).
*/ */
Collection<ContactId> getContacts(MailboxProperties properties) void deleteContact(MailboxProperties properties, ContactId contactId)
throws IOException, ApiException, TolerableFailureException; throws IOException, ApiException, TolerableFailureException;
/**
* Gets a list of {@link ContactId}s from the mailbox.
* These are the contacts that the mailbox already knows about.
*/
Collection<ContactId> getContacts(MailboxProperties properties)
throws IOException, ApiException;
@Immutable @Immutable
@JsonSerialize @JsonSerialize
class MailboxContact { class MailboxContact {

View File

@@ -113,7 +113,7 @@ class MailboxApiImpl implements MailboxApi {
@Override @Override
public void deleteContact(MailboxProperties properties, ContactId contactId) public void deleteContact(MailboxProperties properties, ContactId contactId)
throws IOException, ApiException { throws IOException, ApiException, TolerableFailureException {
if (!properties.isOwner()) throw new IllegalArgumentException(); if (!properties.isOwner()) throw new IllegalArgumentException();
String url = properties.getOnionAddress() + "/contacts/" + String url = properties.getOnionAddress() + "/contacts/" +
contactId.getInt(); contactId.getInt();
@@ -123,15 +123,15 @@ class MailboxApiImpl implements MailboxApi {
.build(); .build();
OkHttpClient client = httpClientProvider.get(); OkHttpClient client = httpClientProvider.get();
Response response = client.newCall(request).execute(); Response response = client.newCall(request).execute();
if (response.code() == 404) throw new TolerableFailureException();
if (response.code() != 200) throw new ApiException(); if (response.code() != 200) throw new ApiException();
} }
@Override @Override
public Collection<ContactId> getContacts(MailboxProperties properties) public Collection<ContactId> getContacts(MailboxProperties properties)
throws IOException, ApiException, TolerableFailureException { throws IOException, ApiException {
if (!properties.isOwner()) throw new IllegalArgumentException(); if (!properties.isOwner()) throw new IllegalArgumentException();
Response response = sendGetRequest(properties, "/contacts"); Response response = sendGetRequest(properties, "/contacts");
if (response.code() == 404) throw new TolerableFailureException();
if (response.code() != 200) throw new ApiException(); if (response.code() != 200) throw new ApiException();
ResponseBody body = response.body(); ResponseBody body = response.body();

View File

@@ -0,0 +1,21 @@
#!/bin/bash
set -e
URL="http://127.0.0.1:8000/status"
attempt_counter=0
max_attempts=200 # 10min - CI for mailbox currently takes ~5min
echo "Waiting for mailbox to come online at $URL"
until [[ "$(curl -s -o /dev/null -w '%{http_code}' $URL)" == "401" ]]; do
if [ ${attempt_counter} -eq ${max_attempts} ]; then
echo "Timed out waiting for mailbox"
exit 1
fi
printf '.'
attempt_counter=$((attempt_counter + 1))
sleep 3
done
echo "Mailbox started"

View File

@@ -230,6 +230,7 @@ public class MailboxApiTest extends BrambleTestCase {
server.enqueue(new MockResponse()); server.enqueue(new MockResponse());
server.enqueue(new MockResponse().setResponseCode(205)); server.enqueue(new MockResponse().setResponseCode(205));
server.enqueue(new MockResponse().setResponseCode(401)); server.enqueue(new MockResponse().setResponseCode(401));
server.enqueue(new MockResponse().setResponseCode(404));
server.start(); server.start();
String baseUrl = getBaseUrl(server); String baseUrl = getBaseUrl(server);
MailboxProperties properties = MailboxProperties properties =
@@ -257,6 +258,14 @@ public class MailboxApiTest extends BrambleTestCase {
assertEquals("DELETE", request3.getMethod()); assertEquals("DELETE", request3.getMethod());
assertEquals("/contacts/" + contactId.getInt(), request3.getPath()); assertEquals("/contacts/" + contactId.getInt(), request3.getPath());
assertToken(request3, token); assertToken(request3, token);
// tolerable 404 not found error
assertThrows(TolerableFailureException.class,
() -> api.deleteContact(properties, contactId));
RecordedRequest request4 = server.takeRequest();
assertEquals("/contacts/" + contactId.getInt(), request4.getPath());
assertEquals("DELETE", request4.getMethod());
assertToken(request4, token);
} }
@Test @Test
@@ -286,7 +295,6 @@ public class MailboxApiTest extends BrambleTestCase {
server.enqueue(new MockResponse().setBody(invalidResponse3)); server.enqueue(new MockResponse().setBody(invalidResponse3));
server.enqueue(new MockResponse().setResponseCode(401)); server.enqueue(new MockResponse().setResponseCode(401));
server.enqueue(new MockResponse().setResponseCode(500)); server.enqueue(new MockResponse().setResponseCode(500));
server.enqueue(new MockResponse().setResponseCode(404));
server.start(); server.start();
String baseUrl = getBaseUrl(server); String baseUrl = getBaseUrl(server);
MailboxProperties properties = MailboxProperties properties =
@@ -350,14 +358,6 @@ public class MailboxApiTest extends BrambleTestCase {
assertEquals("/contacts", request8.getPath()); assertEquals("/contacts", request8.getPath());
assertEquals("GET", request8.getMethod()); assertEquals("GET", request8.getMethod());
assertToken(request8, token); assertToken(request8, token);
// tolerable 404 not found error
assertThrows(TolerableFailureException.class,
() -> api.getContacts(properties));
RecordedRequest request9 = server.takeRequest();
assertEquals("/contacts", request9.getPath());
assertEquals("GET", request9.getMethod());
assertToken(request9, token);
} }
@Test @Test

View File

@@ -0,0 +1,109 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.WeakSingletonProvider;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.mailbox.MailboxApi.ApiException;
import org.briarproject.bramble.mailbox.MailboxApi.MailboxContact;
import org.briarproject.bramble.mailbox.MailboxApi.TolerableFailureException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.util.Arrays;
import javax.annotation.Nonnull;
import javax.net.SocketFactory;
import okhttp3.OkHttpClient;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.bramble.test.TestUtils.getMailboxSecret;
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
public class MailboxIntegrationTest extends BrambleTestCase {
private final static String URL_BASE = "http://127.0.0.1:8000";
private final static String SETUP_TOKEN =
"54686973206973206120736574757020746f6b656e20666f722042726961722e";
private final OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(SocketFactory.getDefault())
.connectTimeout(60_000, MILLISECONDS)
.build();
private final WeakSingletonProvider<OkHttpClient> httpClientProvider =
new WeakSingletonProvider<OkHttpClient>() {
@Override
@Nonnull
public OkHttpClient createInstance() {
return client;
}
};
private final MailboxApiImpl api = new MailboxApiImpl(httpClientProvider);
// needs to be static to keep values across different tests
private static MailboxProperties ownerProperties;
/**
* Called before each test to make sure the mailbox is setup once
* before starting with individual tests.
* {@link BeforeClass} needs to be static, so we can't use the API class.
*/
@Before
public void ensureSetup() throws IOException, ApiException {
// Skip this test unless it's explicitly enabled in the environment
assumeTrue(isOptionalTestEnabled(MailboxIntegrationTest.class));
if (ownerProperties != null) return;
MailboxProperties setupProperties =
new MailboxProperties(URL_BASE, SETUP_TOKEN, true);
String ownerToken = api.setup(setupProperties);
ownerProperties = new MailboxProperties(URL_BASE, ownerToken, true);
}
@Test
public void testStatus() throws Exception {
assertTrue(api.checkStatus(ownerProperties));
}
@Test
public void testContactApi() throws Exception {
ContactId contactId1 = new ContactId(1);
ContactId contactId2 = new ContactId(2);
MailboxContact mailboxContact1 = getMailboxContact(contactId1);
MailboxContact mailboxContact2 = getMailboxContact(contactId2);
// no contacts initially
assertEquals(emptyList(), api.getContacts(ownerProperties));
// added contact gets returned
api.addContact(ownerProperties, mailboxContact1);
assertEquals(singletonList(contactId1),
api.getContacts(ownerProperties));
// second contact also gets returned
api.addContact(ownerProperties, mailboxContact2);
assertEquals(Arrays.asList(contactId1, contactId2),
api.getContacts(ownerProperties));
// after both contacts get deleted, the list is empty again
api.deleteContact(ownerProperties, contactId1);
api.deleteContact(ownerProperties, contactId2);
assertEquals(emptyList(), api.getContacts(ownerProperties));
// deleting again is tolerable
assertThrows(TolerableFailureException.class,
() -> api.deleteContact(ownerProperties, contactId2));
}
private MailboxContact getMailboxContact(ContactId contactId) {
return new MailboxContact(contactId, getMailboxSecret(),
getMailboxSecret(), getMailboxSecret());
}
}