summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorNiklas Berglund <niklas.berglund@gmail.com>2024-08-13 14:51:14 +0200
committerNiklas Berglund <niklas.berglund@gmail.com>2024-08-19 11:53:56 +0200
commit89ea752eb3fe3378fb7439a0f5287aad37cb0ea0 (patch)
treeb2cf699bae0972fb0ee87de7962ce345c2ad0cff /android
parent58a811f70b0d9da7ad052ec98b25eff65ee4a1be (diff)
downloadmullvadvpn-89ea752eb3fe3378fb7439a0f5287aad37cb0ea0.tar.xz
mullvadvpn-89ea752eb3fe3378fb7439a0f5287aad37cb0ea0.zip
Fix for failing mockapi and e2e tests
Diffstat (limited to 'android')
-rw-r--r--android/BuildInstructions.md3
-rw-r--r--android/gradle/libs.versions.toml2
-rwxr-xr-xandroid/scripts/run-instrumented-tests.sh2
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt3
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt12
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt9
-rw-r--r--android/test/e2e/build.gradle.kts9
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt4
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt13
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/annotations/HighlyRateLimited.kt37
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/constant/Constants.kt1
-rw-r--r--android/test/firebase/e2e-play-stagemole.yml3
-rw-r--r--android/test/mockapi/build.gradle.kts8
13 files changed, 72 insertions, 34 deletions
diff --git a/android/BuildInstructions.md b/android/BuildInstructions.md
index b6dc1defca..fdbea86715 100644
--- a/android/BuildInstructions.md
+++ b/android/BuildInstructions.md
@@ -238,3 +238,6 @@ the `ENABLE_IN_APP_VERSION_NOTIFICATIONS` property can be set in `local.properti
```
ENABLE_IN_APP_VERSION_NOTIFICATIONS=false
```
+
+### Run tests highly affected by rate limiting
+To avoid being rate limited we avoid running tests sending requests that are highly rate limited too often. If you want to run these tests you can set `enable_highly_rate_limited_tests=true` in `local.properties`. The default value is `false`.
diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml
index f603f70053..90a53d5c6d 100644
--- a/android/gradle/libs.versions.toml
+++ b/android/gradle/libs.versions.toml
@@ -71,7 +71,7 @@ android-gradle-aapt = { module = "com.android.tools.build:aapt2" }
android-volley = { module = "com.android.volley:volley", version.ref = "android-volley" }
# AndroidX
-androidx-activity-Compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activitycompose" }
+androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activitycompose" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
androidx-coresplashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-coresplashscreen" }
androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
diff --git a/android/scripts/run-instrumented-tests.sh b/android/scripts/run-instrumented-tests.sh
index 9ff3ec1b05..650e7f0fee 100755
--- a/android/scripts/run-instrumented-tests.sh
+++ b/android/scripts/run-instrumented-tests.sh
@@ -16,6 +16,7 @@ TEST_SERVICES_URL=https://dl.google.com/android/maven2/androidx/test/services/te
PARTNER_AUTH="${PARTNER_AUTH:-}"
VALID_TEST_ACCOUNT_NUMBER="${VALID_TEST_ACCOUNT_NUMBER:-}"
INVALID_TEST_ACCOUNT_NUMBER="${INVALID_TEST_ACCOUNT_NUMBER:-}"
+ENABLE_HIGHLY_RATE_LIMITED_TESTS="${ENABLE_HIGHLY_RATE_LIMITED_TESTS:-false}"
REPORT_DIR="${REPORT_DIR:-}"
while [[ "$#" -gt 0 ]]; do
@@ -130,6 +131,7 @@ case "$TEST_TYPE" in
echo "Error: The variable PARTNER_AUTH or VALID_TEST_ACCOUNT_NUMBER must be set."
exit 1
fi
+ OPTIONAL_TEST_ARGUMENTS+=" -e enable_highly_rate_limited_tests $ENABLE_HIGHLY_RATE_LIMITED_TESTS"
USE_ORCHESTRATOR="true"
PACKAGE_NAME="net.mullvad.mullvadvpn"
if [[ "$INFRA_FLAVOR" =~ ^(devmole|stagemole)$ ]]; then
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
index 77c1e92c5e..6d17b85b6a 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -16,7 +16,6 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
-import net.mullvad.mullvadvpn.lib.common.constant.BuildTypes
import net.mullvad.mullvadvpn.lib.common.constant.GRPC_SOCKET_FILE_NAMED_ARGUMENT
import net.mullvad.mullvadvpn.lib.common.constant.KEY_CONNECT_ACTION
import net.mullvad.mullvadvpn.lib.common.constant.KEY_DISCONNECT_ACTION
@@ -150,7 +149,7 @@ class MullvadVpnService : TalpidVpnService() {
private fun startDaemon() {
val apiEndpointConfiguration =
- if (Build.TYPE == BuildTypes.DEBUG) {
+ if (BuildConfig.DEBUG) {
intentProvider.getLatestIntent()?.getApiEndpointConfigurationExtras()
?: apiEndpointConfiguration
} else {
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
index b3e99eec98..9f3d727d29 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/extension/UiAutomatorExtensions.kt
@@ -24,13 +24,11 @@ fun UiDevice.findObjectWithTimeout(
wait(Until.hasObject(selector), timeout)
- return try {
- findObject(selector)
- } catch (e: NullPointerException) {
- throw IllegalArgumentException(
- "No matches for selector within timeout ($timeout): $selector"
- )
- }
+ val foundObject = findObject(selector)
+
+ require(foundObject != null) { "No matches for selector within timeout ($timeout): $selector" }
+
+ return foundObject
}
fun UiDevice.clickAgreeOnPrivacyDisclaimer() {
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
index 07ea1aeca1..bc2481e55f 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/interactor/AppInteractor.kt
@@ -52,15 +52,6 @@ class AppInteractor(
ensureLoggedIn()
}
- fun launchAndCreateAccount() {
- launch()
- device.clickAgreeOnPrivacyDisclaimer()
- device.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove()
- waitForLoginPrompt()
- attemptCreateAccount()
- ensureAccountCreated()
- }
-
fun attemptLogin(accountNumber: String) {
val loginObject =
device.findObjectWithTimeout(By.clazz("android.widget.EditText")).apply {
diff --git a/android/test/e2e/build.gradle.kts b/android/test/e2e/build.gradle.kts
index 2e9d19b83c..fa59f81940 100644
--- a/android/test/e2e/build.gradle.kts
+++ b/android/test/e2e/build.gradle.kts
@@ -46,6 +46,7 @@ android {
put("clearPackageData", "true")
addOptionalPropertyAsArgument("valid_test_account_number")
addOptionalPropertyAsArgument("invalid_test_account_number")
+ addOptionalPropertyAsArgument("enable_highly_rate_limited_tests")
}
}
@@ -142,4 +143,12 @@ dependencies {
implementation(libs.kotlin.stdlib)
androidTestUtil(libs.androidx.test.orchestrator)
+
+ // Needed or else the app crashes when launched
+ implementation(Dependencies.junit5AndroidTestCompose)
+ implementation(libs.compose.material3)
+
+ // Need these for forcing later versions of dependencies
+ implementation(libs.compose.ui)
+ implementation(libs.androidx.activity.compose)
}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
index 2efb299246..bfcc1181dd 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
@@ -5,8 +5,8 @@ import net.mullvad.mullvadvpn.test.common.constant.LOGIN_FAILURE_TIMEOUT
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+import net.mullvad.mullvadvpn.test.e2e.annotations.HighlyRateLimited
import net.mullvad.mullvadvpn.test.e2e.misc.AccountTestRule
-import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
@@ -27,7 +27,7 @@ class LoginTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
}
@Test
- @Disabled("Disabled to avoid getting rate-limited.")
+ @HighlyRateLimited
fun testLoginWithInvalidCredentials() {
// Given
val invalidDummyAccountNumber = accountTestRule.invalidAccountNumber
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
index 4d77c2a33a..7a8c8818f4 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LogoutTest.kt
@@ -23,17 +23,4 @@ class LogoutTest : EndToEndTest(BuildConfig.FLAVOR_infrastructure) {
// Then
assertNotNull(device.findObjectWithTimeout(By.text("Login")))
}
-
- @Test
- fun testCreateAccountAndLogout() {
- // Given
- app.launchAndCreateAccount()
-
- // When
- app.clickAccountCog()
- app.clickActionButtonByText("Log out")
-
- // Then
- assertNotNull(device.findObjectWithTimeout(By.text("Login")))
- }
}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/annotations/HighlyRateLimited.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/annotations/HighlyRateLimited.kt
new file mode 100644
index 0000000000..a923e03b46
--- /dev/null
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/annotations/HighlyRateLimited.kt
@@ -0,0 +1,37 @@
+package net.mullvad.mullvadvpn.test.e2e.annotations
+
+import androidx.test.platform.app.InstrumentationRegistry
+import net.mullvad.mullvadvpn.test.e2e.constant.ENABLE_HIGHLY_RATE_LIMITED
+import org.junit.jupiter.api.extension.ConditionEvaluationResult
+import org.junit.jupiter.api.extension.ExecutionCondition
+import org.junit.jupiter.api.extension.ExtendWith
+import org.junit.jupiter.api.extension.ExtensionContext
+
+/**
+ * Annotation for tests making use of API endpoints/requests that are highly rate limited such as
+ * failed login requests.
+ */
+@Retention(AnnotationRetention.RUNTIME)
+@ExtendWith(HighlyRateLimited.ShouldRunWhenSeverelyAffectedByRateLimiting::class)
+annotation class HighlyRateLimited {
+ class ShouldRunWhenSeverelyAffectedByRateLimiting : ExecutionCondition {
+ override fun evaluateExecutionCondition(
+ context: ExtensionContext?
+ ): ConditionEvaluationResult {
+ val enableHighlyRateLimited =
+ InstrumentationRegistry.getArguments()
+ .getString(ENABLE_HIGHLY_RATE_LIMITED)
+ ?.toBoolean() ?: false
+
+ if (enableHighlyRateLimited) {
+ return ConditionEvaluationResult.enabled(
+ "Running test highly affected by rate limiting."
+ )
+ } else {
+ return ConditionEvaluationResult.disabled(
+ "Skipping test highly affected by rate limiting."
+ )
+ }
+ }
+ }
+}
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/constant/Constants.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/constant/Constants.kt
index baf3dcae3d..6dbda8f57e 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/constant/Constants.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/constant/Constants.kt
@@ -4,3 +4,4 @@ const val LOG_TAG = "mullvad-e2e"
const val PARTNER_AUTH = "partner_auth"
const val VALID_TEST_ACCOUNT_NUMBER_ARGUMENT_KEY = "valid_test_account_number"
const val INVALID_TEST_ACCOUNT_NUMBER_ARGUMENT_KEY = "invalid_test_account_number"
+const val ENABLE_HIGHLY_RATE_LIMITED = "enable_highly_rate_limited_tests"
diff --git a/android/test/firebase/e2e-play-stagemole.yml b/android/test/firebase/e2e-play-stagemole.yml
index a3b48c5699..9d3fe92eff 100644
--- a/android/test/firebase/e2e-play-stagemole.yml
+++ b/android/test/firebase/e2e-play-stagemole.yml
@@ -16,3 +16,6 @@ default:
- {model: blueline, version: 28, locale: en, orientation: portrait} # pixel 3
- {model: cactus, version: 27, locale: en, orientation: portrait} # redmi 6a
- {model: starqlteue, version: 26, locale: en, orientation: portrait} # galaxy s9
+ environment-variables:
+ clearPackageData: "true"
+ runnerBuilder: "de.mannodermaus.junit5.AndroidJUnit5Builder"
diff --git a/android/test/mockapi/build.gradle.kts b/android/test/mockapi/build.gradle.kts
index cc13c6dbed..78994f610a 100644
--- a/android/test/mockapi/build.gradle.kts
+++ b/android/test/mockapi/build.gradle.kts
@@ -88,4 +88,12 @@ dependencies {
implementation(libs.mockkWebserver)
androidTestUtil(libs.androidx.test.orchestrator)
+
+ // Needed or else the app crashes when launched
+ implementation(Dependencies.junit5AndroidTestCompose)
+ implementation(libs.compose.material3)
+
+ // Need these for forcing later versions of dependencies
+ implementation(libs.compose.ui)
+ implementation(libs.androidx.activity.compose)
}