From c92dc3d39f8c25d3ad7d0a91b25baa33dc458ada Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Tue, 28 Mar 2023 15:33:55 +0100 Subject: [PATCH] Add unit test for CircumventionProviderImpl. --- onionwrapper-core/build.gradle | 2 + .../briarproject/onionwrapper/BaseTest.java | 41 +++++++++ .../CircumventionProviderImplTest.java | 91 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 onionwrapper-core/src/test/java/org/briarproject/onionwrapper/BaseTest.java create mode 100644 onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java diff --git a/onionwrapper-core/build.gradle b/onionwrapper-core/build.gradle index 7b9afdf..0a83e78 100644 --- a/onionwrapper-core/build.gradle +++ b/onionwrapper-core/build.gradle @@ -12,4 +12,6 @@ dependencies { api 'com.google.code.findbugs:jsr305:3.0.2' api 'javax.inject:javax.inject:1' api 'org.briarproject:jtorctl:0.5' + + testImplementation "junit:junit:4.13.2" } diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/BaseTest.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/BaseTest.java new file mode 100644 index 0000000..dcc9950 --- /dev/null +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/BaseTest.java @@ -0,0 +1,41 @@ +package org.briarproject.onionwrapper; + +import org.junit.After; +import org.junit.Before; + +import java.util.logging.Logger; + +import javax.annotation.Nullable; + +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; + +class BaseTest { + + private static final Logger LOG = getLogger(BaseTest.class.getName()); + + @Nullable + protected volatile Throwable exceptionInBackgroundThread = null; + + BaseTest() { + // Ensure exceptions thrown on worker threads cause tests to fail + Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { + LOG.log(WARNING, "Caught unhandled exception", throwable); + exceptionInBackgroundThread = throwable; + }); + } + + @Before + public void beforeTestCase() { + exceptionInBackgroundThread = null; + } + + @After + public void afterTestCase() { + Throwable thrown = exceptionInBackgroundThread; + if (thrown != null) { + LOG.log(WARNING, "Background thread has thrown an exception unexpectedly", thrown); + throw new AssertionError(thrown); + } + } +} diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java new file mode 100644 index 0000000..187f396 --- /dev/null +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java @@ -0,0 +1,91 @@ +package org.briarproject.onionwrapper; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +import static java.util.Arrays.asList; +import static org.briarproject.onionwrapper.CircumventionProvider.BLOCKED; +import static org.briarproject.onionwrapper.CircumventionProvider.BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.DEFAULT_OBFS4; +import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.MEEK; +import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4; +import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.SNOWFLAKE; +import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.VANILLA; +import static org.briarproject.onionwrapper.CircumventionProvider.DEFAULT_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.DPI_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.NON_DEFAULT_BRIDGES; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +public class CircumventionProviderImplTest extends BaseTest { + + private final CircumventionProviderImpl provider = + new CircumventionProviderImpl(); + + @Test + public void testInvariants() { + Set<String> blocked = new HashSet<>(asList(BLOCKED)); + Set<String> bridges = new HashSet<>(asList(BRIDGES)); + Set<String> defaultBridges = new HashSet<>(asList(DEFAULT_BRIDGES)); + Set<String> nonDefaultBridges = + new HashSet<>(asList(NON_DEFAULT_BRIDGES)); + Set<String> dpiBridges = new HashSet<>(asList(DPI_BRIDGES)); + // BRIDGES should be a subset of BLOCKED + assertTrue(blocked.containsAll(bridges)); + // BRIDGES should be the union of the bridge type sets + Set<String> union = new HashSet<>(defaultBridges); + union.addAll(nonDefaultBridges); + union.addAll(dpiBridges); + assertEquals(bridges, union); + // The bridge type sets should not overlap + assertEmptyIntersection(defaultBridges, nonDefaultBridges); + assertEmptyIntersection(defaultBridges, dpiBridges); + assertEmptyIntersection(nonDefaultBridges, dpiBridges); + } + + @Test + public void testGetBestBridgeType() { + for (String country : DEFAULT_BRIDGES) { + assertEquals(asList(DEFAULT_OBFS4, VANILLA), + provider.getSuitableBridgeTypes(country)); + } + for (String country : NON_DEFAULT_BRIDGES) { + assertEquals(asList(NON_DEFAULT_OBFS4, VANILLA), + provider.getSuitableBridgeTypes(country)); + } + for (String country : DPI_BRIDGES) { + assertEquals(asList(NON_DEFAULT_OBFS4, MEEK, SNOWFLAKE), + provider.getSuitableBridgeTypes(country)); + } + assertEquals(asList(DEFAULT_OBFS4, VANILLA), + provider.getSuitableBridgeTypes("ZZ")); + } + + @Test + public void testHasSnowflakeParamsWithLetsEncrypt() { + testHasSnowflakeParams(true); + } + + @Test + public void testHasSnowflakeParamsWithoutLetsEncrypt() { + testHasSnowflakeParams(false); + } + + private void testHasSnowflakeParams(boolean letsEncrypt) { + String tmParams = provider.getSnowflakeParams("TM", letsEncrypt); + String defaultParams = provider.getSnowflakeParams("ZZ", letsEncrypt); + assertFalse(tmParams.isEmpty()); + assertFalse(defaultParams.isEmpty()); + assertNotEquals(defaultParams, tmParams); + } + + private <T> void assertEmptyIntersection(Set<T> a, Set<T> b) { + Set<T> intersection = new HashSet<>(a); + intersection.retainAll(b); + assertTrue(intersection.isEmpty()); + } +} -- GitLab