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 (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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 (limited to 'app/src') 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 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 (limited to 'app/src') 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 (limited to 'app/src') 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 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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 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 (limited to 'app/src') 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(-) (limited to 'app/src') 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 (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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 (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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 (limited to 'app/src') 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 (limited to 'app/src') 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 (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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 --- .../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 +++++--------------- 18 files changed, 921 insertions(+), 1314 deletions(-) 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 (limited to 'app/src') 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(-) (limited to 'app/src') 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(-) (limited to 'app/src') 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