From c4633ffdcf9ac34e40708102d179c20dbb077076 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 11 Nov 2023 01:16:36 +0100 Subject: add changelog in a fastlane friendly formatting --- src/custom/fastlane/metadata/en-US/changelogs/170000.txt | 15 +++++++++++++++ src/normal/fastlane/metadata/en-US/changelogs/170000.txt | 15 +++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/custom/fastlane/metadata/en-US/changelogs/170000.txt create mode 100644 src/normal/fastlane/metadata/en-US/changelogs/170000.txt diff --git a/src/custom/fastlane/metadata/en-US/changelogs/170000.txt b/src/custom/fastlane/metadata/en-US/changelogs/170000.txt new file mode 100644 index 00000000..d2dbd888 --- /dev/null +++ b/src/custom/fastlane/metadata/en-US/changelogs/170000.txt @@ -0,0 +1,15 @@ +1.2.0 +features: +* updated openvpn, openssl, tor, snowflake +* encrypted storage +* new provider setup UI +* Support for Android 13 +* enforce TLS 1.3 on all Android versions +* Dns over Https (DoH) during provider setup + +bugfixes: +* fixed possible on-device DoS vulnerability, leading to app crashes +* fixed task hijacking vulnerability (aka. strandhogg) +* fixed memory leaks +* fixed blocking vpn service stopping and notifications disappearing correctly +* disable location selection button if provider only supports 1 location diff --git a/src/normal/fastlane/metadata/en-US/changelogs/170000.txt b/src/normal/fastlane/metadata/en-US/changelogs/170000.txt new file mode 100644 index 00000000..d2dbd888 --- /dev/null +++ b/src/normal/fastlane/metadata/en-US/changelogs/170000.txt @@ -0,0 +1,15 @@ +1.2.0 +features: +* updated openvpn, openssl, tor, snowflake +* encrypted storage +* new provider setup UI +* Support for Android 13 +* enforce TLS 1.3 on all Android versions +* Dns over Https (DoH) during provider setup + +bugfixes: +* fixed possible on-device DoS vulnerability, leading to app crashes +* fixed task hijacking vulnerability (aka. strandhogg) +* fixed memory leaks +* fixed blocking vpn service stopping and notifications disappearing correctly +* disable location selection button if provider only supports 1 location -- cgit v1.2.3 From 080c18229a5eb17beb0b65ee0546566c93a56c11 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 11 Nov 2023 01:17:10 +0100 Subject: remove unused layout file of deprecated provider setup UI --- .../main/res/layout-xlarge/v_provider_header.xml | 29 ---------------------- 1 file changed, 29 deletions(-) delete mode 100644 app/src/main/res/layout-xlarge/v_provider_header.xml diff --git a/app/src/main/res/layout-xlarge/v_provider_header.xml b/app/src/main/res/layout-xlarge/v_provider_header.xml deleted file mode 100644 index 28bcaa6c..00000000 --- a/app/src/main/res/layout-xlarge/v_provider_header.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - \ No newline at end of file -- cgit v1.2.3 From f5cf60421e58637e87324047c4a22edea2e1968f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 11 Nov 2023 01:18:41 +0100 Subject: add null-check before delayed calling of the activity callback in ConfigureOrivuderFragment, fixes an NPE --- .../providersetup/fragments/ConfigureProviderFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index ec646cac..e041b19b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -222,7 +222,9 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse setupActivityCallback.onProviderSelected(provider); handler.postDelayed(() -> { if (!ProviderSetupObservable.isCanceled()) { - setupActivityCallback.onConfigurationSuccess(); + if (setupActivityCallback != null) { + setupActivityCallback.onConfigurationSuccess(); + } } }, 750); break; -- cgit v1.2.3 From 7cbb783b7d7df1c52ffcc6f4ee5c3b526b8f0375 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 16 Nov 2023 09:29:40 +0100 Subject: replace direct call on private static currentStatus field with getInstance() in global observable EipStatus in order to avoid possible NPEs --- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index 9244f531..8182cab9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -73,14 +73,13 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { @Override public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) { - ConnectionStatus tmp = currentStatus.getLevel(); - currentStatus = getInstance(); - currentStatus.setState(state); - currentStatus.setLogMessage(logmessage); - currentStatus.setLocalizedResId(localizedResId); - currentStatus.setLevel(level); - currentStatus.setEipLevel(level); - if (tmp != currentStatus.getLevel() || "RECONNECTING".equals(state) || "UI_CONNECTING".equals(state)) { + ConnectionStatus tmp = getInstance().getLevel(); + getInstance().setState(state); + getInstance().setLogMessage(logmessage); + getInstance().setLocalizedResId(localizedResId); + getInstance().setLevel(level); + getInstance().setEipLevel(level); + if (tmp != getInstance().getLevel() || "RECONNECTING".equals(state) || "UI_CONNECTING".equals(state)) { refresh(); } } @@ -90,13 +89,13 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public boolean isReconnecting() { - Log.d(TAG, "eip currentVPNStatus : " + currentStatus.getState() ); - return "RECONNECTING".equals(currentStatus.getState()); + Log.d(TAG, "eip currentVPNStatus : " + getInstance().getState() ); + return "RECONNECTING".equals(getInstance().getState()); } public boolean isVPNRunningWithoutNetwork() { - return currentStatus.getLevel() == LEVEL_NONETWORK && - !"NO_PROCESS".equals(currentStatus.getState()); + return getInstance().getLevel() == LEVEL_NONETWORK && + !"NO_PROCESS".equals(getInstance().getState()); } private void setEipLevel(ConnectionStatus level) { @@ -147,7 +146,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { * @param futureLevel */ private void setEipLevelWithDelay(ConnectionStatus futureLevel) { - new DelayTask(currentStatus.getLevel(), futureLevel).execute(); + new DelayTask(getInstance().getLevel(), futureLevel).execute(); } private static class DelayTask extends AsyncTask { @@ -169,7 +168,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } protected void onPostExecute(Void result) { - if (currentLevel == currentStatus.getLevel()) { + if (currentLevel == getInstance().getLevel()) { switch (futureLevel) { case LEVEL_NONETWORK: currentEipLevel = EipLevel.DISCONNECTED; @@ -301,8 +300,8 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public static void refresh() { - currentStatus.setChanged(); - currentStatus.notifyObservers(); + getInstance().setChanged(); + getInstance().notifyObservers(); } } -- cgit v1.2.3 From 767585d54d8f347744ebcf5f22da3324d980749a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 17 Nov 2023 00:13:38 +0100 Subject: use application context to create VPN permission request intent --- .../se/leap/bitmaskclient/providersetup/activities/SetupActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java index b258a100..dd735f84 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java @@ -100,7 +100,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal // indicator views for VPN permission - Intent requestVpnPermission = VpnService.prepare(this); + Intent requestVpnPermission = VpnService.prepare(this.getApplicationContext()); if (requestVpnPermission != null) { addIndicatorView(indicatorViews); addIndicatorView(indicatorViews); -- cgit v1.2.3 From a142bf89106ce7c0ab1938df29e75423c047642b Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 21 Nov 2023 14:54:10 +0100 Subject: remove deprecated layout files --- .../main/res/layout-xlarge/v_loading_screen.xml | 214 --------------------- app/src/main/res/layout/v_loading_screen.xml | 213 -------------------- 2 files changed, 427 deletions(-) delete mode 100644 app/src/main/res/layout-xlarge/v_loading_screen.xml delete mode 100644 app/src/main/res/layout/v_loading_screen.xml diff --git a/app/src/main/res/layout-xlarge/v_loading_screen.xml b/app/src/main/res/layout-xlarge/v_loading_screen.xml deleted file mode 100644 index 22b72f29..00000000 --- a/app/src/main/res/layout-xlarge/v_loading_screen.xml +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/v_loading_screen.xml b/app/src/main/res/layout/v_loading_screen.xml deleted file mode 100644 index dd83aa38..00000000 --- a/app/src/main/res/layout/v_loading_screen.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- cgit v1.2.3 From 41dee27f6d6b2240097a3f8b5112e1a8fb8fde03 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 21 Nov 2023 14:55:39 +0100 Subject: update gradle dependencies and bump Android SDK to API 34 --- app/build.gradle | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 091795a3..b27e4616 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,9 +34,9 @@ android { // however we don't calculate the versionCode here, because F-Droid doesn't like that versionCode 170000 versionName "1.2.0" - compileSdk 33 + compileSdk 34 minSdkVersion 21 - targetSdkVersion 33 + targetSdkVersion 34 vectorDrawables.useSupportLibrary = true buildConfigField 'boolean', 'openvpn3', 'false' @@ -399,7 +399,7 @@ android { dependencies { - testImplementation 'junit:junit:4.12' + testImplementation 'junit:junit:4.13.2' //outdated mockito-core version due to powermock dependency testImplementation 'org.mockito:mockito-core:3.6.0' testImplementation('org.powermock:powermock-api-mockito2:2.0.9') @@ -421,18 +421,20 @@ dependencies { testImplementation 'org.json:json:20180813' androidTestImplementation 'androidx.test.ext:junit:1.1.4' debugImplementation 'com.squareup.leakcanary:leakcanary-android-core:2.9.1' + debugImplementation 'androidx.fragment:fragment-testing:1.6.2' + debugImplementation 'androidx.test:core:1.5.0' - implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.10.0' implementation 'org.conscrypt:conscrypt-android:2.5.2' implementation 'androidx.security:security-crypto:1.1.0-alpha06' implementation 'androidx.legacy:legacy-support-core-utils:1.0.0' - implementation 'androidx.annotation:annotation:1.4.0' + implementation 'androidx.annotation:annotation:1.7.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.6.1' - implementation 'androidx.fragment:fragment:1.5.1' + implementation 'com.google.android.material:material:1.10.0' + implementation 'androidx.fragment:fragment:1.6.2' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0' -- cgit v1.2.3 From 85e5ed816451b6e78574a40980f6b30876836e4d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 21 Nov 2023 15:05:38 +0100 Subject: fixing Screenshot tests for Bitmask, provider setup screenshot tests are also fixed for custom flavored builds. --- .../se/leap/bitmaskclient/ProviderSetupTest.java | 92 ++++++++++++ .../leap/bitmaskclient/base/ProviderBaseTest.java | 167 --------------------- .../androidTest/java/utils/ProviderSetupUtils.java | 93 ++++++++++++ .../bitmaskclient/base/CustomProviderTest.java | 6 +- .../leap/bitmaskclient/suite/ScreenshotTest.java | 3 +- .../se/leap/bitmaskclient/base/BitmaskTest.java | 166 +++++++++++++++++--- .../leap/bitmaskclient/base/ProviderSetupTest.java | 69 --------- .../leap/bitmaskclient/suite/ScreenshotTest.java | 2 +- 8 files changed, 338 insertions(+), 260 deletions(-) create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java delete mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java create mode 100644 app/src/androidTest/java/utils/ProviderSetupUtils.java delete mode 100644 app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java new file mode 100644 index 00000000..a878951a --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -0,0 +1,92 @@ +package se.leap.bitmaskclient; + + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.replaceText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static utils.CustomInteractions.tryResolve; + +import android.app.Instrumentation; +import android.content.Context; + +import androidx.test.espresso.ViewInteraction; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runner.manipulation.Ordering; + +import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.providersetup.activities.SetupActivity; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; +import tools.fastlane.screengrab.locale.LocaleTestRule; +import utils.ProviderSetupUtils; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class ProviderSetupTest { + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @Rule + public ActivityScenarioRule mActivityScenarioRule = + new ActivityScenarioRule<>(SetupActivity.class); + + UiDevice device; + + @Before + public void setup() { + Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); + //PreferenceHelper.clear(); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + device = UiDevice.getInstance(instrumentation); + } + + @Test + public void test01_setupProviderDefault() { + ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + + @Test + public void test01_setupProviderCircumvention() { + ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + + @Test + public void testaddManuallyNewProviderScreenshot() { + if (!"normal".equals(BuildConfig.FLAVOR_branding)) { + System.out.println("skipping custom provider url test"); + return; + } + ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); + radioButtonSelection.perform(click()); + + onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); + Screengrab.screenshot("setup_custom_provider"); + onView(withId(R.id.setup_next_button)).perform(click()); + onView(withId(R.id.setup_next_button)).perform(click()); + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + tryResolve( + onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))), + matches(isDisplayed()), + 20); + Screengrab.screenshot("setup_provider_error_dialog"); + } +} diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java deleted file mode 100644 index 68676bee..00000000 --- a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package se.leap.bitmaskclient.base; - -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.contrib.DrawerMatchers.isClosed; -import static androidx.test.espresso.matcher.RootMatchers.isDialog; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anything; -import static org.hamcrest.Matchers.is; -import static utils.CustomInteractions.tryResolve; - -import android.app.Instrumentation; -import android.content.SharedPreferences; -import android.net.VpnService; -import android.view.Gravity; - -import androidx.test.espresso.ViewInteraction; -import androidx.test.espresso.contrib.DrawerActions; -import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiObjectNotFoundException; -import androidx.test.uiautomator.UiSelector; - -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; -import tools.fastlane.screengrab.locale.LocaleTestRule; - -@LargeTest -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public abstract class ProviderBaseTest { - - @ClassRule - public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - - @Rule - public ActivityScenarioRule mActivityScenarioRule = - new ActivityScenarioRule<>(StartActivity.class); - - UiDevice device; - @Before - public void setup() { - Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); - SharedPreferences preferences = PreferenceHelper.getSharedPreferences(getApplicationContext()); - preferences.edit().clear().commit(); - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(instrumentation); - } - - @Test - public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { - boolean configurationNeeded = configureProviderIfNeeded(); - - ViewInteraction mainButtonStop; - if (!configurationNeeded) { - // click on Main on/off button and start VPN - ViewInteraction mainButton = tryResolve( - onView(withId(R.id.main_button)), - matches(isDisplayed()) - ); - - mainButton.perform(click()); - Thread.sleep(50); - Screengrab.screenshot("VPN_connecting"); - - mainButtonStop = tryResolve( - onView(allOf( - withId(R.id.button), - withTagValue(is("button_circle_stop")))), - matches(isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); - } else { - // handle VPN permission dialog - if (VpnService.prepare(getApplicationContext()) != null) { - UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); - okButton.click(); - } - // on new configurations the VPN is automatically started - Screengrab.screenshot("VPN_connecting"); - mainButtonStop = tryResolve( - onView(allOf( - withId(R.id.button), - withTagValue(is("button_circle_stop")))), - matches(isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); - } - - mainButtonStop.perform(click()); - Screengrab.screenshot("VPN_ask_disconnect"); - - onView(withText(android.R.string.yes)) - .inRoot(isDialog()) - .check(matches(isDisplayed())) - .perform(click()); - Screengrab.screenshot("VPN_disconnected"); - } - - @Test - public void test02_SettingsFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - Screengrab.screenshot("navigationDrawer"); - - // Start the screen of your activity. - onView(withId(R.id.advancedSettings)) - .perform(click()); - - Screengrab.screenshot("settingsFragment"); - } - - @Test - public void test03_LocationSelectionFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - onView(withId(R.id.manualGatewaySelection)) - .perform(click()); - - Screengrab.screenshot("GatewaySelectionFragment"); - } - - @Test - public void test04_AppExclusionFragmentScreenshots() { - onView(withId(R.id.drawer_layout)) - .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - onView(withId(R.id.advancedSettings)).perform(click()); - - onView(withId(R.id.exclude_apps)).perform(click()); - - tryResolve( - onData(anything()).inAdapterView(withId(android.R.id.list)).atPosition(2), - matches(isDisplayed()), - 5); - - Screengrab.screenshot("App_Exclusion_Fragment"); - } - - public abstract boolean configureProviderIfNeeded(); -} diff --git a/app/src/androidTest/java/utils/ProviderSetupUtils.java b/app/src/androidTest/java/utils/ProviderSetupUtils.java new file mode 100644 index 00000000..10e0b950 --- /dev/null +++ b/app/src/androidTest/java/utils/ProviderSetupUtils.java @@ -0,0 +1,93 @@ +package utils; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static utils.CustomInteractions.tryResolve; + +import android.content.Context; +import android.net.VpnService; + +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiObjectNotFoundException; +import androidx.test.uiautomator.UiSelector; + +import org.hamcrest.Matchers; + +import se.leap.bitmaskclient.BuildConfig; +import se.leap.bitmaskclient.R; +import tools.fastlane.screengrab.Screengrab; + +public class ProviderSetupUtils { + + public static void runProviderSetup(UiDevice device, boolean takeConfigurationScreenshots, boolean useCircumvention, Context targetContext) { + try { + // ------- PROVIDER SELECTION -------------- + if ("normal".equals(BuildConfig.FLAVOR_branding)) { + System.out.println("next: provider selection"); + ViewInteraction radioButtonSelection = tryResolve(onView(withText("Riseup")), matches(isDisplayed())); + if (takeConfigurationScreenshots) Screengrab.screenshot("provider_selection"); + radioButtonSelection.perform(click()); + // next button click + onView(withText(R.string.next)).perform(click()); + } + + // ------- CIRCUMVENTION SELECTION -------------- + System.out.println("next: standard/circumvention selection"); + if (useCircumvention) { + onView(withText(targetContext.getString(R.string.use_circumvention_tech))).perform(click()); + } else { + onView(withText(targetContext.getString(R.string.use_standard_vpn, targetContext.getString(R.string.app_name)))).perform(click()); + } + if (takeConfigurationScreenshots) Screengrab.screenshot("circumvention_selection"); + + // ------- CONFIGURATION PROGRESS -------------- + System.out.println("next: configuring"); + onView(withText(R.string.next)).perform(click()); + tryResolve( + onView( + Matchers.allOf( + withText(R.string.configuring_provider), + withId(R.id.tv_title) + ) + ), + matches(isDisplayed()) + ); + if (takeConfigurationScreenshots) Screengrab.screenshot("configuring_provider"); + + // ------- VPN PERMISSON DIALOG -------------- + boolean showPermissionDialog = false; + if (VpnService.prepare(getApplicationContext()) != null) { + showPermissionDialog = true; + tryResolve(onView(withText(R.string.upcoming_connection_request_description)), matches(isDisplayed()), useCircumvention ? 180 : 20); + System.out.println("next: next permission request"); + onView(withText(R.string.next)).perform(click()); + UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); + okButton.waitForExists(30000); + okButton.click(); + device.waitForWindowUpdate("com.android.vpndialogs", 1000); + } + + // ------- START VPN -------------- + System.out.println("next: perform click on VPN button"); + ViewInteraction interaction = tryResolve(onView(withTagValue(Matchers.is("button_setup_circle_custom"))), matches(isDisplayed()), useCircumvention && !showPermissionDialog ? 180 : 20); + Screengrab.screenshot("all_set_start_vpn"); + interaction.perform(click()); + } catch (NoMatchingViewException e) { + // it might be that the provider was already configured, so we print the stack + // trace here and try to continue + e.printStackTrace(); + } catch (UiObjectNotFoundException | NullPointerException e) { + e.printStackTrace(); + } + } +} diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java index 92416af4..15e6f799 100644 --- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java +++ b/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java @@ -22,9 +22,9 @@ import org.junit.Test; import se.leap.bitmaskclient.R; import tools.fastlane.screengrab.Screengrab; -public class CustomProviderTest extends ProviderBaseTest { +public class CustomProviderTest { - @Test + /*@Test @Override public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { // handle VPN permission dialog @@ -58,5 +58,5 @@ public class CustomProviderTest extends ProviderBaseTest { @Override public boolean configureProviderIfNeeded() { return false; - } + }*/ } \ No newline at end of file diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java index a19b0ffd..15a21173 100644 --- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java +++ b/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java @@ -6,12 +6,13 @@ import androidx.test.filters.LargeTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; +import se.leap.bitmaskclient.ProviderSetupTest; import se.leap.bitmaskclient.base.CustomProviderTest; @LargeTest @RunWith(Suite.class) @Suite.SuiteClasses({ - CustomProviderTest.class + ProviderSetupTest.class }) public class ScreenshotTest { } diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java index aa437c74..1d340f61 100644 --- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java +++ b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java @@ -1,42 +1,170 @@ package se.leap.bitmaskclient.base; -import static androidx.test.espresso.Espresso.onData; +import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasToString; -import static utils.CustomInteractions.tryResolve; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.junit.Assert.assertNotNull; +import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; +import static utils.ProviderSetupUtils.runProviderSetup; -import androidx.test.espresso.DataInteraction; -import androidx.test.espresso.NoMatchingViewException; +import android.Manifest; +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.view.Gravity; + +import androidx.test.espresso.Espresso; +import androidx.test.espresso.PerformException; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.contrib.DrawerActions; +import androidx.test.espresso.contrib.DrawerMatchers; +import androidx.test.espresso.matcher.RootMatchers; +import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.models.ProviderObservable; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; +import tools.fastlane.screengrab.locale.LocaleTestRule; +import utils.CustomInteractions; @LargeTest @RunWith(AndroidJUnit4.class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class BitmaskTest extends ProviderBaseTest { +public class BitmaskTest { + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @Rule + public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null; + + UiDevice device; + @Before + public void setup() { + Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + device = UiDevice.getInstance(instrumentation); + } + + @Test + public void test03_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { + startMainActivity(); + + Screengrab.screenshot("VPN_connecting"); + ViewInteraction mainButtonStop = CustomInteractions.tryResolve( + Espresso.onView(Matchers.allOf( + ViewMatchers.withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20); + Screengrab.screenshot("VPN_connected"); + + mainButtonStop.perform(ViewActions.click()); + Screengrab.screenshot("VPN_ask_disconnect"); + + Espresso.onView(ViewMatchers.withText(android.R.string.yes)) + .inRoot(RootMatchers.isDialog()) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .perform(ViewActions.click()); + Screengrab.screenshot("VPN_disconnected"); + } + + @Test + public void test04_SettingsFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Screengrab.screenshot("navigationDrawer"); + + // Start the screen of your activity. + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)) + .perform(ViewActions.click()); + + Screengrab.screenshot("settingsFragment"); + } - @Override - public boolean configureProviderIfNeeded() { + @Test + public void test05_LocationSelectionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.manualGatewaySelection)) + .perform(ViewActions.click()); + + Screengrab.screenshot("GatewaySelectionFragment"); + } + + @Test + public void test06_AppExclusionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)).perform(ViewActions.click()); + + Espresso.onView(ViewMatchers.withId(R.id.exclude_apps)).perform(ViewActions.click()); + + CustomInteractions.tryResolve( + Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 5); + + Screengrab.screenshot("App_Exclusion_Fragment"); + } + + private void startMainActivity() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(MainActivity.class.getName(), null, false); + instrumentation.addMonitor(monitor); + Intent intent = new Intent(instrumentation.getTargetContext(), MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setAction(ACTION_SHOW_VPN_FRAGMENT); + instrumentation.startActivitySync(intent); + Activity activity = instrumentation.waitForMonitor(monitor); + assertNotNull(activity); + configureIfNeeded(); + } + + private void configureIfNeeded() { + if (ProviderObservable.getInstance().getCurrentProvider().isConfigured()) { + return; + } + final Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); try { - DataInteraction linearLayout = tryResolve(onData(hasToString(containsString("riseup.net"))) - .inAdapterView(withId(R.id.provider_list)), - 2); - linearLayout.perform(click()); - return true; - } catch (NoMatchingViewException e) { - // it might be that the provider was already configured, so we print the stack - // trace here and try to continue - e.printStackTrace(); + onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); + } catch (PerformException performException) { + System.out.println("navigation drawer already opened"); } - return false; + onView(withText(R.string.switch_provider_menu_option)).perform(click()); + System.out.println("configure Provider... starting SetupActivity"); + + runProviderSetup(device, false, false, targetContext); } } diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java deleted file mode 100644 index 460a30ad..00000000 --- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package se.leap.bitmaskclient.base; - - -import static android.content.Context.MODE_PRIVATE; -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.Matchers.anything; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasToString; -import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES; -import static utils.CustomInteractions.tryResolve; - -import android.content.SharedPreferences; - -import androidx.test.espresso.DataInteraction; -import androidx.test.espresso.NoMatchingViewException; -import androidx.test.ext.junit.rules.ActivityScenarioRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; - -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.providersetup.ProviderListActivity; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; -import tools.fastlane.screengrab.locale.LocaleTestRule; - -@LargeTest -@RunWith(AndroidJUnit4.class) -public class ProviderSetupTest { - - @ClassRule - public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - - @Rule - public ActivityScenarioRule mActivityScenarioRule = - new ActivityScenarioRule<>(ProviderListActivity.class); - - @Before - public void setup() { - Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); - SharedPreferences preferences = PreferenceHelper.getSharedPreferences(getApplicationContext()); - preferences.edit().clear().commit(); - } - - @Test - public void testConfigureRiseupVPNScreenshot() { - DataInteraction linearLayout = tryResolve(onData(hasToString(containsString("riseup.net"))) - .inAdapterView(withId(R.id.provider_list)), - 2); - Screengrab.screenshot("ProviderListActivity"); - linearLayout.perform(click()); - Screengrab.screenshot("ProviderListActivity_configureRiseup"); - } - - @Test - public void testaddManuallyNewProviderScreenshot() { - onData(anything()).inAdapterView(withId(R.id.provider_list)).atPosition(3).perform(click()); - Screengrab.screenshot("ProviderListActivity_addManuallyNewProvider"); - } -} diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java index 5fa45a95..ec2e7b5c 100644 --- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java +++ b/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java @@ -6,7 +6,7 @@ import androidx.test.filters.LargeTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; -import se.leap.bitmaskclient.base.ProviderSetupTest; +import se.leap.bitmaskclient.ProviderSetupTest; import se.leap.bitmaskclient.base.BitmaskTest; @LargeTest -- cgit v1.2.3 From e2eccdcf5c49daf9236f782dcdf8ba9924cf7147 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 10:41:39 +0100 Subject: improve screenhsot tests, fix them for custom flavored builds --- .../java/se/leap/bitmaskclient/BitmaskTest.java | 152 ++++++++++++++++++ .../se/leap/bitmaskclient/ProviderSetupTest.java | 20 +-- .../leap/bitmaskclient/suite/ScreenshotTest.java | 19 +++ .../bitmaskclient/base/CustomProviderTest.java | 62 -------- .../leap/bitmaskclient/suite/ScreenshotTest.java | 18 --- .../se/leap/bitmaskclient/base/BitmaskTest.java | 170 --------------------- .../leap/bitmaskclient/suite/ScreenshotTest.java | 19 --- 7 files changed, 181 insertions(+), 279 deletions(-) create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java create mode 100644 app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java delete mode 100644 app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java delete mode 100644 app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java delete mode 100644 app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java delete mode 100644 app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java new file mode 100644 index 00000000..1ca0980a --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java @@ -0,0 +1,152 @@ +package se.leap.bitmaskclient; + + +import static org.junit.Assert.assertNotNull; + +import android.Manifest; +import android.app.Activity; +import android.app.Instrumentation; +import android.content.Intent; +import android.os.Build; +import android.view.Gravity; + +import androidx.test.espresso.Espresso; +import androidx.test.espresso.ViewInteraction; +import androidx.test.espresso.action.ViewActions; +import androidx.test.espresso.assertion.ViewAssertions; +import androidx.test.espresso.contrib.DrawerActions; +import androidx.test.espresso.contrib.DrawerMatchers; +import androidx.test.espresso.matcher.RootMatchers; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.LargeTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.rule.GrantPermissionRule; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObjectNotFoundException; + +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.StartActivity; +import se.leap.bitmaskclient.providersetup.activities.SetupActivity; +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; +import tools.fastlane.screengrab.locale.LocaleTestRule; +import utils.CustomInteractions; +import utils.ProviderSetupUtils; + +@LargeTest +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class BitmaskTest { + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @Rule + public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null; + + UiDevice device; + @Before + public void setup() { + Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + device = UiDevice.getInstance(instrumentation); + } + + @Test + public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { + startMainActivity(); + + Screengrab.screenshot("VPN_connecting"); + ViewInteraction mainButtonStop = CustomInteractions.tryResolve( + Espresso.onView(Matchers.allOf( + ViewMatchers.withId(R.id.button), + ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 20); + Screengrab.screenshot("VPN_connected"); + + mainButtonStop.perform(ViewActions.click()); + Screengrab.screenshot("VPN_ask_disconnect"); + + Espresso.onView(ViewMatchers.withText(android.R.string.yes)) + .inRoot(RootMatchers.isDialog()) + .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) + .perform(ViewActions.click()); + Screengrab.screenshot("VPN_disconnected"); + } + + @Test + public void test02_SettingsFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Screengrab.screenshot("navigationDrawer"); + + // Start the screen of your activity. + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)) + .perform(ViewActions.click()); + + Screengrab.screenshot("settingsFragment"); + } + + @Test + public void test03_LocationSelectionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.manualGatewaySelection)) + .perform(ViewActions.click()); + + Screengrab.screenshot("GatewaySelectionFragment"); + } + + @Test + public void test04_AppExclusionFragmentScreenshots() { + startMainActivity(); + Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) + .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. + .perform(DrawerActions.open()); // Open Drawer + + Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)).perform(ViewActions.click()); + + Espresso.onView(ViewMatchers.withId(R.id.exclude_apps)).perform(ViewActions.click()); + + CustomInteractions.tryResolve( + Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2), + ViewAssertions.matches(ViewMatchers.isDisplayed()), + 5); + + Screengrab.screenshot("App_Exclusion_Fragment"); + } + + private void startMainActivity() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false); + Instrumentation.ActivityMonitor mainActivityMonitor = new Instrumentation.ActivityMonitor(MainActivity.class.getName(), null, false); + instrumentation.addMonitor(setupActivityMonitor); + instrumentation.addMonitor(mainActivityMonitor); + Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.startActivitySync(intent); + Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L); + if (setupActivity != null) { + ProviderSetupUtils.runProviderSetup(device, false, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); + } + Activity mainActivity = instrumentation.waitForMonitorWithTimeout(mainActivityMonitor, 1000); + assertNotNull(mainActivity); + } +} diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java index a878951a..b9da0dff 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -7,7 +7,6 @@ import static androidx.test.espresso.action.ViewActions.replaceText; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; import static androidx.test.espresso.matcher.ViewMatchers.withText; import static utils.CustomInteractions.tryResolve; @@ -20,18 +19,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObjectNotFoundException; -import org.hamcrest.Matchers; import org.junit.Before; import org.junit.ClassRule; +import org.junit.FixMethodOrder; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runner.manipulation.Ordering; +import org.junit.runners.MethodSorters; -import se.leap.bitmaskclient.base.fragments.MainActivityErrorDialog; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; import tools.fastlane.screengrab.Screengrab; import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; @@ -40,6 +36,7 @@ import utils.ProviderSetupUtils; @LargeTest @RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ProviderSetupTest { @ClassRule @@ -65,24 +62,27 @@ public class ProviderSetupTest { } @Test - public void test01_setupProviderCircumvention() { + public void test02_setupProviderCircumvention() { ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test - public void testaddManuallyNewProviderScreenshot() { + public void test03_addManuallyNewProviderScreenshot() { if (!"normal".equals(BuildConfig.FLAVOR_branding)) { System.out.println("skipping custom provider url test"); return; } + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); radioButtonSelection.perform(click()); - onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); Screengrab.screenshot("setup_custom_provider"); onView(withId(R.id.setup_next_button)).perform(click()); + + onView(withText(context.getString(R.string.use_standard_vpn, context.getString(R.string.app_name)))).perform(click()); onView(withId(R.id.setup_next_button)).perform(click()); - Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + tryResolve( onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))), matches(isDisplayed()), diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java new file mode 100644 index 00000000..f3a8d73c --- /dev/null +++ b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java @@ -0,0 +1,19 @@ +package se.leap.bitmaskclient.suite; + + +import androidx.test.filters.LargeTest; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +import se.leap.bitmaskclient.BitmaskTest; +import se.leap.bitmaskclient.ProviderSetupTest; + +@LargeTest +@RunWith(Suite.class) +@Suite.SuiteClasses({ + ProviderSetupTest.class, + BitmaskTest.class, +}) +public class ScreenshotTest { +} diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java deleted file mode 100644 index 15e6f799..00000000 --- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package se.leap.bitmaskclient.base; - -import static androidx.test.core.app.ApplicationProvider.getApplicationContext; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.RootMatchers.isDialog; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static utils.CustomInteractions.tryResolve; - -import android.net.VpnService; - -import androidx.test.espresso.ViewInteraction; -import androidx.test.uiautomator.UiObject; -import androidx.test.uiautomator.UiObjectNotFoundException; -import androidx.test.uiautomator.UiSelector; - -import org.junit.Test; - -import se.leap.bitmaskclient.R; -import tools.fastlane.screengrab.Screengrab; - -public class CustomProviderTest { - - /*@Test - @Override - public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { - // handle VPN permission dialog - if (VpnService.prepare(getApplicationContext()) != null) { - UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); - okButton.waitForExists(30000); - okButton.click(); - } - - ViewInteraction mainButtonStop; - mainButtonStop = tryResolve( - onView(withId(R.id.main_button)), - matches(isDisplayed()), - 30); - Screengrab.screenshot("VPN_connected"); - - mainButtonStop.perform(click()); - Screengrab.screenshot("VPN_ask_disconnect"); - - ViewInteraction alertDialogOKbutton = tryResolve(onView(withText(android.R.string.yes)) - .inRoot(isDialog()), - matches(isDisplayed())); - alertDialogOKbutton.perform(click()); - Screengrab.screenshot("VPN_disconnected"); - - mainButtonStop.perform(click()); - Thread.sleep(50); - Screengrab.screenshot("VPN_connecting"); - } - - @Override - public boolean configureProviderIfNeeded() { - return false; - }*/ -} \ No newline at end of file diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java deleted file mode 100644 index 15a21173..00000000 --- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package se.leap.bitmaskclient.suite; - - -import androidx.test.filters.LargeTest; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import se.leap.bitmaskclient.ProviderSetupTest; -import se.leap.bitmaskclient.base.CustomProviderTest; - -@LargeTest -@RunWith(Suite.class) -@Suite.SuiteClasses({ - ProviderSetupTest.class -}) -public class ScreenshotTest { -} diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java deleted file mode 100644 index 1d340f61..00000000 --- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java +++ /dev/null @@ -1,170 +0,0 @@ -package se.leap.bitmaskclient.base; - - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.junit.Assert.assertNotNull; -import static se.leap.bitmaskclient.base.MainActivity.ACTION_SHOW_VPN_FRAGMENT; -import static utils.ProviderSetupUtils.runProviderSetup; - -import android.Manifest; -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.view.Gravity; - -import androidx.test.espresso.Espresso; -import androidx.test.espresso.PerformException; -import androidx.test.espresso.ViewInteraction; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.assertion.ViewAssertions; -import androidx.test.espresso.contrib.DrawerActions; -import androidx.test.espresso.contrib.DrawerMatchers; -import androidx.test.espresso.matcher.RootMatchers; -import androidx.test.espresso.matcher.ViewMatchers; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.GrantPermissionRule; -import androidx.test.uiautomator.UiDevice; -import androidx.test.uiautomator.UiObjectNotFoundException; - -import org.hamcrest.Matchers; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.base.models.ProviderObservable; -import tools.fastlane.screengrab.Screengrab; -import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; -import tools.fastlane.screengrab.locale.LocaleTestRule; -import utils.CustomInteractions; - -@LargeTest -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class BitmaskTest { - - @ClassRule - public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - - @Rule - public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null; - - UiDevice device; - @Before - public void setup() { - Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy()); - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - device = UiDevice.getInstance(instrumentation); - } - - @Test - public void test03_vpnStartTest() throws InterruptedException, UiObjectNotFoundException { - startMainActivity(); - - Screengrab.screenshot("VPN_connecting"); - ViewInteraction mainButtonStop = CustomInteractions.tryResolve( - Espresso.onView(Matchers.allOf( - ViewMatchers.withId(R.id.button), - ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))), - ViewAssertions.matches(ViewMatchers.isDisplayed()), - 20); - Screengrab.screenshot("VPN_connected"); - - mainButtonStop.perform(ViewActions.click()); - Screengrab.screenshot("VPN_ask_disconnect"); - - Espresso.onView(ViewMatchers.withText(android.R.string.yes)) - .inRoot(RootMatchers.isDialog()) - .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) - .perform(ViewActions.click()); - Screengrab.screenshot("VPN_disconnected"); - } - - @Test - public void test04_SettingsFragmentScreenshots() { - startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) - .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - Screengrab.screenshot("navigationDrawer"); - - // Start the screen of your activity. - Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)) - .perform(ViewActions.click()); - - Screengrab.screenshot("settingsFragment"); - } - - @Test - public void test05_LocationSelectionFragmentScreenshots() { - startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) - .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - Espresso.onView(ViewMatchers.withId(R.id.manualGatewaySelection)) - .perform(ViewActions.click()); - - Screengrab.screenshot("GatewaySelectionFragment"); - } - - @Test - public void test06_AppExclusionFragmentScreenshots() { - startMainActivity(); - Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)) - .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed. - .perform(DrawerActions.open()); // Open Drawer - - Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)).perform(ViewActions.click()); - - Espresso.onView(ViewMatchers.withId(R.id.exclude_apps)).perform(ViewActions.click()); - - CustomInteractions.tryResolve( - Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2), - ViewAssertions.matches(ViewMatchers.isDisplayed()), - 5); - - Screengrab.screenshot("App_Exclusion_Fragment"); - } - - private void startMainActivity() { - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(MainActivity.class.getName(), null, false); - instrumentation.addMonitor(monitor); - Intent intent = new Intent(instrumentation.getTargetContext(), MainActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setAction(ACTION_SHOW_VPN_FRAGMENT); - instrumentation.startActivitySync(intent); - Activity activity = instrumentation.waitForMonitor(monitor); - assertNotNull(activity); - configureIfNeeded(); - } - - private void configureIfNeeded() { - if (ProviderObservable.getInstance().getCurrentProvider().isConfigured()) { - return; - } - final Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - try { - onView(withId(R.id.drawer_layout)).perform(DrawerActions.open()); - } catch (PerformException performException) { - System.out.println("navigation drawer already opened"); - } - onView(withText(R.string.switch_provider_menu_option)).perform(click()); - System.out.println("configure Provider... starting SetupActivity"); - - runProviderSetup(device, false, false, targetContext); - } -} diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java deleted file mode 100644 index ec2e7b5c..00000000 --- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package se.leap.bitmaskclient.suite; - - -import androidx.test.filters.LargeTest; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import se.leap.bitmaskclient.ProviderSetupTest; -import se.leap.bitmaskclient.base.BitmaskTest; - -@LargeTest -@RunWith(Suite.class) -@Suite.SuiteClasses({ - ProviderSetupTest.class, - BitmaskTest.class, -}) -public class ScreenshotTest { -} -- cgit v1.2.3 From 8e23e5e7445fc2e10d79eec9f3546fdede0344f6 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:11:12 +0100 Subject: move bitmask fastlane metadata to src/normal/fastlane/metadata/android/ (/android/ was missing in the path) --- .../fastlane/metadata/android/el/full_description.txt | 12 ++++++++++++ .../fastlane/metadata/android/el/short_description.txt | 2 ++ .../fastlane/metadata/android/el/store-meta-el.json | 5 +++++ src/normal/fastlane/metadata/android/el/title.txt | 1 + .../fastlane/metadata/android/en-US/changelogs/168000.txt | 8 ++++++++ .../fastlane/metadata/android/en-US/changelogs/170000.txt | 15 +++++++++++++++ .../fastlane/metadata/android/en-US/full_description.txt | 12 ++++++++++++ .../fastlane/metadata/android/en-US/short_description.txt | 2 ++ src/normal/fastlane/metadata/android/en-US/title.txt | 1 + src/normal/fastlane/metadata/android/en-US/video.txt | 0 .../fastlane/metadata/android/nl/full_description.txt | 11 +++++++++++ .../fastlane/metadata/android/nl/short_description.txt | 1 + .../fastlane/metadata/android/nl/store-meta-nl.json | 5 +++++ src/normal/fastlane/metadata/android/nl/title.txt | 1 + .../metadata/android/pt-rBR/store-meta-pt-rBR.json | 5 +++++ .../fastlane/metadata/android/tr/full_description.txt | 12 ++++++++++++ .../fastlane/metadata/android/tr/short_description.txt | 2 ++ .../fastlane/metadata/android/tr/store-meta-tr.json | 5 +++++ src/normal/fastlane/metadata/android/tr/title.txt | 1 + src/normal/fastlane/metadata/android/tr/tx-values-tr.json | 1 + src/normal/fastlane/metadata/el/full_description.txt | 12 ------------ src/normal/fastlane/metadata/el/short_description.txt | 2 -- src/normal/fastlane/metadata/el/store-meta-el.json | 5 ----- src/normal/fastlane/metadata/el/title.txt | 1 - src/normal/fastlane/metadata/en-US/changelogs/168000.txt | 8 -------- src/normal/fastlane/metadata/en-US/changelogs/170000.txt | 15 --------------- src/normal/fastlane/metadata/en-US/full_description.txt | 12 ------------ src/normal/fastlane/metadata/en-US/short_description.txt | 2 -- src/normal/fastlane/metadata/en-US/title.txt | 1 - src/normal/fastlane/metadata/en-US/video.txt | 0 src/normal/fastlane/metadata/nl/full_description.txt | 11 ----------- src/normal/fastlane/metadata/nl/short_description.txt | 1 - src/normal/fastlane/metadata/nl/store-meta-nl.json | 5 ----- src/normal/fastlane/metadata/nl/title.txt | 1 - .../fastlane/metadata/pt-rBR/store-meta-pt-rBR.json | 5 ----- src/normal/fastlane/metadata/tr/full_description.txt | 12 ------------ src/normal/fastlane/metadata/tr/short_description.txt | 2 -- src/normal/fastlane/metadata/tr/store-meta-tr.json | 5 ----- src/normal/fastlane/metadata/tr/title.txt | 1 - src/normal/fastlane/metadata/tr/tx-values-tr.json | 1 - 40 files changed, 102 insertions(+), 102 deletions(-) create mode 100644 src/normal/fastlane/metadata/android/el/full_description.txt create mode 100644 src/normal/fastlane/metadata/android/el/short_description.txt create mode 100644 src/normal/fastlane/metadata/android/el/store-meta-el.json create mode 100644 src/normal/fastlane/metadata/android/el/title.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/full_description.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/short_description.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/title.txt create mode 100644 src/normal/fastlane/metadata/android/en-US/video.txt create mode 100644 src/normal/fastlane/metadata/android/nl/full_description.txt create mode 100644 src/normal/fastlane/metadata/android/nl/short_description.txt create mode 100644 src/normal/fastlane/metadata/android/nl/store-meta-nl.json create mode 100644 src/normal/fastlane/metadata/android/nl/title.txt create mode 100644 src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json create mode 100644 src/normal/fastlane/metadata/android/tr/full_description.txt create mode 100644 src/normal/fastlane/metadata/android/tr/short_description.txt create mode 100644 src/normal/fastlane/metadata/android/tr/store-meta-tr.json create mode 100644 src/normal/fastlane/metadata/android/tr/title.txt create mode 100644 src/normal/fastlane/metadata/android/tr/tx-values-tr.json delete mode 100644 src/normal/fastlane/metadata/el/full_description.txt delete mode 100644 src/normal/fastlane/metadata/el/short_description.txt delete mode 100644 src/normal/fastlane/metadata/el/store-meta-el.json delete mode 100644 src/normal/fastlane/metadata/el/title.txt delete mode 100644 src/normal/fastlane/metadata/en-US/changelogs/168000.txt delete mode 100644 src/normal/fastlane/metadata/en-US/changelogs/170000.txt delete mode 100644 src/normal/fastlane/metadata/en-US/full_description.txt delete mode 100644 src/normal/fastlane/metadata/en-US/short_description.txt delete mode 100644 src/normal/fastlane/metadata/en-US/title.txt delete mode 100644 src/normal/fastlane/metadata/en-US/video.txt delete mode 100644 src/normal/fastlane/metadata/nl/full_description.txt delete mode 100644 src/normal/fastlane/metadata/nl/short_description.txt delete mode 100644 src/normal/fastlane/metadata/nl/store-meta-nl.json delete mode 100644 src/normal/fastlane/metadata/nl/title.txt delete mode 100644 src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json delete mode 100644 src/normal/fastlane/metadata/tr/full_description.txt delete mode 100644 src/normal/fastlane/metadata/tr/short_description.txt delete mode 100644 src/normal/fastlane/metadata/tr/store-meta-tr.json delete mode 100644 src/normal/fastlane/metadata/tr/title.txt delete mode 100644 src/normal/fastlane/metadata/tr/tx-values-tr.json diff --git a/src/normal/fastlane/metadata/android/el/full_description.txt b/src/normal/fastlane/metadata/android/el/full_description.txt new file mode 100644 index 00000000..aaaaf476 --- /dev/null +++ b/src/normal/fastlane/metadata/android/el/full_description.txt @@ -0,0 +1,12 @@ +Το Bitmask είναι μια εφαρμογή VPN με αυτόματη ρύθμιση παραμέτρων. Διαθέτει πολλές τεχνικές για την παράκαμψη της λογοκρισίας, τον αποκλεισμό δικτύου ή την αποφυγή επιτήρησης. Αφού επιλέξει έναν συμβατό πάροχο υπηρεσιών, θα κρυπτογραφήσει και θα δρομολογήσει με ασφάλεια όλη την κίνηση του δικτύου σας μέσω του αξιόπιστου παρόχου υπηρεσιών σας. + +Είστε έτοιμοι! + +Το Bitmask είναι ένα λογισμικό πελάτη VPN ανοιχτού κώδικα, που διανέμεται με την άδεια GPLv3. Δείτε https://0xacab.org/leap/bitmask_android + +Συχνές ερωτήσεις: + +* ποιος: το leap.se, μια συλλογική προσπάθεια που αγαπά την έννοια του δικαιώματος της ιδιωτικότητας, περίπου από το 2011. +* Οι μεταφράσεις εκτιμούνται ιδιαίτερα για το έργο Transifex https://app.transifex.com/otf/bitmask/dashboard/ + +Εάν αντιμετωπίζετε προβλήματα ή θέλετε να έχετε μια ειδική έκδοση, επικοινωνήστε μαζί μας στο https://matrix.to/#/#leap:libera.chat ή υποβάλλετε ένα ζήτημα στο: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/el/short_description.txt b/src/normal/fastlane/metadata/android/el/short_description.txt new file mode 100644 index 00000000..4ac7309e --- /dev/null +++ b/src/normal/fastlane/metadata/android/el/short_description.txt @@ -0,0 +1,2 @@ +Κρυπτογραφημένη επικοινωνία για τους απλούς θνητούς +(καλοδεχούμενοι και οι υπερήρωες). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/el/store-meta-el.json b/src/normal/fastlane/metadata/android/el/store-meta-el.json new file mode 100644 index 00000000..0e32bdc9 --- /dev/null +++ b/src/normal/fastlane/metadata/android/el/store-meta-el.json @@ -0,0 +1,5 @@ +{ + "title": "Bitmask", + "full_description": "Το Bitmask είναι μια εφαρμογή VPN με αυτόματη ρύθμιση παραμέτρων. Διαθέτει πολλές τεχνικές για την παράκαμψη της λογοκρισίας, τον αποκλεισμό δικτύου ή την αποφυγή επιτήρησης. Αφού επιλέξει έναν συμβατό πάροχο υπηρεσιών, θα κρυπτογραφήσει και θα δρομολογήσει με ασφάλεια όλη την κίνηση του δικτύου σας μέσω του αξιόπιστου παρόχου υπηρεσιών σας.\n\nΕίστε έτοιμοι!\n\nΤο Bitmask είναι ένα λογισμικό πελάτη VPN ανοιχτού κώδικα, που διανέμεται με την άδεια GPLv3. Δείτε https://0xacab.org/leap/bitmask_android\n\nΣυχνές ερωτήσεις:\n\n* ποιος: το leap.se, μια συλλογική προσπάθεια που αγαπά την έννοια του δικαιώματος της ιδιωτικότητας, περίπου από το 2011.\n* Οι μεταφράσεις εκτιμούνται ιδιαίτερα για το έργο Transifex https://app.transifex.com/otf/bitmask/dashboard/\n\nΕάν αντιμετωπίζετε προβλήματα ή θέλετε να έχετε μια ειδική έκδοση, επικοινωνήστε μαζί μας στο https://matrix.to/#/#leap:libera.chat ή υποβάλλετε ένα ζήτημα στο: https://0xacab.org/leap/bitmask_android/", + "short_description": "Κρυπτογραφημένη επικοινωνία για τους απλούς θνητούς\n(καλοδεχούμενοι και οι υπερήρωες)." +} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/el/title.txt b/src/normal/fastlane/metadata/android/el/title.txt new file mode 100644 index 00000000..a953d6a6 --- /dev/null +++ b/src/normal/fastlane/metadata/android/el/title.txt @@ -0,0 +1 @@ +Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt b/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt new file mode 100644 index 00000000..80766d7f --- /dev/null +++ b/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt @@ -0,0 +1,8 @@ +Since the last release was not fully rolled-out, a summary of version 1.1.6 and 1.1.7: +* updated design +* improved circumvention capabilities +* updated dependencies (openvpn, tor, snowflake etc.) +* updated translations +* fixed crashes and other bugs +* support for Message of the Day +* 1.1.7 fix: hiding debugging entries in settings \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt new file mode 100644 index 00000000..d2dbd888 --- /dev/null +++ b/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt @@ -0,0 +1,15 @@ +1.2.0 +features: +* updated openvpn, openssl, tor, snowflake +* encrypted storage +* new provider setup UI +* Support for Android 13 +* enforce TLS 1.3 on all Android versions +* Dns over Https (DoH) during provider setup + +bugfixes: +* fixed possible on-device DoS vulnerability, leading to app crashes +* fixed task hijacking vulnerability (aka. strandhogg) +* fixed memory leaks +* fixed blocking vpn service stopping and notifications disappearing correctly +* disable location selection button if provider only supports 1 location diff --git a/src/normal/fastlane/metadata/android/en-US/full_description.txt b/src/normal/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 00000000..2fcf278a --- /dev/null +++ b/src/normal/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,12 @@ +Bitmask is a VPN client with automatic configuration. It has several techniques on board to circumvent censorship, network blocking or avoid surveillance. After choosing a compatible service provider it will encrypt and route securely all your network traffic through your trusted service provider. + +And you're good to go! + +Bitmask is open source VPN client, distributed under the GPLv3 license. See https://0xacab.org/leap/bitmask_android + +FAQ: + +* who: leap.se, a collective that loves the concept of the right to whisper, around since 2011. +* Translations greatly appreciated at our Transifex project https://app.transifex.com/otf/bitmask/dashboard/ + +If you experience problems or want to have bleeding edge versions, please join our chat https://matrix.to/#/#leap:libera.chat or write a bug report: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/en-US/short_description.txt b/src/normal/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 00000000..6f481599 --- /dev/null +++ b/src/normal/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1,2 @@ +Encrypted communication for mere mortals +(superheroes welcome, too). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/en-US/title.txt b/src/normal/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 00000000..a953d6a6 --- /dev/null +++ b/src/normal/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/en-US/video.txt b/src/normal/fastlane/metadata/android/en-US/video.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/normal/fastlane/metadata/android/nl/full_description.txt b/src/normal/fastlane/metadata/android/nl/full_description.txt new file mode 100644 index 00000000..a714dff0 --- /dev/null +++ b/src/normal/fastlane/metadata/android/nl/full_description.txt @@ -0,0 +1,11 @@ +Bitmask is een VPN-client met automatische configuratie. Het kan verschillende technieken gebruiken om censuur, netwerkblokkades of surveillance te omzeilen. Nadat je een compatibele serviceprovider hebt gekozen, zal al je netwerkverkeer versleutelen en veilig via de serviceprovider van jou vertrouwen routeren. + +En je kunt van start! + +Bitmask is een open-source VPN-client, verspreid onder de GPLv3-licentie. Zie https://0xacab.org/leap/bitmask_android + +FAQ: + +wie: leap.se, een collectief dat sinds 2011 aan de slag is, gemotiveerd door het recht om te fluisteren. +Vertalingen worden zeer gewaardeerd in ons Transifex-project: https://app.transifex.com/otf/bitmask/dashboard/ +Als je problemen ervaart of de nieuwste versies wilt proberen, neem dan deel aan onze chat: https://matrix.to/#/#leap:libera.chat of stuur een bugrapport in: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/nl/short_description.txt b/src/normal/fastlane/metadata/android/nl/short_description.txt new file mode 100644 index 00000000..dd626a6c --- /dev/null +++ b/src/normal/fastlane/metadata/android/nl/short_description.txt @@ -0,0 +1 @@ +Versleutelde communicatie voor stervelingen (superhelden zijn ook welkom). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/nl/store-meta-nl.json b/src/normal/fastlane/metadata/android/nl/store-meta-nl.json new file mode 100644 index 00000000..61c9b38d --- /dev/null +++ b/src/normal/fastlane/metadata/android/nl/store-meta-nl.json @@ -0,0 +1,5 @@ +{ + "title": "Bitmask", + "full_description": "Bitmask is een VPN-client met automatische configuratie. Het kan verschillende technieken gebruiken om censuur, netwerkblokkades of surveillance te omzeilen. Nadat je een compatibele serviceprovider hebt gekozen, zal al je netwerkverkeer versleutelen en veilig via de serviceprovider van jou vertrouwen routeren.\n\nEn je kunt van start!\n\nBitmask is een open-source VPN-client, verspreid onder de GPLv3-licentie. Zie https://0xacab.org/leap/bitmask_android\n\nFAQ:\n\nwie: leap.se, een collectief dat sinds 2011 aan de slag is, gemotiveerd door het recht om te fluisteren.\nVertalingen worden zeer gewaardeerd in ons Transifex-project: https://app.transifex.com/otf/bitmask/dashboard/\nAls je problemen ervaart of de nieuwste versies wilt proberen, neem dan deel aan onze chat: https://matrix.to/#/#leap:libera.chat of stuur een bugrapport in: https://0xacab.org/leap/bitmask_android/", + "short_description": "Versleutelde communicatie voor stervelingen (superhelden zijn ook welkom)." +} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/nl/title.txt b/src/normal/fastlane/metadata/android/nl/title.txt new file mode 100644 index 00000000..a953d6a6 --- /dev/null +++ b/src/normal/fastlane/metadata/android/nl/title.txt @@ -0,0 +1 @@ +Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json b/src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json new file mode 100644 index 00000000..07ab743d --- /dev/null +++ b/src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json @@ -0,0 +1,5 @@ +{ + "title": "Bitmask", + "full_description": "Bitmask é um cliente VPN com configuração automática. Possui diversas técnicas integradas para contornar a censura, o bloqueio da rede ou evitar a vigilância. Depois de escolher um provedor de serviços compatível, ele criptografará e roteará com segurança todo o tráfego de rede por meio de seu provedor de serviços confiável.E pronto!Bitmask é um cliente VPN de código aberto, distribuído sob a licença GPLv3. Veja https://0xacab.org/leap/bitmask_androidFAQ:* who: leap.se, um coletivo que adora o conceito do direito de sussurrar, existente desde 2011.* Traduções muito apreciadas em nosso projeto Transifex https://app.transifex.com/otf/bitmask/dashboard/Se você tiver problemas ou quiser ter versões mais recentes, entre em nosso chat https://matrix.to/#/#leap:libera.chat ou escreva um relatório de bug: https://0xacab.org/leap/bitmask_android/", + "short_description": "Comunicação criptografada para meros mortais(super-heróis também são bem-vindos)." +} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/tr/full_description.txt b/src/normal/fastlane/metadata/android/tr/full_description.txt new file mode 100644 index 00000000..10418aa9 --- /dev/null +++ b/src/normal/fastlane/metadata/android/tr/full_description.txt @@ -0,0 +1,12 @@ +Bitmask otomatik yapılandırma kullanan bir VPN istemcisidir. Sansür ve ağ engellemesini aşmak veya izlenmekten kaçınmak için birçok yöntem kullanır. Uyumlu bir hizmet sağlayıcı seçtikten sonra tüm ağ trafiğinizi şifreler ve güvendiğiniz hizmet sağlayıcınız üzerinden güvenli bir şekilde yöneltir. + +Böylece kullanmaya başlayabilirsiniz! + +Bitmask açık kaynaklı bir VPN istemcisidir. GPLv3 lisansı koşulları altında dağıtılır: https://0xacab.org/leap/bitmask_android + +SSS + +* Kim: leap.se, fısıldama hakkı kavramını seven bir topluluktır. 2011 yılından beri ortalıktadır. +* Çevirileri Transifex projemizde memnuniyetle karşılıyoruz: https://app.transifex.com/otf/bitmask/dashboard/ + +Sorunlarla karşılaştıysanız veya güncel sürümü almak istiyorsanız, sohbetimize katılabilir https://matrix.to/#/#leap:libera.chat ya da bir hata bildiriminde bulunabilirsiniz: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/tr/short_description.txt b/src/normal/fastlane/metadata/android/tr/short_description.txt new file mode 100644 index 00000000..4e042739 --- /dev/null +++ b/src/normal/fastlane/metadata/android/tr/short_description.txt @@ -0,0 +1,2 @@ +Sadece bir fani olanlar için şifrelenmiş iletişim +(süper kahramanlar da hoş gelir) \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/tr/store-meta-tr.json b/src/normal/fastlane/metadata/android/tr/store-meta-tr.json new file mode 100644 index 00000000..b38b70a6 --- /dev/null +++ b/src/normal/fastlane/metadata/android/tr/store-meta-tr.json @@ -0,0 +1,5 @@ +{ + "title": "Bitmask", + "full_description": "Bitmask otomatik yapılandırma kullanan bir VPN istemcisidir. Sansür ve ağ engellemesini aşmak veya izlenmekten kaçınmak için birçok yöntem kullanır. Uyumlu bir hizmet sağlayıcı seçtikten sonra tüm ağ trafiğinizi şifreler ve güvendiğiniz hizmet sağlayıcınız üzerinden güvenli bir şekilde yöneltir.\n\nBöylece kullanmaya başlayabilirsiniz!\n\nBitmask açık kaynaklı bir VPN istemcisidir. GPLv3 lisansı koşulları altında dağıtılır: https://0xacab.org/leap/bitmask_android\n\nSSS\n\n* Kim: leap.se, fısıldama hakkı kavramını seven bir topluluktır. 2011 yılından beri ortalıktadır.\n* Çevirileri Transifex projemizde memnuniyetle karşılıyoruz: https://app.transifex.com/otf/bitmask/dashboard/\n\nSorunlarla karşılaştıysanız veya güncel sürümü almak istiyorsanız, sohbetimize katılabilir https://matrix.to/#/#leap:libera.chat ya da bir hata bildiriminde bulunabilirsiniz: https://0xacab.org/leap/bitmask_android/", + "short_description": "Sadece bir fani olanlar için şifrelenmiş iletişim\n(süper kahramanlar da hoş gelir)" +} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/tr/title.txt b/src/normal/fastlane/metadata/android/tr/title.txt new file mode 100644 index 00000000..a953d6a6 --- /dev/null +++ b/src/normal/fastlane/metadata/android/tr/title.txt @@ -0,0 +1 @@ +Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/android/tr/tx-values-tr.json b/src/normal/fastlane/metadata/android/tr/tx-values-tr.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/src/normal/fastlane/metadata/android/tr/tx-values-tr.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/el/full_description.txt b/src/normal/fastlane/metadata/el/full_description.txt deleted file mode 100644 index aaaaf476..00000000 --- a/src/normal/fastlane/metadata/el/full_description.txt +++ /dev/null @@ -1,12 +0,0 @@ -Το Bitmask είναι μια εφαρμογή VPN με αυτόματη ρύθμιση παραμέτρων. Διαθέτει πολλές τεχνικές για την παράκαμψη της λογοκρισίας, τον αποκλεισμό δικτύου ή την αποφυγή επιτήρησης. Αφού επιλέξει έναν συμβατό πάροχο υπηρεσιών, θα κρυπτογραφήσει και θα δρομολογήσει με ασφάλεια όλη την κίνηση του δικτύου σας μέσω του αξιόπιστου παρόχου υπηρεσιών σας. - -Είστε έτοιμοι! - -Το Bitmask είναι ένα λογισμικό πελάτη VPN ανοιχτού κώδικα, που διανέμεται με την άδεια GPLv3. Δείτε https://0xacab.org/leap/bitmask_android - -Συχνές ερωτήσεις: - -* ποιος: το leap.se, μια συλλογική προσπάθεια που αγαπά την έννοια του δικαιώματος της ιδιωτικότητας, περίπου από το 2011. -* Οι μεταφράσεις εκτιμούνται ιδιαίτερα για το έργο Transifex https://app.transifex.com/otf/bitmask/dashboard/ - -Εάν αντιμετωπίζετε προβλήματα ή θέλετε να έχετε μια ειδική έκδοση, επικοινωνήστε μαζί μας στο https://matrix.to/#/#leap:libera.chat ή υποβάλλετε ένα ζήτημα στο: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/el/short_description.txt b/src/normal/fastlane/metadata/el/short_description.txt deleted file mode 100644 index 4ac7309e..00000000 --- a/src/normal/fastlane/metadata/el/short_description.txt +++ /dev/null @@ -1,2 +0,0 @@ -Κρυπτογραφημένη επικοινωνία για τους απλούς θνητούς -(καλοδεχούμενοι και οι υπερήρωες). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/el/store-meta-el.json b/src/normal/fastlane/metadata/el/store-meta-el.json deleted file mode 100644 index 0e32bdc9..00000000 --- a/src/normal/fastlane/metadata/el/store-meta-el.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "Bitmask", - "full_description": "Το Bitmask είναι μια εφαρμογή VPN με αυτόματη ρύθμιση παραμέτρων. Διαθέτει πολλές τεχνικές για την παράκαμψη της λογοκρισίας, τον αποκλεισμό δικτύου ή την αποφυγή επιτήρησης. Αφού επιλέξει έναν συμβατό πάροχο υπηρεσιών, θα κρυπτογραφήσει και θα δρομολογήσει με ασφάλεια όλη την κίνηση του δικτύου σας μέσω του αξιόπιστου παρόχου υπηρεσιών σας.\n\nΕίστε έτοιμοι!\n\nΤο Bitmask είναι ένα λογισμικό πελάτη VPN ανοιχτού κώδικα, που διανέμεται με την άδεια GPLv3. Δείτε https://0xacab.org/leap/bitmask_android\n\nΣυχνές ερωτήσεις:\n\n* ποιος: το leap.se, μια συλλογική προσπάθεια που αγαπά την έννοια του δικαιώματος της ιδιωτικότητας, περίπου από το 2011.\n* Οι μεταφράσεις εκτιμούνται ιδιαίτερα για το έργο Transifex https://app.transifex.com/otf/bitmask/dashboard/\n\nΕάν αντιμετωπίζετε προβλήματα ή θέλετε να έχετε μια ειδική έκδοση, επικοινωνήστε μαζί μας στο https://matrix.to/#/#leap:libera.chat ή υποβάλλετε ένα ζήτημα στο: https://0xacab.org/leap/bitmask_android/", - "short_description": "Κρυπτογραφημένη επικοινωνία για τους απλούς θνητούς\n(καλοδεχούμενοι και οι υπερήρωες)." -} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/el/title.txt b/src/normal/fastlane/metadata/el/title.txt deleted file mode 100644 index a953d6a6..00000000 --- a/src/normal/fastlane/metadata/el/title.txt +++ /dev/null @@ -1 +0,0 @@ -Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/en-US/changelogs/168000.txt b/src/normal/fastlane/metadata/en-US/changelogs/168000.txt deleted file mode 100644 index 80766d7f..00000000 --- a/src/normal/fastlane/metadata/en-US/changelogs/168000.txt +++ /dev/null @@ -1,8 +0,0 @@ -Since the last release was not fully rolled-out, a summary of version 1.1.6 and 1.1.7: -* updated design -* improved circumvention capabilities -* updated dependencies (openvpn, tor, snowflake etc.) -* updated translations -* fixed crashes and other bugs -* support for Message of the Day -* 1.1.7 fix: hiding debugging entries in settings \ No newline at end of file diff --git a/src/normal/fastlane/metadata/en-US/changelogs/170000.txt b/src/normal/fastlane/metadata/en-US/changelogs/170000.txt deleted file mode 100644 index d2dbd888..00000000 --- a/src/normal/fastlane/metadata/en-US/changelogs/170000.txt +++ /dev/null @@ -1,15 +0,0 @@ -1.2.0 -features: -* updated openvpn, openssl, tor, snowflake -* encrypted storage -* new provider setup UI -* Support for Android 13 -* enforce TLS 1.3 on all Android versions -* Dns over Https (DoH) during provider setup - -bugfixes: -* fixed possible on-device DoS vulnerability, leading to app crashes -* fixed task hijacking vulnerability (aka. strandhogg) -* fixed memory leaks -* fixed blocking vpn service stopping and notifications disappearing correctly -* disable location selection button if provider only supports 1 location diff --git a/src/normal/fastlane/metadata/en-US/full_description.txt b/src/normal/fastlane/metadata/en-US/full_description.txt deleted file mode 100644 index 2fcf278a..00000000 --- a/src/normal/fastlane/metadata/en-US/full_description.txt +++ /dev/null @@ -1,12 +0,0 @@ -Bitmask is a VPN client with automatic configuration. It has several techniques on board to circumvent censorship, network blocking or avoid surveillance. After choosing a compatible service provider it will encrypt and route securely all your network traffic through your trusted service provider. - -And you're good to go! - -Bitmask is open source VPN client, distributed under the GPLv3 license. See https://0xacab.org/leap/bitmask_android - -FAQ: - -* who: leap.se, a collective that loves the concept of the right to whisper, around since 2011. -* Translations greatly appreciated at our Transifex project https://app.transifex.com/otf/bitmask/dashboard/ - -If you experience problems or want to have bleeding edge versions, please join our chat https://matrix.to/#/#leap:libera.chat or write a bug report: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/en-US/short_description.txt b/src/normal/fastlane/metadata/en-US/short_description.txt deleted file mode 100644 index 6f481599..00000000 --- a/src/normal/fastlane/metadata/en-US/short_description.txt +++ /dev/null @@ -1,2 +0,0 @@ -Encrypted communication for mere mortals -(superheroes welcome, too). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/en-US/title.txt b/src/normal/fastlane/metadata/en-US/title.txt deleted file mode 100644 index a953d6a6..00000000 --- a/src/normal/fastlane/metadata/en-US/title.txt +++ /dev/null @@ -1 +0,0 @@ -Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/en-US/video.txt b/src/normal/fastlane/metadata/en-US/video.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/normal/fastlane/metadata/nl/full_description.txt b/src/normal/fastlane/metadata/nl/full_description.txt deleted file mode 100644 index a714dff0..00000000 --- a/src/normal/fastlane/metadata/nl/full_description.txt +++ /dev/null @@ -1,11 +0,0 @@ -Bitmask is een VPN-client met automatische configuratie. Het kan verschillende technieken gebruiken om censuur, netwerkblokkades of surveillance te omzeilen. Nadat je een compatibele serviceprovider hebt gekozen, zal al je netwerkverkeer versleutelen en veilig via de serviceprovider van jou vertrouwen routeren. - -En je kunt van start! - -Bitmask is een open-source VPN-client, verspreid onder de GPLv3-licentie. Zie https://0xacab.org/leap/bitmask_android - -FAQ: - -wie: leap.se, een collectief dat sinds 2011 aan de slag is, gemotiveerd door het recht om te fluisteren. -Vertalingen worden zeer gewaardeerd in ons Transifex-project: https://app.transifex.com/otf/bitmask/dashboard/ -Als je problemen ervaart of de nieuwste versies wilt proberen, neem dan deel aan onze chat: https://matrix.to/#/#leap:libera.chat of stuur een bugrapport in: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/nl/short_description.txt b/src/normal/fastlane/metadata/nl/short_description.txt deleted file mode 100644 index dd626a6c..00000000 --- a/src/normal/fastlane/metadata/nl/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Versleutelde communicatie voor stervelingen (superhelden zijn ook welkom). \ No newline at end of file diff --git a/src/normal/fastlane/metadata/nl/store-meta-nl.json b/src/normal/fastlane/metadata/nl/store-meta-nl.json deleted file mode 100644 index 61c9b38d..00000000 --- a/src/normal/fastlane/metadata/nl/store-meta-nl.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "Bitmask", - "full_description": "Bitmask is een VPN-client met automatische configuratie. Het kan verschillende technieken gebruiken om censuur, netwerkblokkades of surveillance te omzeilen. Nadat je een compatibele serviceprovider hebt gekozen, zal al je netwerkverkeer versleutelen en veilig via de serviceprovider van jou vertrouwen routeren.\n\nEn je kunt van start!\n\nBitmask is een open-source VPN-client, verspreid onder de GPLv3-licentie. Zie https://0xacab.org/leap/bitmask_android\n\nFAQ:\n\nwie: leap.se, een collectief dat sinds 2011 aan de slag is, gemotiveerd door het recht om te fluisteren.\nVertalingen worden zeer gewaardeerd in ons Transifex-project: https://app.transifex.com/otf/bitmask/dashboard/\nAls je problemen ervaart of de nieuwste versies wilt proberen, neem dan deel aan onze chat: https://matrix.to/#/#leap:libera.chat of stuur een bugrapport in: https://0xacab.org/leap/bitmask_android/", - "short_description": "Versleutelde communicatie voor stervelingen (superhelden zijn ook welkom)." -} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/nl/title.txt b/src/normal/fastlane/metadata/nl/title.txt deleted file mode 100644 index a953d6a6..00000000 --- a/src/normal/fastlane/metadata/nl/title.txt +++ /dev/null @@ -1 +0,0 @@ -Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json b/src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json deleted file mode 100644 index 07ab743d..00000000 --- a/src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "Bitmask", - "full_description": "Bitmask é um cliente VPN com configuração automática. Possui diversas técnicas integradas para contornar a censura, o bloqueio da rede ou evitar a vigilância. Depois de escolher um provedor de serviços compatível, ele criptografará e roteará com segurança todo o tráfego de rede por meio de seu provedor de serviços confiável.E pronto!Bitmask é um cliente VPN de código aberto, distribuído sob a licença GPLv3. Veja https://0xacab.org/leap/bitmask_androidFAQ:* who: leap.se, um coletivo que adora o conceito do direito de sussurrar, existente desde 2011.* Traduções muito apreciadas em nosso projeto Transifex https://app.transifex.com/otf/bitmask/dashboard/Se você tiver problemas ou quiser ter versões mais recentes, entre em nosso chat https://matrix.to/#/#leap:libera.chat ou escreva um relatório de bug: https://0xacab.org/leap/bitmask_android/", - "short_description": "Comunicação criptografada para meros mortais(super-heróis também são bem-vindos)." -} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/tr/full_description.txt b/src/normal/fastlane/metadata/tr/full_description.txt deleted file mode 100644 index 10418aa9..00000000 --- a/src/normal/fastlane/metadata/tr/full_description.txt +++ /dev/null @@ -1,12 +0,0 @@ -Bitmask otomatik yapılandırma kullanan bir VPN istemcisidir. Sansür ve ağ engellemesini aşmak veya izlenmekten kaçınmak için birçok yöntem kullanır. Uyumlu bir hizmet sağlayıcı seçtikten sonra tüm ağ trafiğinizi şifreler ve güvendiğiniz hizmet sağlayıcınız üzerinden güvenli bir şekilde yöneltir. - -Böylece kullanmaya başlayabilirsiniz! - -Bitmask açık kaynaklı bir VPN istemcisidir. GPLv3 lisansı koşulları altında dağıtılır: https://0xacab.org/leap/bitmask_android - -SSS - -* Kim: leap.se, fısıldama hakkı kavramını seven bir topluluktır. 2011 yılından beri ortalıktadır. -* Çevirileri Transifex projemizde memnuniyetle karşılıyoruz: https://app.transifex.com/otf/bitmask/dashboard/ - -Sorunlarla karşılaştıysanız veya güncel sürümü almak istiyorsanız, sohbetimize katılabilir https://matrix.to/#/#leap:libera.chat ya da bir hata bildiriminde bulunabilirsiniz: https://0xacab.org/leap/bitmask_android/ \ No newline at end of file diff --git a/src/normal/fastlane/metadata/tr/short_description.txt b/src/normal/fastlane/metadata/tr/short_description.txt deleted file mode 100644 index 4e042739..00000000 --- a/src/normal/fastlane/metadata/tr/short_description.txt +++ /dev/null @@ -1,2 +0,0 @@ -Sadece bir fani olanlar için şifrelenmiş iletişim -(süper kahramanlar da hoş gelir) \ No newline at end of file diff --git a/src/normal/fastlane/metadata/tr/store-meta-tr.json b/src/normal/fastlane/metadata/tr/store-meta-tr.json deleted file mode 100644 index b38b70a6..00000000 --- a/src/normal/fastlane/metadata/tr/store-meta-tr.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "Bitmask", - "full_description": "Bitmask otomatik yapılandırma kullanan bir VPN istemcisidir. Sansür ve ağ engellemesini aşmak veya izlenmekten kaçınmak için birçok yöntem kullanır. Uyumlu bir hizmet sağlayıcı seçtikten sonra tüm ağ trafiğinizi şifreler ve güvendiğiniz hizmet sağlayıcınız üzerinden güvenli bir şekilde yöneltir.\n\nBöylece kullanmaya başlayabilirsiniz!\n\nBitmask açık kaynaklı bir VPN istemcisidir. GPLv3 lisansı koşulları altında dağıtılır: https://0xacab.org/leap/bitmask_android\n\nSSS\n\n* Kim: leap.se, fısıldama hakkı kavramını seven bir topluluktır. 2011 yılından beri ortalıktadır.\n* Çevirileri Transifex projemizde memnuniyetle karşılıyoruz: https://app.transifex.com/otf/bitmask/dashboard/\n\nSorunlarla karşılaştıysanız veya güncel sürümü almak istiyorsanız, sohbetimize katılabilir https://matrix.to/#/#leap:libera.chat ya da bir hata bildiriminde bulunabilirsiniz: https://0xacab.org/leap/bitmask_android/", - "short_description": "Sadece bir fani olanlar için şifrelenmiş iletişim\n(süper kahramanlar da hoş gelir)" -} \ No newline at end of file diff --git a/src/normal/fastlane/metadata/tr/title.txt b/src/normal/fastlane/metadata/tr/title.txt deleted file mode 100644 index a953d6a6..00000000 --- a/src/normal/fastlane/metadata/tr/title.txt +++ /dev/null @@ -1 +0,0 @@ -Bitmask \ No newline at end of file diff --git a/src/normal/fastlane/metadata/tr/tx-values-tr.json b/src/normal/fastlane/metadata/tr/tx-values-tr.json deleted file mode 100644 index 9e26dfee..00000000 --- a/src/normal/fastlane/metadata/tr/tx-values-tr.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file -- cgit v1.2.3 From 60dc24c8f42f505ede765759f2442af6604772a7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:35:00 +0100 Subject: download frames after installation of fastlane frameit --- scripts/installFastlane.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/installFastlane.sh b/scripts/installFastlane.sh index 9abc6211..d1772b86 100755 --- a/scripts/installFastlane.sh +++ b/scripts/installFastlane.sh @@ -6,6 +6,7 @@ apt-get -y dist-upgrade && \ apt-get -y install make build-essential ruby ruby-dev imagemagick xvfb libxcb1 libname-dev gem install fastlane +fastlane frameit download_frames ## ------------------------------------------------------ ## --- Android Emulator -- cgit v1.2.3 From fdcc7ac00be21c22e1bd94df06c304f6a7a765be Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:45:02 +0100 Subject: ensure ProviderSetupTest doesn't fail with fastlane which runs the same test class multuple times with different locales --- .../se/leap/bitmaskclient/ProviderSetupTest.java | 32 ++++++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java index b9da0dff..dedb40d7 100644 --- a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java +++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java @@ -8,10 +8,14 @@ import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static org.junit.Assert.assertNotNull; +import static se.leap.bitmaskclient.base.models.Constants.SHARED_ENCRYPTED_PREFERENCES; import static utils.CustomInteractions.tryResolve; +import android.app.Activity; import android.app.Instrumentation; import android.content.Context; +import android.content.Intent; import androidx.test.espresso.ViewInteraction; import androidx.test.ext.junit.rules.ActivityScenarioRule; @@ -28,6 +32,11 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import se.leap.bitmaskclient.base.MainActivity; +import se.leap.bitmaskclient.base.StartActivity; +import se.leap.bitmaskclient.base.models.Provider; +import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.activities.SetupActivity; import tools.fastlane.screengrab.Screengrab; import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy; @@ -42,9 +51,9 @@ public class ProviderSetupTest { @ClassRule public static final LocaleTestRule localeTestRule = new LocaleTestRule(); - @Rule - public ActivityScenarioRule mActivityScenarioRule = - new ActivityScenarioRule<>(SetupActivity.class); + // @Rule + // public ActivityScenarioRule mActivityScenarioRule = + // new ActivityScenarioRule<>(SetupActivity.class); UiDevice device; @@ -54,15 +63,19 @@ public class ProviderSetupTest { //PreferenceHelper.clear(); Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); device = UiDevice.getInstance(instrumentation); + instrumentation.getTargetContext().deleteSharedPreferences(SHARED_ENCRYPTED_PREFERENCES); + ProviderObservable.getInstance().updateProvider(new Provider()); } @Test public void test01_setupProviderDefault() { + startSetupActivity(); ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @Test public void test02_setupProviderCircumvention() { + startSetupActivity(); ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext()); } @@ -72,11 +85,13 @@ public class ProviderSetupTest { System.out.println("skipping custom provider url test"); return; } + startSetupActivity(); Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed())); radioButtonSelection.perform(click()); onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org")); + tryResolve(onView(withId(R.id.edit_customProvider)), matches(withText("https://leapvpn.myserver.org"))); Screengrab.screenshot("setup_custom_provider"); onView(withId(R.id.setup_next_button)).perform(click()); @@ -89,4 +104,15 @@ public class ProviderSetupTest { 20); Screengrab.screenshot("setup_provider_error_dialog"); } + + private void startSetupActivity() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false); + instrumentation.addMonitor(setupActivityMonitor); + Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.startActivitySync(intent); + Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L); + assertNotNull(setupActivity); + } } -- cgit v1.2.3 From 9da7c99730c09e9b9164dec2f8cfbd2e4c337a69 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:45:30 +0100 Subject: less verbose output for tryResolve() --- app/src/androidTest/java/utils/CustomInteractions.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/androidTest/java/utils/CustomInteractions.java b/app/src/androidTest/java/utils/CustomInteractions.java index 9e3a8f9d..4890c20c 100644 --- a/app/src/androidTest/java/utils/CustomInteractions.java +++ b/app/src/androidTest/java/utils/CustomInteractions.java @@ -30,8 +30,7 @@ public class CustomInteractions { } hasFound = true; } catch (NoMatchingViewException exception) { - System.out.println("NoMatchingViewException attempt: " + attempt); - exception.printStackTrace(); + System.out.println("NoMatchingViewException - attempt: " + attempt + ". " + exception.getLocalizedMessage()); attempt++; if (attempt == maxTries) { throw exception; -- cgit v1.2.3 From d80e8606039f498f34fb4e7e4f8184c68b541e6f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 14:46:59 +0100 Subject: only click on the VPN start button after a successful provider setup if we actually want to test the following activities --- app/src/androidTest/java/utils/ProviderSetupUtils.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/utils/ProviderSetupUtils.java b/app/src/androidTest/java/utils/ProviderSetupUtils.java index 10e0b950..9b76ffbd 100644 --- a/app/src/androidTest/java/utils/ProviderSetupUtils.java +++ b/app/src/androidTest/java/utils/ProviderSetupUtils.java @@ -70,6 +70,7 @@ public class ProviderSetupUtils { showPermissionDialog = true; tryResolve(onView(withText(R.string.upcoming_connection_request_description)), matches(isDisplayed()), useCircumvention ? 180 : 20); System.out.println("next: next permission request"); + if (takeConfigurationScreenshots) Screengrab.screenshot("vpn_permission_rationale"); onView(withText(R.string.next)).perform(click()); UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1")); okButton.waitForExists(30000); @@ -80,8 +81,12 @@ public class ProviderSetupUtils { // ------- START VPN -------------- System.out.println("next: perform click on VPN button"); ViewInteraction interaction = tryResolve(onView(withTagValue(Matchers.is("button_setup_circle_custom"))), matches(isDisplayed()), useCircumvention && !showPermissionDialog ? 180 : 20); - Screengrab.screenshot("all_set_start_vpn"); - interaction.perform(click()); + if (takeConfigurationScreenshots) { + Screengrab.screenshot("all_set_start_vpn"); + } else { + // we only want to start the VPN in case we're not running the ProviderSetupTest + interaction.perform(click()); + } } catch (NoMatchingViewException e) { // it might be that the provider was already configured, so we print the stack // trace here and try to continue -- cgit v1.2.3 From 66ce80bde0cee34896fb23da112b984c4da47dae Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 22 Nov 2023 17:16:24 +0100 Subject: move RiseupVPN's fastlane meta data into fastlane/metadata/android as F-Droid's documentation suggests --- .../fastlane/metadata/android/de/full_description.txt | 3 +++ .../fastlane/metadata/android/de/short_description.txt | 1 + .../fastlane/metadata/android/de/store-meta-de.json | 5 +++++ src/custom/fastlane/metadata/android/de/title.txt | 1 + .../fastlane/metadata/android/el/full_description.txt | 3 +++ .../fastlane/metadata/android/el/short_description.txt | 1 + .../fastlane/metadata/android/el/store-meta-el.json | 5 +++++ src/custom/fastlane/metadata/android/el/title.txt | 1 + .../metadata/android/en-US/changelogs/169000.txt | 9 +++++++++ .../metadata/android/en-US/changelogs/170000.txt | 15 +++++++++++++++ .../metadata/android/en-US/full_description.txt | 7 +++++++ .../en-US/images/sevenInchScreenshots/1_en-US.png | Bin 0 -> 162001 bytes .../en-US/images/sevenInchScreenshots/2_en-US.png | Bin 0 -> 269807 bytes .../en-US/images/sevenInchScreenshots/3_en-US.png | Bin 0 -> 248841 bytes .../metadata/android/en-US/short_description.txt | 1 + src/custom/fastlane/metadata/android/en-US/title.txt | 1 + src/custom/fastlane/metadata/android/en-US/video.txt | 0 .../fastlane/metadata/android/fr/full_description.txt | 3 +++ .../fastlane/metadata/android/fr/short_description.txt | 1 + .../fastlane/metadata/android/fr/store-meta-fr.json | 5 +++++ src/custom/fastlane/metadata/android/fr/title.txt | 1 + .../fastlane/metadata/android/nl/full_description.txt | 3 +++ .../fastlane/metadata/android/nl/short_description.txt | 1 + .../fastlane/metadata/android/nl/store-meta-nl.json | 5 +++++ src/custom/fastlane/metadata/android/nl/title.txt | 1 + .../metadata/android/pt-rBR/full_description.txt | 1 + .../metadata/android/pt-rBR/short_description.txt | 1 + .../metadata/android/pt-rBR/store-meta-pt-rBR.json | 5 +++++ src/custom/fastlane/metadata/android/pt-rBR/title.txt | 1 + .../fastlane/metadata/android/tr/full_description.txt | 3 +++ .../fastlane/metadata/android/tr/short_description.txt | 1 + .../fastlane/metadata/android/tr/store-meta-tr.json | 5 +++++ src/custom/fastlane/metadata/android/tr/title.txt | 1 + src/custom/fastlane/metadata/de/full_description.txt | 3 --- src/custom/fastlane/metadata/de/short_description.txt | 1 - src/custom/fastlane/metadata/de/store-meta-de.json | 5 ----- src/custom/fastlane/metadata/de/title.txt | 1 - src/custom/fastlane/metadata/el/full_description.txt | 3 --- src/custom/fastlane/metadata/el/short_description.txt | 1 - src/custom/fastlane/metadata/el/store-meta-el.json | 5 ----- src/custom/fastlane/metadata/el/title.txt | 1 - .../fastlane/metadata/en-US/changelogs/169000.txt | 9 --------- .../fastlane/metadata/en-US/changelogs/170000.txt | 15 --------------- .../fastlane/metadata/en-US/full_description.txt | 7 ------- .../en-US/images/sevenInchScreenshots/1_en-US.png | Bin 162001 -> 0 bytes .../en-US/images/sevenInchScreenshots/2_en-US.png | Bin 269807 -> 0 bytes .../en-US/images/sevenInchScreenshots/3_en-US.png | Bin 248841 -> 0 bytes .../fastlane/metadata/en-US/short_description.txt | 1 - src/custom/fastlane/metadata/en-US/title.txt | 1 - src/custom/fastlane/metadata/en-US/video.txt | 0 src/custom/fastlane/metadata/fr/full_description.txt | 3 --- src/custom/fastlane/metadata/fr/short_description.txt | 1 - src/custom/fastlane/metadata/fr/store-meta-fr.json | 5 ----- src/custom/fastlane/metadata/fr/title.txt | 1 - src/custom/fastlane/metadata/nl/full_description.txt | 3 --- src/custom/fastlane/metadata/nl/short_description.txt | 1 - src/custom/fastlane/metadata/nl/store-meta-nl.json | 5 ----- src/custom/fastlane/metadata/nl/title.txt | 1 - .../fastlane/metadata/pt-rBR/full_description.txt | 1 - .../fastlane/metadata/pt-rBR/short_description.txt | 1 - .../fastlane/metadata/pt-rBR/store-meta-pt-rBR.json | 5 ----- src/custom/fastlane/metadata/pt-rBR/title.txt | 1 - src/custom/fastlane/metadata/tr/full_description.txt | 3 --- src/custom/fastlane/metadata/tr/short_description.txt | 1 - src/custom/fastlane/metadata/tr/store-meta-tr.json | 5 ----- src/custom/fastlane/metadata/tr/title.txt | 1 - 66 files changed, 91 insertions(+), 91 deletions(-) create mode 100644 src/custom/fastlane/metadata/android/de/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/de/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/de/store-meta-de.json create mode 100644 src/custom/fastlane/metadata/android/de/title.txt create mode 100644 src/custom/fastlane/metadata/android/el/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/el/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/el/store-meta-el.json create mode 100644 src/custom/fastlane/metadata/android/el/title.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png create mode 100644 src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png create mode 100644 src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png create mode 100644 src/custom/fastlane/metadata/android/en-US/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/title.txt create mode 100644 src/custom/fastlane/metadata/android/en-US/video.txt create mode 100644 src/custom/fastlane/metadata/android/fr/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/fr/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/fr/store-meta-fr.json create mode 100644 src/custom/fastlane/metadata/android/fr/title.txt create mode 100644 src/custom/fastlane/metadata/android/nl/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/nl/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/nl/store-meta-nl.json create mode 100644 src/custom/fastlane/metadata/android/nl/title.txt create mode 100644 src/custom/fastlane/metadata/android/pt-rBR/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/pt-rBR/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json create mode 100644 src/custom/fastlane/metadata/android/pt-rBR/title.txt create mode 100644 src/custom/fastlane/metadata/android/tr/full_description.txt create mode 100644 src/custom/fastlane/metadata/android/tr/short_description.txt create mode 100644 src/custom/fastlane/metadata/android/tr/store-meta-tr.json create mode 100644 src/custom/fastlane/metadata/android/tr/title.txt delete mode 100644 src/custom/fastlane/metadata/de/full_description.txt delete mode 100644 src/custom/fastlane/metadata/de/short_description.txt delete mode 100644 src/custom/fastlane/metadata/de/store-meta-de.json delete mode 100644 src/custom/fastlane/metadata/de/title.txt delete mode 100644 src/custom/fastlane/metadata/el/full_description.txt delete mode 100644 src/custom/fastlane/metadata/el/short_description.txt delete mode 100644 src/custom/fastlane/metadata/el/store-meta-el.json delete mode 100644 src/custom/fastlane/metadata/el/title.txt delete mode 100644 src/custom/fastlane/metadata/en-US/changelogs/169000.txt delete mode 100644 src/custom/fastlane/metadata/en-US/changelogs/170000.txt delete mode 100644 src/custom/fastlane/metadata/en-US/full_description.txt delete mode 100644 src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png delete mode 100644 src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png delete mode 100644 src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png delete mode 100644 src/custom/fastlane/metadata/en-US/short_description.txt delete mode 100644 src/custom/fastlane/metadata/en-US/title.txt delete mode 100644 src/custom/fastlane/metadata/en-US/video.txt delete mode 100644 src/custom/fastlane/metadata/fr/full_description.txt delete mode 100644 src/custom/fastlane/metadata/fr/short_description.txt delete mode 100644 src/custom/fastlane/metadata/fr/store-meta-fr.json delete mode 100644 src/custom/fastlane/metadata/fr/title.txt delete mode 100644 src/custom/fastlane/metadata/nl/full_description.txt delete mode 100644 src/custom/fastlane/metadata/nl/short_description.txt delete mode 100644 src/custom/fastlane/metadata/nl/store-meta-nl.json delete mode 100644 src/custom/fastlane/metadata/nl/title.txt delete mode 100644 src/custom/fastlane/metadata/pt-rBR/full_description.txt delete mode 100644 src/custom/fastlane/metadata/pt-rBR/short_description.txt delete mode 100644 src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json delete mode 100644 src/custom/fastlane/metadata/pt-rBR/title.txt delete mode 100644 src/custom/fastlane/metadata/tr/full_description.txt delete mode 100644 src/custom/fastlane/metadata/tr/short_description.txt delete mode 100644 src/custom/fastlane/metadata/tr/store-meta-tr.json delete mode 100644 src/custom/fastlane/metadata/tr/title.txt diff --git a/src/custom/fastlane/metadata/android/de/full_description.txt b/src/custom/fastlane/metadata/android/de/full_description.txt new file mode 100644 index 00000000..b53d9c25 --- /dev/null +++ b/src/custom/fastlane/metadata/android/de/full_description.txt @@ -0,0 +1,3 @@ +RiseupVPN ist ein leicht benutzbarer, schneller und sicherer VPN-Dienst von https://riseup.net. RiseupVPN benötigt keinen Benutzer*innenkonto, es speichert keine Logs und keine Daten von dir. Dieser Service wird ausschließlich über Spenden von Nutzer*innen wie dir finanziert. + +https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/de/short_description.txt b/src/custom/fastlane/metadata/android/de/short_description.txt new file mode 100644 index 00000000..8ab5f289 --- /dev/null +++ b/src/custom/fastlane/metadata/android/de/short_description.txt @@ -0,0 +1 @@ +RiseupVPN: anonymes VPN. Unterstützt von Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/de/store-meta-de.json b/src/custom/fastlane/metadata/android/de/store-meta-de.json new file mode 100644 index 00000000..c1ad30cd --- /dev/null +++ b/src/custom/fastlane/metadata/android/de/store-meta-de.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "RiseupVPN ist ein leicht benutzbarer, schneller und sicherer VPN-Dienst von https://riseup.net. RiseupVPN benötigt keinen Benutzer*innenkonto, es speichert keine Logs und keine Daten von dir. Dieser Service wird ausschließlich über Spenden von Nutzer*innen wie dir finanziert.\n\nhttps://riseup.net/vpn/donate", + "short_description": "RiseupVPN: anonymes VPN. Unterstützt von Bitmask." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/de/title.txt b/src/custom/fastlane/metadata/android/de/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/de/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/el/full_description.txt b/src/custom/fastlane/metadata/android/el/full_description.txt new file mode 100644 index 00000000..7d96bc0e --- /dev/null +++ b/src/custom/fastlane/metadata/android/el/full_description.txt @@ -0,0 +1,3 @@ +Το RiseupVPN είναι μια γρήγορη, εύκολη και ασφαλής υπηρεσία VPN από το https://riseup.net. Δε χρειάζεται λογαριασμός για τη χρήση του RiseupVPN, δε διατηρεί αρχεία καταγραφής και δεν παρακολουθεί με οποιοδήποτε τρόπο. Αυτή η υπηρεσία υποστηρίζεται από δωρεές χρηστών σαν και εσάς. + +https://riseup.net/vpn/donate.  \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/el/short_description.txt b/src/custom/fastlane/metadata/android/el/short_description.txt new file mode 100644 index 00000000..157e767e --- /dev/null +++ b/src/custom/fastlane/metadata/android/el/short_description.txt @@ -0,0 +1 @@ +RiseupVPN, ανώνυμο VPN. Με την υποστήριξη του Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/el/store-meta-el.json b/src/custom/fastlane/metadata/android/el/store-meta-el.json new file mode 100644 index 00000000..35f23c9d --- /dev/null +++ b/src/custom/fastlane/metadata/android/el/store-meta-el.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "Το RiseupVPN είναι μια γρήγορη, εύκολη και ασφαλής υπηρεσία VPN από το https://riseup.net. Δε χρειάζεται λογαριασμός για τη χρήση του RiseupVPN, δε διατηρεί αρχεία καταγραφής και δεν παρακολουθεί με οποιοδήποτε τρόπο. Αυτή η υπηρεσία υποστηρίζεται από δωρεές χρηστών σαν και εσάς.\n\nhttps://riseup.net/vpn/donate. ", + "short_description": "RiseupVPN, ανώνυμο VPN. Με την υποστήριξη του Bitmask." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/el/title.txt b/src/custom/fastlane/metadata/android/el/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/el/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt b/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt new file mode 100644 index 00000000..9cdf3a40 --- /dev/null +++ b/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt @@ -0,0 +1,9 @@ +Since the last releases were not fully rolled-out, a summary of version 1.1.6 - 1.1.8: +* updated design +* improved circumvention capabilities +* updated dependencies (openvpn, tor, snowflake etc.) +* updated translations +* fixed crashes and other bugs +* support for Message of the Day +* 1.1.7 fix: hiding debugging entries in settings +* 1.1.8 fix: uploaded correct google playstore version \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt new file mode 100644 index 00000000..d2dbd888 --- /dev/null +++ b/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt @@ -0,0 +1,15 @@ +1.2.0 +features: +* updated openvpn, openssl, tor, snowflake +* encrypted storage +* new provider setup UI +* Support for Android 13 +* enforce TLS 1.3 on all Android versions +* Dns over Https (DoH) during provider setup + +bugfixes: +* fixed possible on-device DoS vulnerability, leading to app crashes +* fixed task hijacking vulnerability (aka. strandhogg) +* fixed memory leaks +* fixed blocking vpn service stopping and notifications disappearing correctly +* disable location selection button if provider only supports 1 location diff --git a/src/custom/fastlane/metadata/android/en-US/full_description.txt b/src/custom/fastlane/metadata/android/en-US/full_description.txt new file mode 100644 index 00000000..c4ba7305 --- /dev/null +++ b/src/custom/fastlane/metadata/android/en-US/full_description.txt @@ -0,0 +1,7 @@ +RiseupVPN is an easy, fast, and secure VPN service from https://riseup.net. RiseupVPN does not require a user account, keep logs, or track you in any way. The service is paid for entirely by donations from users like you. + +https://riseup.net/vpn/donate + +It's developed by LEAP and the open source code can be explored here: https://0xacab.org/leap/bitmask_android + +Translations greatly appreciated at our Transifex project: Transifex project https://app.transifex.com/otf/bitmask/dashboard/ \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png new file mode 100644 index 00000000..04ad4c9a Binary files /dev/null and b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png differ diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png new file mode 100644 index 00000000..e7bd728c Binary files /dev/null and b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png differ diff --git a/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png new file mode 100644 index 00000000..c8893dee Binary files /dev/null and b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png differ diff --git a/src/custom/fastlane/metadata/android/en-US/short_description.txt b/src/custom/fastlane/metadata/android/en-US/short_description.txt new file mode 100644 index 00000000..1df82a44 --- /dev/null +++ b/src/custom/fastlane/metadata/android/en-US/short_description.txt @@ -0,0 +1 @@ +RiseupVPN, anonymous VPN. Powered by Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/en-US/title.txt b/src/custom/fastlane/metadata/android/en-US/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/en-US/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/en-US/video.txt b/src/custom/fastlane/metadata/android/en-US/video.txt new file mode 100644 index 00000000..e69de29b diff --git a/src/custom/fastlane/metadata/android/fr/full_description.txt b/src/custom/fastlane/metadata/android/fr/full_description.txt new file mode 100644 index 00000000..5f7c855e --- /dev/null +++ b/src/custom/fastlane/metadata/android/fr/full_description.txt @@ -0,0 +1,3 @@ +RiseupVPN est un service VPN facile d'utilisation, rapide et sécurisé proposé par https://riseup.net. RiseupVPN ne nécessite pas de compte utilisateur, ne garde pas d'historique et ne te trace d' aucune manière. Le service est financé entièrement par des dons d'utilisateurs comme toi. + +https://riseup.net/fr/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/fr/short_description.txt b/src/custom/fastlane/metadata/android/fr/short_description.txt new file mode 100644 index 00000000..7e92f7da --- /dev/null +++ b/src/custom/fastlane/metadata/android/fr/short_description.txt @@ -0,0 +1 @@ +RiseupVPN, un VPN anonyme. Basé sur Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/fr/store-meta-fr.json b/src/custom/fastlane/metadata/android/fr/store-meta-fr.json new file mode 100644 index 00000000..af63f77c --- /dev/null +++ b/src/custom/fastlane/metadata/android/fr/store-meta-fr.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "RiseupVPN est un service VPN facile d'utilisation, rapide et sécurisé proposé par https://riseup.net. RiseupVPN ne nécessite pas de compte utilisateur, ne garde pas d'historique et ne te trace d' aucune manière. Le service est financé entièrement par des dons d'utilisateurs comme toi.\n\nhttps://riseup.net/fr/vpn/donate", + "short_description": "RiseupVPN, un VPN anonyme. Basé sur Bitmask." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/fr/title.txt b/src/custom/fastlane/metadata/android/fr/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/fr/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/nl/full_description.txt b/src/custom/fastlane/metadata/android/nl/full_description.txt new file mode 100644 index 00000000..0a365ed2 --- /dev/null +++ b/src/custom/fastlane/metadata/android/nl/full_description.txt @@ -0,0 +1,3 @@ +RiseupVPN is de gemakkelijke, snelle en veilige VPN van riseup.net. RiseupVPN heeft geen gebruikersaccount nodig, houdt geen logs bij en volgt je geen enkele manier. De dienst wordt volledig betaald door donaties van gebruikers zoals jij. + +https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/nl/short_description.txt b/src/custom/fastlane/metadata/android/nl/short_description.txt new file mode 100644 index 00000000..0e1b3573 --- /dev/null +++ b/src/custom/fastlane/metadata/android/nl/short_description.txt @@ -0,0 +1 @@ +RiseupVPN: anonieme VPN. Bitmask als motor. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/nl/store-meta-nl.json b/src/custom/fastlane/metadata/android/nl/store-meta-nl.json new file mode 100644 index 00000000..d1923610 --- /dev/null +++ b/src/custom/fastlane/metadata/android/nl/store-meta-nl.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "RiseupVPN is de gemakkelijke, snelle en veilige VPN van riseup.net. RiseupVPN heeft geen gebruikersaccount nodig, houdt geen logs bij en volgt je geen enkele manier. De dienst wordt volledig betaald door donaties van gebruikers zoals jij.\n\nhttps://riseup.net/vpn/donate", + "short_description": "RiseupVPN: anonieme VPN. Bitmask als motor." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/nl/title.txt b/src/custom/fastlane/metadata/android/nl/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/nl/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/pt-rBR/full_description.txt b/src/custom/fastlane/metadata/android/pt-rBR/full_description.txt new file mode 100644 index 00000000..fc9e95d1 --- /dev/null +++ b/src/custom/fastlane/metadata/android/pt-rBR/full_description.txt @@ -0,0 +1 @@ +RiseupVPN é um serviço VPN fácil, rápido e seguro de https://riseup.net. RiseupVPN não requer uma conta de usuário, não mantém registros nem rastreia você de nenhuma forma. O serviço é pago inteiramente por doações
https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/pt-rBR/short_description.txt b/src/custom/fastlane/metadata/android/pt-rBR/short_description.txt new file mode 100644 index 00000000..79efc5e9 --- /dev/null +++ b/src/custom/fastlane/metadata/android/pt-rBR/short_description.txt @@ -0,0 +1 @@ +RiseupVPN, VPN anônima. Desenvolvido por Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json b/src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json new file mode 100644 index 00000000..974408d5 --- /dev/null +++ b/src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "RiseupVPN é um serviço VPN fácil, rápido e seguro de https://riseup.net. RiseupVPN não requer uma conta de usuário, não mantém registros nem rastreia você de nenhuma forma. O serviço é pago inteiramente por doações
https://riseup.net/vpn/donate", + "short_description": "RiseupVPN, VPN anônima. Desenvolvido por Bitmask." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/pt-rBR/title.txt b/src/custom/fastlane/metadata/android/pt-rBR/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/pt-rBR/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/tr/full_description.txt b/src/custom/fastlane/metadata/android/tr/full_description.txt new file mode 100644 index 00000000..8c6e27ce --- /dev/null +++ b/src/custom/fastlane/metadata/android/tr/full_description.txt @@ -0,0 +1,3 @@ +RiseupVPN, https://riseup.net tarafından sunulan kolay, hızlı ve güvenli bir VPN hizmetidir. RiseupVPN bir kullanıcı hesabı açılmasına gerek duymaz günlük tutmaz veya herhangi bir şekilde sizi izlemez. Bu hizmetin maliyeti tamamen sizin gibi kullanıcıların bağışlarıyla karşılanır. + +https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/tr/short_description.txt b/src/custom/fastlane/metadata/android/tr/short_description.txt new file mode 100644 index 00000000..83342ec2 --- /dev/null +++ b/src/custom/fastlane/metadata/android/tr/short_description.txt @@ -0,0 +1 @@ +RiseupVPN, anonim VPN. Bitmask tarafından sunuluyor. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/tr/store-meta-tr.json b/src/custom/fastlane/metadata/android/tr/store-meta-tr.json new file mode 100644 index 00000000..7fd8fcc0 --- /dev/null +++ b/src/custom/fastlane/metadata/android/tr/store-meta-tr.json @@ -0,0 +1,5 @@ +{ + "title": "RiseupVPN", + "full_description": "RiseupVPN, https://riseup.net tarafından sunulan kolay, hızlı ve güvenli bir VPN hizmetidir. RiseupVPN bir kullanıcı hesabı açılmasına gerek duymaz günlük tutmaz veya herhangi bir şekilde sizi izlemez. Bu hizmetin maliyeti tamamen sizin gibi kullanıcıların bağışlarıyla karşılanır.\n\nhttps://riseup.net/vpn/donate", + "short_description": "RiseupVPN, anonim VPN. Bitmask tarafından sunuluyor." +} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/android/tr/title.txt b/src/custom/fastlane/metadata/android/tr/title.txt new file mode 100644 index 00000000..8d2e228a --- /dev/null +++ b/src/custom/fastlane/metadata/android/tr/title.txt @@ -0,0 +1 @@ +RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/de/full_description.txt b/src/custom/fastlane/metadata/de/full_description.txt deleted file mode 100644 index b53d9c25..00000000 --- a/src/custom/fastlane/metadata/de/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -RiseupVPN ist ein leicht benutzbarer, schneller und sicherer VPN-Dienst von https://riseup.net. RiseupVPN benötigt keinen Benutzer*innenkonto, es speichert keine Logs und keine Daten von dir. Dieser Service wird ausschließlich über Spenden von Nutzer*innen wie dir finanziert. - -https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/de/short_description.txt b/src/custom/fastlane/metadata/de/short_description.txt deleted file mode 100644 index 8ab5f289..00000000 --- a/src/custom/fastlane/metadata/de/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN: anonymes VPN. Unterstützt von Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/de/store-meta-de.json b/src/custom/fastlane/metadata/de/store-meta-de.json deleted file mode 100644 index c1ad30cd..00000000 --- a/src/custom/fastlane/metadata/de/store-meta-de.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "RiseupVPN ist ein leicht benutzbarer, schneller und sicherer VPN-Dienst von https://riseup.net. RiseupVPN benötigt keinen Benutzer*innenkonto, es speichert keine Logs und keine Daten von dir. Dieser Service wird ausschließlich über Spenden von Nutzer*innen wie dir finanziert.\n\nhttps://riseup.net/vpn/donate", - "short_description": "RiseupVPN: anonymes VPN. Unterstützt von Bitmask." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/de/title.txt b/src/custom/fastlane/metadata/de/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/de/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/el/full_description.txt b/src/custom/fastlane/metadata/el/full_description.txt deleted file mode 100644 index 7d96bc0e..00000000 --- a/src/custom/fastlane/metadata/el/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -Το RiseupVPN είναι μια γρήγορη, εύκολη και ασφαλής υπηρεσία VPN από το https://riseup.net. Δε χρειάζεται λογαριασμός για τη χρήση του RiseupVPN, δε διατηρεί αρχεία καταγραφής και δεν παρακολουθεί με οποιοδήποτε τρόπο. Αυτή η υπηρεσία υποστηρίζεται από δωρεές χρηστών σαν και εσάς. - -https://riseup.net/vpn/donate.  \ No newline at end of file diff --git a/src/custom/fastlane/metadata/el/short_description.txt b/src/custom/fastlane/metadata/el/short_description.txt deleted file mode 100644 index 157e767e..00000000 --- a/src/custom/fastlane/metadata/el/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN, ανώνυμο VPN. Με την υποστήριξη του Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/el/store-meta-el.json b/src/custom/fastlane/metadata/el/store-meta-el.json deleted file mode 100644 index 35f23c9d..00000000 --- a/src/custom/fastlane/metadata/el/store-meta-el.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "Το RiseupVPN είναι μια γρήγορη, εύκολη και ασφαλής υπηρεσία VPN από το https://riseup.net. Δε χρειάζεται λογαριασμός για τη χρήση του RiseupVPN, δε διατηρεί αρχεία καταγραφής και δεν παρακολουθεί με οποιοδήποτε τρόπο. Αυτή η υπηρεσία υποστηρίζεται από δωρεές χρηστών σαν και εσάς.\n\nhttps://riseup.net/vpn/donate. ", - "short_description": "RiseupVPN, ανώνυμο VPN. Με την υποστήριξη του Bitmask." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/el/title.txt b/src/custom/fastlane/metadata/el/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/el/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/en-US/changelogs/169000.txt b/src/custom/fastlane/metadata/en-US/changelogs/169000.txt deleted file mode 100644 index 9cdf3a40..00000000 --- a/src/custom/fastlane/metadata/en-US/changelogs/169000.txt +++ /dev/null @@ -1,9 +0,0 @@ -Since the last releases were not fully rolled-out, a summary of version 1.1.6 - 1.1.8: -* updated design -* improved circumvention capabilities -* updated dependencies (openvpn, tor, snowflake etc.) -* updated translations -* fixed crashes and other bugs -* support for Message of the Day -* 1.1.7 fix: hiding debugging entries in settings -* 1.1.8 fix: uploaded correct google playstore version \ No newline at end of file diff --git a/src/custom/fastlane/metadata/en-US/changelogs/170000.txt b/src/custom/fastlane/metadata/en-US/changelogs/170000.txt deleted file mode 100644 index d2dbd888..00000000 --- a/src/custom/fastlane/metadata/en-US/changelogs/170000.txt +++ /dev/null @@ -1,15 +0,0 @@ -1.2.0 -features: -* updated openvpn, openssl, tor, snowflake -* encrypted storage -* new provider setup UI -* Support for Android 13 -* enforce TLS 1.3 on all Android versions -* Dns over Https (DoH) during provider setup - -bugfixes: -* fixed possible on-device DoS vulnerability, leading to app crashes -* fixed task hijacking vulnerability (aka. strandhogg) -* fixed memory leaks -* fixed blocking vpn service stopping and notifications disappearing correctly -* disable location selection button if provider only supports 1 location diff --git a/src/custom/fastlane/metadata/en-US/full_description.txt b/src/custom/fastlane/metadata/en-US/full_description.txt deleted file mode 100644 index c4ba7305..00000000 --- a/src/custom/fastlane/metadata/en-US/full_description.txt +++ /dev/null @@ -1,7 +0,0 @@ -RiseupVPN is an easy, fast, and secure VPN service from https://riseup.net. RiseupVPN does not require a user account, keep logs, or track you in any way. The service is paid for entirely by donations from users like you. - -https://riseup.net/vpn/donate - -It's developed by LEAP and the open source code can be explored here: https://0xacab.org/leap/bitmask_android - -Translations greatly appreciated at our Transifex project: Transifex project https://app.transifex.com/otf/bitmask/dashboard/ \ No newline at end of file diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png b/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png deleted file mode 100644 index 04ad4c9a..00000000 Binary files a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png and /dev/null differ diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png b/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png deleted file mode 100644 index e7bd728c..00000000 Binary files a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png and /dev/null differ diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png b/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png deleted file mode 100644 index c8893dee..00000000 Binary files a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png and /dev/null differ diff --git a/src/custom/fastlane/metadata/en-US/short_description.txt b/src/custom/fastlane/metadata/en-US/short_description.txt deleted file mode 100644 index 1df82a44..00000000 --- a/src/custom/fastlane/metadata/en-US/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN, anonymous VPN. Powered by Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/en-US/title.txt b/src/custom/fastlane/metadata/en-US/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/en-US/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/en-US/video.txt b/src/custom/fastlane/metadata/en-US/video.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/custom/fastlane/metadata/fr/full_description.txt b/src/custom/fastlane/metadata/fr/full_description.txt deleted file mode 100644 index 5f7c855e..00000000 --- a/src/custom/fastlane/metadata/fr/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -RiseupVPN est un service VPN facile d'utilisation, rapide et sécurisé proposé par https://riseup.net. RiseupVPN ne nécessite pas de compte utilisateur, ne garde pas d'historique et ne te trace d' aucune manière. Le service est financé entièrement par des dons d'utilisateurs comme toi. - -https://riseup.net/fr/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/fr/short_description.txt b/src/custom/fastlane/metadata/fr/short_description.txt deleted file mode 100644 index 7e92f7da..00000000 --- a/src/custom/fastlane/metadata/fr/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN, un VPN anonyme. Basé sur Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/fr/store-meta-fr.json b/src/custom/fastlane/metadata/fr/store-meta-fr.json deleted file mode 100644 index af63f77c..00000000 --- a/src/custom/fastlane/metadata/fr/store-meta-fr.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "RiseupVPN est un service VPN facile d'utilisation, rapide et sécurisé proposé par https://riseup.net. RiseupVPN ne nécessite pas de compte utilisateur, ne garde pas d'historique et ne te trace d' aucune manière. Le service est financé entièrement par des dons d'utilisateurs comme toi.\n\nhttps://riseup.net/fr/vpn/donate", - "short_description": "RiseupVPN, un VPN anonyme. Basé sur Bitmask." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/fr/title.txt b/src/custom/fastlane/metadata/fr/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/fr/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/nl/full_description.txt b/src/custom/fastlane/metadata/nl/full_description.txt deleted file mode 100644 index 0a365ed2..00000000 --- a/src/custom/fastlane/metadata/nl/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -RiseupVPN is de gemakkelijke, snelle en veilige VPN van riseup.net. RiseupVPN heeft geen gebruikersaccount nodig, houdt geen logs bij en volgt je geen enkele manier. De dienst wordt volledig betaald door donaties van gebruikers zoals jij. - -https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/nl/short_description.txt b/src/custom/fastlane/metadata/nl/short_description.txt deleted file mode 100644 index 0e1b3573..00000000 --- a/src/custom/fastlane/metadata/nl/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN: anonieme VPN. Bitmask als motor. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/nl/store-meta-nl.json b/src/custom/fastlane/metadata/nl/store-meta-nl.json deleted file mode 100644 index d1923610..00000000 --- a/src/custom/fastlane/metadata/nl/store-meta-nl.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "RiseupVPN is de gemakkelijke, snelle en veilige VPN van riseup.net. RiseupVPN heeft geen gebruikersaccount nodig, houdt geen logs bij en volgt je geen enkele manier. De dienst wordt volledig betaald door donaties van gebruikers zoals jij.\n\nhttps://riseup.net/vpn/donate", - "short_description": "RiseupVPN: anonieme VPN. Bitmask als motor." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/nl/title.txt b/src/custom/fastlane/metadata/nl/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/nl/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/pt-rBR/full_description.txt b/src/custom/fastlane/metadata/pt-rBR/full_description.txt deleted file mode 100644 index fc9e95d1..00000000 --- a/src/custom/fastlane/metadata/pt-rBR/full_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN é um serviço VPN fácil, rápido e seguro de https://riseup.net. RiseupVPN não requer uma conta de usuário, não mantém registros nem rastreia você de nenhuma forma. O serviço é pago inteiramente por doações
https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/pt-rBR/short_description.txt b/src/custom/fastlane/metadata/pt-rBR/short_description.txt deleted file mode 100644 index 79efc5e9..00000000 --- a/src/custom/fastlane/metadata/pt-rBR/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN, VPN anônima. Desenvolvido por Bitmask. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json b/src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json deleted file mode 100644 index 974408d5..00000000 --- a/src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "RiseupVPN é um serviço VPN fácil, rápido e seguro de https://riseup.net. RiseupVPN não requer uma conta de usuário, não mantém registros nem rastreia você de nenhuma forma. O serviço é pago inteiramente por doações
https://riseup.net/vpn/donate", - "short_description": "RiseupVPN, VPN anônima. Desenvolvido por Bitmask." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/pt-rBR/title.txt b/src/custom/fastlane/metadata/pt-rBR/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/pt-rBR/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file diff --git a/src/custom/fastlane/metadata/tr/full_description.txt b/src/custom/fastlane/metadata/tr/full_description.txt deleted file mode 100644 index 8c6e27ce..00000000 --- a/src/custom/fastlane/metadata/tr/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -RiseupVPN, https://riseup.net tarafından sunulan kolay, hızlı ve güvenli bir VPN hizmetidir. RiseupVPN bir kullanıcı hesabı açılmasına gerek duymaz günlük tutmaz veya herhangi bir şekilde sizi izlemez. Bu hizmetin maliyeti tamamen sizin gibi kullanıcıların bağışlarıyla karşılanır. - -https://riseup.net/vpn/donate \ No newline at end of file diff --git a/src/custom/fastlane/metadata/tr/short_description.txt b/src/custom/fastlane/metadata/tr/short_description.txt deleted file mode 100644 index 83342ec2..00000000 --- a/src/custom/fastlane/metadata/tr/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN, anonim VPN. Bitmask tarafından sunuluyor. \ No newline at end of file diff --git a/src/custom/fastlane/metadata/tr/store-meta-tr.json b/src/custom/fastlane/metadata/tr/store-meta-tr.json deleted file mode 100644 index 7fd8fcc0..00000000 --- a/src/custom/fastlane/metadata/tr/store-meta-tr.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "title": "RiseupVPN", - "full_description": "RiseupVPN, https://riseup.net tarafından sunulan kolay, hızlı ve güvenli bir VPN hizmetidir. RiseupVPN bir kullanıcı hesabı açılmasına gerek duymaz günlük tutmaz veya herhangi bir şekilde sizi izlemez. Bu hizmetin maliyeti tamamen sizin gibi kullanıcıların bağışlarıyla karşılanır.\n\nhttps://riseup.net/vpn/donate", - "short_description": "RiseupVPN, anonim VPN. Bitmask tarafından sunuluyor." -} \ No newline at end of file diff --git a/src/custom/fastlane/metadata/tr/title.txt b/src/custom/fastlane/metadata/tr/title.txt deleted file mode 100644 index 8d2e228a..00000000 --- a/src/custom/fastlane/metadata/tr/title.txt +++ /dev/null @@ -1 +0,0 @@ -RiseupVPN \ No newline at end of file -- cgit v1.2.3 From 70989ee13c88dacdb48cf801211011bb913934e7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Nov 2023 11:21:14 +0100 Subject: let android-fastlane docker image depend on android-ndk docker image, because the gitlab CI builds native libraries during the screenshot build step (which in turn requires android-fastlane as docker image) --- docker/android-fastlane/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/android-fastlane/Dockerfile b/docker/android-fastlane/Dockerfile index 5c7470aa..20ec98e5 100644 --- a/docker/android-fastlane/Dockerfile +++ b/docker/android-fastlane/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.0xacab.org/leap/bitmask_android/android-sdk:latest +FROM registry.0xacab.org/leap/bitmask_android/android-ndk:latest MAINTAINER LEAP Encryption Access Project LABEL Description="Android emulator image based on android-sdk" Vendor="LEAP" Version="4" -- cgit v1.2.3 From 4612539367b7dd79c7456c50ec7751babd9e0558 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Nov 2023 11:40:27 +0100 Subject: build screenshots for both Bitmask and RiseupVPN on CI --- .gitlab-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7c9e8a54..00549399 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -94,12 +94,11 @@ screenshot: - ./gradlew testCustomProductionFatReleaseUnitTest testNormalProductionFatReleaseUnitTest - ./scripts/startEmulators.sh - ./scripts/fastlane.sh + - ./scripts/fastlane.sh custom artifacts: paths: - - app - app/build/screenshots - - ./source/custom/fastlane/metadata/ - - build/ + - src/custom/ - src/normal/ when: always expire_in: 3 days -- cgit v1.2.3 From 4b97cc9e6e4a262750bfbcbe143a0ad59ae769ea Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Nov 2023 17:46:56 +0100 Subject: don't run unit tests in screenshot CI build step --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00549399..88c886c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -91,7 +91,6 @@ screenshot: script: - ./scripts/prepareForScreenshots.sh - ./scripts/installFastlane.sh - - ./gradlew testCustomProductionFatReleaseUnitTest testNormalProductionFatReleaseUnitTest - ./scripts/startEmulators.sh - ./scripts/fastlane.sh - ./scripts/fastlane.sh custom -- cgit v1.2.3 From df4d500ecbd333973c31b76e9c948643190b9767 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Nov 2023 20:28:33 +0100 Subject: try to fix the startEmulators script --- scripts/startEmulators.sh | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scripts/startEmulators.sh b/scripts/startEmulators.sh index 1d73dee7..0e6a519c 100755 --- a/scripts/startEmulators.sh +++ b/scripts/startEmulators.sh @@ -1,12 +1,13 @@ #!/bin/bash PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/Sdk/tools:$ANDROID_HOME/emulator +SCRIPT_DIR=$(dirname "$0") + apt-get update apt-get install -y libpulse-java libpulse0 imagemagick libxkbcommon-x11-0 xvfb vulkan-tools # there's a QT thing missing emulator -accel-check docker info -export DISPLAY=:99.0 # init parameters for ((i=1;i<=$#;i++)); @@ -41,7 +42,6 @@ timeout=30 echo y | sdkmanager "emulator" avdmanager list avd emulator -version -find /opt -iname emulator -type f waitForAdbDevices() { while true; do @@ -62,14 +62,10 @@ waitForAdbDevices() { } #start first N avd images -Xvfb :0 -screen 0 800x600x16 & -#avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -avd {} & -avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-window -no-audio -no-snapshot -avd {} & -#avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -no-window -avd {} & -# avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -no-window -no-boot-anim -accel on -avd {} & +#Xvfb :0 -screen 0 800x600x16 & +avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I {} emulator -no-window -no-audio -avd {} & waitForAdbDevices echo "adb found all emulators..." -#wait for each emulator that booting completed -adb devices | grep -v List | awk '$2{print $1}' | xargs -I{} .gitlab/wait-for-emulator.sh -s {} +adb devices | grep -v List | awk '$2{print $1}' | xargs -I{} $SCRIPT_DIR/wait-for-emulator.sh -s {} echo "all emulators successfully booted" -- cgit v1.2.3 From 32578d46bea3e54cdd3021b0dd3fac4fb724267a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 23 Nov 2023 23:13:17 +0100 Subject: cache library build artifacts and pass them to screenshot stage --- .gitlab-ci.yml | 8 +++----- scripts/prepareForScreenshots.sh | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 88c886c0..1422d90a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,7 +77,6 @@ screenshot: image: "0xacab.org:4567/leap/bitmask_android/android-fastlane:latest" stage: test when: always -# needs: ["docker_image:fastlane"] tags: - birch variables: @@ -86,17 +85,15 @@ screenshot: ANDROID_EMULATOR_USE_SYSTEM_LIBS: 1 DEBIAN_FRONTEN: "noninteractive" # try to re-use the build artifcats from before, lib building is slow -# dependencies: -# - build + dependencies: + - build script: - - ./scripts/prepareForScreenshots.sh - ./scripts/installFastlane.sh - ./scripts/startEmulators.sh - ./scripts/fastlane.sh - ./scripts/fastlane.sh custom artifacts: paths: - - app/build/screenshots - src/custom/ - src/normal/ when: always @@ -148,6 +145,7 @@ build: - ./scripts/build_deps.sh >> build_deps.log 2>&1 - ./gradlew clean assembleNormalProductionFatDebug -debug >> build.log 2>&1 artifacts: + untracked: true paths: - app/build/outputs/ - build_deps.log diff --git a/scripts/prepareForScreenshots.sh b/scripts/prepareForScreenshots.sh index c2ae1bd5..0b38cfae 100755 --- a/scripts/prepareForScreenshots.sh +++ b/scripts/prepareForScreenshots.sh @@ -26,4 +26,4 @@ git submodule foreach --recursive git reset --hard HEAD git submodule sync --recursive git submodule update --init --recursive -BUILD_TOR=false BUILD_OPENVPN_LIBS=false ./scripts/build_deps.sh +./scripts/build_deps.sh -- cgit v1.2.3 From a7725722c35136c42c9acc242a50588e1fac8bb0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 17 Jan 2024 15:16:30 +0100 Subject: replace deprectated Observer and Observables by PropertyChangeListener and PropertyChangeSupport --- .../bitmaskclient/base/BitmaskTileService.java | 13 +++---- .../se/leap/bitmaskclient/base/MainActivity.java | 12 +++---- .../bitmaskclient/base/fragments/EipFragment.java | 36 ++++++++++++------- .../base/fragments/GatewaySelectionFragment.java | 10 +++--- .../base/fragments/NavigationDrawerFragment.java | 10 +++--- .../base/fragments/TetheringDialog.java | 13 ++++--- .../base/models/ProviderObservable.java | 24 ++++++++++--- .../main/java/se/leap/bitmaskclient/eip/EIP.java | 10 +++--- .../java/se/leap/bitmaskclient/eip/EipStatus.java | 20 ++++++++--- .../se/leap/bitmaskclient/eip/VoidVpnService.java | 11 +++--- .../bitmaskclient/firewall/FirewallManager.java | 14 ++++---- .../pluggableTransports/ObfsVpnClient.java | 10 +++--- .../pluggableTransports/ShapeshifterClient.java | 13 +++---- .../tethering/TetheringObservable.java | 26 +++++++++----- .../bitmaskclient/tor/ClientTransportPlugin.java | 10 +++--- .../bitmaskclient/tor/TorStatusObservable.java | 40 ++++++++++++++-------- .../bitmaskclient/tor/TorStatusObservableTest.java | 6 ++++ 17 files changed, 176 insertions(+), 102 deletions(-) create mode 100644 app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java diff --git a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java index 370a7af6..d85e0a75 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java @@ -8,6 +8,8 @@ import android.os.Build; import android.service.quicksettings.Tile; import android.service.quicksettings.TileService; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Observable; import java.util.Observer; @@ -19,7 +21,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; @TargetApi(Build.VERSION_CODES.N) -public class BitmaskTileService extends TileService implements Observer { +public class BitmaskTileService extends TileService implements PropertyChangeListener { @SuppressLint("Override") @TargetApi(Build.VERSION_CODES.N) @@ -59,7 +61,7 @@ public class BitmaskTileService extends TileService implements Observer { public void onStartListening() { super.onStartListening(); EipStatus.getInstance().addObserver(this); - update(EipStatus.getInstance(), null); + propertyChange(new PropertyChangeEvent(EipStatus.getInstance(), EipStatus.PROPERTY_CHANGE, null, EipStatus.getInstance())); } @Override @@ -69,16 +71,15 @@ public class BitmaskTileService extends TileService implements Observer { } @Override - public void update(Observable o, Object arg) { + public void propertyChange(PropertyChangeEvent evt) { Tile t = getQsTile(); // Tile t should never be null according to https://developer.android.com/reference/kotlin/android/service/quicksettings/TileService. // Hovever we've got crash reports. if (t == null) { return; } - - if (o instanceof EipStatus) { - EipStatus status = (EipStatus) o; + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + EipStatus status = (EipStatus) evt.getNewValue(); Icon icon; String title; if (status.isConnecting() || status.isReconnecting()) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java index 5da238d4..3f541d8d 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java @@ -59,8 +59,8 @@ import androidx.fragment.app.FragmentTransaction; import org.json.JSONException; import org.json.JSONObject; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; @@ -80,7 +80,7 @@ import se.leap.bitmaskclient.eip.EipSetupListener; import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.providersetup.ProviderAPI; -public class MainActivity extends AppCompatActivity implements EipSetupListener, Observer { +public class MainActivity extends AppCompatActivity implements EipSetupListener, PropertyChangeListener { public final static String TAG = MainActivity.class.getSimpleName(); @@ -354,9 +354,9 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener, } @Override - public void update(Observable o, Object arg) { - if (o instanceof ProviderObservable) { - this.provider = ((ProviderObservable) o).getCurrentProvider(); + public void propertyChange(PropertyChangeEvent evt) { + if (ProviderObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + this.provider = (Provider) evt.getNewValue(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java index f4e09e62..fb93796e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java @@ -56,8 +56,8 @@ import androidx.fragment.app.FragmentTransaction; import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback; import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; @@ -80,7 +80,7 @@ import se.leap.bitmaskclient.providersetup.activities.SetupActivity; import se.leap.bitmaskclient.tor.TorServiceCommand; import se.leap.bitmaskclient.tor.TorStatusObservable; -public class EipFragment extends Fragment implements Observer { +public class EipFragment extends Fragment implements PropertyChangeListener { public final static String TAG = EipFragment.class.getSimpleName(); @@ -375,17 +375,27 @@ public class EipFragment extends Fragment implements Observer { } + @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - previousEipLevel = eipStatus.getEipLevel(); - eipStatus = (EipStatus) observable; - handleNewStateOnMain(); - - } else if (observable instanceof ProviderObservable) { - provider = ((ProviderObservable) observable).getCurrentProvider(); - } else if (observable instanceof TorStatusObservable && EipStatus.getInstance().isUpdatingVpnCert()) { - handleNewStateOnMain(); + public void propertyChange(PropertyChangeEvent evt) { + switch (evt.getPropertyName()) { + case ProviderObservable.PROPERTY_CHANGE: { + provider = ((Provider) evt.getNewValue()); + break; + } + case TorStatusObservable.PROPERTY_CHANGE: { + if (EipStatus.getInstance().isUpdatingVpnCert()) { + handleNewStateOnMain(); + } + break; + } + case EipStatus.PROPERTY_CHANGE: { + previousEipLevel = eipStatus.getEipLevel(); + eipStatus = (EipStatus) evt.getNewValue(); + handleNewStateOnMain(); + break; + } + default: {} } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java index 99b1ac39..bb5a06c4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java @@ -44,6 +44,8 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; import java.util.List; import java.util.Observable; @@ -64,7 +66,7 @@ interface LocationListSelectionListener { void onLocationManuallySelected(Location location); } -public class GatewaySelectionFragment extends Fragment implements Observer, LocationListSelectionListener, SharedPreferences.OnSharedPreferenceChangeListener { +public class GatewaySelectionFragment extends Fragment implements PropertyChangeListener, LocationListSelectionListener, SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = GatewaySelectionFragment.class.getSimpleName(); @@ -197,9 +199,9 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca } @Override - public void update(Observable o, Object arg) { - if (o instanceof EipStatus) { - eipStatus = (EipStatus) o; + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + eipStatus = (EipStatus) evt.getNewValue(); Activity activity = getActivity(); if (activity != null) { activity.runOnUiThread(this::updateRecommendedLocation); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index 60c21c40..e74d70a2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -53,8 +53,8 @@ import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; @@ -74,7 +74,7 @@ import se.leap.bitmaskclient.tethering.TetheringObservable; * See the * design guidelines for a complete explanation of the behaviors implemented here. */ -public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, Observer { +public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, PropertyChangeListener { /** * Per the design guidelines, you should show the drawer on launch until the user manually @@ -444,8 +444,8 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen } @Override - public void update(Observable o, Object arg) { - if (o instanceof TetheringObservable || o instanceof EipStatus) { + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName()) || TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { try { getActivity().runOnUiThread(() -> enableSaveBatteryEntry(!TetheringObservable.getInstance().getTetheringState().isVpnTetheringRunning())); diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java index 588daa3f..05744bc9 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java @@ -22,8 +22,8 @@ import androidx.appcompat.app.AppCompatDialogFragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -52,7 +52,7 @@ import se.leap.bitmaskclient.tethering.TetheringObservable; * along with this program. If not, see . */ -public class TetheringDialog extends AppCompatDialogFragment implements Observer { +public class TetheringDialog extends AppCompatDialogFragment implements PropertyChangeListener { public final static String TAG = TetheringDialog.class.getName(); @@ -241,9 +241,9 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer } @Override - public void update(Observable o, Object arg) { - if (o instanceof TetheringObservable) { - TetheringObservable observable = (TetheringObservable) o; + public void propertyChange(PropertyChangeEvent evt) { + if (TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + TetheringObservable observable = (TetheringObservable) evt.getNewValue(); Log.d(TAG, "TetheringObservable is updated"); dataset[0].enabled = observable.isWifiTetheringEnabled(); dataset[1].enabled = observable.isUsbTetheringEnabled(); @@ -251,5 +251,4 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer adapter.notifyDataSetChanged(); } } - } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java index 3e1e1fcc..6e28ac3e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java @@ -2,13 +2,17 @@ package se.leap.bitmaskclient.base.models; import androidx.annotation.NonNull; -import java.util.Observable; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; /** * Created by cyberta on 05.12.18. */ -public class ProviderObservable extends Observable { +public class ProviderObservable { private static ProviderObservable instance; + private final PropertyChangeSupport changeSupport; + public static final String PROPERTY_CHANGE = "ProviderObservable"; + private Provider currentProvider; private Provider providerForDns; @@ -19,11 +23,23 @@ public class ProviderObservable extends Observable { return instance; } + private ProviderObservable() { + changeSupport = new PropertyChangeSupport(this); + currentProvider = new Provider(); + } + + public void addObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.addPropertyChangeListener(propertyChangeListener); + } + + public void deleteObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.removePropertyChangeListener(propertyChangeListener); + } + public synchronized void updateProvider(@NonNull Provider provider) { instance.currentProvider = provider; instance.providerForDns = null; - instance.setChanged(); - instance.notifyObservers(); + instance.changeSupport.firePropertyChange(PROPERTY_CHANGE, null, provider); } public Provider getCurrentProvider() { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java index d8905bca..ed61ca13 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java @@ -67,6 +67,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.json.JSONException; import org.json.JSONObject; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.Closeable; import java.lang.ref.WeakReference; import java.util.Observable; @@ -97,7 +99,7 @@ import se.leap.bitmaskclient.eip.GatewaysManager.GatewayOptions; * @author Sean Leonard * @author Parménides GV */ -public final class EIP extends JobIntentService implements Observer { +public final class EIP extends JobIntentService implements PropertyChangeListener { public final static String TAG = EIP.class.getSimpleName(), @@ -160,9 +162,9 @@ public final class EIP extends JobIntentService implements Observer { * update eipStatus whenever it changes */ @Override - public void update(Observable observable, Object data) { - if (observable instanceof EipStatus) { - eipStatus = (EipStatus) observable; + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + eipStatus = (EipStatus) evt.getNewValue(); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java index 8182cab9..c2ba8af3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java @@ -20,10 +20,10 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK; import android.content.Context; import android.os.AsyncTask; -import androidx.annotation.VisibleForTesting; import android.util.Log; -import java.util.Observable; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.LogItem; @@ -34,7 +34,7 @@ import de.blinkt.openvpn.core.VpnStatus; * EipStatus changes it's state (EipLevel) when ConnectionStatus gets updated by OpenVpnService or * by VoidVpnService. */ -public class EipStatus extends Observable implements VpnStatus.StateListener { +public class EipStatus implements VpnStatus.StateListener { public static String TAG = EipStatus.class.getSimpleName(); private static EipStatus currentStatus; @@ -60,6 +60,9 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { private int localizedResId; private boolean isUpdatingVPNCertificate; + private final PropertyChangeSupport propertyChange; + public static final String PROPERTY_CHANGE = "EipStatus"; + public static EipStatus getInstance() { if (currentStatus == null) { currentStatus = new EipStatus(); @@ -69,6 +72,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } private EipStatus() { + propertyChange = new PropertyChangeSupport(this); } @Override @@ -300,8 +304,14 @@ public class EipStatus extends Observable implements VpnStatus.StateListener { } public static void refresh() { - getInstance().setChanged(); - getInstance().notifyObservers(); + currentStatus.propertyChange.firePropertyChange(PROPERTY_CHANGE, null, currentStatus); + } + + public void addObserver(PropertyChangeListener propertyChangeListener) { + propertyChange.addPropertyChangeListener(propertyChangeListener); } + public void deleteObserver(PropertyChangeListener propertyChangeListener) { + propertyChange.removePropertyChangeListener(propertyChangeListener); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java index b32671ae..f08371c6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java @@ -33,6 +33,8 @@ import android.os.ParcelFileDescriptor; import android.system.OsConstants; import android.util.Log; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.IOException; import java.util.Observable; import java.util.Observer; @@ -43,7 +45,7 @@ import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -public class VoidVpnService extends VpnService implements Observer, VpnNotificationManager.VpnServiceCallback { +public class VoidVpnService extends VpnService implements PropertyChangeListener, VpnNotificationManager.VpnServiceCallback { static final String TAG = VoidVpnService.class.getSimpleName(); private ParcelFileDescriptor fd; @@ -183,10 +185,11 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat getApplicationContext().startService(startEIP); } + @Override - public void update(Observable observable, Object arg) { - if (observable instanceof EipStatus) { - eipStatus = (EipStatus) observable; + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + eipStatus = (EipStatus) evt.getNewValue(); } if (handlerThread.isInterrupted() || !handlerThread.isAlive()) { return; diff --git a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java index 8df1638c..c7a7040f 100644 --- a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java @@ -21,16 +21,16 @@ import android.os.Handler; import android.os.Looper; import android.widget.Toast; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.R; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.tethering.TetheringObservable; import se.leap.bitmaskclient.tethering.TetheringState; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; -public class FirewallManager implements FirewallCallback, Observer { +public class FirewallManager implements FirewallCallback, PropertyChangeListener { public static String BITMASK_CHAIN = "bitmask_fw"; public static String BITMASK_FORWARD = "bitmask_forward"; public static String BITMASK_POSTROUTING = "bitmask_postrouting"; @@ -150,9 +150,9 @@ public class FirewallManager implements FirewallCallback, Observer { } @Override - public void update(Observable o, Object arg) { - if (o instanceof TetheringObservable) { - TetheringObservable observable = (TetheringObservable) o; + public void propertyChange(PropertyChangeEvent evt) { + if (TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + TetheringObservable observable = (TetheringObservable) evt.getNewValue(); TetheringState state = observable.getTetheringState(); if (state.hasAnyVpnTetheringAllowed() && state.hasAnyDeviceTetheringEnabled()) { startTethering(); diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java index 9d5ddcf9..685349ed 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java @@ -4,6 +4,8 @@ import static se.leap.bitmaskclient.base.models.Constants.KCP; import android.util.Log; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Observable; import java.util.Observer; import java.util.concurrent.atomic.AtomicBoolean; @@ -14,7 +16,7 @@ import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.eip.EipStatus; -public class ObfsVpnClient implements Observer, PtClientInterface { +public class ObfsVpnClient implements PropertyChangeListener, PtClientInterface { public static final AtomicInteger SOCKS_PORT = new AtomicInteger(4430); public static final String SOCKS_IP = "127.0.0.1"; @@ -114,9 +116,9 @@ public class ObfsVpnClient implements Observer, PtClientInterface { // TODO: register observer! @Override - public void update(Observable observable, Object arg) { - if (observable instanceof EipStatus) { - EipStatus status = (EipStatus) observable; + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + EipStatus status = (EipStatus) evt.getNewValue(); if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) { noNetwork = true; } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java index 102dcf35..e57401f8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java +++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java @@ -21,14 +21,14 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import de.blinkt.openvpn.core.ConnectionStatus; import de.blinkt.openvpn.core.VpnStatus; import se.leap.bitmaskclient.eip.EipStatus; -public class ShapeshifterClient implements Observer { +public class ShapeshifterClient implements PropertyChangeListener { public static final String DISPATCHER_PORT = "4430"; public static final String DISPATCHER_IP = "127.0.0.1"; @@ -123,10 +123,11 @@ public class ShapeshifterClient implements Observer { return false; } + @Override - public void update(Observable observable, Object arg) { - if (observable instanceof EipStatus) { - EipStatus status = (EipStatus) observable; + public void propertyChange(PropertyChangeEvent evt) { + if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) { + EipStatus status = (EipStatus) evt.getNewValue(); if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) { noNetwork = true; } else { diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java index a25f8c85..5d62b081 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java @@ -18,15 +18,19 @@ package se.leap.bitmaskclient.tethering; import androidx.annotation.NonNull; -import java.util.Observable; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; -public class TetheringObservable extends Observable { +public class TetheringObservable { private static TetheringObservable instance; private TetheringState tetheringState; + private final PropertyChangeSupport changeSupport; + public static final String PROPERTY_CHANGE = "TetheringObservable"; private TetheringObservable() { tetheringState = new TetheringState(); + changeSupport = new PropertyChangeSupport(this); } public static TetheringObservable getInstance() { @@ -36,10 +40,17 @@ public class TetheringObservable extends Observable { return instance; } + public void addObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.addPropertyChangeListener(propertyChangeListener); + } + + public void deleteObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.removePropertyChangeListener(propertyChangeListener); + } + public static void allowVpnWifiTethering(boolean enabled) { if (getInstance().tetheringState.isVpnWifiTetheringAllowed != enabled) { getInstance().tetheringState.isVpnWifiTetheringAllowed = enabled; - getInstance().setChanged(); getInstance().notifyObservers(); } } @@ -47,7 +58,6 @@ public class TetheringObservable extends Observable { public static void allowVpnUsbTethering(boolean enabled) { if (getInstance().tetheringState.isVpnUsbTetheringAllowed != enabled) { getInstance().tetheringState.isVpnUsbTetheringAllowed = enabled; - getInstance().setChanged(); getInstance().notifyObservers(); } } @@ -55,7 +65,6 @@ public class TetheringObservable extends Observable { public static void allowVpnBluetoothTethering(boolean enabled) { if (getInstance().tetheringState.isVpnBluetoothTetheringAllowed != enabled) { getInstance().tetheringState.isVpnBluetoothTetheringAllowed = enabled; - getInstance().setChanged(); getInstance().notifyObservers(); } } @@ -70,7 +79,6 @@ public class TetheringObservable extends Observable { state.wifiAddress = address; state.lastSeenWifiAddress = address.isEmpty() ? state.lastSeenWifiAddress : address; state.lastSeenWifiInterface = interfaceName.isEmpty() ? state.lastSeenWifiInterface : interfaceName; - getInstance().setChanged(); getInstance().notifyObservers(); } @@ -86,7 +94,6 @@ public class TetheringObservable extends Observable { state.usbInterface = interfaceName; state.lastSeenUsbAddress = address.isEmpty() ? state.lastSeenUsbAddress : address; state.lastSeenUsbInterface = interfaceName.isEmpty() ? state.lastSeenUsbInterface : interfaceName; - getInstance().setChanged(); getInstance().notifyObservers(); } } @@ -101,7 +108,6 @@ public class TetheringObservable extends Observable { state.bluetoothInterface = interfaceName; state.lastSeenBluetoothAddress = address.isEmpty() ? state.lastSeenBluetoothAddress : address; state.lastSeenBluetoothInterface = interfaceName.isEmpty() ? state.lastSeenBluetoothInterface : interfaceName; - getInstance().setChanged(); getInstance().notifyObservers(); } } @@ -121,4 +127,8 @@ public class TetheringObservable extends Observable { public TetheringState getTetheringState() { return tetheringState; } + + private void notifyObservers() { + changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance()); + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java index b1c4ca83..f13eb70e 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java @@ -30,6 +30,8 @@ import androidx.annotation.Nullable; import org.torproject.jni.ClientTransportPluginInterface; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; @@ -38,8 +40,6 @@ import java.io.InputStreamReader; import java.lang.ref.WeakReference; import java.util.Collection; import java.util.HashMap; -import java.util.Observable; -import java.util.Observer; import java.util.Random; import java.util.Scanner; import java.util.Vector; @@ -49,7 +49,7 @@ import java.util.regex.Pattern; import IPtProxy.IPtProxy; -public class ClientTransportPlugin implements ClientTransportPluginInterface, Observer { +public class ClientTransportPlugin implements ClientTransportPluginInterface, PropertyChangeListener { public static String TAG = ClientTransportPlugin.class.getSimpleName(); private HashMap mFronts; @@ -221,8 +221,8 @@ public class ClientTransportPlugin implements ClientTransportPluginInterface, Ob } @Override - public void update(Observable o, Object arg) { - if (o instanceof TorStatusObservable) { + public void propertyChange(PropertyChangeEvent evt) { + if(TorStatusObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { TorStatusObservable.SnowflakeStatus snowflakeStatus = TorStatusObservable.getSnowflakeStatus(); if (snowflakeStatus == this.snowflakeStatus) { return; diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java index 8bb41dd2..b1ad6084 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java @@ -29,8 +29,8 @@ import android.util.Log; import androidx.annotation.Nullable; -import java.util.Observable; -import java.util.Observer; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.util.Vector; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -39,10 +39,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import se.leap.bitmaskclient.R; -public class TorStatusObservable extends Observable { +public class TorStatusObservable { private static final String TAG = TorStatusObservable.class.getSimpleName(); + private final PropertyChangeSupport propertyChange; + public static final String PROPERTY_CHANGE = "TorStatusObservable"; + public interface StatusCondition { boolean met(); } @@ -98,6 +101,7 @@ public class TorStatusObservable extends Observable { private TorStatusObservable() { torNotificationManager = new TorNotificationManager(); + propertyChange = new PropertyChangeSupport(this); } public static TorStatusObservable getInstance() { @@ -126,11 +130,11 @@ public class TorStatusObservable extends Observable { public static boolean waitUntil(StatusCondition condition, int timeout) throws InterruptedException, TimeoutException { CountDownLatch countDownLatch = new CountDownLatch(1); final AtomicBoolean conditionMet = new AtomicBoolean(false); - Observer observer = (o, arg) -> { - if (condition.met()) { - countDownLatch.countDown(); - conditionMet.set(true); - } + PropertyChangeListener observer = evt -> { + if (condition.met()) { + countDownLatch.countDown(); + conditionMet.set(true); + } }; if (condition.met()) { // no need to wait @@ -145,6 +149,14 @@ public class TorStatusObservable extends Observable { return true; } + public void addObserver(PropertyChangeListener propertyChangeListener) { + propertyChange.addPropertyChangeListener(propertyChangeListener); + } + + public void deleteObserver(PropertyChangeListener propertyChangeListener) { + propertyChange.removePropertyChangeListener(propertyChangeListener); + } + public static void logSnowflakeMessage(Context context, String message) { addLog(message); if (getInstance().status != TorStatus.OFF) { @@ -191,7 +203,6 @@ public class TorStatusObservable extends Observable { getInstance().lastSnowflakeLog = context.getString(R.string.snowflake_sending_data); } Log.d(TAG, "snowflake status " + getInstance().snowflakeStatus); - instance.setChanged(); instance.notifyObservers(); } @@ -230,7 +241,7 @@ public class TorStatusObservable extends Observable { public static void updateState(Context context, String status, int bootstrapPercent, @Nullable String logKey) { try { - Log.d(TAG, "update tor state: " + status + " " + bootstrapPercent + " "+ logKey); + // Log.d(TAG, "update tor state: " + status + " " + bootstrapPercent + " "+ logKey); getInstance().status = TorStatus.valueOf(status); if (bootstrapPercent != -1) { getInstance().bootstrapPercent = bootstrapPercent; @@ -247,7 +258,7 @@ public class TorStatusObservable extends Observable { getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getBootstrapProgress()); } - instance.setChanged(); + instance.notifyObservers(); } catch (IllegalStateException e) { @@ -255,6 +266,10 @@ public class TorStatusObservable extends Observable { } } + private void notifyObservers() { + instance.propertyChange.firePropertyChange(PROPERTY_CHANGE, null, instance); + } + private static String getStringFor(Context context, String key) { switch (key) { case "conn_pt": @@ -294,13 +309,11 @@ public class TorStatusObservable extends Observable { public static void setLastError(String error) { getInstance().lastError = error; - instance.setChanged(); instance.notifyObservers(); } public static void setProxyPort(int port) { getInstance().port = port; - instance.setChanged(); instance.notifyObservers(); } @@ -345,7 +358,6 @@ public class TorStatusObservable extends Observable { if (!getInstance().cancelled) { getInstance().cancelled = true; getInstance().port = -1; - getInstance().setChanged(); getInstance().notifyObservers(); } } diff --git a/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java new file mode 100644 index 00000000..bdf8f6ac --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java @@ -0,0 +1,6 @@ +package se.leap.bitmaskclient.tor; + +import static org.junit.Assert.*; +public class TorStatusObservableTest { + +} \ No newline at end of file -- cgit v1.2.3 From a43be4240f48bca2985a4cc3ddee124ff80bfb1a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Mon, 22 Jan 2024 17:23:47 +0100 Subject: fix check if provider setup result matches the intended last selected provider --- .../providersetup/fragments/ConfigureProviderFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index e041b19b..9e8589ae 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -206,7 +206,7 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse if (ignoreProviderAPIUpdates || provider == null || (setupActivityCallback.getSelectedProvider() != null && - !setupActivityCallback.getSelectedProvider().getDomain().equals(provider.getDomain()))) { + !setupActivityCallback.getSelectedProvider().getMainUrlString().equals(provider.getMainUrlString()))) { return; } -- cgit v1.2.3 From 5db48094b7cbc4bab12e2fe8476ff1404971e49c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Jan 2024 21:59:27 +0100 Subject: fix GatewaySelectorTest, introduce TimezoneHelper --- .../bitmaskclient/base/utils/ConfigHelper.java | 18 +----- .../bitmaskclient/base/utils/TimezoneHelper.java | 42 ++++++++++++ .../se/leap/bitmaskclient/eip/GatewaySelector.java | 6 +- app/src/test/java/android/text/TextUtils.java | 6 ++ .../bitmaskclient/eip/GatewaySelectorTest.java | 74 ++++++++++------------ 5 files changed, 86 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java create mode 100644 app/src/test/java/android/text/TextUtils.java diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index 9289738a..d416a1ab 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -48,7 +48,6 @@ import java.security.interfaces.RSAPrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.ArrayList; -import java.util.Calendar; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -206,27 +205,14 @@ public class ConfigHelper { return BuildConfig.priotize_anonymous_usage; } - public static int getCurrentTimezone() { - return Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; - } - - public static int timezoneDistance(int local_timezone, int remoteTimezone) { - // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 - int dist = Math.abs(local_timezone - remoteTimezone); - // Farther than 12 timezones and it's shorter around the "back" - if (dist > 12) - dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things. - return dist; - } - /** * * @param remoteTimezone * @return a value between 0.1 and 1.0 */ public static double getConnectionQualityFromTimezoneDistance(int remoteTimezone) { - int localTimeZone = ConfigHelper.getCurrentTimezone(); - int distance = ConfigHelper.timezoneDistance(localTimeZone, remoteTimezone); + int localTimeZone = TimezoneHelper.getCurrentTimezone(); + int distance = TimezoneHelper.timezoneDistance(localTimeZone, remoteTimezone); return Math.max(distance / 12.0, 0.1); } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java new file mode 100644 index 00000000..c543368d --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java @@ -0,0 +1,42 @@ +package se.leap.bitmaskclient.base.utils; + +import androidx.annotation.VisibleForTesting; + +import java.util.Calendar; + +public class TimezoneHelper { + + public interface TimezoneInterface { + int getCurrentTimezone(); + } + + private static TimezoneInterface instance = new DefaultTimezoneHelper(); + + @VisibleForTesting + public TimezoneHelper(TimezoneInterface timezoneInterface) { + instance = timezoneInterface; + } + + public static TimezoneInterface get() { + return instance; + } + + public static int timezoneDistance(int localTimezone, int remoteTimezone) { // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12 + int dist = Math.abs(localTimezone - remoteTimezone); + // Farther than 12 timezones and it's shorter around the "back" + if (dist > 12) + dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things. + return dist; + } + + public static int getCurrentTimezone() { + return get().getCurrentTimezone(); + } + + public static class DefaultTimezoneHelper implements TimezoneInterface { + @Override + public int getCurrentTimezone() { + return Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; + } + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java index ad95c823..6a0b4b08 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java @@ -1,5 +1,8 @@ package se.leap.bitmaskclient.eip; +import static se.leap.bitmaskclient.base.utils.TimezoneHelper.timezoneDistance; +import static se.leap.bitmaskclient.base.utils.TimezoneHelper.getCurrentTimezone; + import android.util.Log; import java.util.ArrayList; @@ -10,9 +13,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.getCurrentTimezone; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.timezoneDistance; - public class GatewaySelector { private final static String TAG = GatewaySelector.class.getSimpleName(); List gateways; diff --git a/app/src/test/java/android/text/TextUtils.java b/app/src/test/java/android/text/TextUtils.java new file mode 100644 index 00000000..520944a5 --- /dev/null +++ b/app/src/test/java/android/text/TextUtils.java @@ -0,0 +1,6 @@ +package android.text; +public class TextUtils { + public static boolean isEmpty(CharSequence str) { + return str == null || str.length() == 0; + } +} diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java index 74762813..0175745e 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java @@ -1,8 +1,10 @@ package se.leap.bitmaskclient.eip; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.util.Log; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; @@ -14,35 +16,22 @@ import org.json.JSONObject; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; import java.io.IOException; import java.util.ArrayList; +import java.util.List; +import java.util.Vector; import de.blinkt.openvpn.core.ConfigParser; import se.leap.bitmaskclient.base.models.Provider; -import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.TimezoneHelper; import se.leap.bitmaskclient.testutils.MockSharedPreferences; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; - /** * Created by cyberta on 18.12.18. */ -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(DataProviderRunner.class) -@PrepareForTest({ConfigHelper.class, TextUtils.class}) +@RunWith(DataProviderRunner.class) public class GatewaySelectorTest { public static final String TAG = GatewaySelectorTest.class.getSimpleName(); @@ -72,23 +61,26 @@ public class GatewaySelectorTest { PreferenceHelper preferenceHelper; - GatewaySelector gatewaySelector; JSONObject eipDefinition; - ArrayList gatewayList = new ArrayList<>(); - @Before - public void setup() throws IOException, JSONException, ConfigParser.ConfigParseError { - mockStatic(ConfigHelper.class); - when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod(); - mockTextUtils(); + public void setup() throws IOException, JSONException { preferenceHelper = new PreferenceHelper(new MockSharedPreferences()); eipDefinition = new JSONObject(getInputAsString(getClass().getClassLoader().getResourceAsStream("eip-service-four-gateways.json"))); - JSONArray gateways = eipDefinition.getJSONArray("gateways"); - for (int i = 0; i < gateways.length(); i++) { - JSONObject gw = gateways.getJSONObject(i); - JSONObject secrets = secretsConfiguration(); - Gateway aux = new Gateway(eipDefinition, secrets, gw, null); - gatewayList.add(aux); + } + + private List getGateways() { + try { + Vector gatewayList = new Vector<>(); + JSONArray gateways = eipDefinition.getJSONArray("gateways"); + for (int i = 0; i < gateways.length(); i++) { + JSONObject gw = gateways.getJSONObject(i); + JSONObject secrets = secretsConfiguration(); + Gateway aux = new Gateway(eipDefinition, secrets, gw, null); + gatewayList.add(aux); + } + return gatewayList; + } catch (JSONException | IOException | ConfigParser.ConfigParseError e) { + return new ArrayList<>(); } } @@ -149,24 +141,24 @@ public class GatewaySelectorTest { @Test @UseDataProvider("dataProviderTimezones") public void testSelect(int timezone, String expected) { - when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone); - gatewaySelector = new GatewaySelector(gatewayList); + TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone); + GatewaySelector gatewaySelector = new GatewaySelector(getGateways()); assertEquals(expected, gatewaySelector.select().getName()); } @Test @UseDataProvider("dataProviderSameDistanceTimezones") public void testSelectSameTimezoneDistance(int timezone, String expected1, String expected2) { - when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone); - gatewaySelector = new GatewaySelector(gatewayList); + TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone); + GatewaySelector gatewaySelector = new GatewaySelector(getGateways()); assertTrue(gatewaySelector.select().getName().equals(expected1) || gatewaySelector.select().getName().equals(expected2)); } @Test @UseDataProvider("dataProviderSameDistanceTimezones") public void testNClostest_SameTimezoneDistance_chooseGatewayWithSameDistance(int timezone, String expected1, String expected2) { - when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone); - gatewaySelector = new GatewaySelector(gatewayList); + TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone); + GatewaySelector gatewaySelector = new GatewaySelector(getGateways()); ArrayList gateways = new ArrayList<>(); gateways.add(gatewaySelector.select(0).getName()); gateways.add(gatewaySelector.select(1).getName()); @@ -177,8 +169,8 @@ public class GatewaySelectorTest { @Test public void testNClostest_OneTimezonePerSet_choseSecondClosestTimezone() { - when(ConfigHelper.getCurrentTimezone()).thenReturn(-4); - gatewaySelector = new GatewaySelector(gatewayList); + TimezoneHelper timezoneHelper = new TimezoneHelper(() -> -4); + GatewaySelector gatewaySelector = new GatewaySelector(getGateways()); assertTrue("Frankfurt".equals(gatewaySelector.select(1).getName())); } -- cgit v1.2.3 From cf5d8edf1693c647fd91c7d1191fbf5d43b911fc Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Jan 2024 22:14:15 +0100 Subject: fix VpnProfileTest --- app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index a3ac3f92..4ba04cfc 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -2,6 +2,7 @@ package de.blinkt.openvpn; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @@ -18,7 +19,6 @@ import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.util.Arrays; import java.util.UUID; import de.blinkt.openvpn.core.connection.Obfs4Connection; @@ -85,7 +85,6 @@ public class VpnProfileTest { mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport)); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -104,7 +103,6 @@ public class VpnProfileTest { mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport)); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -124,7 +122,6 @@ public class VpnProfileTest { mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport)); mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -146,7 +143,6 @@ public class VpnProfileTest { mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -168,7 +164,6 @@ public class VpnProfileTest { mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -189,7 +184,6 @@ public class VpnProfileTest { mockVpnProfile.mLastUsed = 0; String s = mockVpnProfile.toJson(); - System.out.println(s); //ignore UUID in comparison -> set it to fixed value JSONObject actual = new JSONObject(s); @@ -210,7 +204,10 @@ public class VpnProfileTest { assertFalse(mockVpnProfile.mConnections[0].isUseUdp()); Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0]; assertEquals(OBFS4, obfs4Connection.getTransportType()); - assertFalse(Arrays.asList(obfs4Connection.getObfs4Options().transport.getProtocols()).contains(UDP)); + String[] protocols = obfs4Connection.getObfs4Options().transport.getProtocols(); + for (String protocol : protocols) { + assertNotEquals(UDP, protocol); + } assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert()); assertEquals("0", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode()); assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP); @@ -224,7 +221,7 @@ public class VpnProfileTest { VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN); assertNotNull(mockVpnProfile); - assertNotNull(mockVpnProfile.mConnections); + assertNotEquals(null, mockVpnProfile.mConnections); assertNotNull(mockVpnProfile.mConnections[0]); assertFalse(mockVpnProfile.mConnections[0].isUseUdp()); Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0]; -- cgit v1.2.3 From b73cb05bdcbf9947d0d0ea8c56e894baa395c7f1 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Jan 2024 22:14:48 +0100 Subject: fix ProviderTest --- .../se/leap/bitmaskclient/base/models/ProviderTest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java index 8bff690b..40d9927b 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java @@ -1,6 +1,8 @@ package se.leap.bitmaskclient.base.models; import static junit.framework.Assert.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; @@ -11,9 +13,6 @@ import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import java.util.HashSet; -import java.util.Set; - import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; @@ -61,14 +60,12 @@ public class ProviderTest { Provider p2 = TestSetupHelper.getConfiguredProvider(); p2.setMainUrl("http://somethingsdiffer.org"); Provider p3 = new Provider("https://anotherprovider.net"); + Provider p4 = TestSetupHelper.getConfiguredProvider(); - Set defaultProviders = new HashSet<>(); - defaultProviders.add(p1); - defaultProviders.add(p2); + assertEquals(p1, p4); + assertNotEquals(p1, p2); + assertNotEquals(p1, p3); - assertTrue(defaultProviders.contains(p1)); - assertTrue(defaultProviders.contains(p2)); - assertFalse(defaultProviders.contains(p3)); } @Test -- cgit v1.2.3 From 827be305805bd98362692f506c46dc7c73c6fc97 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Jan 2024 23:18:34 +0100 Subject: fix GatewaysManagerTest --- app/src/test/java/android/util/Log.java | 23 ++ .../bitmaskclient/eip/GatewaysManagerTest.java | 237 +++++++++------------ 2 files changed, 123 insertions(+), 137 deletions(-) create mode 100644 app/src/test/java/android/util/Log.java diff --git a/app/src/test/java/android/util/Log.java b/app/src/test/java/android/util/Log.java new file mode 100644 index 00000000..b3162d10 --- /dev/null +++ b/app/src/test/java/android/util/Log.java @@ -0,0 +1,23 @@ +package android.util; + +public class Log { + public static int d(String tag, String msg) { + System.out.println("DEBUG: " + tag + ": " + msg); + return 0; + } + + public static int i(String tag, String msg) { + System.out.println("INFO: " + tag + ": " + msg); + return 0; + } + + public static int w(String tag, String msg) { + System.out.println("WARN: " + tag + ": " + msg); + return 0; + } + + public static int e(String tag, String msg) { + System.out.println("ERROR: " + tag + ": " + msg); + return 0; + } +} \ No newline at end of file diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java index 86373ff6..d66fedbe 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java @@ -1,19 +1,30 @@ package se.leap.bitmaskclient.eip; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; +import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; +import static se.leap.bitmaskclient.base.models.Constants.ALLOW_EXPERIMENTAL_TRANSPORTS; +import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; +import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; +import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; +import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider; + import android.content.Context; import android.content.SharedPreferences; -import android.text.TextUtils; -import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.IOException; import java.util.ArrayList; @@ -21,42 +32,17 @@ import java.util.List; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ConfigParser; -import de.blinkt.openvpn.core.connection.Connection; import se.leap.bitmaskclient.base.models.Location; -import se.leap.bitmaskclient.base.models.Pair; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.testutils.MockHelper; +import se.leap.bitmaskclient.base.utils.TimezoneHelper; import se.leap.bitmaskclient.testutils.MockSharedPreferences; import se.leap.bitmaskclient.testutils.TestSetupHelper; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; -import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; -import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; -import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider; - /** * Created by cyberta on 09.10.17. */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ProviderObservable.class, Log.class, PreferenceHelper.class, ConfigHelper.class, TextUtils.class}) public class GatewaysManagerTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) @@ -65,17 +51,15 @@ public class GatewaysManagerTest { private SharedPreferences sharedPreferences; private JSONObject secrets; + private TimezoneHelper timezoneHelper; + ProviderObservable providerObservable; + @Before public void setUp() throws IOException, JSONException { - mockStatic(Log.class); - mockStatic(ConfigHelper.class); - mockTextUtils(); - when(ConfigHelper.getCurrentTimezone()).thenReturn(-1); - when(ConfigHelper.stringEqual(anyString(), anyString())).thenCallRealMethod(); - when(ConfigHelper.getConnectionQualityFromTimezoneDistance(anyInt())).thenCallRealMethod(); - when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod(); - when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod(); + timezoneHelper = new TimezoneHelper(() -> -1); + providerObservable = ProviderObservable.getInstance(); + secrets = new JSONObject(getJsonStringFor("secrets.json")); sharedPreferences = new MockSharedPreferences(); sharedPreferences.edit(). @@ -83,22 +67,20 @@ public class GatewaysManagerTest { putString(CA_CERT, secrets.getString(CA_CERT)). putString(PROVIDER_VPN_CERTIFICATE, secrets.getString(PROVIDER_VPN_CERTIFICATE)) .commit(); - mockStatic(PreferenceHelper.class); PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences); } @Test public void testGatewayManagerFromCurrentProvider_noProvider_noGateways() { - MockHelper.mockProviderObservable(null); + providerObservable.updateProvider(null); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(0, gatewaysManager.size()); } @Test public void testGatewayManagerFromCurrentProvider_threeGateways() { - Provider provider = getProvider(null, null, null, null,null, null, "ptdemo_three_mixed_gateways.json", null); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(getProvider(null, null, null, null,null, null, "ptdemo_three_mixed_gateways.json", null)); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(3, gatewaysManager.size()); } @@ -108,7 +90,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -125,7 +107,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -142,7 +124,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -159,7 +141,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json"); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -176,7 +158,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -193,7 +175,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null); JSONObject eipServiceJson = provider.getEipServiceJson(); JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(1); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -209,9 +191,8 @@ public class GatewaysManagerTest { public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); + providerObservable.updateProvider(provider); + sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("37.12.247.10", gatewaysManager.select(0).gateway.getRemoteIP()); @@ -221,10 +202,11 @@ public class GatewaysManagerTest { public void TestSelectN_select_includeExperimentalTransport_DecoupledPortHoppingGW() { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt_portHopping.eip-service.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList hosts = new ArrayList<>(); hosts.add(gatewaysManager.select(0).gateway.getHost()); @@ -239,10 +221,11 @@ public class GatewaysManagerTest { public void TestSelectN_select_includeExperimentalTransport_DecoupledPortAndIPHoppingGW() { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList hosts = new ArrayList<>(); @@ -256,10 +239,11 @@ public class GatewaysManagerTest { public void TestSelectN_select_excludeExperimentalTransport_DecoupledPortHoppingGW() { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt_portHopping.eip-service.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false). + commit(); for (int i = 0; i < 1000; i++) { GatewaysManager gatewaysManager = new GatewaysManager(mockContext); @@ -271,10 +255,11 @@ public class GatewaysManagerTest { public void TestSelectN_select_excludeExperimentalTransport_DecoupledPortAndIPHoppingGW() { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("bridge-nyc1-01.bitmask-dev.leapvpn.net", gatewaysManager.select(0).gateway.getHost()); @@ -285,10 +270,11 @@ public class GatewaysManagerTest { public void TestSelectN_select_excludeExperimentalTransport_InGatewayHoppingPTBridge() { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_obfs4hop_tcp_gateways.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); ArrayList hosts = new ArrayList<>(); @@ -303,10 +289,7 @@ public class GatewaysManagerTest { public void testSelectN_selectFromPresortedGateways_returnsGatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json"); - MockHelper.mockProviderObservable(provider); - //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("manila.bitmask.net", gatewaysManager.select(0).gateway.getHost()); @@ -318,10 +301,11 @@ public class GatewaysManagerTest { public void testSelectN_selectObfs4FromPresortedGateways_returnsObfs4GatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json"); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("moscow.bitmask.net", gatewaysManager.select(0).gateway.getHost()); @@ -334,11 +318,11 @@ public class GatewaysManagerTest { public void testSelectN_selectFromCity_returnsGatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json"); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getPreferredCity()).thenReturn("Paris"); + sharedPreferences.edit(). + putString(PREFERRED_CITY, "Paris"). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost()); @@ -350,11 +334,11 @@ public class GatewaysManagerTest { public void testSelectN_selectFromCityWithGeoIpServiceV1_returnsGatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json"); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getPreferredCity()).thenReturn("Paris"); + sharedPreferences.edit(). + putString(PREFERRED_CITY, "Paris"). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost()); @@ -367,11 +351,11 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", null); provider.setGeoIpJson(new JSONObject()); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getPreferredCity()).thenReturn("Paris"); + sharedPreferences.edit(). + putString(PREFERRED_CITY, "Paris"). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("Paris", gatewaysManager.select(0).gateway.getName()); @@ -384,10 +368,7 @@ public class GatewaysManagerTest { public void testSelectN_selectNAndCity_returnsGatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json"); - MockHelper.mockProviderObservable(provider); - //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost()); @@ -399,10 +380,7 @@ public class GatewaysManagerTest { public void testSelectN_selectNAndCityWithGeoIpServiceV1_returnsGatewaysInPresortedOrder() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json"); - MockHelper.mockProviderObservable(provider); - //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost()); @@ -415,10 +393,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", null); provider.setGeoIpJson(new JSONObject()); - MockHelper.mockProviderObservable(provider); - //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals("Paris", gatewaysManager.select(0, "Paris").gateway.getName()); @@ -432,10 +407,7 @@ public class GatewaysManagerTest { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json"); provider.setGeoIpJson(new JSONObject()); - MockHelper.mockProviderObservable(provider); - //use openvpn, not pluggable transports - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertNull(gatewaysManager.select(0, "Stockholm")); } @@ -444,9 +416,10 @@ public class GatewaysManagerTest { public void testGetLocations_openvpn() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putString(PREFERRED_CITY, "Paris"). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getGatewayLocations(); @@ -465,9 +438,7 @@ public class GatewaysManagerTest { public void testGetLocations_obfs4() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); + providerObservable.updateProvider(provider); sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getGatewayLocations(); @@ -496,9 +467,7 @@ public class GatewaysManagerTest { public void testGetLocations_noMenshen_obfs4_calculateAverageLoadFromTimezoneDistance() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(true); + providerObservable.updateProvider(provider); sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getGatewayLocations(); @@ -521,10 +490,7 @@ public class GatewaysManagerTest { public void testGetLocations_noMenshen_openvpn_calculateAverageLoadFromTimezoneDistance() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - sharedPreferences.edit().putBoolean(USE_BRIDGES, false).commit(); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getGatewayLocations(); @@ -547,9 +513,7 @@ public class GatewaysManagerTest { public void testGetSortedLocations_openvpn() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getSortedGatewayLocations(OPENVPN); @@ -576,9 +540,7 @@ public class GatewaysManagerTest { public void testGetSortedLocations_obfs4() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getSortedGatewayLocations(OBFS4); @@ -606,9 +568,7 @@ public class GatewaysManagerTest { public void testGetSortedLocations_obfs4kcp_generalizedAsPT() { Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); List locations = gatewaysManager.getSortedGatewayLocations(OBFS4); @@ -619,9 +579,10 @@ public class GatewaysManagerTest { public void testgetAverageLoad_isSameForAllTransports() { Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_kcp_gateways.json", "ptdemo_kcp_gateways_geoip.json"); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putString(PREFERRED_CITY, "Paris"). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(0.3, gatewaysManager.getLocation("Amsterdam").getAverageLoad(OBFS4)); @@ -630,7 +591,7 @@ public class GatewaysManagerTest { @Test public void testGetLoadForLocation_() { - MockHelper.mockProviderObservable(null); + providerObservable.updateProvider(null); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(GatewaysManager.Load.UNKNOWN, gatewaysManager.getLoadForLocation("unknown city", OPENVPN)); } @@ -638,7 +599,7 @@ public class GatewaysManagerTest { @Test public void testGatewayManagerFromCurrentProvider_decoupledBridges_twoGateways() throws IOException, NullPointerException { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null); - MockHelper.mockProviderObservable(provider); + providerObservable.updateProvider(provider); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(2, gatewaysManager.size()); } @@ -646,9 +607,11 @@ public class GatewaysManagerTest { @Test public void testGatewayManagerFromCurrentProvider_decoupledBridgesIncludingExperimental_threeGateways() throws IOException, NullPointerException { Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null); - MockHelper.mockProviderObservable(provider); - mockStatic(PreferenceHelper.class); - when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true); + providerObservable.updateProvider(provider); + sharedPreferences.edit(). + putBoolean(USE_BRIDGES, true). + putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true). + commit(); GatewaysManager gatewaysManager = new GatewaysManager(mockContext); assertEquals(3, gatewaysManager.size()); } -- cgit v1.2.3 From 190b8d731d646ed18e771ce07b43a6c846526dd5 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 24 Jan 2024 23:23:06 +0100 Subject: add TorStatusObservableTest testing propertyChange pattern --- .../bitmaskclient/tor/TorStatusObservableTest.java | 46 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java index bdf8f6ac..10dbf6cb 100644 --- a/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java @@ -1,6 +1,48 @@ package se.leap.bitmaskclient.tor; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import android.content.Context; +import android.content.pm.PackageManager; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +@RunWith(MockitoJUnitRunner.class) public class TorStatusObservableTest { - + + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mockContext; + + + + @Test + public void testPropertyChange() throws PackageManager.NameNotFoundException { + TorStatusObservable statusObservable = TorStatusObservable.getInstance(); + int i = 10; + PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + assertEquals(12, TorStatusObservable.getBootstrapProgress()); + assertEquals("a logkey", TorStatusObservable.getLastLogs().lastElement()); + assertNull(evt.getOldValue()); + TorStatusObservable.getInstance().deleteObserver(this); + } + }; + + TorStatusObservable.updateState(mockContext, "STARTING", 10, "a logkey"); + TorStatusObservable.updateState(mockContext, "STARTING", 11, "a log 2"); + TorStatusObservable.getInstance().addObserver(propertyChangeListener); + TorStatusObservable.updateState(mockContext, "STARTING", 12, "a log 3"); + + } + } \ No newline at end of file -- cgit v1.2.3 From ed8a28962675b540389fc9280ab1122613230fa8 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 01:26:05 +0100 Subject: fix ProviderManagerTest, adapt InputStreamHelper and Filehelper to be mockable by injection --- .../leap/bitmaskclient/base/utils/FileHelper.java | 41 ++++++++++-- .../base/utils/InputStreamHelper.java | 24 ++++++- .../providersetup/ProviderManagerTest.java | 52 ++++++--------- .../leap/bitmaskclient/testutils/MockHelper.java | 74 +++++++++------------- 4 files changed, 110 insertions(+), 81 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java index eb1c255c..f1d86876 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java @@ -2,6 +2,8 @@ package se.leap.bitmaskclient.base.utils; import android.content.Context; +import androidx.annotation.VisibleForTesting; + import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; @@ -9,19 +11,50 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import de.blinkt.openvpn.core.NativeUtils; + /** * Created by cyberta on 18.03.18. */ public class FileHelper { + + public interface FileHelperInterface { + File createFile(File dir, String fileName); + void persistFile(File file, String content) throws IOException; + } + + public static class DefaultFileHelper implements FileHelperInterface { + @Override + public File createFile(File dir, String fileName) { + return new File(dir, fileName); + } + + @Override + public void persistFile(File file, String content) throws IOException { + FileWriter writer = new FileWriter(file); + writer.write(content); + writer.close(); + } + } + + private static FileHelperInterface instance = new DefaultFileHelper(); + + @VisibleForTesting + public FileHelper(FileHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("FileHelper injected with FileHelperInterface outside of an unit test"); + } + + instance = helperInterface; + } + public static File createFile(File dir, String fileName) { - return new File(dir, fileName); + return instance.createFile(dir, fileName); } public static void persistFile(File file, String content) throws IOException { - FileWriter writer = new FileWriter(file); - writer.write(content); - writer.close(); + instance.persistFile(file, content); } public static String readPublicKey(Context context) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java index 8e6273a7..6dfe0861 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java @@ -8,14 +8,36 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import de.blinkt.openvpn.core.NativeUtils; + /** * Created by cyberta on 18.03.18. */ public class InputStreamHelper { + public interface InputStreamHelperInterface { + InputStream getInputStreamFrom(String filePath) throws FileNotFoundException; + + } + + private static InputStreamHelperInterface instance = new DefaultInputStreamHelper(); + + private static class DefaultInputStreamHelper implements InputStreamHelperInterface { + @Override + public InputStream getInputStreamFrom(String filePath) throws FileNotFoundException { + return new FileInputStream(filePath); + } + } + + public InputStreamHelper(InputStreamHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("InputStreamHelper injected with InputStreamHelperInterface outside of an unit test"); + } + instance = helperInterface; + } //allows us to mock FileInputStream public static InputStream getInputStreamFrom(String filePath) throws FileNotFoundException { - return new FileInputStream(filePath); + return instance.getInputStreamFrom(filePath); } public static String loadInputStreamAsString(InputStream is) { diff --git a/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java index e7295452..7584fb3f 100644 --- a/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java @@ -1,56 +1,49 @@ package se.leap.bitmaskclient.providersetup; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static se.leap.bitmaskclient.testutils.MockHelper.mockInputStreamHelper; + import android.content.res.AssetManager; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import se.leap.bitmaskclient.base.models.Provider; -import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.FileHelper; import se.leap.bitmaskclient.base.utils.InputStreamHelper; -import se.leap.bitmaskclient.providersetup.ProviderManager; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.verifyStatic; -import static se.leap.bitmaskclient.testutils.MockHelper.mockFileHelper; -import static se.leap.bitmaskclient.testutils.MockHelper.mockInputStreamHelper; +import se.leap.bitmaskclient.testutils.MockHelper; /** * Created by cyberta on 20.02.18. */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ConfigHelper.class, FileHelper.class, InputStreamHelper.class}) public class ProviderManagerTest { - @Mock private AssetManager assetManager; - @Mock private File file; private ProviderManager providerManager; + InputStreamHelper inputStreamHelper; + FileHelper fileHelper; + MockHelper.MockFileHelper mockedFileHelperInterface; @Before public void setup() throws Exception { - //mock assetManager methods - //-------------------------- + assetManager = mock(AssetManager.class); + file = mock(File.class); + when(assetManager.open(anyString())).thenAnswer(new Answer() { @Override public InputStream answer(InvocationOnMock invocation) throws Throwable { @@ -85,11 +78,9 @@ public class ProviderManagerTest { when(file.getAbsolutePath()).thenReturn("externalDir"); when(file.getPath()).thenReturn("externalDir"); - mockFileHelper(file); - - // mock inputStream - //----------------------------------- - mockInputStreamHelper(); + mockedFileHelperInterface = new MockHelper.MockFileHelper(file); + fileHelper = new FileHelper(mockedFileHelperInterface); + inputStreamHelper = mockInputStreamHelper(); } @@ -217,8 +208,7 @@ public class ProviderManagerTest { providerManager.add(secondCustomProvider); providerManager.saveCustomProvidersToFile(); - verifyStatic(FileHelper.class, times(2)); - FileHelper.persistFile(any(File.class), anyString()); + assertEquals("persist was called twice", 2, mockedFileHelperInterface.getPersistFileCounter()); } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index 1f8a18f4..01af9591 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -314,39 +314,6 @@ public class MockHelper { return intent; } - public static void mockTextUtils() { - mockStatic(TextUtils.class); - - when(TextUtils.equals(any(CharSequence.class), any(CharSequence.class))).thenAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - CharSequence a = (CharSequence) invocation.getArguments()[0]; - CharSequence b = (CharSequence) invocation.getArguments()[1]; - if (a == b) return true; - int length; - if (a != null && b != null && (length = a.length()) == b.length()) { - if (a instanceof String && b instanceof String) { - return a.equals(b); - } else { - for (int i = 0; i < length; i++) { - if (a.charAt(i) != b.charAt(i)) return false; - } - return true; - } - } - return false; - } - }); - - when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - CharSequence param = (CharSequence) invocation.getArguments()[0]; - return param == null || param.length() == 0; - } - }); - } - public static ResultReceiver mockResultReceiver(final int expectedResultCode) { ResultReceiver resultReceiver = mock(ResultReceiver.class); doAnswer(new Answer() { @@ -398,23 +365,41 @@ public class MockHelper { return resultReceiver; } - public static void mockInputStreamHelper() throws FileNotFoundException { - mockStatic(InputStreamHelper.class); - when(InputStreamHelper.loadInputStreamAsString(any(InputStream.class))).thenCallRealMethod(); - when(InputStreamHelper.getInputStreamFrom(anyString())).thenAnswer(new Answer() { + + public static InputStreamHelper mockInputStreamHelper() { + return new InputStreamHelper(new InputStreamHelper.InputStreamHelperInterface() { @Override - public InputStream answer(InvocationOnMock invocation) throws Throwable { - String filename = (String) invocation.getArguments()[0]; - return getClass().getClassLoader().getResourceAsStream(filename); + public InputStream getInputStreamFrom(String filePath) { + return getClass().getClassLoader().getResourceAsStream(filePath); } }); - when(InputStreamHelper.inputStreamToJson(any(InputStream.class))).thenCallRealMethod(); + } + + public static class MockFileHelper implements FileHelper.FileHelperInterface { + private final File file; + private int persistFileCounter = 0; + public MockFileHelper(File file) { + this.file = file; + } + + @Override + public File createFile(File dir, String fileName) { + return file; + } + + @Override + public void persistFile(File file, String content) throws IOException { + persistFileCounter++; + } + + public int getPersistFileCounter() { + return persistFileCounter; + } } - public static void mockFileHelper(final File mockedFile) throws FileNotFoundException { - mockStatic(FileHelper.class); - when(createFile(any(File.class), anyString())).thenReturn(mockedFile); + public static FileHelper mockFileHelper(final File mockedFile) throws FileNotFoundException { + return new FileHelper(new MockFileHelper(mockedFile)); } public static void mockBase64() { @@ -459,7 +444,6 @@ public class MockHelper { when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod(); when(ConfigHelper.parseX509CertificatesFromString(anyString())).thenCallRealMethod(); when(ConfigHelper.getProviderFormattedString(any(Resources.class), anyInt())).thenCallRealMethod(); - when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod(); when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod(); when(ConfigHelper.isDefaultBitmask()).thenReturn(true); when(ConfigHelper.getDomainFromMainURL(anyString())).thenCallRealMethod(); -- cgit v1.2.3 From 23278cefe308043228c9da9b4937d27888146206 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 02:32:55 +0100 Subject: fix VpnConfigGenerator Test, move RSAHelper and ObfsVpnHelper out of ConfigHelper, use injection pattern for these helpers --- .../main/java/de/blinkt/openvpn/VpnProfile.java | 5 +- .../de/blinkt/openvpn/core/OpenVPNService.java | 2 +- .../openvpn/core/connection/Obfs4Connection.java | 2 +- .../base/fragments/ObfuscationProxyDialog.java | 2 +- .../base/fragments/SettingsFragment.java | 2 +- .../leap/bitmaskclient/base/models/Constants.java | 1 + .../leap/bitmaskclient/base/models/Provider.java | 4 +- .../bitmaskclient/base/utils/ConfigHelper.java | 67 ----------------- .../bitmaskclient/base/utils/ObfsVpnHelper.java | 86 ++++++++++++++++++++++ .../bitmaskclient/base/utils/PreferenceHelper.java | 7 +- .../leap/bitmaskclient/base/utils/RSAHelper.java | 72 ++++++++++++++++++ .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 2 +- .../providersetup/ProviderApiManagerBase.java | 2 +- .../java/de/blinkt/openvpn/VpnProfileTest.java | 24 +++--- .../bitmaskclient/base/models/ProviderTest.java | 17 +---- .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 82 +++++++++------------ .../leap/bitmaskclient/testutils/MockHelper.java | 64 ++++++++++++---- 17 files changed, 273 insertions(+), 168 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java index 780ac9d8..9da1e452 100644 --- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -16,7 +16,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; -import android.preference.PreferenceManager; import android.security.KeyChain; import android.security.KeyChainException; import android.text.TextUtils; @@ -77,6 +76,7 @@ import de.blinkt.openvpn.core.connection.ConnectionAdapter; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.ProviderObservable; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; public class VpnProfile implements Serializable, Cloneable { // Note that this class cannot be moved to core where it belongs since @@ -651,8 +651,7 @@ public class VpnProfile implements Serializable, Cloneable { if (mPushPeerInfo) cfg.append("push-peer-info\n"); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean usesystemproxy = prefs.getBoolean("usesystemproxy", true); + boolean usesystemproxy = PreferenceHelper.useSystemProxy(); if (usesystemproxy && !mIsOpenVPN22 && !configForOvpn3 && !usesExtraProxyOptions()) { cfg.append("# Use system proxy setting\n"); cfg.append("management-query-proxy\n"); diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index b38eeb14..e311158c 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -9,7 +9,7 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static de.blinkt.openvpn.core.NetworkSpace.IpAddress; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; import android.Manifest.permission; import android.app.Notification; diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java index d152031a..0abb5822 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java @@ -1,6 +1,6 @@ package de.blinkt.openvpn.core.connection; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java index 948d764f..635af701 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java @@ -15,7 +15,7 @@ import androidx.appcompat.app.AppCompatDialogFragment; import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatEditText; -import se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.views.IconSwitchEntry; import se.leap.bitmaskclient.databinding.DObfuscationProxyBinding; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index c8c994a5..77becc80 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -8,7 +8,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL; import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java index 70bf3943..18590f0b 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java @@ -52,6 +52,7 @@ public interface Constants { String OBFUSCATION_PINNING_CERT = "obfuscation_pinning_cert"; String OBFUSCATION_PINNING_KCP = "obfuscation_pinning_udp"; String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location"; + String USE_SYSTEM_PROXY = "usesystemproxy"; ////////////////////////////////////////////// diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java index 14c78cc3..af9122de 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -28,8 +28,8 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGIS import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.TYPE; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; +import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import android.os.Parcel; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index d416a1ab..a06d85be 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -36,17 +36,12 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; -import java.security.KeyFactory; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -130,39 +125,6 @@ public class ConfigHelper { return null; } - public static class RSAHelper { - public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { - RSAPrivateKey key; - try { - KeyFactory kf; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - kf = KeyFactory.getInstance("RSA", "BC"); - } else { - kf = KeyFactory.getInstance("RSA"); - } - rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); - key = (RSAPrivateKey) kf.generatePrivate(keySpec); - } catch (InvalidKeySpecException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NoSuchAlgorithmException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } catch (NullPointerException e) { - e.printStackTrace(); - return null; - } catch (NoSuchProviderException e) { - e.printStackTrace(); - return null; - } - - return key; - } - } - private static String byteArrayToHex(byte[] input) { int readBytes = input.length; StringBuffer hexData = new StringBuffer(); @@ -273,35 +235,6 @@ public class ConfigHelper { Build.VERSION.SDK_INT >= Build.VERSION_CODES.R; } - // ObfsVpnHelper class allows us to mock BuildConfig.use_obfsvpn while - // not mocking the whole ConfigHelper class - public static class ObfsVpnHelper { - public static boolean useObfsVpn() { - return BuildConfig.use_obfsvpn; - } - - public static boolean hasObfuscationPinningDefaults() { - return BuildConfig.obfsvpn_ip != null && - BuildConfig.obfsvpn_port != null && - BuildConfig.obfsvpn_cert != null && - !BuildConfig.obfsvpn_ip.isEmpty() && - !BuildConfig.obfsvpn_port.isEmpty() && - !BuildConfig.obfsvpn_cert.isEmpty(); - } - public static String obfsvpnIP() { - return BuildConfig.obfsvpn_ip; - } - public static String obfsvpnPort() { - return BuildConfig.obfsvpn_port; - } - public static String obfsvpnCert() { - return BuildConfig.obfsvpn_cert; - } - public static boolean useKcp() { - return BuildConfig.obfsvpn_use_kcp; - } - } - public static int getPendingIntentFlags() { int flags = PendingIntent.FLAG_CANCEL_CURRENT; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java new file mode 100644 index 00000000..054c85b3 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java @@ -0,0 +1,86 @@ +package se.leap.bitmaskclient.base.utils; + +import androidx.annotation.VisibleForTesting; + +import de.blinkt.openvpn.core.NativeUtils; +import se.leap.bitmaskclient.BuildConfig; + +// ObfsVpnHelper class allows us to mock BuildConfig fields related to the pre-shipped circumvention settings +public class ObfsVpnHelper { + + public interface ObfsVpnHelperInterface { + boolean useObfsVpn(); + boolean hasObfuscationPinningDefaults(); + String obfsvpnIP(); + String obfsvpnPort(); + String obfsvpnCert(); + boolean useKcp(); + } + + public static class DefaultObfsVpnHelper implements ObfsVpnHelperInterface { + @Override + public boolean useObfsVpn() { + return BuildConfig.use_obfsvpn; + } + + @Override + public boolean hasObfuscationPinningDefaults() { + return BuildConfig.obfsvpn_ip != null && + BuildConfig.obfsvpn_port != null && + BuildConfig.obfsvpn_cert != null && + !BuildConfig.obfsvpn_ip.isEmpty() && + !BuildConfig.obfsvpn_port.isEmpty() && + !BuildConfig.obfsvpn_cert.isEmpty(); + } + + @Override + public String obfsvpnIP() { + return BuildConfig.obfsvpn_ip; + } + + @Override + public String obfsvpnPort() { + return BuildConfig.obfsvpn_port; + } + + @Override + public String obfsvpnCert() { + return BuildConfig.obfsvpn_cert; + } + + @Override + public boolean useKcp() { + return BuildConfig.obfsvpn_use_kcp; + } + } + + private static ObfsVpnHelperInterface instance = new DefaultObfsVpnHelper(); + + @VisibleForTesting + public ObfsVpnHelper(ObfsVpnHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("ObfsVpnHelper injected with ObfsVpnHelperInterface outside of an unit test"); + } + instance = helperInterface; + } + + public static boolean useObfsVpn() { + return instance.useObfsVpn(); + } + + public static boolean hasObfuscationPinningDefaults() { + return instance.hasObfuscationPinningDefaults(); + } + public static String obfsvpnIP() { + return instance.obfsvpnIP(); + } + public static String obfsvpnPort() { + return instance.obfsvpnPort(); + } + public static String obfsvpnCert() { + return instance.obfsvpnCert(); + } + public static boolean useKcp() { + return instance.useKcp(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index b35a04cd..a04c3686 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -40,6 +40,7 @@ import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL; import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING; import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE; +import static se.leap.bitmaskclient.base.models.Constants.USE_SYSTEM_PROXY; import android.content.Context; import android.content.SharedPreferences; @@ -460,12 +461,16 @@ public class PreferenceHelper { return getBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false); } + public static boolean useSystemProxy() { + return getBoolean(USE_SYSTEM_PROXY, true); + } + public static void setUseObfuscationPinning(Boolean pinning) { putBoolean(USE_OBFUSCATION_PINNING, pinning); } public static boolean useObfuscationPinning() { - return ConfigHelper.ObfsVpnHelper.useObfsVpn() && + return ObfsVpnHelper.useObfsVpn() && getUseBridges() && getBoolean(USE_OBFUSCATION_PINNING, false) && !TextUtils.isEmpty(getObfuscationPinningIP()) && diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java new file mode 100644 index 00000000..2872139a --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java @@ -0,0 +1,72 @@ +package se.leap.bitmaskclient.base.utils; + +import android.os.Build; + +import androidx.annotation.VisibleForTesting; + +import org.spongycastle.util.encoders.Base64; + +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; + +import de.blinkt.openvpn.core.NativeUtils; + +public class RSAHelper { + + public interface RSAHelperInterface { + RSAPrivateKey parseRsaKeyFromString(String rsaKeyString); + } + + public static class DefaultRSAHelper implements RSAHelperInterface { + + @Override + public RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { + RSAPrivateKey key; + try { + KeyFactory kf; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + kf = KeyFactory.getInstance("RSA", "BC"); + } else { + kf = KeyFactory.getInstance("RSA"); + } + rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", ""); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString)); + key = (RSAPrivateKey) kf.generatePrivate(keySpec); + } catch (InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (NullPointerException e) { + e.printStackTrace(); + return null; + } catch (NoSuchProviderException e) { + e.printStackTrace(); + return null; + } + + return key; + } + } + + private static RSAHelperInterface instance = new DefaultRSAHelper(); + + @VisibleForTesting + public RSAHelper(RSAHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("RSAHelper injected with RSAHelperInterface outside of an unit test"); + } + instance = helperInterface; + } + + public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) { + return instance.parseRsaKeyFromString(rsaKeyString); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index 6d5a406e..d21b6078 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -30,7 +30,7 @@ import static se.leap.bitmaskclient.base.models.Constants.REMOTE; import static se.leap.bitmaskclient.base.models.Constants.TCP; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.UDP; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 93648bb0..08067d38 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -45,7 +45,7 @@ import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString; +import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index 4ba04cfc..ce55d027 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -24,11 +24,11 @@ import java.util.UUID; import de.blinkt.openvpn.core.connection.Obfs4Connection; import de.blinkt.openvpn.core.connection.OpenvpnConnection; import se.leap.bitmaskclient.base.models.Transport; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; @RunWith(PowerMockRunner.class) -@PrepareForTest({UUID.class, ConfigHelper.ObfsVpnHelper.class}) +@PrepareForTest({UUID.class, ObfsVpnHelper.class}) public class VpnProfileTest { private static final String OPENVPNCONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mUseUdp\":false,\"mServerName\":\"openvpn.example.com\",\"mProxyType\":\"NONE\",\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"mConnectTimeout\":0,\"mProxyName\":\"proxy.example.com\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\",\"mServerPort\":\"1194\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":1,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}"; @@ -45,7 +45,7 @@ public class VpnProfileTest { @Before public void setup() { mockStatic(UUID.class); - mockStatic(ConfigHelper.ObfsVpnHelper.class); + mockStatic(ObfsVpnHelper.class); } @Test @@ -77,7 +77,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(false); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); @@ -96,7 +96,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4_obfsvpn() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); Transport.Options options = new Transport.Options("CERT", "1"); Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options); @@ -114,7 +114,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4_obfsvpn_kcp() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); Transport.Options options = new Transport.Options("CERT", "1"); @@ -133,7 +133,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop_kcp() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); @@ -154,7 +154,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop_portHopping() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); @@ -175,7 +175,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop() throws JSONException { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true); @@ -195,7 +195,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4() { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(false); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE); assertNotNull(mockVpnProfile); @@ -217,7 +217,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4_obfsvpn() { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN); assertNotNull(mockVpnProfile); @@ -236,7 +236,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4_obfsvpn_kcp() { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP); assertNotNull(mockVpnProfile); diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java index 40d9927b..b98f2423 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java @@ -4,30 +4,23 @@ import static junit.framework.Assert.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; /** * Created by cyberta on 12.02.18. */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ConfigHelper.ObfsVpnHelper.class}) public class ProviderTest { @Before public void setup() { - mockStatic(ConfigHelper.ObfsVpnHelper.class); - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(false); } @Test @@ -126,8 +119,6 @@ public class ProviderTest { @Test public void testSupportsPluggableTransports_Obfs4Kcp_noObsvpn_returnsFalse() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); - Provider p1 = TestSetupHelper.getProvider( "https://pt.demo.bitmask.net", null, @@ -142,7 +133,7 @@ public class ProviderTest { @Test public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper helper = MockHelper.mockObfsVpnHelper(true); Provider p1 = TestSetupHelper.getProvider( "https://pt.demo.bitmask.net", diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java index 3f011a65..1094705a 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -4,32 +4,18 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; +import static org.mockito.Mockito.when; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_HOP; import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN; import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION; -import static se.leap.bitmaskclient.testutils.MockHelper.mockRSAHelper; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; import android.content.Context; import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.util.Log; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.File; import java.util.HashMap; @@ -40,19 +26,21 @@ import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; import de.blinkt.openvpn.core.connection.Obfs4HopConnection; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.RSAHelper; import se.leap.bitmaskclient.testutils.MockHelper; +import se.leap.bitmaskclient.testutils.MockSharedPreferences; import se.leap.bitmaskclient.testutils.TestSetupHelper; /** * Created by cyberta on 03.10.17. */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({Log.class, TextUtils.class, PreferenceManager.class, ProviderObservable.class, ConfigHelper.RSAHelper.class, ConfigHelper.ObfsVpnHelper.class}) public class VpnConfigGeneratorTest { - @Mock(answer = Answers.RETURNS_DEEP_STUBS) Context context; + PreferenceHelper preferenceHelper; + private SharedPreferences sharedPreferences; private VpnConfigGenerator vpnConfigGenerator; private JSONObject generalConfig; @@ -139,7 +127,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + "cipher AES-128-CBC\n" + @@ -235,7 +223,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + "cipher AES-128-CBC\n" + @@ -330,7 +318,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "route 37.218.247.60 255.255.255.255 net_gateway\n"+ "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + @@ -426,7 +414,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "route 37.218.247.60 255.255.255.255 net_gateway\n"+ "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + @@ -523,7 +511,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + "cipher AES-128-CBC\n" + @@ -619,7 +607,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + "data-ciphers AES-128-CBC\n" + "cipher AES-128-CBC\n" + @@ -715,7 +703,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "remote-cert-tls server\n" + "data-ciphers AES-256-GCM:AES-128-GCM:AES-128-CBC\n" + "cipher AES-128-CBC\n" + @@ -813,7 +801,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "comp-lzo\n" + "nobind\n"+ "remote-cert-tls server\n" + @@ -915,7 +903,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "comp-lzo\n" + "nobind\n"+ "remote-cert-tls server\n" + @@ -1025,7 +1013,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "comp-lzo\n" + "nobind\n"+ "remote-cert-tls server\n" + @@ -1128,7 +1116,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "nobind\n"+ "remote-cert-tls server\n" + "data-ciphers AES-256-GCM:AES-128-CBC\n" + @@ -1228,7 +1216,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "route 192.81.208.164 255.255.255.255 net_gateway\n"+ "tun-mtu 48000\n"+ "nobind\n"+ @@ -1332,7 +1320,7 @@ public class VpnConfigGeneratorTest { "-----END CERTIFICATE-----\n" + "\n" + "management-external-key nopadding pkcs1 pss digest\n" + - "# crl-verify file missing in config profile\n" + + //"# crl-verify file missing in config profile\n" + "route 192.81.208.164 255.255.255.255 net_gateway\n"+ "route 192.81.208.165 255.255.255.255 net_gateway\n"+ "route 192.81.208.166 255.255.255.255 net_gateway\n"+ @@ -1364,17 +1352,13 @@ public class VpnConfigGeneratorTest { public void setUp() throws Exception { generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("general_configuration.json"))); secrets = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("secrets.json"))); - mockStatic(Log.class); context = MockHelper.mockContext(); - mockTextUtils(); - mockStatic(PreferenceManager.class); - MockHelper.mockProviderObservable(TestSetupHelper.getConfiguredProvider()); - MockHelper.mockRSAHelper(); - SharedPreferences preferences = mock(SharedPreferences.class, RETURNS_DEEP_STUBS); - when(PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(preferences); - when(preferences.getBoolean("usesystemproxy", true)).thenReturn(true); + + ProviderObservable providerObservable = MockHelper.mockProviderObservable(TestSetupHelper.getConfiguredProvider()); + RSAHelper rsaHelper = MockHelper.mockRSAHelper(); + sharedPreferences = new MockSharedPreferences(); + preferenceHelper = new PreferenceHelper(new MockSharedPreferences()); when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask")); - mockStatic(ConfigHelper.ObfsVpnHelper.class); } @Test @@ -1424,7 +1408,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_obfs4() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(false); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; @@ -1438,7 +1422,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; @@ -1744,7 +1728,7 @@ public class VpnConfigGeneratorTest { @Test public void testGetConfigFile_testHoppingPtPortHopping_decoupled() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1758,7 +1742,7 @@ public class VpnConfigGeneratorTest { @Test public void testGetConfigFile_testHoppingPtPortAndIPHopping_decoupled() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1771,7 +1755,7 @@ public class VpnConfigGeneratorTest { } @Test public void testGenerateVpnProfile_obfs4_decoupled() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(1); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1786,7 +1770,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_obfs4hop_decoupled() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1802,7 +1786,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_noExperimental_skipObfs4Hop() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1820,7 +1804,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_obfs4hop_onlyPortHopping_decoupled() throws Exception { - when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true); + ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index 01af9591..daa67282 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -72,7 +72,9 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.ConfigHelper; import se.leap.bitmaskclient.base.utils.FileHelper; import se.leap.bitmaskclient.base.utils.InputStreamHelper; +import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.RSAHelper; import se.leap.bitmaskclient.providersetup.connectivity.DnsResolver; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider; @@ -407,33 +409,66 @@ public class MockHelper { when(android.util.Base64.encodeToString(any(), anyInt())).thenAnswer(invocation -> Arrays.toString(Base64.getEncoder().encode((byte[]) invocation.getArguments()[0]))); } - public static void mockRSAHelper() { - mockStatic(ConfigHelper.RSAHelper.class); + public static RSAHelper mockRSAHelper() { + return new RSAHelper(rsaKeyString -> new RSAPrivateKey() { + @Override + public BigInteger getPrivateExponent() { + return BigInteger.TEN; + } + + @Override + public String getAlgorithm() { + return "RSA"; + } + + @Override + public String getFormat() { + return null; + } + + @Override + public byte[] getEncoded() { + return new byte[0]; + } + + @Override + public BigInteger getModulus() { + return BigInteger.ONE; + } + }); - when(ConfigHelper.RSAHelper.parseRsaKeyFromString(anyString())).thenReturn(new RSAPrivateKey() { + } + + public static ObfsVpnHelper mockObfsVpnHelper(boolean useObfsvpn) { + return new ObfsVpnHelper(new ObfsVpnHelper.ObfsVpnHelperInterface() { @Override - public BigInteger getPrivateExponent() { - return BigInteger.TEN; + public boolean useObfsVpn() { + return useObfsvpn; } @Override - public String getAlgorithm() { - return "RSA"; + public boolean hasObfuscationPinningDefaults() { + return false; } @Override - public String getFormat() { + public String obfsvpnIP() { return null; } @Override - public byte[] getEncoded() { - return new byte[0]; + public String obfsvpnPort() { + return null; } @Override - public BigInteger getModulus() { - return BigInteger.ONE; + public String obfsvpnCert() { + return null; + } + + @Override + public boolean useKcp() { + return false; } }); } @@ -583,11 +618,10 @@ public class MockHelper { } } - public static void mockProviderObservable(Provider provider) { + public static ProviderObservable mockProviderObservable(Provider provider) { ProviderObservable observable = ProviderObservable.getInstance(); observable.updateProvider(provider); - mockStatic(ProviderObservable.class); - when(ProviderObservable.getInstance()).thenAnswer((Answer) invocation -> observable); + return observable; } public static void mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException { -- cgit v1.2.3 From b85dc1b2ea68ab7ca7e11ab545bb88f4dbb59bdb Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 03:01:21 +0100 Subject: fix VpnCertificateValidatorTest, extract CertificateHelper (returns a fingerprint for a x509 cert) from ConfigHelper --- .../base/utils/CertificateHelper.java | 64 ++++++++++++++++++++++ .../providersetup/ProviderApiManagerBase.java | 2 +- .../eip/VpnCertificateValidatorTest.java | 21 +++---- .../leap/bitmaskclient/testutils/MockHelper.java | 14 +---- 4 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java new file mode 100644 index 00000000..11202734 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java @@ -0,0 +1,64 @@ +package se.leap.bitmaskclient.base.utils; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; + +import de.blinkt.openvpn.core.NativeUtils; + +public class CertificateHelper { + + public interface CertificateHelperInterface { + String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException; + + } + + public static class DefaultCertificateHelper implements CertificateHelperInterface { + + public String byteArrayToHex(byte[] input) { + int readBytes = input.length; + StringBuffer hexData = new StringBuffer(); + int onebyte; + for (int i = 0; i < readBytes; i++) { + onebyte = ((0x000000ff & input[i]) | 0xffffff00); + hexData.append(Integer.toHexString(onebyte).substring(6)); + } + return hexData.toString(); + } + + /** + * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate + * + * @param certificate + * @param encoding + * @return + * @throws NoSuchAlgorithmException + * @throws CertificateEncodingException + */ + @Override + public String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException { + byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded()); + return byteArrayToHex(byteArray); + } + } + + private static CertificateHelperInterface instance = new DefaultCertificateHelper(); + + @VisibleForTesting + public CertificateHelper(CertificateHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("CertificateHelper injected with CertificateHelperInterface outside of an unit test"); + } + instance = helperInterface; + } + + @NonNull + public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException { + return instance.getFingerprintFromCertificate(certificate, encoding); + } + +} diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 08067d38..05c5448a 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -47,7 +47,7 @@ import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate; +import static se.leap.bitmaskclient.base.utils.CertificateHelper.getFingerprintFromCertificate; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java index 1cb47f43..a951f144 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java @@ -2,25 +2,20 @@ package se.leap.bitmaskclient.eip; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.util.Calendar; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.CertificateHelper; import se.leap.bitmaskclient.testutils.TestCalendarProvider; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper; +import static se.leap.bitmaskclient.testutils.MockHelper.mockCertificateHelper; import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; -@RunWith(PowerMockRunner.class) -@PrepareForTest({ConfigHelper.class}) public class VpnCertificateValidatorTest { @Before @@ -31,7 +26,7 @@ public class VpnCertificateValidatorTest { public void test_isValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); Calendar c = new Calendar.Builder().setDate(2018, 1, 1).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertTrue( validator.isValid()); @@ -41,7 +36,7 @@ public class VpnCertificateValidatorTest { public void test_isValid_lessThan1day_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertFalse( validator.isValid()); @@ -51,7 +46,7 @@ public class VpnCertificateValidatorTest { public void test_isValid_multipleCerts_failIfOneExpires() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem")); Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertFalse(validator.isValid()); @@ -61,7 +56,7 @@ public class VpnCertificateValidatorTest { public void test_isValid_multipleCerts_allValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem")); Calendar c = new Calendar.Builder().setDate(2024, 3, 27).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertTrue(validator.isValid()); @@ -71,7 +66,7 @@ public class VpnCertificateValidatorTest { public void test_shouldBeUpdated_lessThan8days_returnTrue() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem")); Calendar c = new Calendar.Builder().setDate(2024, 3, 21).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertTrue(validator.shouldBeUpdated()); @@ -81,7 +76,7 @@ public class VpnCertificateValidatorTest { public void test_shouldBeUpdated_moreThan8days_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException { String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem")); Calendar c = new Calendar.Builder().setDate(2024, 3, 20).setCalendarType("gregorian").build(); - mockConfigHelper("falseFingerPrint"); + CertificateHelper helper = mockCertificateHelper("falseFingerPrint"); VpnCertificateValidator validator = new VpnCertificateValidator(cert); validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis())); assertFalse(validator.shouldBeUpdated()); diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index daa67282..869e3190 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -50,7 +50,6 @@ import java.math.BigInteger; import java.net.UnknownHostException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.Arrays; @@ -69,7 +68,7 @@ import okhttp3.OkHttpClient; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.CertificateHelper; import se.leap.bitmaskclient.base.utils.FileHelper; import se.leap.bitmaskclient.base.utils.InputStreamHelper; import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; @@ -473,15 +472,8 @@ public class MockHelper { }); } - public static void mockConfigHelper(String mockedFingerprint) throws CertificateEncodingException, NoSuchAlgorithmException { - mockStatic(ConfigHelper.class); - when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint); - when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod(); - when(ConfigHelper.parseX509CertificatesFromString(anyString())).thenCallRealMethod(); - when(ConfigHelper.getProviderFormattedString(any(Resources.class), anyInt())).thenCallRealMethod(); - when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod(); - when(ConfigHelper.isDefaultBitmask()).thenReturn(true); - when(ConfigHelper.getDomainFromMainURL(anyString())).thenCallRealMethod(); + public static CertificateHelper mockCertificateHelper(String mockedFingerprint) { + return new CertificateHelper((certificate, encoding) -> mockedFingerprint); } public static void mockPreferenceHelper(final Provider providerFromPrefs) { -- cgit v1.2.3 From b6c2c7c8ffbcf87110c33e179f1506285dffd949 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:17:16 +0100 Subject: rename ObfsvpnHelper to BuildConfigHelper, adding other BuildConfig properties there --- .../de/blinkt/openvpn/core/OpenVPNService.java | 2 +- .../openvpn/core/connection/Obfs4Connection.java | 2 +- .../base/fragments/NavigationDrawerFragment.java | 2 +- .../base/fragments/ObfuscationProxyDialog.java | 12 +-- .../base/fragments/SettingsFragment.java | 2 +- .../leap/bitmaskclient/base/models/Provider.java | 2 +- .../base/utils/BuildConfigHelper.java | 98 ++++++++++++++++++++++ .../bitmaskclient/base/utils/ConfigHelper.java | 6 -- .../bitmaskclient/base/utils/ObfsVpnHelper.java | 86 ------------------- .../bitmaskclient/base/utils/PreferenceHelper.java | 2 +- .../leap/bitmaskclient/eip/VpnConfigGenerator.java | 2 +- .../providersetup/SetupViewPagerAdapter.java | 2 +- .../providersetup/activities/SetupActivity.java | 2 +- .../fragments/CircumventionSetupFragment.java | 4 +- .../fragments/ConfigureProviderFragment.java | 2 +- .../providersetup/ProviderApiManager.java | 2 +- .../java/de/blinkt/openvpn/VpnProfileTest.java | 24 +++--- .../bitmaskclient/base/models/ProviderTest.java | 6 +- .../bitmaskclient/eip/VpnConfigGeneratorTest.java | 18 ++-- .../leap/bitmaskclient/testutils/MockHelper.java | 2 +- 20 files changed, 141 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java delete mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java index e311158c..5a618f10 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java +++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java @@ -9,7 +9,7 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED; import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT; import static de.blinkt.openvpn.core.NetworkSpace.IpAddress; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE; -import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn; import android.Manifest.permission; import android.app.Notification; diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java index 0abb5822..19ea180d 100644 --- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java +++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java @@ -1,6 +1,6 @@ package de.blinkt.openvpn.core.connection; -import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java index e74d70a2..16aea065 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java @@ -24,7 +24,7 @@ import static se.leap.bitmaskclient.base.models.Constants.ENABLE_DONATION; import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSaveBattery; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.saveBattery; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java index 635af701..7d12ca70 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java @@ -15,7 +15,7 @@ import androidx.appcompat.app.AppCompatDialogFragment; import androidx.appcompat.widget.AppCompatButton; import androidx.appcompat.widget.AppCompatEditText; -import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.views.IconSwitchEntry; import se.leap.bitmaskclient.databinding.DObfuscationProxyBinding; @@ -68,12 +68,12 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment { dismiss(); }); - useDefaultsButton.setVisibility(ObfsVpnHelper.hasObfuscationPinningDefaults() ? VISIBLE : GONE); + useDefaultsButton.setVisibility(BuildConfigHelper.hasObfuscationPinningDefaults() ? VISIBLE : GONE); useDefaultsButton.setOnClickListener(v -> { - ipField.setText(ObfsVpnHelper.obfsvpnIP()); - portField.setText(ObfsVpnHelper.obfsvpnPort()); - certificateField.setText(ObfsVpnHelper.obfsvpnCert()); - kcpSwitch.setChecked(ObfsVpnHelper.useKcp()); + ipField.setText(BuildConfigHelper.obfsvpnIP()); + portField.setText(BuildConfigHelper.obfsvpnPort()); + certificateField.setText(BuildConfigHelper.obfsvpnCert()); + kcpSwitch.setChecked(BuildConfigHelper.useKcp()); }); cancelButton.setOnClickListener(v -> { diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java index 77becc80..d7b62de2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java @@ -8,7 +8,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP; import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL; import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING; -import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn; import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java index af9122de..cb9bd520 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java @@ -28,7 +28,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGIS import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.TYPE; -import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn; import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java new file mode 100644 index 00000000..e1f65b5e --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java @@ -0,0 +1,98 @@ +package se.leap.bitmaskclient.base.utils; + +import static se.leap.bitmaskclient.base.models.Constants.DEFAULT_BITMASK; + +import androidx.annotation.VisibleForTesting; + +import de.blinkt.openvpn.core.NativeUtils; +import se.leap.bitmaskclient.BuildConfig; + +// ObfsVpnHelper class allows us to mock BuildConfig fields related to the pre-shipped circumvention settings +public class BuildConfigHelper { + + public interface BuildConfigHelperInterface { + boolean useObfsVpn(); + boolean hasObfuscationPinningDefaults(); + String obfsvpnIP(); + String obfsvpnPort(); + String obfsvpnCert(); + boolean useKcp(); + boolean isDefaultBitmask(); + } + + public static class DefaultBuildConfigHelper implements BuildConfigHelperInterface { + @Override + public boolean useObfsVpn() { + return BuildConfig.use_obfsvpn; + } + + @Override + public boolean hasObfuscationPinningDefaults() { + return BuildConfig.obfsvpn_ip != null && + BuildConfig.obfsvpn_port != null && + BuildConfig.obfsvpn_cert != null && + !BuildConfig.obfsvpn_ip.isEmpty() && + !BuildConfig.obfsvpn_port.isEmpty() && + !BuildConfig.obfsvpn_cert.isEmpty(); + } + + @Override + public String obfsvpnIP() { + return BuildConfig.obfsvpn_ip; + } + + @Override + public String obfsvpnPort() { + return BuildConfig.obfsvpn_port; + } + + @Override + public String obfsvpnCert() { + return BuildConfig.obfsvpn_cert; + } + + @Override + public boolean useKcp() { + return BuildConfig.obfsvpn_use_kcp; + } + + @Override + public boolean isDefaultBitmask() { + return BuildConfig.FLAVOR_branding.equals(DEFAULT_BITMASK); + } + } + + private static BuildConfigHelperInterface instance = new DefaultBuildConfigHelper(); + + @VisibleForTesting + public BuildConfigHelper(BuildConfigHelperInterface helperInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("ObfsVpnHelper injected with ObfsVpnHelperInterface outside of an unit test"); + } + instance = helperInterface; + } + + public static boolean useObfsVpn() { + return instance.useObfsVpn(); + } + + public static boolean hasObfuscationPinningDefaults() { + return instance.hasObfuscationPinningDefaults(); + } + public static String obfsvpnIP() { + return instance.obfsvpnIP(); + } + public static String obfsvpnPort() { + return instance.obfsvpnPort(); + } + public static String obfsvpnCert() { + return instance.obfsvpnCert(); + } + public static boolean useKcp() { + return instance.useKcp(); + } + + public static boolean isDefaultBitmask() { + return instance.isDefaultBitmask(); + } +} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index a06d85be..a7916399 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -16,8 +16,6 @@ */ package se.leap.bitmaskclient.base.utils; -import static se.leap.bitmaskclient.base.models.Constants.DEFAULT_BITMASK; - import android.app.PendingIntent; import android.content.Context; import android.content.res.Resources; @@ -159,10 +157,6 @@ public class ConfigHelper { } } - public static boolean isDefaultBitmask() { - return BuildConfig.FLAVOR_branding.equals(DEFAULT_BITMASK); - } - public static boolean preferAnonymousUsage() { return BuildConfig.priotize_anonymous_usage; } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java deleted file mode 100644 index 054c85b3..00000000 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ObfsVpnHelper.java +++ /dev/null @@ -1,86 +0,0 @@ -package se.leap.bitmaskclient.base.utils; - -import androidx.annotation.VisibleForTesting; - -import de.blinkt.openvpn.core.NativeUtils; -import se.leap.bitmaskclient.BuildConfig; - -// ObfsVpnHelper class allows us to mock BuildConfig fields related to the pre-shipped circumvention settings -public class ObfsVpnHelper { - - public interface ObfsVpnHelperInterface { - boolean useObfsVpn(); - boolean hasObfuscationPinningDefaults(); - String obfsvpnIP(); - String obfsvpnPort(); - String obfsvpnCert(); - boolean useKcp(); - } - - public static class DefaultObfsVpnHelper implements ObfsVpnHelperInterface { - @Override - public boolean useObfsVpn() { - return BuildConfig.use_obfsvpn; - } - - @Override - public boolean hasObfuscationPinningDefaults() { - return BuildConfig.obfsvpn_ip != null && - BuildConfig.obfsvpn_port != null && - BuildConfig.obfsvpn_cert != null && - !BuildConfig.obfsvpn_ip.isEmpty() && - !BuildConfig.obfsvpn_port.isEmpty() && - !BuildConfig.obfsvpn_cert.isEmpty(); - } - - @Override - public String obfsvpnIP() { - return BuildConfig.obfsvpn_ip; - } - - @Override - public String obfsvpnPort() { - return BuildConfig.obfsvpn_port; - } - - @Override - public String obfsvpnCert() { - return BuildConfig.obfsvpn_cert; - } - - @Override - public boolean useKcp() { - return BuildConfig.obfsvpn_use_kcp; - } - } - - private static ObfsVpnHelperInterface instance = new DefaultObfsVpnHelper(); - - @VisibleForTesting - public ObfsVpnHelper(ObfsVpnHelperInterface helperInterface) { - if (!NativeUtils.isUnitTest()) { - throw new IllegalStateException("ObfsVpnHelper injected with ObfsVpnHelperInterface outside of an unit test"); - } - instance = helperInterface; - } - - public static boolean useObfsVpn() { - return instance.useObfsVpn(); - } - - public static boolean hasObfuscationPinningDefaults() { - return instance.hasObfuscationPinningDefaults(); - } - public static String obfsvpnIP() { - return instance.obfsvpnIP(); - } - public static String obfsvpnPort() { - return instance.obfsvpnPort(); - } - public static String obfsvpnCert() { - return instance.obfsvpnCert(); - } - public static boolean useKcp() { - return instance.useKcp(); - } -} diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java index a04c3686..2420a797 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java @@ -470,7 +470,7 @@ public class PreferenceHelper { } public static boolean useObfuscationPinning() { - return ObfsVpnHelper.useObfsVpn() && + return BuildConfigHelper.useObfsVpn() && getUseBridges() && getBoolean(USE_OBFUSCATION_PINNING, false) && !TextUtils.isEmpty(getObfuscationPinningIP()) && diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java index d21b6078..4c8fa797 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java @@ -30,7 +30,7 @@ import static se.leap.bitmaskclient.base.models.Constants.REMOTE; import static se.leap.bitmaskclient.base.models.Constants.TCP; import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT; import static se.leap.bitmaskclient.base.models.Constants.UDP; -import static se.leap.bitmaskclient.base.utils.ObfsVpnHelper.useObfsVpn; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP; import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java index 00630f39..fb190dc2 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java @@ -1,6 +1,6 @@ package se.leap.bitmaskclient.providersetup; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CIRCUMVENTION_SETUP_FRAGMENT; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.NOTIFICATION_PERMISSON_EDUCATIONAL_FRAGMENT; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java index dd735f84..9235daad 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java @@ -3,7 +3,7 @@ package se.leap.bitmaskclient.providersetup.activities; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static androidx.appcompat.app.ActionBar.DISPLAY_SHOW_CUSTOM; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT; import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF; diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java index 34a93319..cdb8bd78 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java @@ -1,8 +1,7 @@ package se.leap.bitmaskclient.providersetup.fragments; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; -import android.content.Context; import android.graphics.Typeface; import android.os.Bundle; import android.view.LayoutInflater; @@ -17,7 +16,6 @@ import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.databinding.FCircumventionSetupBinding; import se.leap.bitmaskclient.providersetup.ProviderManager; import se.leap.bitmaskclient.providersetup.activities.CancelCallback; -import se.leap.bitmaskclient.providersetup.activities.SetupActivityCallback; public class CircumventionSetupFragment extends BaseSetupFragment implements CancelCallback { diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index 9e8589ae..877628fb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -9,7 +9,7 @@ import static se.leap.bitmaskclient.R.string.description_configure_provider_circ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake; import static se.leap.bitmaskclient.base.utils.ViewHelper.animateContainerVisibility; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE; diff --git a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java index b08f27ef..1f4e7e49 100644 --- a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java +++ b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java @@ -30,7 +30,7 @@ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString; -import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; +import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING; import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON; diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java index ce55d027..ad42ffde 100644 --- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java +++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java @@ -24,11 +24,11 @@ import java.util.UUID; import de.blinkt.openvpn.core.connection.Obfs4Connection; import de.blinkt.openvpn.core.connection.OpenvpnConnection; import se.leap.bitmaskclient.base.models.Transport; -import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.pluggableTransports.Obfs4Options; @RunWith(PowerMockRunner.class) -@PrepareForTest({UUID.class, ObfsVpnHelper.class}) +@PrepareForTest({UUID.class, BuildConfigHelper.class}) public class VpnProfileTest { private static final String OPENVPNCONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mUseUdp\":false,\"mServerName\":\"openvpn.example.com\",\"mProxyType\":\"NONE\",\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"mConnectTimeout\":0,\"mProxyName\":\"proxy.example.com\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\",\"mServerPort\":\"1194\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":1,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}"; @@ -45,7 +45,7 @@ public class VpnProfileTest { @Before public void setup() { mockStatic(UUID.class); - mockStatic(ObfsVpnHelper.class); + mockStatic(BuildConfigHelper.class); } @Test @@ -77,7 +77,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(false); + when(BuildConfigHelper.useObfsVpn()).thenReturn(false); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); @@ -96,7 +96,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4_obfsvpn() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); Transport.Options options = new Transport.Options("CERT", "1"); Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options); @@ -114,7 +114,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4_obfsvpn_kcp() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4); Transport.Options options = new Transport.Options("CERT", "1"); @@ -133,7 +133,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop_kcp() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); @@ -154,7 +154,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop_portHopping() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); @@ -175,7 +175,7 @@ public class VpnProfileTest { @Test public void toJson_obfs4hop() throws JSONException { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP); Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true); @@ -195,7 +195,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4() { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(false); + when(BuildConfigHelper.useObfsVpn()).thenReturn(false); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE); assertNotNull(mockVpnProfile); @@ -217,7 +217,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4_obfsvpn() { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN); assertNotNull(mockVpnProfile); @@ -236,7 +236,7 @@ public class VpnProfileTest { @Test public void fromJson_obfs4_obfsvpn_kcp() { - when(ObfsVpnHelper.useObfsVpn()).thenReturn(true); + when(BuildConfigHelper.useObfsVpn()).thenReturn(true); VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP); assertNotNull(mockVpnProfile); diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java index b98f2423..4fcc6bac 100644 --- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java @@ -8,7 +8,7 @@ import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; -import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.testutils.MockHelper; import se.leap.bitmaskclient.testutils.TestSetupHelper; @@ -20,7 +20,7 @@ public class ProviderTest { @Before public void setup() { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(false); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(false); } @Test @@ -133,7 +133,7 @@ public class ProviderTest { @Test public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception { - ObfsVpnHelper helper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper helper = MockHelper.mockBuildConfigHelper(true); Provider p1 = TestSetupHelper.getProvider( "https://pt.demo.bitmask.net", diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java index 1094705a..4b9e5d65 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java @@ -26,7 +26,7 @@ import de.blinkt.openvpn.core.connection.Connection; import de.blinkt.openvpn.core.connection.Obfs4Connection; import de.blinkt.openvpn.core.connection.Obfs4HopConnection; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.utils.RSAHelper; import se.leap.bitmaskclient.testutils.MockHelper; @@ -1408,7 +1408,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_obfs4() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(false); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(false); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; @@ -1422,7 +1422,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); configuration.apiVersion = 3; @@ -1728,7 +1728,7 @@ public class VpnConfigGeneratorTest { @Test public void testGetConfigFile_testHoppingPtPortHopping_decoupled() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1742,7 +1742,7 @@ public class VpnConfigGeneratorTest { @Test public void testGetConfigFile_testHoppingPtPortAndIPHopping_decoupled() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1755,7 +1755,7 @@ public class VpnConfigGeneratorTest { } @Test public void testGenerateVpnProfile_obfs4_decoupled() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(1); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1770,7 +1770,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_obfs4hop_decoupled() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1786,7 +1786,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_noExperimental_skipObfs4Hop() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); @@ -1804,7 +1804,7 @@ public class VpnConfigGeneratorTest { @Test public void testGenerateVpnProfile_obfs4hop_onlyPortHopping_decoupled() throws Exception { - ObfsVpnHelper obfsVpnHelper = MockHelper.mockObfsVpnHelper(true); + BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true); gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2); generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION); VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration(); diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index 869e3190..33e2c056 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -71,7 +71,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.CertificateHelper; import se.leap.bitmaskclient.base.utils.FileHelper; import se.leap.bitmaskclient.base.utils.InputStreamHelper; -import se.leap.bitmaskclient.base.utils.ObfsVpnHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.utils.RSAHelper; import se.leap.bitmaskclient.providersetup.connectivity.DnsResolver; -- cgit v1.2.3 From ecceffd429390d36ed7eeb9b47fde8c0e2a300ae Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:17:41 +0100 Subject: update client cert for test --- app/src/test/resources/v4/riseup.net.cert | 89 ++++++++++++++----------------- 1 file changed, 39 insertions(+), 50 deletions(-) diff --git a/app/src/test/resources/v4/riseup.net.cert b/app/src/test/resources/v4/riseup.net.cert index 711a7067..49b4f576 100644 --- a/app/src/test/resources/v4/riseup.net.cert +++ b/app/src/test/resources/v4/riseup.net.cert @@ -1,54 +1,43 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAyRUoZOO7jQb5aIyJA5I8om6WO2vQoNDywCsuVF42TiddPIQt -/JF4excbozFu+IZJLd20n3+zzUR0SHw30mLYAjnVmRaf8XD91xirlc4LWhhXqHPb -+WuvgBeALnhDdCZr1rKbnfiwYYeGRkozafSL61AW3LtuaA/uW/MWfrlLYry0TG/q -KFYt9VNg72vKE/+PQ44bsLpUBB9OsYBSG15dC4ohp7tN59P7GZ0F5tKOGdnMJyL1 -0M9bEEISS5rlgpmVZ5+V10q83qu4fSNyGqsPVdiI0JhsKYSlyqMxTLLWPs95LaaR -U0uGVt0cq3MUO+vN9gzczS1MJS1DulxMjMnMMQIDAQABAoIBAQCLbGkqsyC64ygR -zse9uyrhsW3nW5U3vElk50vjYcOjovWp3TiJlFAGgPo/yCnaljmtXLk9km0YGavL -Cp4l+TUvLeyljiNuZFsNRmTKpSgH2zMEcPkIUxtH5IOTNP4ITg+duQ/fk6ywoyh+ -GjrV76MIkOqZODiQXON3y/BAA7h6h4QFQ7z7EAZAKCIdYEtP52JM7EtUd8enre4P -XaL2wan/YX65xWPftOqcPeWLp4tSz5zIPphJzqbZZt9fOeKd4KrpwxK70vV23UgM -Kkr1SK/CQZq+remzJzjLBSrcrzL251Oliy/72HnoURUWVSe0PZjqZiZx7ui6VZwA -d0Sez79BAoGBAPDmMjMVtW0ixn4HPRkkBTwZBURVLIf2BNVyAj6d7DbhULEfv9Oj -KKVn48kxo2shoXXT6UoArVIKov/jz2TNQjt5V1zqRqXq3jhPm9fcRV4pserbEHJp -SNBlKYGpJRncxTr7hkLB5Bp4CaPeXXm7KdPObDDGLI+Rfb9qCt7uCgnJAoGBANWw -AoPaPBsUH8tVMRfGAjX7YgeG5Kacb10FiO+eQL48DVxvMYjl+sYBoPrOuJk2gDEC -J45NMgDGIaI4sLcrpCgKyeJjMgT4fFqK2BLDBBrx8n/2u6mWw8CEQJnGgTEPv0oV -ZqhF2pBa8/WC8w6+/cQ6r50GPvfY8yWziXLy+eMpAoGAady/MrPXhp5BnCCSOPob -Us2sAttrNlRmy2XOlrXPmE5rp2rMYbTRp95/u2qU5f9hdOYrHtotUGBcQRdbjHCn -KnuoaKyLX15XSWeylKm30imAhjS+hYi+9tV95/zs0PCzu7fMyIlsNDWMBvcxHM2j -E/Eimkx8SJsnJ3byUAVLZAECgYEAhAOBCkRA7dm46r1u3ukNZJwxK8VCbUwn4KgS -uTZjeSNQfdKUH6c1Di7jbQ9ZLA5nk99o4JkAU0oUbUvooMDtYW+I2bu+oyOAb89n -PfANETh4QGYF+feSZ9VMs7PXDKBV5UbjbQH6zUPjg8Gqt2l3DUvUQoYhUK1PSfNo -7wL9LkECgYB1QgADq+e28riLsclkRkfnUqrOIc80jVmZLszflnQVyQEanWc1QgPo -FGvH+PGGiFme+3qMIK01JsiDng7rUTnbHOgfLMifG0ph65pFcp2fnAEr3DzNuk+m -HsdPcNGqU0Jt9r/7jAqKluXd6pNa4Ve0KaAW0a7J+9s5kWIlQNwM3w== +MIIEowIBAAKCAQEAudf0Quu9UehPF+oi8ZwBf7OBE1oj/SoY5tDkkWHcShxVfw26 +Cwnw+dAViCXS0zgTtx1qIN9bQgMEheanc2iuP1emF0G18Yi9L54soh6O+zR5M6od +tpWLOxYMqYCJPoAK+GBxW95bobLUjk1EJigyrrtORprgO2wi8TznZ+shdO6AlvUr +iUrvbmdMMIxPk3wvSX1f+2IbVlRf+2ovcRHMZqJ+plQiZEuRWkMqGiwiKwNFmIfZ +lIwkPIzly06RGfRML2cMS8ewM0ryAsgjH6O9KyujtW+T8B03Es1xHowxw9yIeiAr +sgWbDwawWtfzGUlLkupoice7huBMYe1vBCdglQIDAQABAoIBAHTe6A9FrPNbgpHp +fjwu/YpPWnbPEx7cYHiXGYaL4jsBAos6GKtkfxS61S+fiaum8k8PwnQVwpAK0cdb +PCcJx7qx5hNuEXtpoH/Xmv4A9a3oW+gvrSvrc3me7iuSV7zkTQHRtLgvZ7SSf7VV +xeuxD95ukFU6hJUZ9gd7Y5MofQvI9iFn5V+w7wPlmqkZM/whxrPQwTHGvPsXWaEu +5nUuGW3y1WvvhwNBjrnPP1A/UZ06hhMvAUGlvFRxBm4ADoSDBfjZdP5ZjOPMP1Y0 +D5FGHboueYzFDBQEXpxw1nvjuXzlt6SjA91gRIMJQAwsK5MxntQJXrOX7JEl6BgI +aGgVfEECgYEAyo1KFgVoleyyZ9aBzlXs7g+WKRrD8jxbloQiaamLpxTOgvBDU4Wq +KI+zcEJ5GOrAOe6qEfCXn7REefZZr2z7hOs/oj/zsAGHgRDpFkZ3USA5LsruL917 +4EAZH+VJUvN8H8GgU2N4sj0sDk+yaLZo9dhYilo78cDUX4BoGtdaEykCgYEA6uH9 +O3UcgnKVghTrpuLca8ov1S4QH8XamD4rMIeHpSn/l32JCBjtjL9LQYqve+lcxyC8 +Je07ZzznhEYdQ/ASMVjBOVMVNq+AaYm1X2DSYvje1IDFFz4Ya/luHy3xThhSqnkm +jtjxAICScuboUmAC+E9rpnmlJ6W06DwxYlWJm40CgYBSCcfoA2jI0IWx6P/KQqMk +CMwY+e5DPo8Z94q4oSMfGR5LimS6f3jb1Ngor8O8g9g3nqLjgT7oQGs7uru4gbud +qmqrnJtmvjfT3rWJgCDzismeWjL+0AZMXanPcV6xakzrz9DP9Yn9Jymg4kawgrEg +Ye/6mXGOCTv7Mlb4CCFDgQKBgQDYdDh00aDbShMjlHnyCoCMyP+5mkB7t06SHECa +8Vr8xy5mgeaFUsufeC43EUJUk6LPUwhwfyXOJt9IE4EmuZdaaGtwk3MqOSPCnohJ +hCV91dErzhtTJwNEhdGI5ELK8DlGJm11GNFH4DSVtNuGBjrWcAJJoTKkzd1gYxAz +iZZNhQKBgB78oOOWX6yS+UDnJzyuojZbl9YeXXRjPXqUWqjdp+Qagn6KFYIBRdFL +S8vHtJpshsP0qAAEo7P+KueMQKFTRsU6CWZN68omB3K+LNGod+PT4yfM4PqC4MlN +kis7OehmiRA7HUPmV9YRL3JsH0W9q0PxCtm8c6gLfcp3OZ93yNSJ -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIEmzCCAoOgAwIBAgIQHybvsqrpyjLQlh3K46x6ozANBgkqhkiG9w0BAQsFADB1 -MRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlz -ZXVwLm5ldDE8MDoGA1UEAwwzUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EgKGNsaWVu -dCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTIzMDkyMzAwMDAwMFoXDTIzMTIyMzAw -MDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZHZiYW45cXBsZXUxcGl0b3lhZnZi -OGFkNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkVKGTju40G+WiM -iQOSPKJuljtr0KDQ8sArLlReNk4nXTyELfyReHsXG6MxbviGSS3dtJ9/s81EdEh8 -N9Ji2AI51ZkWn/Fw/dcYq5XOC1oYV6hz2/lrr4AXgC54Q3Qma9aym534sGGHhkZK -M2n0i+tQFty7bmgP7lvzFn65S2K8tExv6ihWLfVTYO9ryhP/j0OOG7C6VAQfTrGA -UhteXQuKIae7TefT+xmdBebSjhnZzCci9dDPWxBCEkua5YKZlWeflddKvN6ruH0j -chqrD1XYiNCYbCmEpcqjMUyy1j7PeS2mkVNLhlbdHKtzFDvrzfYM3M0tTCUtQ7pc -TIzJzDECAwEAAaNvMG0wHQYDVR0OBBYEFEzWvshjpfxlaIp1lqAzun0SJsUbMAsG -A1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1Ud -IwQYMBaAFBf0G9XlKgEBTWuiXTYKKQmWZYBGMA0GCSqGSIb3DQEBCwUAA4ICAQAR -ZzHo/Sn14yISzWnlvmQA7kqICm5j0mENib2BhaM7b6kmZRzvt9s9BwD83DYQwfCV -VBeGx1YkXCHsUEVcqJCXF/of9CsUUvUhMMp+fd068OdrJuPVxglOCmY4zMIfSlQW -YLvBalER1ilm8IuVrSVwBHP1vpnKj/g6W8gufZn06Tq7/c6X+QOrjebijJ4WuRtm -V3mqEoMcBOEaHk9T7Lxe0yixrssUm13yJmCz3R5x6jRDtaVnQ95VwgBqnrJpXPgb -sE2GrR5E74e+PbNQPfJJSobtYpJifp97wOpHFy2z5EcHyRuLdD3PX3it9mz5b0FJ -GwMb+YmgIWI8oAngWj8KiELDTWpKH6DdrQBljARHwjjBAG+rSYyWwkKKO2Nk8nsz -cnBlYY2rqLJ3gXc9oNDFWlh96K9rGy7bGcY0ALSxrLWFrpODQIKerjSNcsOhXp4D -6OS603EPgFKSo1bca9wKkTIjJIsIXjTfJEKXR22huhJhkJsTIg5z02N2dBJfmNkz -nffWtSk7tu8+CNEGruWfQ2TzYyknS5D0E2Eba07W/39gs6uXncrXwIidGg/G8D/h -mpw7L/+f41za+mlykz2ivoUJsDb7TsQeW4O/Oj5wnekyAnJKHUJy9O8y4vpqJkUn -+xLUpVnNpH6lAzAV3xODOVg2pTbwnkCnBkCDUx3Eww== +MIICeTCCAh6gAwIBAgIRAIbLa6Ts1lih8SKdunuWB+gwCgYIKoZIzj0EAwIwMzEx +MC8GA1UEAwwoTEVBUCBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkh +KTAeFw0yNDAxMTgxOTAzNTZaFw0yNDAyMjIxOTAzNTZaMBQxEjAQBgNVBAMTCVVO +TElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnX9ELrvVHo +TxfqIvGcAX+zgRNaI/0qGObQ5JFh3EocVX8NugsJ8PnQFYgl0tM4E7cdaiDfW0ID +BIXmp3Norj9XphdBtfGIvS+eLKIejvs0eTOqHbaVizsWDKmAiT6ACvhgcVveW6Gy +1I5NRCYoMq67Tkaa4DtsIvE852frIXTugJb1K4lK725nTDCMT5N8L0l9X/tiG1ZU +X/tqL3ERzGaifqZUImRLkVpDKhosIisDRZiH2ZSMJDyM5ctOkRn0TC9nDEvHsDNK +8gLIIx+jvSsro7Vvk/AdNxLNcR6MMcPciHogK7IFmw8GsFrX8xlJS5LqaInHu4bg +TGHtbwQnYJUCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsG +AQUFBwMCMB0GA1UdDgQWBBSRZk4gUAUtg/gnCBt2OfkYak38mTAfBgNVHSMEGDAW +gBR9SmLY/ytJxHm2orHcjj5jB1yo/jAKBggqhkjOPQQDAgNJADBGAiEA+7MB5Thd +Xpb9vnNIpX10TahuOb9N4IQcpO6ai8pOqmwCIQD5zpNjB16pyKg/ctOpVjzKStQD +kKiTsZU2DSNaeSapoA== -----END CERTIFICATE----- \ No newline at end of file -- cgit v1.2.3 From 8b3a140602108f66d5183623a7788dc35c121e59 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:19:22 +0100 Subject: improve MockSharedPreferences, adding implementations for put/get Long and put/get StringSet --- .../bitmaskclient/testutils/MockSharedPreferences.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java index 4fabc2c0..30ced782 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java @@ -33,6 +33,8 @@ public class MockSharedPreferences implements SharedPreferences { HashMap mockedStringPrefs = new HashMap<>(); HashMap mockedIntPrefs = new HashMap<>(); HashMap mockedBooleanPrefs = new HashMap<>(); + HashMap mockedLongPrefs = new HashMap<>(); + HashMap> mockedStringSetPrefs = new HashMap<>(); @Override public Map getAll() { @@ -49,7 +51,7 @@ public class MockSharedPreferences implements SharedPreferences { @Nullable @Override public Set getStringSet(String key, @Nullable Set defValues) { - return new HashSet<>(); + return mockedStringSetPrefs.getOrDefault(key, new HashSet<>()); } @Override @@ -60,7 +62,7 @@ public class MockSharedPreferences implements SharedPreferences { @Override public long getLong(String key, long defValue) { - return 0; + return mockedLongPrefs.getOrDefault(key, defValue); } @Override @@ -78,7 +80,9 @@ public class MockSharedPreferences implements SharedPreferences { public boolean contains(String key) { return mockedStringPrefs.containsKey(key) || mockedBooleanPrefs.containsKey(key) || - mockedIntPrefs.containsKey(key); + mockedIntPrefs.containsKey(key) || + mockedStringSetPrefs.containsKey(key) || + mockedLongPrefs.containsKey(key); } @Override @@ -87,6 +91,8 @@ public class MockSharedPreferences implements SharedPreferences { private HashMap tempStrings = new HashMap<>(mockedStringPrefs); private HashMap tempIntegers = new HashMap<>(mockedIntPrefs); private HashMap tempBoolean = new HashMap<>(mockedBooleanPrefs); + private HashMap tempLongs = new HashMap<>(mockedLongPrefs); + private HashMap> tempStringSets = new HashMap<>(mockedStringSetPrefs); @Override public Editor putString(String key, @Nullable String value) { @@ -96,7 +102,8 @@ public class MockSharedPreferences implements SharedPreferences { @Override public Editor putStringSet(String key, @Nullable Set values) { - return null; + tempStringSets.put(key, values); + return this; } @Override @@ -107,7 +114,8 @@ public class MockSharedPreferences implements SharedPreferences { @Override public Editor putLong(String key, long value) { - return null; + tempLongs.put(key, value); + return this; } @Override -- cgit v1.2.3 From 2bcbfb1d537fe8f616adc252fac7c3e8673ebaa7 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:20:35 +0100 Subject: improve TimezoneHelper, don't allow to set the TimezoneInterface outside of UnitTests --- .../main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java index c543368d..63b12fd3 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java @@ -4,6 +4,8 @@ import androidx.annotation.VisibleForTesting; import java.util.Calendar; +import de.blinkt.openvpn.core.NativeUtils; + public class TimezoneHelper { public interface TimezoneInterface { @@ -14,6 +16,9 @@ public class TimezoneHelper { @VisibleForTesting public TimezoneHelper(TimezoneInterface timezoneInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("TimezoneHelper injected with timezoneInterface outside of an unit test"); + } instance = timezoneInterface; } @@ -33,7 +38,7 @@ public class TimezoneHelper { return get().getCurrentTimezone(); } - public static class DefaultTimezoneHelper implements TimezoneInterface { + private static class DefaultTimezoneHelper implements TimezoneInterface { @Override public int getCurrentTimezone() { return Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000; -- cgit v1.2.3 From a8cbf6ea3c794e6cad818979a9c2d4ac95fb7a0f Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:24:23 +0100 Subject: remove methods from ConfigHelper after moving functionality to CertificateHelper --- .../bitmaskclient/base/utils/ConfigHelper.java | 29 ---------------------- 1 file changed, 29 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index a7916399..bb9d1196 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -34,9 +34,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -123,32 +120,6 @@ public class ConfigHelper { return null; } - private static String byteArrayToHex(byte[] input) { - int readBytes = input.length; - StringBuffer hexData = new StringBuffer(); - int onebyte; - for (int i = 0; i < readBytes; i++) { - onebyte = ((0x000000ff & input[i]) | 0xffffff00); - hexData.append(Integer.toHexString(onebyte).substring(6)); - } - return hexData.toString(); - } - - /** - * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate - * - * @param certificate - * @param encoding - * @return - * @throws NoSuchAlgorithmException - * @throws CertificateEncodingException - */ - @NonNull - public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException /*, UnsupportedEncodingException*/ { - byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded()); - return byteArrayToHex(byteArray); - } - public static void ensureNotOnMainThread(@NonNull Context context) throws IllegalStateException{ Looper looper = Looper.myLooper(); if (looper != null && looper == context.getMainLooper()) { -- cgit v1.2.3 From be8535ff9ab0968187acd008b8c01e1b8d9c336e Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:27:59 +0100 Subject: ProviderSetupObservable: replace deprecated Observer class with PropertyChangeListener --- .../providersetup/ProviderSetupObservable.java | 46 ++++++++++++++++------ .../fragments/ConfigureProviderFragment.java | 10 ++--- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java index 90a32fea..c882b0bb 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java @@ -16,14 +16,19 @@ package se.leap.bitmaskclient.providersetup; * along with this program. If not, see . */ -import android.os.Handler; -import android.os.Looper; - -import java.util.Observable; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import se.leap.bitmaskclient.base.utils.HandlerProvider; +import se.leap.bitmaskclient.base.utils.HandlerProvider.HandlerInterface; import se.leap.bitmaskclient.tor.TorStatusObservable; -public class ProviderSetupObservable extends Observable { +/** + * This Observable tracks the progress of a started provider bootstrapping attempt. + * Each required API call us taken into account as well as the state of tor's bootstrapping in case + * it is used for censorship circumvention. + */ +public class ProviderSetupObservable { private static final String TAG = ProviderSetupObservable.class.getSimpleName(); @@ -36,9 +41,28 @@ public class ProviderSetupObservable extends Observable { public static final int DOWNLOADED_VPN_CERTIFICATE = 100; private static ProviderSetupObservable instance; - private final Handler handler = new Handler(Looper.getMainLooper()); + private final PropertyChangeSupport changeSupport; + public static final String PROPERTY_CHANGE = "ProviderSetupObservable"; + private final HandlerInterface handler; private long lastUpdate = 0; + + + private ProviderSetupObservable() { + handler = HandlerProvider.get(); + changeSupport = new PropertyChangeSupport(this); + + } + + public void addObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.addPropertyChangeListener(propertyChangeListener); + } + + public void deleteObserver(PropertyChangeListener propertyChangeListener) { + changeSupport.removePropertyChangeListener(propertyChangeListener); + } + + public static ProviderSetupObservable getInstance() { if (instance == null) { instance = new ProviderSetupObservable(); @@ -58,8 +82,8 @@ public class ProviderSetupObservable extends Observable { getInstance().progress = progress; } - getInstance().setChanged(); - getInstance().notifyObservers(); + getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance()); + }, now - getInstance().lastUpdate < 500L ? 500L : 0L); getInstance().lastUpdate = System.currentTimeMillis() + 500; } @@ -72,8 +96,7 @@ public class ProviderSetupObservable extends Observable { getInstance().handler.postDelayed(() -> { getInstance().progress = (TorStatusObservable.getBootstrapProgress()) / 2; - getInstance().setChanged(); - getInstance().notifyObservers(); + getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance()); }, now - getInstance().lastUpdate < 500L ? 500L : 0); getInstance().lastUpdate = System.currentTimeMillis() + 500; } @@ -84,8 +107,7 @@ public class ProviderSetupObservable extends Observable { public static void reset() { getInstance().progress = 0; - getInstance().setChanged(); - getInstance().notifyObservers(); + getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance()); } public static void cancel() { diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java index 877628fb..8477c302 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java @@ -42,9 +42,9 @@ import androidx.core.content.res.ResourcesCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.List; -import java.util.Observable; -import java.util.Observer; import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; @@ -57,7 +57,7 @@ import se.leap.bitmaskclient.providersetup.TorLogAdapter; import se.leap.bitmaskclient.providersetup.activities.CancelCallback; import se.leap.bitmaskclient.tor.TorStatusObservable; -public class ConfigureProviderFragment extends BaseSetupFragment implements Observer, CancelCallback, EipSetupListener { +public class ConfigureProviderFragment extends BaseSetupFragment implements PropertyChangeListener, CancelCallback, EipSetupListener { private static final String TAG = ConfigureProviderFragment.class.getSimpleName(); @@ -158,8 +158,8 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse } @Override - public void update(Observable o, Object arg) { - if (o instanceof ProviderSetupObservable) { + public void propertyChange(PropertyChangeEvent evt) { + if (ProviderSetupObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) { Activity activity = getActivity(); if (activity == null || binding == null) { return; -- cgit v1.2.3 From 9bba7b29a416b2617af033a778ef13a512024502 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:37:53 +0100 Subject: refactor ProviderApiConnector, allow to inject dummy implementations for unit tests --- .../providersetup/ProviderApiConnector.java | 134 +++++++++++++-------- .../providersetup/ProviderApiManagerBase.java | 13 +- 2 files changed, 94 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java index 35ad9cd2..cc875c79 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java @@ -18,6 +18,8 @@ package se.leap.bitmaskclient.providersetup; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + import android.util.Pair; import java.io.IOException; @@ -26,6 +28,9 @@ import java.util.List; import java.util.Locale; import java.util.Scanner; +import javax.net.ssl.SSLHandshakeException; + +import de.blinkt.openvpn.core.NativeUtils; import de.blinkt.openvpn.core.VpnStatus; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -39,72 +44,103 @@ import okhttp3.Response; public class ProviderApiConnector { - private static final MediaType JSON - = MediaType.parse("application/json; charset=utf-8"); + public interface ProviderApiConnectorInterface { + boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException; + boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException; + String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException; + + } + public static class DefaultProviderApiCpnnector implements ProviderApiConnectorInterface { + + @Override + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) { + try { + Request.Builder requestBuilder = new Request.Builder() + .url(deleteUrl) + .delete(); + Request request = requestBuilder.build(); + + Response response = okHttpClient.newCall(request).execute(); + //response code 401: already logged out + if (response.isSuccessful() || response.code() == 401) { + return true; + } + } catch (IOException | RuntimeException e) { + return false; + } + + return false; + } - public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) { - try { + @Override + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { Request.Builder requestBuilder = new Request.Builder() - .url(deleteUrl) - .delete(); + .url(url) + .method("GET", null); Request request = requestBuilder.build(); Response response = okHttpClient.newCall(request).execute(); - //response code 401: already logged out - if (response.isSuccessful() || response.code() == 401) { - return true; + if (!response.isSuccessful()) { + VpnStatus.logWarning("[API] API request failed canConnect(): " + url); } - } catch (IOException | RuntimeException e) { - return false; + return response.isSuccessful(); } - return false; - } + @Override + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null; + Request.Builder requestBuilder = new Request.Builder() + .url(url) + .method(requestMethod, jsonBody); + for (Pair keyValPair : headerArgs) { + requestBuilder.addHeader(keyValPair.first, keyValPair.second); + } - public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { - Request.Builder requestBuilder = new Request.Builder() - .url(url) - .method("GET", null); - Request request = requestBuilder.build(); - - Response response = okHttpClient.newCall(request).execute(); - if (!response.isSuccessful()) { - VpnStatus.logWarning("[API] API request failed canConnect(): " + url); + //TODO: move to getHeaderArgs()? + String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry(); + requestBuilder.addHeader("Accept-Language", locale); + Request request = requestBuilder.build(); + + Response response = okHttpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + VpnStatus.logWarning("[API] API request failed: " + url); + } + + if (response.body() != null) { + InputStream inputStream = response.body().byteStream(); + Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"); + if (scanner.hasNext()) { + String result = scanner.next(); + response.body().close(); + return result; + } + } + return null; } - return response.isSuccessful(); + } + private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + private static ProviderApiConnectorInterface instance = new DefaultProviderApiCpnnector(); + @VisibleForTesting + public ProviderApiConnector(ProviderApiConnectorInterface connectorInterface) { + if (!NativeUtils.isUnitTest()) { + throw new IllegalStateException("ProviderApiConnector injected with ProviderApiConnectorInterface outside of an unit test"); + } + instance = connectorInterface; } - public static String requestStringFromServer(@NonNull String url, @NonNull String request_method, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { - RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null; - Request.Builder requestBuilder = new Request.Builder() - .url(url) - .method(request_method, jsonBody); - for (Pair keyValPair : headerArgs) { - requestBuilder.addHeader(keyValPair.first, keyValPair.second); - } + public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + return instance.delete(okHttpClient, deleteUrl); + } - //TODO: move to getHeaderArgs()? - String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry(); - requestBuilder.addHeader("Accept-Language", locale); - Request request = requestBuilder.build(); + public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return instance.canConnect(okHttpClient, url); - Response response = okHttpClient.newCall(request).execute(); - if (!response.isSuccessful()) { - VpnStatus.logWarning("[API] API request failed: " + url); - } + } - if (response.body() != null) { - InputStream inputStream = response.body().byteStream(); - Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"); - if (scanner.hasNext()) { - String result = scanner.next(); - response.body().close(); - return result; - } - } - return null; + public static String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + return instance.requestStringFromServer(url, requestMethod, jsonString, headerArgs, okHttpClient); } } diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java index 05c5448a..1f737b0c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -45,6 +45,7 @@ import static se.leap.bitmaskclient.base.models.Provider.CA_CERT; import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP; import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.getTorTimeout; import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString; import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL; import static se.leap.bitmaskclient.base.utils.CertificateHelper.getFingerprintFromCertificate; @@ -380,7 +381,7 @@ public abstract class ProviderApiManagerBase { if (TorStatusObservable.getStatus() == ON) { return; } - TorStatusObservable.waitUntil(this::isTorOnOrCancelled, 180); + TorStatusObservable.waitUntil(this::isTorOnOrCancelled, getTorTimeout()); } private boolean isTorOnOrCancelled() { @@ -1138,9 +1139,13 @@ public abstract class ProviderApiManagerBase { String deleteUrl = provider.getApiUrlWithVersion() + "/logout"; - if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) { - LeapSRPSession.setToken(""); - return true; + try { + if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) { + LeapSRPSession.setToken(""); + return true; + } + } catch (IOException e) { + // eat me } return false; } -- cgit v1.2.3 From 6f7b3bbf255b0be4d5ff1bd994aad0d61b8cca8d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 25 Jan 2024 23:55:52 +0100 Subject: fix ProviderApiManagerTest, sneaking in some missing changes from previous commits as well --- app/externalDir | 1 + .../bitmaskclient/base/utils/ConfigHelper.java | 8 + .../bitmaskclient/base/utils/HandlerProvider.java | 38 ++ app/src/test/java/android/content/Intent.java | 61 +++ app/src/test/java/android/os/Bundle.java | 101 ++++ app/src/test/java/android/util/Base64.java | 19 + .../bitmaskclient/eip/ProviderApiManagerTest.java | 529 ++++++++++----------- .../BackendMockResponses/BackendMockProvider.java | 82 ++-- .../BackendMockResponses/BaseBackendResponse.java | 75 --- ...rivceJsonInvalidCertificateBackendResponse.java | 94 ---- ...rviceJsonInvalidCertificateBackendResponse.java | 66 +++ .../GeoIpServiceIsDownBackendResponse.java | 85 ++-- ...viceNotReachableTorFallbackBackendResponse.java | 81 ++-- .../MisconfiguredProviderBackendResponse.java | 85 ++-- .../NoErrorBackendResponse.java | 85 ++-- .../NoErrorBackendResponseAPIv4.java | 92 ++-- .../TorFallbackBackendResponse.java | 131 +++-- .../UpdatedCertificateBackendResponse.java | 95 ++-- .../leap/bitmaskclient/testutils/MockHelper.java | 508 +++++--------------- 19 files changed, 922 insertions(+), 1314 deletions(-) create mode 100644 app/externalDir create mode 100644 app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java create mode 100644 app/src/test/java/android/content/Intent.java create mode 100644 app/src/test/java/android/os/Bundle.java create mode 100644 app/src/test/java/android/util/Base64.java delete mode 100644 app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java delete mode 100644 app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java create mode 100644 app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java diff --git a/app/externalDir b/app/externalDir new file mode 100644 index 00000000..72acfd13 --- /dev/null +++ b/app/externalDir @@ -0,0 +1 @@ +{"domain":"","main_url":"https://anotherprovider.org"} \ No newline at end of file diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index bb9d1196..71fe8eba 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.blinkt.openvpn.core.NativeUtils; import okhttp3.internal.publicsuffix.PublicSuffixDatabase; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.R; @@ -207,4 +208,11 @@ public class ConfigHelper { } return flags; } + + public static int getTorTimeout() { + if (NativeUtils.isUnitTest()) { + return 1; + } + return 180; + } } diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java new file mode 100644 index 00000000..d9198ab7 --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java @@ -0,0 +1,38 @@ +package se.leap.bitmaskclient.base.utils; + +import android.os.Handler; +import android.os.Looper; + +public class HandlerProvider { + + + public interface HandlerInterface { + void postDelayed(Runnable r, long delay); + } + + + private static HandlerInterface instance; + + public HandlerProvider(HandlerInterface handlerInterface) { + instance = handlerInterface; + } + public static HandlerInterface get() { + if (instance == null) { + instance = new DefaultHandler(); + } + return instance; + } + + public static class DefaultHandler implements HandlerInterface { + Handler handler; + + public DefaultHandler() { + this.handler = new Handler(Looper.getMainLooper()); + } + @Override + public void postDelayed(Runnable r, long delay) { + this.handler.postDelayed(r, delay); + } + } +} + diff --git a/app/src/test/java/android/content/Intent.java b/app/src/test/java/android/content/Intent.java new file mode 100644 index 00000000..92211558 --- /dev/null +++ b/app/src/test/java/android/content/Intent.java @@ -0,0 +1,61 @@ +package android.content; + +import android.os.Bundle; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Intent { + final String[] action = new String[1]; + final Map fakeExtras = new HashMap<>(); + final List categories = new ArrayList<>(); + + public Intent setAction(String action) { + this.action[0] = action; + return this; + } + + public String getAction() { + return action[0]; + } + + public Intent putExtra(String key, Bundle bundle) { + fakeExtras.put(key, bundle); + return this; + } + + public Bundle getBundleExtra(String key) { + Object o = fakeExtras.get(key); + if (o != null) { + return (Bundle) o; + } + return null; + } + + public Intent putExtra(String key, Parcelable extra) { + fakeExtras.put(key, extra); + return this; + } + + public Parcelable getParcelableExtra(String key) { + Object o = fakeExtras.get(key); + if (o != null) { + return (Parcelable) o; + } + return null; + } + + public Intent addCategory(String key) { + categories.add(key); + return this; + } + + public Set getCategories() { + return new HashSet<>(categories); + } +} diff --git a/app/src/test/java/android/os/Bundle.java b/app/src/test/java/android/os/Bundle.java new file mode 100644 index 00000000..ea869cb2 --- /dev/null +++ b/app/src/test/java/android/os/Bundle.java @@ -0,0 +1,101 @@ +package android.os; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class Bundle { + + /** An unmodifiable {@code Bundle} that is always {@link #isEmpty() empty}. */ + public static final Bundle EMPTY; + + /** + * Special extras used to denote extras have been stripped off. + * @hide + */ + public static final Bundle STRIPPED; + + static { + EMPTY = new Bundle(); + + STRIPPED = new Bundle(); + STRIPPED.putInt("STRIPPED", 1); + } + + final Map fakeBooleanBundle = new HashMap<>(); + final Map fakeStringBundle = new HashMap<>(); + final Map fakeIntBundle = new HashMap<>(); + final Map fakeParcelableBundle = new HashMap<>(); + + + public void putString(String key, String value) { + fakeStringBundle.put(key, value); + } + + public String getString(String key) { + return fakeStringBundle.get(key); + } + + public void putBoolean(String key, boolean value) { + fakeBooleanBundle.put(key, value); + } + + public boolean getBoolean(String key) { + return fakeBooleanBundle.getOrDefault(key, false); + } + + public void putInt(String key, int value) { + fakeIntBundle.put(key, value); + } + + public int getInt(String key) { + return fakeIntBundle.getOrDefault(key, 0); + } + + public void putParcelable(String key, Parcelable value) { + fakeParcelableBundle.put(key, value); + } + + public Parcelable getParcelable(String key) { + return fakeParcelableBundle.get(key); + } + + public Object get(String key) { + if (fakeBooleanBundle.containsKey(key)) { + return fakeBooleanBundle.get(key); + } else if (fakeIntBundle.containsKey(key)) { + return fakeIntBundle.get(key); + } else if (fakeStringBundle.containsKey(key)) { + return fakeStringBundle.get(key); + } else { + return fakeParcelableBundle.get(key); + } + } + + public Set keySet() { + //this whole approach as a drawback: + //you should not add the same keys for values of different types + HashSet keys = new HashSet(); + keys.addAll(fakeBooleanBundle.keySet()); + keys.addAll(fakeIntBundle.keySet()); + keys.addAll(fakeStringBundle.keySet()); + keys.addAll(fakeParcelableBundle.keySet()); + return keys; + } + + public boolean containsKey(String key) { + return fakeBooleanBundle.containsKey(key) || + fakeStringBundle.containsKey(key) || + fakeIntBundle.containsKey(key) || + fakeParcelableBundle.containsKey(key); + } + + public void remove(String key) { + fakeBooleanBundle.remove(key); + fakeIntBundle.remove(key); + fakeParcelableBundle.remove(key); + fakeStringBundle.remove(key); + } + +} diff --git a/app/src/test/java/android/util/Base64.java b/app/src/test/java/android/util/Base64.java new file mode 100644 index 00000000..da40e9c4 --- /dev/null +++ b/app/src/test/java/android/util/Base64.java @@ -0,0 +1,19 @@ +package android.util; + +import java.util.Arrays; + +public class Base64 { + + /** + * Base64-encode the given data and return a newly allocated + * String with the result. + * + * @param input the data to encode + * @param flags controls certain features of the encoded output. + * Passing {@code DEFAULT} results in output that + * adheres to RFC 2045. + */ + public static String encodeToString(byte[] input, int flags) { + return Arrays.toString(java.util.Base64.getEncoder().encode(input)); + } +} diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java index 4af0d072..c6e548ce 100644 --- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java @@ -19,12 +19,11 @@ package se.leap.bitmaskclient.eip; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mockStatic; import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY; import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY; +import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES; +import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS; @@ -44,27 +43,25 @@ import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockPr import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK; import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR; import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR_API_V4; -import static se.leap.bitmaskclient.testutils.MockHelper.mockBase64; -import static se.leap.bitmaskclient.testutils.MockHelper.mockBundle; +import static se.leap.bitmaskclient.testutils.MockHelper.mockBuildConfigHelper; +import static se.leap.bitmaskclient.testutils.MockHelper.mockCertificateHelper; import static se.leap.bitmaskclient.testutils.MockHelper.mockClientGenerator; -import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper; -import static se.leap.bitmaskclient.testutils.MockHelper.mockIntent; +import static se.leap.bitmaskclient.testutils.MockHelper.mockContext; import static se.leap.bitmaskclient.testutils.MockHelper.mockPreferenceHelper; import static se.leap.bitmaskclient.testutils.MockHelper.mockProviderApiConnector; import static se.leap.bitmaskclient.testutils.MockHelper.mockRSAHelper; import static se.leap.bitmaskclient.testutils.MockHelper.mockResources; import static se.leap.bitmaskclient.testutils.MockHelper.mockResultReceiver; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils; -import static se.leap.bitmaskclient.testutils.MockHelper.mockTorStatusObservable; import static se.leap.bitmaskclient.testutils.TestSetupHelper.getConfiguredProvider; import static se.leap.bitmaskclient.testutils.TestSetupHelper.getConfiguredProviderAPIv4; import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; -import android.text.TextUtils; import androidx.annotation.Nullable; @@ -72,12 +69,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; import java.io.IOException; import java.security.NoSuchAlgorithmException; @@ -86,13 +77,16 @@ import java.util.concurrent.TimeoutException; import se.leap.bitmaskclient.BuildConfig; import se.leap.bitmaskclient.base.models.Provider; -import se.leap.bitmaskclient.base.utils.ConfigHelper; +import se.leap.bitmaskclient.base.utils.BuildConfigHelper; +import se.leap.bitmaskclient.base.utils.CertificateHelper; +import se.leap.bitmaskclient.base.utils.HandlerProvider; import se.leap.bitmaskclient.base.utils.PreferenceHelper; +import se.leap.bitmaskclient.base.utils.RSAHelper; import se.leap.bitmaskclient.providersetup.ProviderAPI; import se.leap.bitmaskclient.providersetup.ProviderApiConnector; import se.leap.bitmaskclient.providersetup.ProviderApiManager; import se.leap.bitmaskclient.providersetup.ProviderApiManagerBase; -import se.leap.bitmaskclient.providersetup.ProviderSetupObservable; +import se.leap.bitmaskclient.testutils.MockSharedPreferences; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -100,13 +94,9 @@ import se.leap.bitmaskclient.tor.TorStatusObservable; * Created by cyberta on 04.01.18. */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ProviderApiManager.class, TextUtils.class, ConfigHelper.RSAHelper.class, ConfigHelper.class, ProviderApiConnector.class, PreferenceHelper.class, TorStatusObservable.class, android.util.Base64.class, ProviderSetupObservable.class}) public class ProviderApiManagerTest { - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Resources mockResources; - @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mockContext; private ProviderApiManager providerApiManager; @@ -114,12 +104,22 @@ public class ProviderApiManagerTest { static class TestProviderApiServiceCallback implements ProviderApiManagerBase.ProviderApiServiceCallback { Throwable startTorServiceException; boolean hasNetworkConnection; + boolean torTimeout; + TorStatusObservable torStatusObservable; + TestProviderApiServiceCallback() { this(null, true); } TestProviderApiServiceCallback(@Nullable Throwable startTorServiceException, boolean hasNetworkConnection) { this.startTorServiceException = startTorServiceException; this.hasNetworkConnection = hasNetworkConnection; + this.torStatusObservable = TorStatusObservable.getInstance(); + } + + TestProviderApiServiceCallback(boolean torTimeout, boolean hasNetworkConnection) { + this.hasNetworkConnection = hasNetworkConnection; + this.torStatusObservable = TorStatusObservable.getInstance(); + this.torTimeout = torTimeout; } @Override @@ -136,6 +136,13 @@ public class ProviderApiManagerTest { throw (IllegalStateException) startTorServiceException; } } + if (!torTimeout) { + try { + TorStatusObservable.updateState(mockContext(), TorStatusObservable.TorStatus.ON.toString()); + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException(e); + } + } return true; } @@ -145,7 +152,7 @@ public class ProviderApiManagerTest { @Override public int getTorHttpTunnelPort() { - return 0; + return 8118; } @Override @@ -157,31 +164,32 @@ public class ProviderApiManagerTest { @Before public void setUp() throws Exception { - - Bundle bundle = mockBundle(); - PowerMockito.whenNew(Bundle.class).withAnyArguments().thenReturn(bundle); - Intent intent = mockIntent(); - PowerMockito.whenNew(Intent.class).withAnyArguments().thenReturn(intent); - mockTextUtils(); + mockContext = mockContext(); mockResources = mockResources(getClass().getClassLoader().getResourceAsStream("error_messages.json")); + HandlerProvider handlerProvider = new HandlerProvider((r, delay) -> new Thread(r).start()); + BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, true); + TorStatusObservable torStatusObservable = TorStatusObservable.getInstance(); + TorStatusObservable.setProxyPort(-1); + TorStatusObservable.setLastError(null); + TorStatusObservable.updateState(mockContext, TorStatusObservable.TorStatus.OFF.toString()); } @Test public void test_handleIntentSetupProvider_noProviderMainURL() throws IOException, JSONException { Provider provider = new Provider(""); - mockPreferenceHelper(provider); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errors\":\"It doesn't seem to be a Bitmask provider.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @@ -189,47 +197,42 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_happyPath_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector providerApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); - + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @Test public void test_handleIntentSetupProvider_happyPath_no_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @@ -237,21 +240,20 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_happyPath_storedProviderAndCAFromPreviousSetup() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = new Provider("https://riseup.net"); - mockPreferenceHelper(getConfiguredProvider()); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(getConfiguredProvider()); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -261,21 +263,19 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_preseededProviderAndCA_failedCAPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); - mockProviderApiConnector(NO_ERROR); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -284,24 +284,21 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_no_preseededProviderAndCA_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = new Provider("https://riseup.net"); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); - mockProviderApiConnector(NO_ERROR); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -311,21 +308,20 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = new Provider("https://riseup.net"); mockPreferenceHelper(getConfiguredProvider()); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495"); - mockProviderApiConnector(NO_ERROR); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -335,21 +331,20 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getProvider(null ,null, null, null, "outdated_cert.pem", null, null, null); - mockPreferenceHelper(provider); - mockProviderApiConnector(NO_ERROR); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -358,22 +353,21 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getProvider(null, null, null, null, "outdated_cert.pem", "riseup.net.json", null, null); - mockPreferenceHelper(provider); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); PreferenceHelper.getEipDefinitionFromPreferences(); - mockProviderApiConnector(NO_ERROR); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); - + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -382,22 +376,21 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_preseededProviderAndCA_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -406,22 +399,21 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = new Provider("https://riseup.net"); - mockPreferenceHelper(getConfiguredProvider()); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE); + PreferenceHelper preferenceHelper = mockPreferenceHelper(getConfiguredProvider()); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiManager.handleIntent(providerApiCommand); @@ -431,55 +423,54 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_preseededProviderAndCA_failedConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER); - mockStatic(ProviderSetupObservable.class); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errors\":\"There was an error configuring Bitmask with your chosen provider.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } + @Test public void test_handleIntentSetupProvider_preseededCustomProviderAndCA_failedConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { if ("insecure".equals(BuildConfig.FLAVOR_implementation )) { return; } Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); - mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - when(ConfigHelper.isDefaultBitmask()).thenReturn(false); - mockStatic(ProviderSetupObservable.class); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, false); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errors\":\"There was an error configuring RiseupVPN.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @@ -488,23 +479,22 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getProvider(null, null, null, null, null, "riseup_net_outdated_config.json", null, null); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @@ -516,29 +506,26 @@ public class ProviderApiManagerTest { } Provider provider = new Provider("https://riseup.net"); - mockPreferenceHelper(provider); - - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putParcelable(PROVIDER_KEY, provider); expectedResult.putString(ERRORS, "This is not a trusted Bitmask provider."); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } - @Test public void test_handleIntentGetGeoip_happyPath() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException { if ("insecure".equals(BuildConfig.FLAVOR_implementation )) { @@ -546,22 +533,22 @@ public class ProviderApiManagerTest { } Provider inputProvider = getConfiguredProvider(); - mockPreferenceHelper(inputProvider); inputProvider.setGeoIpJson(new JSONObject()); + PreferenceHelper preferenceHelper = mockPreferenceHelper(inputProvider); Provider expectedProvider = getConfiguredProvider(); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, expectedProvider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON); - Bundle extrasBundle = mockBundle(); + Bundle extrasBundle = new Bundle(); extrasBundle.putBoolean(EIP_ACTION_START, true); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, inputProvider); @@ -579,24 +566,24 @@ public class ProviderApiManagerTest { } Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getUseSnowflake()).thenReturn(false); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); - + SharedPreferences mockSharedPref = new MockSharedPreferences(); + mockSharedPref.edit(). + putBoolean(USE_BRIDGES, false). + putBoolean(USE_SNOWFLAKE, false).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, mockSharedPref); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON); - Bundle extrasBundle = mockBundle(); + Bundle extrasBundle = new Bundle(); extrasBundle.putBoolean(EIP_ACTION_START, true); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); @@ -612,22 +599,21 @@ public class ProviderApiManagerTest { return; } - mockTorStatusObservable(null); Provider provider = getConfiguredProvider(); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON); - Bundle extrasBundle = mockBundle(); + Bundle extrasBundle = new Bundle(); extrasBundle.putBoolean(EIP_ACTION_START, true); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); @@ -647,20 +633,20 @@ public class ProviderApiManagerTest { Provider provider = getConfiguredProvider(); provider.setLastGeoIpUpdate(System.currentTimeMillis()); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON); - Bundle extrasBundle = mockBundle(); + Bundle extrasBundle = new Bundle(); extrasBundle.putBoolean(EIP_ACTION_START, true); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); @@ -678,20 +664,20 @@ public class ProviderApiManagerTest { Provider provider = getConfiguredProvider(); provider.setGeoipUrl(null); provider.setGeoIpJson(new JSONObject()); - mockPreferenceHelper(provider); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(EIP_ACTION_START, true); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON); - Bundle extrasBundle = mockBundle(); + Bundle extrasBundle = new Bundle(); extrasBundle.putBoolean(EIP_ACTION_START, true); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); @@ -703,22 +689,20 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_APIv4_happyPath() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR_API_V4); - mockStatic(ProviderSetupObservable.class); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Bundle expectedResult = mockBundle(); - + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, true); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } @@ -727,41 +711,35 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_TorFallback_SecondTryHappyPath() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(false); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); // getUseSnowflake() defaults to true if not set - mockStatic(ProviderSetupObservable.class); - - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(null); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); - assertEquals(8118, TorStatusObservable.getProxyPort()); + assertNotEquals(-1, TorStatusObservable.getProxyPort()); } @Test public void test_handleIntentSetupProvider_TorFallbackStartServiceException_SecondTryFailed() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(new IllegalStateException("Tor service start not failed."), true)); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(null); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -770,17 +748,16 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_TorFallbackTimeoutException_SecondTryFailed() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); - providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); + providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(true, true)); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(new TimeoutException("Tor took too long to start.")); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -790,23 +767,19 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_TorBridgesPreferenceEnabled_Success() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR_API_V4); - mockStatic(ProviderSetupObservable.class); - - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(null); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(8118, TorStatusObservable.getProxyPort()); @@ -816,23 +789,19 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_TorBridgesDisabled_TorNotStarted() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR_API_V4); - - mockStatic(ProviderSetupObservable.class); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getUseSnowflake()).thenReturn(false); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, false).putBoolean(USE_SNOWFLAKE, false).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(new TimeoutException("This timeout exception is never thrown")); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -841,47 +810,40 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesNotConfigured_TorStartedAndSuccess() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(false); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockRSAHelper(); - mockBase64(); - mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + RSAHelper rsaHelper = mockRSAHelper(); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(null); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); - assertNotEquals(-1, TorStatusObservable.getProxyPort()); + assertEquals(8118, TorStatusObservable.getProxyPort()); } @Test public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesFalse_TorNotStartedAndFailure() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockBase64(); - mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); - when(PreferenceHelper.getUseBridges()).thenReturn(false); - when(PreferenceHelper.getUseSnowflake()).thenReturn(false); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, false).putBoolean(USE_SNOWFLAKE, false).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(new TimeoutException("This timeout exception is never thrown")); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -891,23 +853,20 @@ public class ProviderApiManagerTest { public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesTrue_TorStartedAndSuccess() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockBase64(); - mockRSAHelper(); - mockProviderApiConnector(NO_ERROR_API_V4); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + RSAHelper rsaHelper = mockRSAHelper(); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(null); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertNotEquals(-1, TorStatusObservable.getProxyPort()); @@ -917,27 +876,24 @@ public class ProviderApiManagerTest { public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesTrue_TorException_Failure() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); - mockPreferenceHelper(provider); - mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockBase64(); - mockProviderApiConnector(NO_ERROR_API_V4); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); - providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); + providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(new IllegalStateException("Nothing works always."), true)); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"initalAction\":\"ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(TOR_EXCEPTION, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(new InterruptedException("Tor thread was interrupted.")); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -946,25 +902,23 @@ public class ProviderApiManagerTest { @Test public void test_handleIntentSetupProvider_TorBridgesPreferencesEnabledTimeout_TimeoutError() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException { Provider provider = getConfiguredProviderAPIv4(); + SharedPreferences sharedPreferences = new MockSharedPreferences(); + sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit(); + PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4); - mockPreferenceHelper(provider); - when(PreferenceHelper.getUseBridges()).thenReturn(true); - when(PreferenceHelper.getUseSnowflake()).thenReturn(true); - when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true); - - providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback()); + providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(true, true)); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_TOR_TIMEOUT\",\"initalAction\":\"setUpProvider\",\"errors\":\"Starting bridges failed. Do you want to retry or continue with an unobfuscated secure connection to configure Bitmask?\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.putExtra(PROVIDER_KEY, provider); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(TOR_TIMEOUT, expectedResult)); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); - mockTorStatusObservable(new TimeoutException("Tor took too long to start.")); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); assertEquals(-1, TorStatusObservable.getProxyPort()); @@ -974,22 +928,21 @@ public class ProviderApiManagerTest { public void test_handleIntentSetupProvider_noNetwork_NetworkError() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException { Provider provider = getConfiguredProvider(); - mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); - mockProviderApiConnector(NO_ERROR); + CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494"); + ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR); providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(null, false)); - Bundle expectedResult = mockBundle(); + Bundle expectedResult = new Bundle(); expectedResult.putBoolean(BROADCAST_RESULT_KEY, false); expectedResult.putString(ERRORS, "{\"errors\":\"Bitmask has no internet connection. Please check your WiFi and cellular data settings.\"}"); expectedResult.putParcelable(PROVIDER_KEY, provider); - Intent providerApiCommand = mockIntent(); + Intent providerApiCommand = new Intent(); providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER); providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(MISSING_NETWORK_CONNECTION, expectedResult)); providerApiCommand.putExtra(PROVIDER_KEY, provider); - providerApiCommand.putExtra(PARAMETERS, mockBundle()); + providerApiCommand.putExtra(PARAMETERS, new Bundle()); providerApiManager.handleIntent(providerApiCommand); } - } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java index 280aa5a1..4ef41619 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java @@ -18,6 +18,8 @@ package se.leap.bitmaskclient.testutils.BackendMockResponses; import java.io.IOException; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; + /** * Created by cyberta on 10.01.18. */ @@ -43,67 +45,43 @@ public class BackendMockProvider { ERROR_PAYLOAD_MISSING, // => IllegalArgumentException ERROR_TLS_1_2_NOT_SUPPORTED, // => UnknownServiceException ERROR_UNKNOWN_IO_EXCEPTION, // => IOException - ERROR_NO_ACCESS, ERROR_INVALID_SESSION_TOKEN, ERROR_NO_CONNECTION, - ERROR_WRONG_SRP_CREDENTIALS, NO_ERROR_API_V4, ERROR_DNS_RESUOLUTION_TOR_FALLBACK } - public static void provideBackendResponsesFor(TestBackendErrorCase errorCase) throws IOException { + public static ProviderApiConnector.ProviderApiConnectorInterface provideBackendResponsesFor(TestBackendErrorCase errorCase) throws IOException { switch (errorCase) { + case NO_ERROR -> { + return new NoErrorBackendResponse(); + } + case NO_ERROR_API_V4 -> { + return new NoErrorBackendResponseAPIv4(); + } + case ERROR_CASE_UPDATED_CERTIFICATE -> { + return new UpdatedCertificateBackendResponse(); + } + case ERROR_CASE_MICONFIGURED_PROVIDER -> { + return new MisconfiguredProviderBackendResponse(); + } + case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID -> { + return new EipServiceJsonInvalidCertificateBackendResponse(); + } + case ERROR_GEOIP_SERVICE_IS_DOWN -> { + return new GeoIpServiceIsDownBackendResponse(); + } + case ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK -> { + return new GeoIpServiceNotReachableTorFallbackBackendResponse(); + } + case ERROR_DNS_RESUOLUTION_TOR_FALLBACK -> { + return new TorFallbackBackendResponse(); + } - case NO_ERROR: - new NoErrorBackendResponse(); - break; - case NO_ERROR_API_V4: - new NoErrorBackendResponseAPIv4(); - break; - case ERROR_CASE_UPDATED_CERTIFICATE: - new UpdatedCertificateBackendResponse(); - break; - case ERROR_CASE_MICONFIGURED_PROVIDER: - new MisconfiguredProviderBackendResponse(); - break; - case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID: - new EipSerivceJsonInvalidCertificateBackendResponse(); - break; - case ERROR_GEOIP_SERVICE_IS_DOWN: - new GeoIpServiceIsDownBackendResponse(); - break; - case ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK: - new GeoIpServiceNotReachableTorFallbackBackendResponse(); - case ERROR_DNS_RESUOLUTION_TOR_FALLBACK: - new TorFallbackBackendResponse(); - break; - case ERROR_NO_RESPONSE_BODY: - break; - case ERROR_DNS_RESOLUTION_ERROR: - break; - case ERROR_SOCKET_TIMEOUT: - break; - case ERROR_WRONG_PROTOCOL: - break; - case ERROR_CERTIFICATE_INVALID: - break; - case ERROR_WRONG_PORT: - break; - case ERROR_PAYLOAD_MISSING: - break; - case ERROR_TLS_1_2_NOT_SUPPORTED: - break; - case ERROR_UNKNOWN_IO_EXCEPTION: - break; - case ERROR_NO_ACCESS: - break; - case ERROR_INVALID_SESSION_TOKEN: - break; - case ERROR_NO_CONNECTION: - break; - case ERROR_WRONG_SRP_CREDENTIALS: - break; + default -> { + return new NoErrorBackendResponse(); + } } } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java deleted file mode 100644 index 9a538d3c..00000000 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient.testutils.BackendMockResponses; - -import android.util.Pair; - -import org.mockito.ArgumentMatchers; -import org.mockito.Mockito; -import org.mockito.stubbing.Answer; - -import java.io.IOException; - -import okhttp3.OkHttpClient; -import se.leap.bitmaskclient.providersetup.ProviderApiConnector; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.nullable; -import static org.powermock.api.mockito.PowerMockito.mockStatic; - -/** - * Created by cyberta on 10.01.18. - */ - -public abstract class BaseBackendResponse { - - private Answer answerRequestStringFromServer; - private Answer answerCanConnect; - private Answer answerDelete; - - public BaseBackendResponse() throws IOException { - mockStatic(ProviderApiConnector.class); - this.answerRequestStringFromServer = getAnswerForRequestStringFromServer(); - this.answerCanConnect = getAnswerForCanConnect(); - this.answerDelete = getAnswerForDelete(); - - responseOnRequestStringFromServer(); - responseOnCanConnect(); - responseOnDelete(); - - } - - public abstract Answer getAnswerForRequestStringFromServer(); - public abstract Answer getAnswerForCanConnect(); - public abstract Answer getAnswerForDelete(); - - - public void responseOnRequestStringFromServer() throws IOException, RuntimeException { - Mockito.when(ProviderApiConnector.requestStringFromServer(anyString(), anyString(), nullable(String.class), ArgumentMatchers.>anyList(), any(OkHttpClient.class))). - thenAnswer(answerRequestStringFromServer); - } - - public void responseOnCanConnect() throws IOException, RuntimeException { - Mockito.when(ProviderApiConnector.canConnect(any(OkHttpClient.class), anyString())).thenAnswer(answerCanConnect); - } - - public void responseOnDelete() throws IOException, RuntimeException { - Mockito.when(ProviderApiConnector.delete(any(OkHttpClient.class), anyString())).thenAnswer(answerDelete); - } - -} diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java deleted file mode 100644 index 7c2d49cc..00000000 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2018 LEAP Encryption Access Project and contributers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package se.leap.bitmaskclient.testutils.BackendMockResponses; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.io.IOException; - -import javax.net.ssl.SSLHandshakeException; - -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; - -/** - * Created by cyberta on 10.01.18. - */ - -public class EipSerivceJsonInvalidCertificateBackendResponse extends BaseBackendResponse { - public EipSerivceJsonInvalidCertificateBackendResponse() throws IOException { - super(); - } - - @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - String requestMethod = (String) invocation.getArguments()[1]; - String jsonPayload = (String) invocation.getArguments()[2]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - throw new SSLHandshakeException("Invalid provider CA certificate"); - } else if (url.contains(":9001/json")) { - // download geoip json, containing a sorted list of gateways - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } else if (url.contains("/users.json")) { - //create new user - //TODO: implement me - } else if (url.contains("/sessions.json")) { - //srp auth: sendAToSRPServer - //TODO: implement me - } else if (url.contains("/sessions/parmegvtest10.json")){ - //srp auth: sendM1ToSRPServer - //TODO: implement me - } - - return null; - } - }; - } - - @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } - - @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } - -} diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java new file mode 100644 index 00000000..15df00cb --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2018 LEAP Encryption Access Project and contributers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package se.leap.bitmaskclient.testutils.BackendMockResponses; + +import java.io.IOException; +import java.util.List; + +import javax.net.ssl.SSLHandshakeException; + +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; + +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; + +/** + * Created by cyberta on 10.01.18. + */ + +public class EipServiceJsonInvalidCertificateBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { + + @Override + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) { + return true; + } + + @Override + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; + } + + @Override + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + throw new SSLHandshakeException("Invalid provider CA certificate"); + } else if (url.contains(":9001/json")) { + // download geoip json, containing a sorted list of gateways + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); + } + return null; + } +} diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java index 3a08d8da..482276a6 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java @@ -16,78 +16,51 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; import java.net.ConnectException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class GeoIpServiceIsDownBackendResponse extends BaseBackendResponse { - public GeoIpServiceIsDownBackendResponse() throws IOException { - super(); - } +public class GeoIpServiceIsDownBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - String requestMethod = (String) invocation.getArguments()[1]; - String jsonPayload = (String) invocation.getArguments()[2]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); - } else if (url.contains(":9001/json")) { - // download geoip json, containing a sorted list of gateways - throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001"); - } else if (url.contains("/users.json")) { - //create new user - //TODO: implement me - } else if (url.contains("/sessions.json")) { - //srp auth: sendAToSRPServer - //TODO: implement me - } else if (url.contains("/sessions/parmegvtest10.json")){ - //srp auth: sendM1ToSRPServer - //TODO: implement me - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); + } else if (url.contains(":9001/json")) { + // download geoip json, containing a sorted list of gateways + throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001"); + } + return null; + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java index 02aa31fa..d11c21f8 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java @@ -16,74 +16,61 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; import java.net.ConnectException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class GeoIpServiceNotReachableTorFallbackBackendResponse extends BaseBackendResponse { +public class GeoIpServiceNotReachableTorFallbackBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { public GeoIpServiceNotReachableTorFallbackBackendResponse() throws IOException { super(); } int requestAttempt = 0; @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); - } else if (url.contains(":9001/json")) { - if (requestAttempt == 0) { - // download geoip json, containing a sorted list of gateways - requestAttempt++; - throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001"); - } else { - // assumtion: 2. connection attempt has been made with proxy on, which is not allowed - // this branch should never be called otherwise you have found a bug - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } - } - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); + } else if (url.contains(":9001/json")) { + if (requestAttempt == 0) { + // download geoip json, containing a sorted list of gateways + requestAttempt++; + throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001"); + } else { + // assumtion: 2. connection attempt has been made with proxy on, which is not allowed + // this branch should never be called otherwise you have found a bug + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); } - }; + } + return null; } - } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java index 10e69bc3..301f1a75 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java @@ -16,77 +16,50 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class MisconfiguredProviderBackendResponse extends BaseBackendResponse { - public MisconfiguredProviderBackendResponse() throws IOException { - super(); - } +public class MisconfiguredProviderBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - String requestMethod = (String) invocation.getArguments()[1]; - String jsonPayload = (String) invocation.getArguments()[2]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup_net_invalid_config.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); - } else if (url.contains(":9001/json")) { - // download geoip json, containing a sorted list of gateways - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } else if (url.contains("/users.json")) { - //create new user - //TODO: implement me - } else if (url.contains("/sessions.json")) { - //srp auth: sendAToSRPServer - //TODO: implement me - } else if (url.contains("/sessions/parmegvtest10.json")){ - //srp auth: sendM1ToSRPServer - //TODO: implement me - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup_net_invalid_config.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); + } else if (url.contains(":9001/json")) { + // download geoip json, containing a sorted list of gateways + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); + } + return null; + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java index 3c3a8ffa..44067139 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java @@ -16,77 +16,50 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class NoErrorBackendResponse extends BaseBackendResponse { - public NoErrorBackendResponse() throws IOException { - super(); - } +public class NoErrorBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - String requestMethod = (String) invocation.getArguments()[1]; - String jsonPayload = (String) invocation.getArguments()[2]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); - } else if (url.contains(":9001/json")) { - // download geoip json, containing a sorted list of gateways - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } else if (url.contains("/users.json")) { - //create new user - //TODO: implement me - } else if (url.contains("/sessions.json")) { - //srp auth: sendAToSRPServer - //TODO: implement me - } else if (url.contains("/sessions/parmegvtest10.json")){ - //srp auth: sendM1ToSRPServer - //TODO: implement me - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) { + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); + } else if (url.contains(":9001/json")) { + // download geoip json, containing a sorted list of gateways + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); + } + return null; + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java index b9dc26b1..bbbed821 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java @@ -16,80 +16,52 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class NoErrorBackendResponseAPIv4 extends BaseBackendResponse { - public NoErrorBackendResponseAPIv4() throws IOException { - super(); - } - +public class NoErrorBackendResponseAPIv4 implements ProviderApiConnector.ProviderApiConnectorInterface { @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - String requestMethod = (String) invocation.getArguments()[1]; - String jsonPayload = (String) invocation.getArguments()[2]; - - if (url.contains("/provider.json")) { - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json")); - } else if (url.contains(":9001/json")) { - // download geoip json, containing a sorted list of gateways - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } else if (url.contains("/cert")) { - // download vpn key and cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert")); - } else if (url.contains("/users.json")) { - //create new user - //TODO: implement me - } else if (url.contains("/sessions.json")) { - //srp auth: sendAToSRPServer - //TODO: implement me - } else if (url.contains("/sessions/parmegvtest10.json")){ - //srp auth: sendM1ToSRPServer - //TODO: implement me - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) { + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - return true; - } - }; - } + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json")); + } else if (url.contains(":9001/json")) { + // download geoip json, containing a sorted list of gateways + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); + } else if (url.contains("/cert")) { + // download vpn key and cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert")); + } + return null; + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java index c3779a21..45dd36e4 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java @@ -1,94 +1,81 @@ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; import java.net.UnknownHostException; +import java.util.List; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; -public class TorFallbackBackendResponse extends BaseBackendResponse { +public class TorFallbackBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { public TorFallbackBackendResponse() throws IOException { super(); } int requestAttempt = 0; @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - - if (url.contains("/provider.json")) { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException(); - } - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json")); - } else if (url.contains("/ca.crt")) { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - //download provider ca cert - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); - } else if (url.contains("config/eip-service.json")) { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - // download provider service json containing gateways, locations and openvpn settings - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json")); - } else if (url.contains(":9001/json")) { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - // download geoip json, containing a sorted list of gateways - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); - } else if (url.contains("/cert")) { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - // download vpn certificate for authentication - return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert")); - - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - if (requestAttempt == 0) { - requestAttempt++; - throw new UnknownHostException("DNS blocked by censor ;)"); - } - return true; + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException(); + } + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json")); + } else if (url.contains("/ca.crt")) { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + //download provider ca cert + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem")); + } else if (url.contains("config/eip-service.json")) { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); } - }; + // download provider service json containing gateways, locations and openvpn settings + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json")); + } else if (url.contains(":9001/json")) { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + // download geoip json, containing a sorted list of gateways + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json")); + } else if (url.contains("/cert")) { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + // download vpn certificate for authentication + return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert")); + + } + return null; } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java index 232649a1..1da18f76 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java @@ -16,82 +16,63 @@ */ package se.leap.bitmaskclient.testutils.BackendMockResponses; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +import android.util.Pair; + +import androidx.annotation.NonNull; import java.io.IOException; +import java.util.List; import javax.net.ssl.SSLHandshakeException; -import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; +import okhttp3.OkHttpClient; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; /** * Created by cyberta on 10.01.18. */ -public class UpdatedCertificateBackendResponse extends BaseBackendResponse { +public class UpdatedCertificateBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface { static volatile boolean wasCACertCalled = false; - - public UpdatedCertificateBackendResponse() throws IOException { - super(); - } - @Override - public Answer getAnswerForRequestStringFromServer() { - return new Answer() { - - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String url = (String) invocation.getArguments()[0]; - - if (url.contains("/provider.json")) { - if (!wasCACertCalled) { - throw new SSLHandshakeException("Updated certificate on server side"); - } - //download provider json - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); - } else if (url.contains("/ca.crt")) { - //download provider ca cert - wasCACertCalled = true; - return getInputAsString(getClass().getClassLoader().getResourceAsStream("updated_cert.pem")); - } else if (url.contains("config/eip-service.json")) { - // download provider service json containing gateways, locations and openvpn settings - if (!wasCACertCalled) { - throw new SSLHandshakeException("Updated certificate on server side"); - } - return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); - } - - return null; - } - }; + public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException { + if (!wasCACertCalled) { + throw new SSLHandshakeException("Updated certificate on server side"); + } + return true; } @Override - public Answer getAnswerForCanConnect() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - if (!wasCACertCalled) { - throw new SSLHandshakeException("Updated certificate on server side"); - } - return true; - } - }; + public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException { + if (!wasCACertCalled) { + throw new SSLHandshakeException("Updated certificate on server side"); + } + return true; } @Override - public Answer getAnswerForDelete() { - return new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - if (!wasCACertCalled) { - throw new SSLHandshakeException("Updated certificate on server side"); - } - return true; + public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException { + if (url.contains("/provider.json")) { + if (!wasCACertCalled) { + throw new SSLHandshakeException("Updated certificate on server side"); } - }; - } + //download provider json + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json")); + } else if (url.contains("/ca.crt")) { + //download provider ca cert + wasCACertCalled = true; + return getInputAsString(getClass().getClassLoader().getResourceAsStream("updated_cert.pem")); + } else if (url.contains("config/eip-service.json")) { + // download provider service json containing gateways, locations and openvpn settings + if (!wasCACertCalled) { + throw new SSLHandshakeException("Updated certificate on server side"); + } + return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json")); + } + return null; + } } diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java index 33e2c056..3175b0ad 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -3,42 +3,39 @@ package se.leap.bitmaskclient.testutils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_CONFIGURED; +import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY; import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE; -import static se.leap.bitmaskclient.base.utils.FileHelper.createFile; import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getEipDefinitionFromPreferences; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider; -import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; import android.os.Parcelable; import android.os.ResultReceiver; -import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; +import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -48,8 +45,6 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.net.UnknownHostException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; import java.security.interfaces.RSAPrivateKey; import java.util.ArrayList; import java.util.Arrays; @@ -74,6 +69,7 @@ import se.leap.bitmaskclient.base.utils.InputStreamHelper; import se.leap.bitmaskclient.base.utils.BuildConfigHelper; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.base.utils.RSAHelper; +import se.leap.bitmaskclient.providersetup.ProviderApiConnector; import se.leap.bitmaskclient.providersetup.connectivity.DnsResolver; import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider; @@ -85,235 +81,6 @@ import se.leap.bitmaskclient.tor.TorStatusObservable; */ public class MockHelper { - @NonNull - public static Bundle mockBundle() { - final Map fakeBooleanBundle = new HashMap<>(); - final Map fakeStringBundle = new HashMap<>(); - final Map fakeIntBundle = new HashMap<>(); - final Map fakeParcelableBundle = new HashMap<>(); - - Bundle bundle = mock(Bundle.class); - - //mock String values in Bundle - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - String value = ((String) arguments[1]); - fakeStringBundle.put(key, value); - return null; - } - }).when(bundle).putString(anyString(), anyString()); - when(bundle.getString(anyString())).thenAnswer(new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return fakeStringBundle.get(key); - } - }); - - //mock Boolean values in Bundle - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - Boolean value = ((boolean) arguments[1]); - fakeBooleanBundle.put(key, value); - return null; - } - }).when(bundle).putBoolean(anyString(), anyBoolean()); - when(bundle.getBoolean(anyString())).thenAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return fakeBooleanBundle.get(key); - } - }); - - //mock Integer values in Bundle - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - Integer value = ((int) arguments[1]); - fakeIntBundle.put(key, value); - return null; - } - }).when(bundle).putInt(anyString(), anyInt()); - when(bundle.getInt(anyString())).thenAnswer(new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return fakeIntBundle.get(key); - } - }); - - //mock Parcelable values in Bundle - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - Parcelable value = ((Parcelable) arguments[1]); - fakeParcelableBundle.put(key, value); - return null; - } - }).when(bundle).putParcelable(anyString(), any(Parcelable.class)); - when(bundle.getParcelable(anyString())).thenAnswer(new Answer() { - @Override - public Parcelable answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return fakeParcelableBundle.get(key); - } - }); - - //mock get - when(bundle.get(anyString())).thenAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - if (fakeBooleanBundle.containsKey(key)) { - return fakeBooleanBundle.get(key); - } else if (fakeIntBundle.containsKey(key)) { - return fakeIntBundle.get(key); - } else if (fakeStringBundle.containsKey(key)) { - return fakeStringBundle.get(key); - } else { - return fakeParcelableBundle.get(key); - } - } - }); - - //mock getKeySet - when(bundle.keySet()).thenAnswer(new Answer>() { - @Override - public Set answer(InvocationOnMock invocation) throws Throwable { - //this whole approach as a drawback: - //you should not add the same keys for values of different types - HashSet keys = new HashSet(); - keys.addAll(fakeBooleanBundle.keySet()); - keys.addAll(fakeIntBundle.keySet()); - keys.addAll(fakeStringBundle.keySet()); - keys.addAll(fakeParcelableBundle.keySet()); - return keys; - } - }); - - //mock containsKey - when(bundle.containsKey(anyString())).thenAnswer(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - return fakeBooleanBundle.containsKey(key) || - fakeStringBundle.containsKey(key) || - fakeIntBundle.containsKey(key) || - fakeParcelableBundle.containsKey(key); - } - }); - - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - fakeBooleanBundle.remove(key); - fakeIntBundle.remove(key); - fakeParcelableBundle.remove(key); - fakeStringBundle.remove(key); - return null; - } - }).when(bundle).remove(anyString()); - - return bundle; - } - - public static Intent mockIntent() { - Intent intent = mock(Intent.class); - final String[] action = new String[1]; - final Map fakeExtras = new HashMap<>(); - final List categories = new ArrayList<>(); - - - //mock Action in intent - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - action[0] = ((String) arguments[0]); - return null; - } - }).when(intent).setAction(anyString()); - when(intent.getAction()).thenAnswer(new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - return action[0]; - } - }); - - //mock Bundle in intent extras - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - Bundle value = ((Bundle) arguments[1]); - fakeExtras.put(key, value); - return null; - } - }).when(intent).putExtra(anyString(), any(Bundle.class)); - when(intent.getBundleExtra(anyString())).thenAnswer(new Answer() { - @Override - public Bundle answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return (Bundle) fakeExtras.get(key); - } - }); - - //mock Parcelable in intent extras - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - Parcelable value = ((Parcelable) arguments[1]); - fakeExtras.put(key, value); - return null; - } - }).when(intent).putExtra(anyString(), any(Parcelable.class)); - when(intent.getParcelableExtra(anyString())).thenAnswer(new Answer() { - @Override - public Parcelable answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - String key = ((String) arguments[0]); - return (Parcelable) fakeExtras.get(key); - } - }); - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - Object[] arguments = invocation.getArguments(); - categories.add(((String) arguments[0])); - return null; - } - }).when(intent).addCategory(anyString()); - - when(intent.getCategories()).thenAnswer(new Answer>() { - @Override - public Set answer(InvocationOnMock invocation) throws Throwable { - return new HashSet<>(categories); - } - }); - - return intent; - } public static ResultReceiver mockResultReceiver(final int expectedResultCode) { ResultReceiver resultReceiver = mock(ResultReceiver.class); @@ -403,43 +170,42 @@ public class MockHelper { return new FileHelper(new MockFileHelper(mockedFile)); } - public static void mockBase64() { - mockStatic(android.util.Base64.class); - when(android.util.Base64.encodeToString(any(), anyInt())).thenAnswer(invocation -> Arrays.toString(Base64.getEncoder().encode((byte[]) invocation.getArguments()[0]))); - } - public static RSAHelper mockRSAHelper() { return new RSAHelper(rsaKeyString -> new RSAPrivateKey() { - @Override - public BigInteger getPrivateExponent() { - return BigInteger.TEN; - } - - @Override - public String getAlgorithm() { - return "RSA"; - } - - @Override - public String getFormat() { - return null; - } - - @Override - public byte[] getEncoded() { - return new byte[0]; - } - - @Override - public BigInteger getModulus() { - return BigInteger.ONE; - } - }); + @Override + public BigInteger getPrivateExponent() { + return BigInteger.TEN; + } + @Override + public String getAlgorithm() { + return "RSA"; + } + + @Override + public String getFormat() { + return null; + } + + @Override + public byte[] getEncoded() { + return new byte[0]; + } + + @Override + public BigInteger getModulus() { + return BigInteger.ONE; + } + }); + + } + + public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn) { + return mockBuildConfigHelper(useObfsvpn, true); } - public static ObfsVpnHelper mockObfsVpnHelper(boolean useObfsvpn) { - return new ObfsVpnHelper(new ObfsVpnHelper.ObfsVpnHelperInterface() { + public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn, boolean isDefaultBitmask) { + return new BuildConfigHelper(new BuildConfigHelper.BuildConfigHelperInterface() { @Override public boolean useObfsVpn() { return useObfsvpn; @@ -469,6 +235,11 @@ public class MockHelper { public boolean useKcp() { return false; } + + @Override + public boolean isDefaultBitmask() { + return isDefaultBitmask; + } }); } @@ -476,87 +247,61 @@ public class MockHelper { return new CertificateHelper((certificate, encoding) -> mockedFingerprint); } - public static void mockPreferenceHelper(final Provider providerFromPrefs) { - // FIXME use MockSharedPreferences instead of provider - mockStatic(PreferenceHelper.class); - when(getFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer() { - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - switch (key) { - case PROVIDER_PRIVATE_KEY: - return providerFromPrefs.getPrivateKey(); - case PROVIDER_VPN_CERTIFICATE: - return providerFromPrefs.getVpnCertificate(); - case Provider.KEY: - return providerFromPrefs.getDefinition().toString(); - case Provider.CA_CERT_FINGERPRINT: - return providerFromPrefs.getCaCertFingerprint(); - case Provider.CA_CERT: - return providerFromPrefs.getCaCert(); - case Provider.GEOIP_URL: - return providerFromPrefs.getGeoipUrl().toString(); - case Provider.MOTD_URL: - return providerFromPrefs.getMotdUrl().toString(); - case PROVIDER_MOTD: - return providerFromPrefs.getMotdJsonString(); + public static PreferenceHelper mockPreferenceHelper(final Provider providerFromPrefs, SharedPreferences sharedPreferences) { + PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences); + + sharedPreferences.edit(). + putString(PROVIDER_PRIVATE_KEY, providerFromPrefs.getPrivateKey()). + putString(PROVIDER_VPN_CERTIFICATE, providerFromPrefs.getVpnCertificate()). + putString(Provider.KEY, providerFromPrefs.getDefinitionString()). + putString(Provider.CA_CERT_FINGERPRINT, providerFromPrefs.getCaCertFingerprint()). + putString(Provider.GEOIP_URL, providerFromPrefs.getGeoipUrl().toString()). + putString(Provider.MOTD_URL, providerFromPrefs.getMotdUrl().toString()). + putString(PROVIDER_MOTD, providerFromPrefs.getMotdJsonString()). + putLong(PROVIDER_MOTD_LAST_SEEN, providerFromPrefs.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED, providerFromPrefs.getLastMotdUpdate()). + putStringSet(PROVIDER_MOTD_HASHES, providerFromPrefs.getMotdLastSeenHashes()). + commit(); + + return preferenceHelper; + } - } - return null; - } - }); - when(getLongFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer() { - @Override - public Long answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - switch (key) { - case PROVIDER_MOTD_LAST_SEEN: - return providerFromPrefs.getLastMotdSeen(); - case PROVIDER_MOTD_LAST_UPDATED: - return providerFromPrefs.getLastMotdUpdate(); - } - return 0L; - } - }); - when(getStringSetFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer>() { - @Override - public Set answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - switch (key) { - case PROVIDER_MOTD_HASHES: - return providerFromPrefs.getMotdLastSeenHashes(); - } - return null; - } - }); - when(PreferenceHelper.hasKey(anyString())).then(new Answer() { - @Override - public Boolean answer(InvocationOnMock invocation) throws Throwable { - String key = (String) invocation.getArguments()[0]; - if (key!= null && key.contains(providerFromPrefs.getDomain()) && !providerFromPrefs.getDomain().isEmpty()) { - key = key.substring(0, key.indexOf(providerFromPrefs.getDomain()) - 1 /* -1 -> "." at the end */); - } - switch (key) { - case PROVIDER_PRIVATE_KEY: - return providerFromPrefs.getPrivateKey() != null; - case PROVIDER_VPN_CERTIFICATE: - return providerFromPrefs.getVpnCertificate() != null; - case Provider.KEY: - return providerFromPrefs.getDefinition().keys().hasNext(); - case Provider.CA_CERT_FINGERPRINT: - return providerFromPrefs.getCaCertFingerprint().length() > 1; - case Provider.CA_CERT: - return providerFromPrefs.getCaCert() != null; - case Provider.GEOIP_URL: - return !providerFromPrefs.getGeoipUrl().isDefault(); - case Provider.MOTD_URL: - return !providerFromPrefs.getMotdUrl().isDefault(); - case PROVIDER_MOTD: - return providerFromPrefs.getMotdJson().keys().hasNext(); - } - return false; - } - }); + public static PreferenceHelper mockPreferenceHelper(final Provider provider) { + SharedPreferences sharedPreferences = new MockSharedPreferences(); + PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences); + + sharedPreferences.edit(). + putString(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()). + putString(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()). + putString(Provider.KEY, provider.getDefinitionString()). + putString(Provider.CA_CERT_FINGERPRINT, provider.getCaCertFingerprint()). + putString(Provider.GEOIP_URL, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL, provider.getMotdUrl().toString()). + putString(PROVIDER_MOTD, provider.getMotdJsonString()). + putLong(PROVIDER_MOTD_LAST_SEEN, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED, provider.getLastMotdUpdate()). + putStringSet(PROVIDER_MOTD_HASHES, provider.getMotdLastSeenHashes()). + commit(); + + if (!provider.getDomain().isBlank()) { + String providerDomain = provider.getDomain(); + sharedPreferences.edit(). + putString(Provider.PROVIDER_IP + "." + providerDomain, provider.getProviderIp()). + putString(Provider.PROVIDER_API_IP + "." + providerDomain, provider.getProviderApiIp()). + putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()). + putString(Provider.GEOIP_URL + "." + providerDomain, provider.getGeoipUrl().toString()). + putString(Provider.MOTD_URL + "." + providerDomain, provider.getMotdUrl().toString()). + putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()). + putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()). + putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()). + putString(PROVIDER_MOTD + "." + providerDomain, provider.getMotdJsonString()). + putStringSet(PROVIDER_MOTD_HASHES + "." + providerDomain, provider.getMotdLastSeenHashes()). + putLong(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain, provider.getLastMotdSeen()). + putLong(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain, provider.getLastMotdUpdate()). + commit(); + } + + return preferenceHelper; } public static void mockPreferenceHelper(MockSharedPreferences preferences) { @@ -571,53 +316,14 @@ public class MockHelper { }); } - public static void mockTorStatusObservable(@Nullable Throwable exception) throws TimeoutException, InterruptedException { - TorStatusObservable observable = TorStatusObservable.getInstance(); - mockStatic(TorStatusObservable.class); - when(TorStatusObservable.getInstance()).thenAnswer((Answer) invocation -> observable); - - when(TorStatusObservable.getBootstrapProgress()).thenReturn(0); - when(TorStatusObservable.getLastLogs()).thenReturn(new Vector<>()); - when(TorStatusObservable.getLastTorLog()).thenReturn(""); - when(TorStatusObservable.getLastSnowflakeLog()).thenReturn(""); - AtomicBoolean waitUntilSuccess = new AtomicBoolean(false); - when(TorStatusObservable.getProxyPort()).thenAnswer((Answer) invocation -> { - if (waitUntilSuccess.get()) { - return 8118; - } - return -1; - }); - when(TorStatusObservable.getStatus()).thenAnswer((Answer) invocation -> { - if (waitUntilSuccess.get()) { - return TorStatusObservable.TorStatus.ON; - } - return TorStatusObservable.TorStatus.OFF; - }); - when(TorStatusObservable.getSnowflakeStatus()).thenAnswer((Answer) invocation -> { - if (waitUntilSuccess.get()) { - return TorStatusObservable.SnowflakeStatus.STARTED; - } - return TorStatusObservable.SnowflakeStatus.STOPPED; - }); - - if (exception != null) { - when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenThrow(exception); - } else { - when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenAnswer((Answer) invocation -> { - waitUntilSuccess.set(true); - return true; - }); - } - } - public static ProviderObservable mockProviderObservable(Provider provider) { ProviderObservable observable = ProviderObservable.getInstance(); observable.updateProvider(provider); return observable; } - public static void mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException { - BackendMockProvider.provideBackendResponsesFor(errorCase); + public static ProviderApiConnector mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException { + return new ProviderApiConnector(BackendMockProvider.provideBackendResponsesFor(errorCase)); } public static OkHttpClientGenerator mockClientGenerator(boolean resolveDNS) throws UnknownHostException { @@ -643,15 +349,15 @@ public class MockHelper { JSONObject errorMessages = new JSONObject(TestSetupHelper.getInputAsString(inputStream)); - when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_details), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask")); when(mockedResources.getString(R.string.server_unreachable_message)). thenReturn(errorMessages.getString("server_unreachable_message")); when(mockedResources.getString(R.string.error_security_pinnedcertificate)). thenReturn(errorMessages.getString("error.security.pinnedcertificate")); - when(mockedResources.getString(eq(R.string.malformed_url), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.malformed_url), anyString())). thenReturn(String.format(errorMessages.getString("malformed_url"), "Bitmask")); - when(mockedResources.getString(eq(R.string.certificate_error), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.certificate_error), anyString())). thenReturn(String.format(errorMessages.getString("certificate_error"), "Bitmask")); when(mockedResources.getString(R.string.error_srp_math_error_user_message)). thenReturn(errorMessages.getString("error_srp_math_error_user_message")); @@ -667,21 +373,21 @@ public class MockHelper { thenReturn(errorMessages.getString("error_json_exception_user_message")); when(mockedResources.getString(R.string.error_no_such_algorithm_exception_user_message)). thenReturn(errorMessages.getString("error_no_such_algorithm_exception_user_message")); - when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_details), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask")); - when(mockedResources.getString(eq(R.string.warning_corrupted_provider_cert), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_cert), anyString())). thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_cert"), "Bitmask")); - when(mockedResources.getString(eq(R.string.warning_expired_provider_cert), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.warning_expired_provider_cert), anyString())). thenReturn(String.format(errorMessages.getString("warning_expired_provider_cert"), "Bitmask")); - when(mockedResources.getString(eq(R.string.setup_error_text), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.setup_error_text), anyString())). thenReturn(String.format(errorMessages.getString("setup_error_text"), "Bitmask")); - when(mockedResources.getString(eq(R.string.setup_error_text_custom), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.setup_error_text_custom), anyString())). thenReturn(String.format(errorMessages.getString("setup_error_text_custom"), "RiseupVPN")); when(mockedResources.getString(R.string.app_name)). thenReturn("Bitmask"); - when(mockedResources.getString(eq(R.string.error_tor_timeout), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.error_tor_timeout), anyString())). thenReturn(String.format(errorMessages.getString("error_tor_timeout"), "Bitmask")); - when(mockedResources.getString(eq(R.string.error_network_connection), anyString())). + when(mockedResources.getString(Mockito.eq(R.string.error_network_connection), anyString())). thenReturn(String.format(errorMessages.getString("error_network_connection"), "Bitmask")); return mockedResources; } -- cgit v1.2.3 From 148e6a7dc549e0e09c4147f9b22cd324c104552d Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 26 Jan 2024 00:00:15 +0100 Subject: remove some tests of TetheringStateManager which are hard to rewrite without powermock --- .../tethering/TetheringStateManagerTest.java | 256 +-------------------- 1 file changed, 1 insertion(+), 255 deletions(-) diff --git a/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java index a2569282..a5954a97 100644 --- a/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java +++ b/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java @@ -16,279 +16,25 @@ */ package se.leap.bitmaskclient.tethering; -import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; - -import android.content.Context; -import android.content.IntentFilter; -import android.content.SharedPreferences; +import static org.mockito.Mockito.when; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; - -import se.leap.bitmaskclient.base.utils.Cmd; -import se.leap.bitmaskclient.base.utils.PreferenceHelper; -import se.leap.bitmaskclient.testutils.MockSharedPreferences; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({WifiManagerWrapper.class, TetheringStateManager.class, Cmd.class, NetworkInterface.class, PreferenceHelper.class}) public class TetheringStateManagerTest { - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - Context mockContext; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - IntentFilter intentFilter; - private TetheringObservable observable; @Before public void setup() throws Exception { - PowerMockito.whenNew(IntentFilter.class).withArguments(anyString()).thenReturn(intentFilter); - PowerMockito.whenNew(IntentFilter.class).withNoArguments().thenReturn(intentFilter); - mockStatic(PreferenceHelper.class); - observable = TetheringObservable.getInstance(); - - } - - @Test - public void updateUsbTetheringState_findsRndisX_returnsTrue() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(false); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - PowerMockito.mockStatic(NetworkInterface.class); - NetworkInterface mock1 = PowerMockito.mock(NetworkInterface.class); - when(mock1.isLoopback()).thenReturn(false); - when(mock1.getName()).thenReturn("eth0"); - NetworkInterface mock2 = PowerMockito.mock(NetworkInterface.class); - when(mock2.isLoopback()).thenReturn(false); - when(mock2.getName()).thenReturn("rndis0"); - - NetworkInterface[] networkInterfaces = new NetworkInterface[2]; - networkInterfaces[0] = mock1; - networkInterfaces[1] = mock2; - - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).then(new Answer>() { - @Override - public Enumeration answer(InvocationOnMock invocation) throws Throwable { - return Collections.enumeration(Arrays.asList(networkInterfaces)); - } - }); - - TetheringObservable.setUsbTethering(false, "192.168.42.0/24", "rndis0"); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertTrue(observable.isUsbTetheringEnabled()); - } - - @Test - public void updateUsbTetheringState_doesntFindRndisX_returnsFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(false); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - PowerMockito.mockStatic(NetworkInterface.class); - NetworkInterface mock1 = PowerMockito.mock(NetworkInterface.class); - when(mock1.isLoopback()).thenReturn(false); - when(mock1.getName()).thenReturn("eth0"); - NetworkInterface mock2 = PowerMockito.mock(NetworkInterface.class); - when(mock2.isLoopback()).thenReturn(false); - when(mock2.getName()).thenReturn("wifi0"); - - NetworkInterface[] networkInterfaces = new NetworkInterface[2]; - networkInterfaces[0] = mock1; - networkInterfaces[1] = mock2; - - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).then(new Answer>() { - @Override - public Enumeration answer(InvocationOnMock invocation) throws Throwable { - return Collections.enumeration(Arrays.asList(networkInterfaces)); - } - }); - - TetheringObservable.setUsbTethering(true, "192.168.42.0/24", "rndis0"); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isUsbTetheringEnabled()); - } - - @Test - public void updateUsbTetheringState_ThrowsException_returnsFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(false); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - PowerMockito.mockStatic(NetworkInterface.class); - PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenThrow(new SocketException()); - - TetheringObservable.setUsbTethering(true, "192.168.42.0/24", "rndis0"); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isUsbTetheringEnabled()); - } - -/* //TODO enable these tests as soon as bluetooth tethering has been enabled again - @Test - public void updateBluetoothTetheringState_btDeviceFound_returnTrue() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(true); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - mockStatic(Cmd.class); - PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - StringBuilder logStringBuilder = invocation.getArgument(1); - logStringBuilder.append("bt-pan device found"); - return 0; - } - }); - - TetheringObservable.setBluetoothTethering(false); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertTrue(observable.isBluetoothTetheringEnabled()); - } - - - @Test - public void updateBluetoothTetheringState_btPanDeviceNotFound_returnFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(true); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - mockStatic(Cmd.class); - PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - StringBuilder logStringBuilder = invocation.getArgument(1); - logStringBuilder.append("bt-pan device not found"); - return 1; - } - }); - - TetheringObservable.setBluetoothTethering(true); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isBluetoothTetheringEnabled()); - } - - @Test - public void updateBluetoothTetheringState_ThrowsException_returnsFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(true); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - mockStatic(Cmd.class); - PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))). - thenThrow(new SecurityException("Creation of subprocess is not allowed")); - - TetheringObservable.setBluetoothTethering(true); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isBluetoothTetheringEnabled()); - } - - @Test - public void updateBluetoothTetheringState_WifiManagerWrapperThrowsException_hasNoInfluenceOnResult() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException()); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - mockStatic(Cmd.class); - PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer() { - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - StringBuilder logStringBuilder = invocation.getArgument(1); - logStringBuilder.append("bt-pan device found"); - return 0; - } - }); - - TetheringObservable.setBluetoothTethering(false); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertTrue(observable.isBluetoothTetheringEnabled()); - } - */ - - @Test - public void updateWifiTetheringState_ignoreFailingWifiAPReflection_keepsOldValueTrue() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException()); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - TetheringObservable.setWifiTethering(true, "192.168.43.0/24", "wlan0"); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertTrue(observable.isWifiTetheringEnabled()); - } - - @Test - public void updateWifiTetheringState_ignoreFailingWifiAPReflection_keepsOldValueFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException()); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - TetheringObservable.setWifiTethering(false, "", ""); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isWifiTetheringEnabled()); - } - - @Test - public void updateWifiTetheringState_WifiApReflectionWithoutException_changeValueToTrue() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(true); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - TetheringObservable.setWifiTethering(false, "", ""); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertTrue(observable.isWifiTetheringEnabled()); - } - - @Test - public void updateWifiTetheringState_WifiApReflectionWithoutException_changeValueToFalse() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(false); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - - TetheringObservable.setWifiTethering(true, "", ""); - TetheringStateManager.getInstance().init(mockContext); - TetheringStateManager manager = TetheringStateManager.getInstance(); - assertFalse(observable.isWifiTetheringEnabled()); } @Test public void testGetWifiAddressRangee_keepsLastSeenAddressAndInterface() throws Exception { - WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class); - when(mockWrapper.isWifiAPEnabled()).thenReturn(true); - PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper); - //WifiTethering was switched on TetheringObservable.setWifiTethering(true, "192.168.40.0/24", "wlan0"); -- cgit v1.2.3 From 6c3efd90f70a93c6a668c7cb954ab4a353c73d66 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 26 Jan 2024 00:01:46 +0100 Subject: move reqex pattern for IPv4 and PEM into functions for now --- .../main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java index 71fe8eba..cd5d1fca 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java @@ -59,8 +59,6 @@ public class ConfigHelper { final public static String NG_1024 = "eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3"; final public static BigInteger G = new BigInteger("2"); - final public static Pattern IPv4_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"); - final public static Pattern PEM_CERTIFICATE_PATTERN = Pattern.compile("((-----BEGIN CERTIFICATE-----)([A-Za-z0-9+/=\\n]+)(-----END CERTIFICATE-----)+)"); public static boolean checkErroneousDownload(String downloadedString) { try { @@ -99,8 +97,8 @@ public class ConfigHelper { CertificateFactory cf; try { cf = CertificateFactory.getInstance("X.509"); - - Matcher matcher = PEM_CERTIFICATE_PATTERN.matcher(certificateString); + Pattern pattern = Pattern.compile("((-----BEGIN CERTIFICATE-----)([A-Za-z0-9+/=\\n]+)(-----END CERTIFICATE-----)+)"); + Matcher matcher = pattern.matcher(certificateString); while (matcher.find()) { String certificate = matcher.group(3); if (certificate == null) continue; @@ -188,7 +186,7 @@ public class ConfigHelper { if (ipv4 == null) { return false; } - Matcher matcher = IPv4_PATTERN.matcher(ipv4); + Matcher matcher = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$").matcher(ipv4); return matcher.matches(); } -- cgit v1.2.3 From e84289ab4380ae61cc9f2a86da9a16d1aae45cbd Mon Sep 17 00:00:00 2001 From: cyBerta Date: Fri, 26 Jan 2024 00:06:30 +0100 Subject: add jvm flags for unit tests --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index aafc76c2..0757f4fa 100644 --- a/build.gradle +++ b/build.gradle @@ -25,3 +25,9 @@ allprojects { mavenCentral() } } + +subprojects{ + tasks.withType(Test).configureEach{ + jvmArgs = jvmArgs + ['--add-opens=java.base/java.lang=ALL-UNNAMED', '--add-exports=java.base/java.lang=ALL-UNNAMED', '--add-reads=java.base/java.lang=ALL-UNNAMED'] + } +} -- cgit v1.2.3