diff options
Diffstat (limited to 'app/src/test/java/se/leap/bitmaskclient/testutils')
4 files changed, 266 insertions, 9 deletions
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 d76e4029..280aa5a1 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 @@ -33,6 +33,7 @@ public class BackendMockProvider { ERROR_CASE_MICONFIGURED_PROVIDER, ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID, ERROR_GEOIP_SERVICE_IS_DOWN, + ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK, ERROR_NO_RESPONSE_BODY, // => NullPointerException ERROR_DNS_RESOLUTION_ERROR, // => UnkownHostException ERROR_SOCKET_TIMEOUT, // => SocketTimeoutException @@ -46,7 +47,8 @@ public class BackendMockProvider { ERROR_INVALID_SESSION_TOKEN, ERROR_NO_CONNECTION, ERROR_WRONG_SRP_CREDENTIALS, - NO_ERROR_API_V4 + NO_ERROR_API_V4, + ERROR_DNS_RESUOLUTION_TOR_FALLBACK } @@ -71,6 +73,11 @@ public class BackendMockProvider { 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: 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 new file mode 100644 index 00000000..02aa31fa --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java @@ -0,0 +1,89 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + */ +package se.leap.bitmaskclient.testutils.BackendMockResponses; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.IOException; +import java.net.ConnectException; + +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +/** + * Created by cyberta on 10.01.18. + */ + +public class GeoIpServiceNotReachableTorFallbackBackendResponse extends BaseBackendResponse { + public GeoIpServiceNotReachableTorFallbackBackendResponse() throws IOException { + super(); + } + int requestAttempt = 0; + + @Override + public Answer<String> getAnswerForRequestStringFromServer() { + return new Answer<String>() { + @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; + } + }; + } + + @Override + public Answer<Boolean> getAnswerForCanConnect() { + return new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + + @Override + public Answer<Boolean> getAnswerForDelete() { + return new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return true; + } + }; + } + +} 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 new file mode 100644 index 00000000..dc12ae89 --- /dev/null +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java @@ -0,0 +1,86 @@ +package se.leap.bitmaskclient.testutils.BackendMockResponses; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import java.io.IOException; +import java.net.UnknownHostException; + +import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString; + +public class TorFallbackBackendResponse extends BaseBackendResponse { + public TorFallbackBackendResponse() throws IOException { + super(); + } + int requestAttempt = 0; + + @Override + public Answer<String> getAnswerForRequestStringFromServer() { + return new Answer<String>() { + @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")); + } + + return null; + } + }; + } + + @Override + public Answer<Boolean> getAnswerForCanConnect() { + return new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + return true; + } + }; + } + + @Override + public Answer<Boolean> getAnswerForDelete() { + return new Answer<Boolean>() { + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + if (requestAttempt == 0) { + requestAttempt++; + throw new UnknownHostException("DNS blocked by censor ;)"); + } + return true; + } + }; + } +} 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 5a341cd1..0086e4c2 100644 --- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java +++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java @@ -9,9 +9,11 @@ import android.content.res.Resources; import android.os.Bundle; import android.os.Parcelable; import android.os.ResultReceiver; -import androidx.annotation.NonNull; import android.text.TextUtils; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.json.JSONException; import org.json.JSONObject; import org.mockito.invocation.InvocationOnMock; @@ -32,18 +34,22 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Vector; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import okhttp3.OkHttpClient; -import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; +import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.base.models.ProviderObservable; -import se.leap.bitmaskclient.R; -import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider; -import se.leap.bitmaskclient.testutils.matchers.BundleMatcher; 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.PreferenceHelper; +import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator; +import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider; +import se.leap.bitmaskclient.testutils.matchers.BundleMatcher; +import se.leap.bitmaskclient.tor.TorStatusObservable; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -202,6 +208,18 @@ public class MockHelper { } }); + 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; } @@ -319,6 +337,20 @@ public class MockHelper { }); } + public static ResultReceiver mockResultReceiver(final int expectedResultCode) { + ResultReceiver resultReceiver = mock(ResultReceiver.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Object[] arguments = invocation.getArguments(); + int resultCode = (int) arguments[0]; + assertEquals("expected resultCode: ", expectedResultCode, resultCode); + return null; + } + }).when(resultReceiver).send(anyInt(), any(Bundle.class)); + return resultReceiver; + } + public static ResultReceiver mockResultReceiver(final int expectedResultCode, final Bundle expectedBundle) { ResultReceiver resultReceiver = mock(ResultReceiver.class); @@ -423,7 +455,46 @@ public class MockHelper { }); } - public static void mockProviderObserver(Provider provider) { + public static void mockTorStatusObservable(@Nullable Throwable exception) throws TimeoutException, InterruptedException { + TorStatusObservable observable = TorStatusObservable.getInstance(); + mockStatic(TorStatusObservable.class); + when(TorStatusObservable.getInstance()).thenAnswer((Answer<TorStatusObservable>) 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<Integer>) invocation -> { + if (waitUntilSuccess.get()) { + return 8118; + } + return -1; + }); + when(TorStatusObservable.getStatus()).thenAnswer((Answer<TorStatusObservable.TorStatus>) invocation -> { + if (waitUntilSuccess.get()) { + return TorStatusObservable.TorStatus.ON; + } + return TorStatusObservable.TorStatus.OFF; + }); + when(TorStatusObservable.getSnowflakeStatus()).thenAnswer((Answer<TorStatusObservable.SnowflakeStatus>) invocation -> { + if (waitUntilSuccess.get()) { + return TorStatusObservable.SnowflakeStatus.ON; + } + return TorStatusObservable.SnowflakeStatus.OFF; + }); + + if (exception != null) { + when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenThrow(exception); + } else { + when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenAnswer((Answer<Boolean>) invocation -> { + waitUntilSuccess.set(true); + return true; + }); + } + } + + public static void mockProviderObservable(Provider provider) { ProviderObservable observable = ProviderObservable.getInstance(); observable.updateProvider(provider); mockStatic(ProviderObservable.class); @@ -445,8 +516,8 @@ public class MockHelper { public static OkHttpClientGenerator mockClientGenerator(boolean resolveDNS) throws UnknownHostException { OkHttpClientGenerator mockClientGenerator = mock(OkHttpClientGenerator.class); OkHttpClient mockedOkHttpClient = mock(OkHttpClient.class, RETURNS_DEEP_STUBS); - when(mockClientGenerator.initCommercialCAHttpClient(any(JSONObject.class))).thenReturn(mockedOkHttpClient); - when(mockClientGenerator.initSelfSignedCAHttpClient(anyString(), any(JSONObject.class))).thenReturn(mockedOkHttpClient); + when(mockClientGenerator.initCommercialCAHttpClient(any(JSONObject.class), anyInt())).thenReturn(mockedOkHttpClient); + when(mockClientGenerator.initSelfSignedCAHttpClient(anyString(), anyInt(), any(JSONObject.class))).thenReturn(mockedOkHttpClient); if (resolveDNS) { when(mockedOkHttpClient.dns().lookup(anyString())).thenReturn(new ArrayList<>()); } else { @@ -498,6 +569,10 @@ public class MockHelper { thenReturn(String.format(errorMessages.getString("setup_error_text"), "Bitmask")); when(mockedResources.getString(R.string.app_name)). thenReturn("Bitmask"); + when(mockedResources.getString(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())). + thenReturn(String.format(errorMessages.getString("error_network_connection"), "Bitmask")); return mockedResources; } |