Skip to content

Commit

Permalink
Fix for failing mockapi and e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasberglund committed Aug 19, 2024
1 parent 58a811f commit 89ea752
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 37 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/android-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,9 @@ jobs:
- test-type: app
path: android/app/build/outputs/apk
test-repeat: 1
# Disabled (test-repeat='0') due to flakiness unless overridden by input.
- test-type: mockapi
path: android/test/mockapi/build/outputs/apk
test-repeat: ${{ github.event.inputs.mockapi_test_repeat || 0 }}
test-repeat: ${{ github.event.inputs.mockapi_test_repeat || 1 }}
steps:
- name: Prepare report dir
if: ${{ matrix.test-repeat != 0 }}
Expand Down Expand Up @@ -470,7 +469,8 @@ jobs:

instrumented-e2e-tests:
name: Run instrumented e2e tests
runs-on: [self-hosted, android-device]
# Temporary workaround for targeting the runner android-runner-v1
runs-on: [self-hosted, android-device, android-emulator]
if: github.event_name == 'schedule' || github.event.inputs.run_e2e_tests == 'true'
timeout-minutes: 30
needs: [build-app, build-instrumented-tests]
Expand Down Expand Up @@ -507,6 +507,7 @@ jobs:
INFRA_FLAVOR: prod
VALID_TEST_ACCOUNT_NUMBER: ${{ secrets.ANDROID_PROD_TEST_ACCOUNT }}
INVALID_TEST_ACCOUNT_NUMBER: '0000000000000000'
ENABLE_HIGHLY_RATE_LIMITED_TESTS: ${{ github.event_name == 'schedule' && 'true' || 'false' }}
REPORT_DIR: ${{ steps.prepare-report-dir.outputs.report_dir }}
run: ./android/scripts/run-instrumented-tests.sh

Expand All @@ -521,6 +522,7 @@ jobs:
clearPackageData=true,\
runnerBuilder=de.mannodermaus.junit5.AndroidJUnit5Builder,\
invalid_test_account_number=0000000000000000,\
enable_highly_rate_limited_tests=${{ github.event_name == 'schedule' && 'true' || 'false' }},\
partner_auth=${{ secrets.STAGEMOLE_PARTNER_AUTH }}"
strategy:
fail-fast: false
Expand Down
3 changes: 3 additions & 0 deletions android/BuildInstructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
2 changes: 1 addition & 1 deletion android/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
2 changes: 2 additions & 0 deletions android/scripts/run-instrumented-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions android/test/e2e/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ android {
put("clearPackageData", "true")
addOptionalPropertyAsArgument("valid_test_account_number")
addOptionalPropertyAsArgument("invalid_test_account_number")
addOptionalPropertyAsArgument("enable_highly_rate_limited_tests")
}
}

Expand Down Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")))
}
}
Original file line number Diff line number Diff line change
@@ -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."
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
3 changes: 3 additions & 0 deletions android/test/firebase/e2e-play-stagemole.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
8 changes: 8 additions & 0 deletions android/test/mockapi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit 89ea752

Please sign in to comment.