Все картинки в отчёте
This commit is contained in:
@@ -28,10 +28,6 @@ android {
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
testInstrumentationRunnerArguments["yandex.oauth.token"] =
|
||||
localProps.getProperty("yandex.test.oauth.token").orEmpty()
|
||||
testInstrumentationRunnerArguments["yandex.user.id"] =
|
||||
localProps.getProperty("yandex.test.user.id").orEmpty()
|
||||
testInstrumentationRunnerArguments["yandex.vault.uuid"] =
|
||||
localProps.getProperty("yandex.test.vault.uuid").orEmpty()
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.github.nullptroma.wallenc.app.integration.yandex
|
||||
|
||||
import android.util.Log
|
||||
import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.github.nullptroma.wallenc.infrastructure.android.db.app.AppDb
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
/**
|
||||
* Ручной helper: после входа в Yandex через приложение печатает в Logcat маскированный
|
||||
* токен и подсказку для local.properties. Запускать вручную из Android Studio.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@Ignore("Manual: export Yandex credentials to local.properties")
|
||||
class ExportYandexTestCredentialsTest {
|
||||
|
||||
@Test
|
||||
fun printFirstAccountCredentialsToLogcat() {
|
||||
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
|
||||
val db = Room.databaseBuilder(context, AppDb::class.java, "wallenc.db")
|
||||
.build()
|
||||
try {
|
||||
val row = runBlocking {
|
||||
db.yandexAccountDao.observeAll().first().firstOrNull()
|
||||
}
|
||||
if (row == null) {
|
||||
Log.i(TAG, "No Yandex accounts in DB. Link a vault in the app first.")
|
||||
return
|
||||
}
|
||||
Log.i(TAG, "Add to local.properties:")
|
||||
Log.i(TAG, "yandex.test.oauth.token=<copy full token from app debug storage if needed>")
|
||||
Log.i(TAG, "yandex.test.oauth.token.prefix=${maskToken(row.oauthToken)}")
|
||||
Log.i(TAG, "yandex.test.user.id=${row.yandexUserId}")
|
||||
Log.i(TAG, "yandex.test.vault.uuid=${row.vaultUuid}")
|
||||
} finally {
|
||||
db.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun maskToken(token: String): String {
|
||||
if (token.length <= 8) return "***"
|
||||
return token.take(4) + "…" + token.takeLast(4)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "WallencYandexExport"
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,15 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
|
||||
/**
|
||||
* Live-прогон Disk API. Пути только `app:/` — как в [YandexVault]; токен из Auth SDK
|
||||
* обычно имеет `cloud_api:disk.app_folder`, без полного доступа к `disk:/` (там 403).
|
||||
*/
|
||||
@RunWith(JUnit4::class)
|
||||
class YandexDiskLiveIntegrationTest {
|
||||
|
||||
private lateinit var repository: YandexDiskRepository
|
||||
private val testFolder = "disk:/wallenc-integration-test"
|
||||
private val testFolder = "app:/wallenc-integration-test"
|
||||
private val probeFileName = "wallenc-probe.txt"
|
||||
private val probePath = "$testFolder/$probeFileName"
|
||||
private val probePayload = "wallenc-integration-probe".encodeToByteArray()
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.github.nullptroma.wallenc.app.sync
|
||||
|
||||
import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncPaths
|
||||
import com.github.nullptroma.wallenc.domain.interfaces.IStorageSyncGroupStore
|
||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||
import com.github.nullptroma.wallenc.domain.tasks.StorageSyncTriggerReason
|
||||
import com.github.nullptroma.wallenc.usecases.RunStorageSyncUseCase
|
||||
import com.github.nullptroma.wallenc.usecases.StorageSyncReadiness
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
@@ -13,13 +11,10 @@ import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -29,15 +24,11 @@ class StorageSyncBootstrap @Inject constructor(
|
||||
private val scheduler: StorageSyncScheduler,
|
||||
private val vaultsManager: IVaultsManager,
|
||||
private val syncRunner: RunStorageSyncUseCase,
|
||||
private val syncReadiness: StorageSyncReadiness,
|
||||
private val groupStore: IStorageSyncGroupStore,
|
||||
) {
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
private val startupSyncScheduled = AtomicBoolean(false)
|
||||
|
||||
fun start() {
|
||||
scheduler.ensureScheduled()
|
||||
scheduleStartupSyncOnce()
|
||||
scope.launch {
|
||||
combine(
|
||||
vaultsManager.allStorages,
|
||||
@@ -86,31 +77,4 @@ class StorageSyncBootstrap @Inject constructor(
|
||||
}
|
||||
return System.currentTimeMillis() >= syncRunner.debounceSuppressUntilMs.value
|
||||
}
|
||||
|
||||
/**
|
||||
* Одна синхронизация после готовности хранилищ при старте процесса — не ждать только WorkManager
|
||||
* (особенно если periodic work откладывался из‑за перезапусков процесса).
|
||||
*/
|
||||
private fun scheduleStartupSyncOnce() {
|
||||
scope.launch {
|
||||
combine(
|
||||
vaultsManager.allStorages,
|
||||
vaultsManager.unlockManager.openedStorages,
|
||||
) { rootStorages, opened ->
|
||||
(rootStorages + opened.values).distinctBy { it.uuid }
|
||||
}
|
||||
.map { it.isNotEmpty() }
|
||||
.distinctUntilChanged()
|
||||
.filter { it }
|
||||
.first()
|
||||
if (!startupSyncScheduled.compareAndSet(false, true)) {
|
||||
return@launch
|
||||
}
|
||||
if (groupStore.getGroups().isEmpty()) {
|
||||
return@launch
|
||||
}
|
||||
syncReadiness.awaitReady()
|
||||
syncRunner.enqueue(StorageSyncTriggerReason.Background)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user