From f2111fcbaf08122b152862daf1dd03b62786ab44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= <sebastian@mobanisto.de> Date: Fri, 14 Apr 2023 12:01:22 +0200 Subject: [PATCH] Run tests on Linux and Windows * Enable Github CI to run tests on Linux and Windows * Adapt tests to work on both platforms * Also prepares the project for macOS support --- .github/workflows/checks.yaml | 33 ++++ .gitignore | 1 + .idea/codeStyles/Project.xml | 161 ++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .../org/briarproject/onionwrapper/OS.java | 17 ++ .../briarproject/onionwrapper/OsUtils.java | 21 +++ .../onionwrapper/StringUtils.java | 9 + .../onionwrapper/StringUtils.java | 12 ++ .../briarproject/onionwrapper/TestUtils.java | 11 ++ onionwrapper-java/build.gradle | 12 +- .../onionwrapper/BootstrapTest.java | 15 +- ...urcesTest.java => ResourcesLinuxTest.java} | 2 +- .../onionwrapper/ResourcesWindowsTest.java | 36 ++++ 13 files changed, 328 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/checks.yaml create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 buildSrc/src/main/java/org/briarproject/onionwrapper/OS.java create mode 100644 buildSrc/src/main/java/org/briarproject/onionwrapper/OsUtils.java create mode 100644 buildSrc/src/main/java/org/briarproject/onionwrapper/StringUtils.java create mode 100644 onionwrapper-core/src/test/java/org/briarproject/onionwrapper/StringUtils.java rename onionwrapper-java/src/test/java/org/briarproject/onionwrapper/{ResourcesTest.java => ResourcesLinuxTest.java} (95%) create mode 100644 onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesWindowsTest.java diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml new file mode 100644 index 0000000..a4978c9 --- /dev/null +++ b/.github/workflows/checks.yaml @@ -0,0 +1,33 @@ +name: Onion Wrapper CI +on: + push: + branches: + - master + pull_request: + branches: + - master +jobs: + build-linux: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + - name: Run Gradle tests + run: ./gradlew check --info --stacktrace + build-windows: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + - name: Run Gradle tests + run: ./gradlew check --info --stacktrace diff --git a/.gitignore b/.gitignore index 68aed59..0871d79 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ !/.idea/codeStyles .DS_Store /build +/buildSrc/build /captures .externalNativeBuild .cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a8370a0 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,161 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <option name="SOFT_MARGINS" value="80,100" /> + <JavaCodeStyleSettings> + <option name="IMPORT_LAYOUT_TABLE"> + <value> + <package name="android" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="com" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="junit" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="net" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="org" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="java" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="javax" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="" withSubpackages="true" static="false" /> + <emptyLine /> + <package name="" withSubpackages="true" static="true" /> + <emptyLine /> + </value> + </option> + <option name="JD_ALIGN_PARAM_COMMENTS" value="false" /> + <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" /> + <option name="JD_INDENT_ON_CONTINUATION" value="true" /> + </JavaCodeStyleSettings> + <JetCodeStyleSettings> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + </JetCodeStyleSettings> + <codeStyleSettings language="JAVA"> + <option name="ALIGN_MULTILINE_PARAMETERS" value="false" /> + <option name="METHOD_CALL_CHAIN_WRAP" value="1" /> + <option name="WRAP_LONG_LINES" value="true" /> + <indentOptions> + <option name="USE_TAB_CHARACTER" value="true" /> + <option name="SMART_TABS" value="true" /> + </indentOptions> + </codeStyleSettings> + <codeStyleSettings language="XML"> + <indentOptions> + <option name="CONTINUATION_INDENT_SIZE" value="4" /> + <option name="USE_TAB_CHARACTER" value="true" /> + <option name="SMART_TABS" value="true" /> + </indentOptions> + <arrangement> + <rules> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:android</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>xmlns:.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:id</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*:name</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>name</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>style</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>^$</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> + </AND> + </match> + <order>ANDROID_ATTRIBUTE_ORDER</order> + </rule> + </section> + <section> + <rule> + <match> + <AND> + <NAME>.*</NAME> + <XML_ATTRIBUTE /> + <XML_NAMESPACE>.*</XML_NAMESPACE> + </AND> + </match> + <order>BY_NAME</order> + </rule> + </section> + </rules> + </arrangement> + </codeStyleSettings> + <codeStyleSettings language="kotlin"> + <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + </codeStyleSettings> + </code_scheme> +</component> \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + </state> +</component> \ No newline at end of file diff --git a/buildSrc/src/main/java/org/briarproject/onionwrapper/OS.java b/buildSrc/src/main/java/org/briarproject/onionwrapper/OS.java new file mode 100644 index 0000000..cc48f22 --- /dev/null +++ b/buildSrc/src/main/java/org/briarproject/onionwrapper/OS.java @@ -0,0 +1,17 @@ +package org.briarproject.onionwrapper; + +public enum OS { + Linux("linux"), + Windows("windows"), + MacOS("macos"); + + private String id; + + OS(String id) { + this.id = id; + } + + public String getId() { + return id; + } +} diff --git a/buildSrc/src/main/java/org/briarproject/onionwrapper/OsUtils.java b/buildSrc/src/main/java/org/briarproject/onionwrapper/OsUtils.java new file mode 100644 index 0000000..5b4ee27 --- /dev/null +++ b/buildSrc/src/main/java/org/briarproject/onionwrapper/OsUtils.java @@ -0,0 +1,21 @@ +package org.briarproject.onionwrapper; + +import static org.briarproject.onionwrapper.StringUtils.startsWithIgnoreCase; + +public class OsUtils { + + public static final OS currentOS; + + static { + String os = System.getProperty("os.name"); + if (os.equalsIgnoreCase("Mac OS X")) { + currentOS = OS.MacOS; + } else if (startsWithIgnoreCase(os, "Win")) { + currentOS = OS.Windows; + } else if (startsWithIgnoreCase(os, "Linux")) { + currentOS = OS.Linux; + } else { + throw new AssertionError("Unknown OS name: " + os); + } + } +} diff --git a/buildSrc/src/main/java/org/briarproject/onionwrapper/StringUtils.java b/buildSrc/src/main/java/org/briarproject/onionwrapper/StringUtils.java new file mode 100644 index 0000000..2a9b5db --- /dev/null +++ b/buildSrc/src/main/java/org/briarproject/onionwrapper/StringUtils.java @@ -0,0 +1,9 @@ +package org.briarproject.onionwrapper; + +public class StringUtils { + + // see https://stackoverflow.com/a/38947571 + static boolean startsWithIgnoreCase(String s, String prefix) { + return s.regionMatches(true, 0, prefix, 0, prefix.length()); + } +} diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/StringUtils.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/StringUtils.java new file mode 100644 index 0000000..bd03d2f --- /dev/null +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/StringUtils.java @@ -0,0 +1,12 @@ +package org.briarproject.onionwrapper; + +import org.briarproject.nullsafety.NotNullByDefault; + +@NotNullByDefault +public class StringUtils { + + // see https://stackoverflow.com/a/38947571 + static boolean startsWithIgnoreCase(String s, String prefix) { + return s.regionMatches(true, 0, prefix, 0, prefix.length()); + } +} diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java index d7b8afa..2c6b65e 100644 --- a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/TestUtils.java @@ -12,6 +12,7 @@ import javax.annotation.concurrent.ThreadSafe; import static java.util.Arrays.asList; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; +import static org.briarproject.onionwrapper.StringUtils.startsWithIgnoreCase; @ThreadSafe @NotNullByDefault @@ -58,6 +59,16 @@ public class TestUtils { return os != null && os.contains("Linux"); } + public static boolean isWindows() { + String os = System.getProperty("os.name"); + return os != null && startsWithIgnoreCase(os, "Win"); + } + + public static boolean isMac() { + String os = System.getProperty("os.name"); + return os != null && os.equalsIgnoreCase("Mac OS X"); + } + @Nullable public static String getArchitectureForTorBinary() { String arch = System.getProperty("os.arch"); diff --git a/onionwrapper-java/build.gradle b/onionwrapper-java/build.gradle index 1df23d9..2f7e3f2 100644 --- a/onionwrapper-java/build.gradle +++ b/onionwrapper-java/build.gradle @@ -1,3 +1,7 @@ +import static org.briarproject.onionwrapper.OS.Linux +import static org.briarproject.onionwrapper.OS.Windows +import static org.briarproject.onionwrapper.OsUtils.currentOS + plugins { id 'java-library' id 'com.vanniktech.maven.publish' version '0.18.0' @@ -16,9 +20,11 @@ dependencies { testImplementation project(path: ':onionwrapper-core', configuration: 'testOutput') testImplementation 'junit:junit:4.13.2' - testImplementation 'org.briarproject:tor-linux:0.4.7.13-2' - testImplementation 'org.briarproject:obfs4proxy-linux:0.0.14-tor2' - testImplementation 'org.briarproject:snowflake-linux:2.5.1' + if (currentOS == Linux || currentOS == Windows) { + testImplementation "org.briarproject:tor-$currentOS.id:0.4.7.13-2" + testImplementation "org.briarproject:obfs4proxy-$currentOS.id:0.0.14-tor2" + testImplementation "org.briarproject:snowflake-$currentOS.id:2.5.1" + } } mavenPublishing { diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java index 6681b05..516b1ec 100644 --- a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BootstrapTest.java @@ -16,6 +16,7 @@ import static org.briarproject.onionwrapper.TestUtils.deleteTestDirectory; import static org.briarproject.onionwrapper.TestUtils.getArchitectureForTorBinary; import static org.briarproject.onionwrapper.TestUtils.getTestDirectory; import static org.briarproject.onionwrapper.TestUtils.isLinux; +import static org.briarproject.onionwrapper.TestUtils.isWindows; import static org.briarproject.onionwrapper.TorWrapper.TorState.CONNECTED; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeNotNull; @@ -34,7 +35,7 @@ public class BootstrapTest extends BaseTest { @Before public void setUp() { - assumeTrue(isLinux()); + assumeTrue(isLinux() || isWindows()); assumeNotNull(getArchitectureForTorBinary()); } @@ -47,8 +48,16 @@ public class BootstrapTest extends BaseTest { @Test public void testBootstrapping() throws Exception { String architecture = requireNonNull(getArchitectureForTorBinary()); - TorWrapper tor = new UnixTorWrapper(executor, executor, architecture, torDir, - CONTROL_PORT, SOCKS_PORT); + TorWrapper tor; + if (isLinux()) { + tor = new UnixTorWrapper(executor, executor, architecture, torDir, + CONTROL_PORT, SOCKS_PORT); + } else if (isWindows()) { + tor = new WindowsTorWrapper(executor, executor, architecture, torDir, + CONTROL_PORT, SOCKS_PORT); + } else { + throw new AssertionError("Running on unsupported OS"); + } boolean connected; try { diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesLinuxTest.java similarity index 95% rename from onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesTest.java rename to onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesLinuxTest.java index 084070b..7ebbf50 100644 --- a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesTest.java +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesLinuxTest.java @@ -7,7 +7,7 @@ import static org.briarproject.onionwrapper.TestUtils.isLinux; import static org.junit.Assert.assertNotNull; import static org.junit.Assume.assumeTrue; -public class ResourcesTest { +public class ResourcesLinuxTest { @Before public void setUp() { diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesWindowsTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesWindowsTest.java new file mode 100644 index 0000000..01a0137 --- /dev/null +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/ResourcesWindowsTest.java @@ -0,0 +1,36 @@ +package org.briarproject.onionwrapper; + +import org.junit.Before; +import org.junit.Test; + +import static org.briarproject.onionwrapper.TestUtils.isWindows; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeTrue; + +public class ResourcesWindowsTest { + + @Before + public void setUp() { + assumeTrue(isWindows()); + } + + @Test + public void testCanLoadTor() { + testCanLoadResource("x86_64/tor.exe"); + } + + @Test + public void testCanLoadObfs4() { + testCanLoadResource("x86_64/obfs4proxy.exe"); + } + + @Test + public void testCanLoadSnowflake() { + testCanLoadResource("x86_64/snowflake.exe"); + } + + private void testCanLoadResource(String name) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + assertNotNull(classLoader.getResourceAsStream(name)); + } +} -- GitLab