summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/android-app.yml2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/AccountRepository.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/DeviceRepository.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSource.kt1
-rwxr-xr-xandroid/scripts/run-instrumented-tests-repeat.sh15
-rw-r--r--android/test/mockapi/build.gradle.kts1
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt4
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt12
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt26
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/DateTimeUtils.kt13
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/JsonUtils.kt (renamed from android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/JsonUtils.kt)15
12 files changed, 63 insertions, 33 deletions
diff --git a/.github/workflows/android-app.yml b/.github/workflows/android-app.yml
index c2dd84ee99..f800fbe138 100644
--- a/.github/workflows/android-app.yml
+++ b/.github/workflows/android-app.yml
@@ -151,7 +151,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- test-type: [app]
+ test-type: [app, mockapi]
steps:
- name: Checkout repository
uses: actions/checkout@v3
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/AccountRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/AccountRepository.kt
index a402d985f9..9d59ff6843 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/AccountRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/AccountRepository.kt
@@ -43,9 +43,6 @@ class AccountRepository(
.flatMapReadyConnectionOrDefault(flowOf()) { state ->
state.container.accountDataSource.accountExpiry
}
- .onStart {
- fetchAccountExpiry()
- }
.stateIn(
CoroutineScope(dispatcher),
SharingStarted.WhileSubscribed(),
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/DeviceRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/DeviceRepository.kt
index 044888e9af..bd47e8719f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/DeviceRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/DeviceRepository.kt
@@ -30,9 +30,6 @@ class DeviceRepository(
.flatMapLatest { state ->
if (state is ServiceConnectionState.ConnectedReady) {
state.container.deviceDataSource.deviceStateUpdates
- .onStart {
- state.container.deviceDataSource.getDevice()
- }
} else {
flowOf(DeviceState.Unknown)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt
index 23edd1efbf..05f6740a42 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt
@@ -26,6 +26,7 @@ class ServiceConnectionAccountDataSource(
trySend(event.expiry)
}
dispatcher.registerHandler(Event.AccountExpiryEvent::class, handler)
+ connection.send(Request.FetchAccountExpiry.message)
awaitClose {
// The current dispatcher doesn't support unregistration of handlers.
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSource.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSource.kt
index 56e7ee4d28..39159a1a17 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSource.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSource.kt
@@ -17,6 +17,7 @@ class ServiceConnectionDeviceDataSource(
trySend(event.newState)
}
dispatcher.registerHandler(Event.DeviceStateEvent::class, handler)
+ connection.trySendRequest(Request.GetDevice, false)
awaitClose {
// The current dispatcher doesn't support unregistration of handlers.
}
diff --git a/android/scripts/run-instrumented-tests-repeat.sh b/android/scripts/run-instrumented-tests-repeat.sh
new file mode 100755
index 0000000000..146cbf3d05
--- /dev/null
+++ b/android/scripts/run-instrumented-tests-repeat.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+
+set -eu
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd "$SCRIPT_DIR"
+
+TEST_TYPE=$1
+REPEAT_COUNT=$2
+
+for ((i=1; i <= REPEAT_COUNT; i++))
+do
+ echo "### Run $i ###"
+ ./run-instrumented-tests.sh "$TEST_TYPE"
+done
diff --git a/android/test/mockapi/build.gradle.kts b/android/test/mockapi/build.gradle.kts
index cbdd8c0295..5ac80e2ea5 100644
--- a/android/test/mockapi/build.gradle.kts
+++ b/android/test/mockapi/build.gradle.kts
@@ -54,6 +54,7 @@ dependencies {
implementation(Dependencies.AndroidX.testRunner)
implementation(Dependencies.AndroidX.testRules)
implementation(Dependencies.AndroidX.testUiAutomator)
+ implementation(Dependencies.jodaTime)
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.mockkWebserver)
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
index 60bd0e293a..4626468026 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/Extensions.kt
@@ -1,5 +1,7 @@
package net.mullvad.mullvadvpn.test.mockapi
+import android.util.Log
+import net.mullvad.mullvadvpn.test.mockapi.constant.LOG_TAG
import okhttp3.mockwebserver.MockResponse
import okio.Buffer
import org.json.JSONException
@@ -13,6 +15,8 @@ fun Buffer.getAccountToken(): String? {
return try {
JSONObject(readUtf8()).getString("account_number")
} catch (ex: JSONException) {
+ Log.e(LOG_TAG, "Unable to parse account number")
+ ex.printStackTrace()
null
}
}
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
index 51d0ac7ee6..ef118d35e2 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
@@ -2,10 +2,9 @@ package net.mullvad.mullvadvpn.test.mockapi
import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.By
-import java.time.OffsetDateTime
-import java.time.temporal.ChronoUnit
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel31AndAbove
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
+import net.mullvad.mullvadvpn.test.mockapi.util.currentUtcTimeWithOffsetZero
import org.junit.Test
import org.junit.runner.RunWith
@@ -17,8 +16,7 @@ class LoginMockApiTest : MockApiTest() {
val validAccountToken = "1234123412341234"
apiDispatcher.apply {
expectedAccountToken = null
- accountExpiry =
- OffsetDateTime.now().plusDays(1).truncatedTo(ChronoUnit.SECONDS)
+ accountExpiry = currentUtcTimeWithOffsetZero().plusDays(1)
}
app.launch(endpoint)
@@ -37,8 +35,7 @@ class LoginMockApiTest : MockApiTest() {
val validAccountToken = "1234123412341234"
apiDispatcher.apply {
expectedAccountToken = validAccountToken
- accountExpiry =
- OffsetDateTime.now().plusDays(1).truncatedTo(ChronoUnit.SECONDS)
+ accountExpiry = currentUtcTimeWithOffsetZero().plusDays(1)
}
// Act
@@ -57,8 +54,7 @@ class LoginMockApiTest : MockApiTest() {
val validAccountToken = "1234123412341234"
apiDispatcher.apply {
expectedAccountToken = validAccountToken
- accountExpiry =
- OffsetDateTime.now().minusDays(1).truncatedTo(ChronoUnit.SECONDS)
+ accountExpiry = currentUtcTimeWithOffsetZero().minusDays(1)
}
// Act
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
index b41ad34fa6..e3708a47f1 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiDispatcher.kt
@@ -1,29 +1,30 @@
package net.mullvad.mullvadvpn.test.mockapi
import android.util.Log
-import java.time.OffsetDateTime
-import java.time.temporal.ChronoUnit
import net.mullvad.mullvadvpn.test.mockapi.constant.ACCOUNT_URL_PATH
import net.mullvad.mullvadvpn.test.mockapi.constant.AUTH_TOKEN_URL_PATH
import net.mullvad.mullvadvpn.test.mockapi.constant.DEVICES_URL_PATH
import net.mullvad.mullvadvpn.test.mockapi.constant.DUMMY_ACCESS_TOKEN
import net.mullvad.mullvadvpn.test.mockapi.constant.DUMMY_DEVICE_NAME
import net.mullvad.mullvadvpn.test.mockapi.constant.DUMMY_ID
+import net.mullvad.mullvadvpn.test.mockapi.constant.LOG_TAG
+import net.mullvad.mullvadvpn.test.mockapi.util.currentUtcTimeWithOffsetZero
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
import okio.Buffer
+import org.joda.time.DateTime
import org.json.JSONArray
class MockApiDispatcher : Dispatcher() {
var expectedAccountToken: String? = null
- var accountExpiry: OffsetDateTime? = null
+ var accountExpiry: DateTime? = null
private var cachedPubKeyFromAppUnderTest: String? = null
override fun dispatch(request: RecordedRequest): MockResponse {
- Log.d("mullvad", "Request: $request")
+ Log.d(LOG_TAG, "Request: $request (body=${request.body.peek().readUtf8()})")
return when (request.path) {
AUTH_TOKEN_URL_PATH -> handleLoginRequest(request.body)
DEVICES_URL_PATH -> {
@@ -36,6 +37,8 @@ class MockApiDispatcher : Dispatcher() {
"$DEVICES_URL_PATH/$DUMMY_ID" -> handleDeviceInfoRequest()
ACCOUNT_URL_PATH -> handleAccountInfoRequest()
else -> MockResponse().setResponseCode(404)
+ }.also { response ->
+ Log.d(LOG_TAG, "Response: $response (body=${response.getBody()?.peek()?.readUtf8()})")
}
}
@@ -49,10 +52,14 @@ class MockApiDispatcher : Dispatcher() {
.setBody(
accessTokenJsonResponse(
accessToken = DUMMY_ACCESS_TOKEN,
- expiry = OffsetDateTime.now().plusDays(1).truncatedTo(ChronoUnit.SECONDS)
+ expiry = currentUtcTimeWithOffsetZero().plusDays(1)
).toString()
)
} else {
+ Log.e(
+ LOG_TAG,
+ "Unexpected account token (expected=$expectedAccountToken was=$accountToken)"
+ )
MockResponse().setResponseCode(400)
}
}
@@ -81,8 +88,7 @@ class MockApiDispatcher : Dispatcher() {
id = DUMMY_ID,
name = DUMMY_DEVICE_NAME,
publicKey = cachedKey,
- creationDate = OffsetDateTime.now().minusDays(1)
- .truncatedTo(ChronoUnit.SECONDS)
+ creationDate = currentUtcTimeWithOffsetZero().minusDays(1)
).toString()
)
} ?: MockResponse().setResponseCode(400)
@@ -102,8 +108,7 @@ class MockApiDispatcher : Dispatcher() {
id = DUMMY_ID,
name = DUMMY_DEVICE_NAME,
publicKey = newKey,
- creationDate = OffsetDateTime.now().minusDays(1)
- .truncatedTo(ChronoUnit.SECONDS)
+ creationDate = currentUtcTimeWithOffsetZero().minusDays(1)
).toString()
)
} ?: MockResponse().setResponseCode(400)
@@ -120,8 +125,7 @@ class MockApiDispatcher : Dispatcher() {
id = DUMMY_ID,
name = DUMMY_DEVICE_NAME,
publicKey = cachedKey,
- creationDate = OffsetDateTime.now().minusDays(1)
- .truncatedTo(ChronoUnit.SECONDS)
+ creationDate = currentUtcTimeWithOffsetZero().minusDays(1)
)
).toString()
)
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/DateTimeUtils.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/DateTimeUtils.kt
new file mode 100644
index 0000000000..81042f70d2
--- /dev/null
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/DateTimeUtils.kt
@@ -0,0 +1,13 @@
+package net.mullvad.mullvadvpn.test.mockapi.util
+
+import org.joda.time.DateTime
+import org.joda.time.DateTimeZone
+import org.joda.time.format.DateTimeFormat
+
+private const val STRICT_ISO8601_AND_RFC3339_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZ"
+
+fun currentUtcTimeWithOffsetZero() = DateTime.now(DateTimeZone.forOffsetHours(0))
+
+fun DateTime.formatStrictlyAccordingToIso8601AndRfc3339(): String {
+ return toString(DateTimeFormat.forPattern(STRICT_ISO8601_AND_RFC3339_PATTERN))
+}
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/JsonUtils.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/JsonUtils.kt
index d6ee2bc6cb..145cbafbd2 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/JsonUtils.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/util/JsonUtils.kt
@@ -1,15 +1,16 @@
package net.mullvad.mullvadvpn.test.mockapi
-import java.time.OffsetDateTime
+import net.mullvad.mullvadvpn.test.mockapi.util.formatStrictlyAccordingToIso8601AndRfc3339
+import org.joda.time.DateTime
import org.json.JSONArray
import org.json.JSONObject
fun accountInfoJson(
id: String,
- expiry: OffsetDateTime
+ expiry: DateTime
) = JSONObject().apply {
put("id", id)
- put("expiry", expiry.toString())
+ put("expiry", expiry.formatStrictlyAccordingToIso8601AndRfc3339())
put("max_ports", 5)
put("can_add_ports", true)
put("max_devices", 5)
@@ -20,13 +21,13 @@ fun deviceJson(
id: String,
name: String,
publicKey: String,
- creationDate: OffsetDateTime
+ creationDate: DateTime
) = JSONObject().apply {
put("id", id)
put("name", name)
put("pubkey", publicKey)
put("hijack_dns", true)
- put("created", creationDate.toString())
+ put("created", creationDate.formatStrictlyAccordingToIso8601AndRfc3339())
put("ipv4_address", "127.0.0.1/32")
put("ipv6_address", "fc00::1/128")
put("ports", JSONArray())
@@ -34,8 +35,8 @@ fun deviceJson(
fun accessTokenJsonResponse(
accessToken: String,
- expiry: OffsetDateTime
+ expiry: DateTime
) = JSONObject().apply {
put("access_token", accessToken)
- put("expiry", expiry.toString())
+ put("expiry", expiry.formatStrictlyAccordingToIso8601AndRfc3339())
}