Enable automatic coding style linting with ktlint (also on CI)
This way the coding style is guaranteed to stay consistent.
This commit is contained in:
parent
53937bda2f
commit
6c531066e7
31 changed files with 167 additions and 70 deletions
4
.editorconfig
Normal file
4
.editorconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
[*.{kt,kts}]
|
||||
indent_size=4
|
||||
insert_final_newline=true
|
||||
max_line_length=100
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,6 +9,7 @@ out/
|
|||
lib/
|
||||
.idea/*
|
||||
!.idea/runConfigurations*
|
||||
!.idea/inspectionProfiles*
|
||||
!.idea/codeStyles*
|
||||
*.ipr
|
||||
*.iws
|
||||
|
|
|
@ -131,6 +131,16 @@
|
|||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="LINE_COMMENT_ADD_SPACE" value="true" />
|
||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
|
||||
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
|
||||
<option name="ENUM_CONSTANTS_WRAP" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
|
|
10
.idea/inspectionProfiles/Project_Default.xml
Normal file
10
.idea/inspectionProfiles/Project_Default.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AndroidLintMangledCRLF" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="LongLine" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
<inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
|
@ -24,7 +24,7 @@ before_cache:
|
|||
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
|
||||
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
|
||||
|
||||
script: ./gradlew check assemble
|
||||
script: ./gradlew check assemble ktlintCheck
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import groovy.xml.XmlUtil
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
id "kotlin-android"
|
||||
id "org.jlleitschuh.gradle.ktlint" version "9.4.0"
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
|
@ -74,6 +77,17 @@ android {
|
|||
|
||||
apply from: '../gradle/dependencies.gradle'
|
||||
|
||||
ktlint {
|
||||
version = "0.36.0" // https://github.com/pinterest/ktlint/issues/764
|
||||
android = true
|
||||
enableExperimentalRules = false
|
||||
verbose = true
|
||||
disabledRules = [
|
||||
"import-ordering",
|
||||
"no-blank-line-before-rbrace",
|
||||
]
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
tasks.withType(JavaCompile) {
|
||||
if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
|
||||
|
@ -92,9 +106,14 @@ preBuild.doLast {
|
|||
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
|
||||
parsedXml.component[1].remove(jdkNode)
|
||||
|
||||
def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
|
||||
def apiString = android.compileSdkVersion.substring("android-".length())
|
||||
def sdkString = "Android API " + apiString + " Platform"
|
||||
//noinspection GroovyResultOfObjectAllocationIgnored // the note gets inserted
|
||||
new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
|
||||
new Node(parsedXml.component[1], 'orderEntry', [
|
||||
'type' : 'jdk',
|
||||
'jdkName': sdkString,
|
||||
'jdkType': 'Android SDK'
|
||||
])
|
||||
XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
|
||||
|
||||
} catch (NullPointerException | FileNotFoundException ex) {
|
||||
|
|
|
@ -56,7 +56,7 @@ class App : Application() {
|
|||
cryptoModule,
|
||||
headerModule,
|
||||
metadataModule,
|
||||
documentsProviderModule, // storage plugin
|
||||
documentsProviderModule, // storage plugin
|
||||
backupModule,
|
||||
restoreModule,
|
||||
appModule
|
||||
|
|
|
@ -69,7 +69,9 @@ abstract class UsbMonitor : BroadcastReceiver() {
|
|||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action ?: return
|
||||
if (intent.action == ACTION_USB_DEVICE_ATTACHED || intent.action == ACTION_USB_DEVICE_DETACHED) {
|
||||
if (intent.action == ACTION_USB_DEVICE_ATTACHED ||
|
||||
intent.action == ACTION_USB_DEVICE_DETACHED
|
||||
) {
|
||||
val device = intent.extras?.getParcelable<UsbDevice>(EXTRA_DEVICE) ?: return
|
||||
Log.d(TAG, "New USB mass-storage device attached.")
|
||||
device.log()
|
||||
|
|
|
@ -115,7 +115,8 @@ internal class CryptoImpl(
|
|||
val cipher = cipherFactory.createEncryptionCipher()
|
||||
|
||||
check(cipher.getOutputSize(cleartext.size) <= MAX_SEGMENT_LENGTH) {
|
||||
"Cipher's output size ${cipher.getOutputSize(cleartext.size)} is larger than maximum segment length ($MAX_SEGMENT_LENGTH)"
|
||||
"Cipher's output size ${cipher.getOutputSize(cleartext.size)} is larger" +
|
||||
"than maximum segment length ($MAX_SEGMENT_LENGTH)"
|
||||
}
|
||||
encryptSegment(cipher, outputStream, cleartext)
|
||||
}
|
||||
|
@ -162,9 +163,9 @@ internal class CryptoImpl(
|
|||
"expected '$expectedPackageName'."
|
||||
)
|
||||
}
|
||||
if (header.key != expectedKey) {
|
||||
throw SecurityException("Invalid key '${header.key}' in header, expected '$expectedKey'.")
|
||||
}
|
||||
if (header.key != expectedKey) throw SecurityException(
|
||||
"Invalid key '${header.key}' in header, expected '$expectedKey'."
|
||||
)
|
||||
|
||||
return header
|
||||
}
|
||||
|
@ -190,9 +191,9 @@ internal class CryptoImpl(
|
|||
@Throws(EOFException::class, IOException::class, SecurityException::class)
|
||||
private fun decryptSegment(inputStream: InputStream, maxSegmentLength: Int): ByteArray {
|
||||
val segmentHeader = headerReader.readSegmentHeader(inputStream)
|
||||
if (segmentHeader.segmentLength > maxSegmentLength) {
|
||||
throw SecurityException("Segment length too long: ${segmentHeader.segmentLength} > $maxSegmentLength")
|
||||
}
|
||||
if (segmentHeader.segmentLength > maxSegmentLength) throw SecurityException(
|
||||
"Segment length too long: ${segmentHeader.segmentLength} > $maxSegmentLength"
|
||||
)
|
||||
|
||||
val buffer = ByteArray(segmentHeader.segmentLength.toInt())
|
||||
val bytesRead = inputStream.read(buffer)
|
||||
|
|
|
@ -22,7 +22,9 @@ data class VersionHeader(
|
|||
"Package $packageName has name longer than $MAX_PACKAGE_LENGTH_SIZE"
|
||||
}
|
||||
key?.let {
|
||||
check(key.length <= MAX_KEY_LENGTH_SIZE) { "Key $key is longer than $MAX_KEY_LENGTH_SIZE" }
|
||||
check(key.length <= MAX_KEY_LENGTH_SIZE) {
|
||||
"Key $key is longer than $MAX_KEY_LENGTH_SIZE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,15 +33,21 @@ internal class HeaderReaderImpl : HeaderReader {
|
|||
|
||||
val packageLength = buffer.short.toInt()
|
||||
if (packageLength <= 0) throw SecurityException("Invalid package length: $packageLength")
|
||||
if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException("Too large package length: $packageLength")
|
||||
if (packageLength > buffer.remaining()) throw SecurityException("Not enough bytes for package name")
|
||||
if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException(
|
||||
"Too large package length: $packageLength"
|
||||
)
|
||||
if (packageLength > buffer.remaining()) throw SecurityException(
|
||||
"Not enough bytes for package name"
|
||||
)
|
||||
val packageName = ByteArray(packageLength)
|
||||
.apply { buffer.get(this) }
|
||||
.toString(Utf8)
|
||||
|
||||
val keyLength = buffer.short.toInt()
|
||||
if (keyLength < 0) throw SecurityException("Invalid key length: $keyLength")
|
||||
if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException("Too large key length: $keyLength")
|
||||
if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException(
|
||||
"Too large key length: $keyLength"
|
||||
)
|
||||
if (keyLength > buffer.remaining()) throw SecurityException("Not enough bytes for key")
|
||||
val key = if (keyLength == 0) null else ByteArray(keyLength)
|
||||
.apply { buffer.get(this) }
|
||||
|
|
|
@ -80,7 +80,8 @@ class MetadataManager(
|
|||
"APK backup returned version null"
|
||||
}
|
||||
check(it.version == null || it.version < packageMetadata.version) {
|
||||
"APK backup backed up the same or a smaller version: was ${it.version} is ${packageMetadata.version}"
|
||||
"APK backup backed up the same or a smaller version:" +
|
||||
"was ${it.version} is ${packageMetadata.version}"
|
||||
}
|
||||
}
|
||||
val oldPackageMetadata = metadata.packageMetadataMap[packageName]
|
||||
|
|
|
@ -78,9 +78,9 @@ internal class MetadataReaderImpl(private val crypto: Crypto) : MetadataReader {
|
|||
)
|
||||
}
|
||||
val token = meta.getLong(JSON_METADATA_TOKEN)
|
||||
if (expectedToken != null && token != expectedToken) {
|
||||
throw SecurityException("Invalid token '$token' in metadata, expected '$expectedToken'.")
|
||||
}
|
||||
if (expectedToken != null && token != expectedToken) throw SecurityException(
|
||||
"Invalid token '$token' in metadata, expected '$expectedToken'."
|
||||
)
|
||||
// get package metadata
|
||||
val packageMetadataMap = PackageMetadataMap()
|
||||
for (packageName in json.keys()) {
|
||||
|
|
|
@ -15,7 +15,9 @@ internal const val REQUEST_CODE_UNINSTALL = 4576841
|
|||
class RestoreErrorBroadcastReceiver : BroadcastReceiver() {
|
||||
|
||||
// using KoinComponent would crash robolectric tests :(
|
||||
private val notificationManager: BackupNotificationManager by lazy { get().get<BackupNotificationManager>() }
|
||||
private val notificationManager: BackupNotificationManager by lazy {
|
||||
get().get<BackupNotificationManager>()
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action != ACTION_RESTORE_ERROR_UNINSTALL) return
|
||||
|
@ -24,7 +26,7 @@ class RestoreErrorBroadcastReceiver : BroadcastReceiver() {
|
|||
|
||||
val packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME)!!
|
||||
|
||||
@Suppress("DEPRECATION") // the alternative doesn't work for us
|
||||
@Suppress("DEPRECATION") // the alternative doesn't work for us
|
||||
val i = Intent(Intent.ACTION_UNINSTALL_PACKAGE).apply {
|
||||
data = "package:$packageName".toUri()
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
|
|
|
@ -186,7 +186,9 @@ internal class RestoreViewModel(
|
|||
// we need to start a new session and retrieve the restore sets before starting the restore
|
||||
val restoreSetResult = getAvailableRestoreSets()
|
||||
if (restoreSetResult.hasError()) {
|
||||
mRestoreBackupResult.postValue(RestoreBackupResult(app.getString(R.string.restore_finished_error)))
|
||||
mRestoreBackupResult.postValue(
|
||||
RestoreBackupResult(app.getString(R.string.restore_finished_error))
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -196,7 +198,9 @@ internal class RestoreViewModel(
|
|||
if (restoreAllResult != 0) {
|
||||
if (session == null) Log.e(TAG, "session was null")
|
||||
else Log.e(TAG, "restoreAll() returned non-zero value")
|
||||
mRestoreBackupResult.postValue(RestoreBackupResult(app.getString(R.string.restore_finished_error)))
|
||||
mRestoreBackupResult.postValue(
|
||||
RestoreBackupResult(app.getString(R.string.restore_finished_error))
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -306,8 +310,9 @@ internal class RestoreViewModel(
|
|||
val restorableBackups = restoreSets.mapNotNull { set ->
|
||||
getRestorableBackup(set, backupMetadata[set.token])
|
||||
}
|
||||
if (restorableBackups.isEmpty()) RestoreSetResult(app.getString(R.string.restore_set_empty_result))
|
||||
else RestoreSetResult(restorableBackups)
|
||||
if (restorableBackups.isEmpty()) {
|
||||
RestoreSetResult(app.getString(R.string.restore_set_empty_result))
|
||||
} else RestoreSetResult(restorableBackups)
|
||||
}
|
||||
}
|
||||
continuation.resume(result)
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.stevesoltys.seedvault.settings
|
|||
|
||||
import android.app.backup.IBackupManager
|
||||
import android.content.Context
|
||||
import android.content.Context.BACKUP_SERVICE
|
||||
import android.content.Context.BACKUP_SERVICE // ktlint-disable no-unused-imports
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.hardware.usb.UsbDevice
|
||||
|
@ -11,7 +11,7 @@ import android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED
|
|||
import android.os.Bundle
|
||||
import android.os.RemoteException
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE
|
||||
import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE // ktlint-disable no-unused-imports
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
|
|
|
@ -2,10 +2,10 @@ package com.stevesoltys.seedvault.transport
|
|||
|
||||
import android.app.Service
|
||||
import android.app.backup.BackupManager
|
||||
import android.app.backup.BackupManager.FLAG_NON_INCREMENTAL_BACKUP
|
||||
import android.app.backup.BackupManager.FLAG_NON_INCREMENTAL_BACKUP // ktlint-disable no-unused-imports
|
||||
import android.app.backup.IBackupManager
|
||||
import android.content.Context
|
||||
import android.content.Context.BACKUP_SERVICE
|
||||
import android.content.Context.BACKUP_SERVICE // ktlint-disable no-unused-imports
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
|
|
|
@ -79,8 +79,8 @@ class ApkBackup(
|
|||
// do not backup if we have the version already and signatures did not change
|
||||
if (version <= backedUpVersion && !signaturesChanged(packageMetadata, signatures)) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"Package $packageName with version $version already has a backup ($backedUpVersion)" +
|
||||
TAG, "Package $packageName with version $version" +
|
||||
" already has a backup ($backedUpVersion)" +
|
||||
" with the same signature. Not backing it up."
|
||||
)
|
||||
return null
|
||||
|
|
|
@ -327,12 +327,16 @@ internal class BackupCoordinator(
|
|||
*/
|
||||
suspend fun finishBackup(): Int = when {
|
||||
kv.hasState() -> {
|
||||
check(!full.hasState()) { "K/V backup has state, but full backup has dangling state as well" }
|
||||
check(!full.hasState()) {
|
||||
"K/V backup has state, but full backup has dangling state as well"
|
||||
}
|
||||
onPackageBackedUp(kv.getCurrentPackage()!!) // not-null because we have state
|
||||
kv.finishBackup()
|
||||
}
|
||||
full.hasState() -> {
|
||||
check(!kv.hasState()) { "Full backup has state, but K/V backup has dangling state as well" }
|
||||
check(!kv.hasState()) {
|
||||
"Full backup has state, but K/V backup has dangling state as well"
|
||||
}
|
||||
onPackageBackedUp(full.getCurrentPackage()!!) // not-null because we have state
|
||||
full.finishBackup()
|
||||
}
|
||||
|
@ -352,15 +356,17 @@ internal class BackupCoordinator(
|
|||
val packageName = packageInfo.packageName
|
||||
try {
|
||||
nm.onOptOutAppBackup(packageName, i + 1, notAllowedPackages.size)
|
||||
val packageState = if (packageInfo.isStopped()) WAS_STOPPED else NOT_ALLOWED
|
||||
val packageState =
|
||||
if (packageInfo.isStopped()) WAS_STOPPED else NOT_ALLOWED
|
||||
val wasBackedUp = backUpApk(packageInfo, packageState)
|
||||
if (!wasBackedUp) {
|
||||
val packageMetadata = metadataManager.getPackageMetadata(packageName)
|
||||
val packageMetadata =
|
||||
metadataManager.getPackageMetadata(packageName)
|
||||
val oldPackageState = packageMetadata?.state
|
||||
if (oldPackageState != null && oldPackageState != packageState) {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Package $packageName was in $oldPackageState, update to $packageState"
|
||||
TAG, "Package $packageName was in $oldPackageState" +
|
||||
", update to $packageState"
|
||||
)
|
||||
plugin.getMetadataOutputStream().use {
|
||||
metadataManager.onPackageBackupError(packageInfo, packageState, it)
|
||||
|
|
|
@ -62,7 +62,7 @@ internal class ApkInstaller(private val context: Context) {
|
|||
}
|
||||
// Don't set more sessionParams intentionally here.
|
||||
// We saw strange permission issues when doing setInstallReason() or setting installFlags.
|
||||
@Suppress("BlockingMethodInNonBlockingContext") // flows on Dispatcher.IO
|
||||
@Suppress("BlockingMethodInNonBlockingContext") // flows on Dispatcher.IO
|
||||
val session = installer.openSession(installer.createSession(sessionParams))
|
||||
val sizeBytes = cachedApk.length()
|
||||
session.use { s ->
|
||||
|
@ -96,7 +96,9 @@ internal class ApkInstaller(private val context: Context) {
|
|||
val success = i.getIntExtra(EXTRA_STATUS, -1) == STATUS_SUCCESS
|
||||
val statusMsg = i.getStringExtra(EXTRA_STATUS_MESSAGE)!!
|
||||
|
||||
check(packageName == expectedPackageName) { "Expected $expectedPackageName, but got $packageName." }
|
||||
check(packageName == expectedPackageName) {
|
||||
"Expected $expectedPackageName, but got $packageName."
|
||||
}
|
||||
Log.d(TAG, "Received result for $packageName: success=$success $statusMsg")
|
||||
|
||||
// delete cached APK file
|
||||
|
|
|
@ -95,9 +95,9 @@ internal class ApkRestore(
|
|||
|
||||
// check APK's SHA-256 hash
|
||||
val sha256 = messageDigest.digest().encodeBase64()
|
||||
if (metadata.sha256 != sha256) {
|
||||
throw SecurityException("Package $packageName has sha256 '$sha256', but '${metadata.sha256}' expected.")
|
||||
}
|
||||
if (metadata.sha256 != sha256) throw SecurityException(
|
||||
"Package $packageName has sha256 '$sha256', but '${metadata.sha256}' expected."
|
||||
)
|
||||
|
||||
// parse APK (GET_SIGNATURES is needed even though deprecated)
|
||||
@Suppress("DEPRECATION") val flags = GET_SIGNING_CERTIFICATES or GET_SIGNATURES
|
||||
|
@ -105,9 +105,9 @@ internal class ApkRestore(
|
|||
?: throw IOException("getPackageArchiveInfo returned null")
|
||||
|
||||
// check APK package name
|
||||
if (packageName != packageInfo.packageName) {
|
||||
throw SecurityException("Package $packageName expected, but ${packageInfo.packageName} found.")
|
||||
}
|
||||
if (packageName != packageInfo.packageName) throw SecurityException(
|
||||
"Package $packageName expected, but ${packageInfo.packageName} found."
|
||||
)
|
||||
|
||||
// check APK version code
|
||||
if (metadata.version != packageInfo.longVersionCode) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.stevesoltys.seedvault.ui.storage
|
||||
|
||||
|
||||
import android.content.Context
|
||||
import android.text.format.Formatter
|
||||
import android.view.LayoutInflater
|
||||
|
|
|
@ -277,9 +277,15 @@ internal class StorageRootFetcher(private val context: Context, private val isRe
|
|||
|
||||
private fun getIcon(context: Context, authority: String, rootId: String, icon: Int): Drawable? {
|
||||
return getPackageIcon(context, authority, icon) ?: when {
|
||||
authority == AUTHORITY_STORAGE && rootId == ROOT_ID_DEVICE -> context.getDrawable(R.drawable.ic_phone_android)
|
||||
authority == AUTHORITY_STORAGE && rootId != ROOT_ID_HOME -> context.getDrawable(R.drawable.ic_usb)
|
||||
authority == AUTHORITY_NEXTCLOUD -> context.getDrawable(R.drawable.nextcloud)
|
||||
authority == AUTHORITY_STORAGE && rootId == ROOT_ID_DEVICE -> {
|
||||
context.getDrawable(R.drawable.ic_phone_android)
|
||||
}
|
||||
authority == AUTHORITY_STORAGE && rootId != ROOT_ID_HOME -> {
|
||||
context.getDrawable(R.drawable.ic_usb)
|
||||
}
|
||||
authority == AUTHORITY_NEXTCLOUD -> {
|
||||
context.getDrawable(R.drawable.nextcloud)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,4 +23,4 @@ class KeyManagerTestImpl : KeyManager {
|
|||
return key
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2090,31 +2090,36 @@ class WordListTest {
|
|||
@Suppress("MaxLineLength")
|
||||
fun `12 words generate expected seed`() {
|
||||
assertEquals(
|
||||
"64AA8C388EC0F3A13C7E51653BC766E30668D30952AB34381C4B174BF3278774B4EE43D0BA08BCBCE0D0B806DEB7AA364A83525C34847078B2A8002A3E116066",
|
||||
"64AA8C388EC0F3A13C7E51653BC766E30668D30952AB34381C4B174BF3278774" +
|
||||
"B4EE43D0BA08BCBCE0D0B806DEB7AA364A83525C34847078B2A8002A3E116066",
|
||||
SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(
|
||||
"write wrong yard year yellow you young youth zebra zero zone zoo", ""
|
||||
).toHexString("")
|
||||
)
|
||||
assertEquals(
|
||||
"E911FAA42F389AA9F6D5A40B2ECB876B06D6D1FFBD5885C54720398EB11918CAB8F7BAD70FD5BE39BEB4EB065610700D1CFF1D4BFAA26F998357E15E79002779",
|
||||
"E911FAA42F389AA9F6D5A40B2ECB876B06D6D1FFBD5885C54720398EB11918CA" +
|
||||
"B8F7BAD70FD5BE39BEB4EB065610700D1CFF1D4BFAA26F998357E15E79002779",
|
||||
SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(
|
||||
"matrix lava they brand negative spray floor gym purity picture ritual disorder", ""
|
||||
).toHexString("")
|
||||
)
|
||||
assertEquals(
|
||||
"DDB26091680CF30D0DC615546E4612327DB287B6B2B8B8947A3E12580315D38C3BF7DD0EB4E9E50B10A41925332E0C8ED43C80DBA29281EF331A1DFA858BF1C9",
|
||||
"DDB26091680CF30D0DC615546E4612327DB287B6B2B8B8947A3E12580315D38C" +
|
||||
"3BF7DD0EB4E9E50B10A41925332E0C8ED43C80DBA29281EF331A1DFA858BF1C9",
|
||||
SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(
|
||||
"middle rack south alert ribbon tube hope involve defy oxygen gloom rabbit", ""
|
||||
).toHexString("")
|
||||
)
|
||||
assertEquals(
|
||||
"4815B580D0DCDA08334C92B3CB9A8436CD581C55841FB2794FB1E3D6E389F447C8C6520B2FE567720950F5B39BE7EC42C0BC98D3C63F8FEF642B5BD3EE4CDD7B",
|
||||
"4815B580D0DCDA08334C92B3CB9A8436CD581C55841FB2794FB1E3D6E389F447" +
|
||||
"C8C6520B2FE567720950F5B39BE7EC42C0BC98D3C63F8FEF642B5BD3EE4CDD7B",
|
||||
SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(
|
||||
"interest mask trial hold foot segment fade page monitor apple garden shuffle", ""
|
||||
).toHexString("")
|
||||
)
|
||||
assertEquals(
|
||||
"FF462543D8FB9DAE6C17FA7BA047238664207FCC797D6688E10DD1B3CFD183D4928AD088E8287B69BABCAEB0F87A2DFF2ADD49A7FDB7EB2554D7344F09C41A76",
|
||||
"FF462543D8FB9DAE6C17FA7BA047238664207FCC797D6688E10DD1B3CFD183D4" +
|
||||
"928AD088E8287B69BABCAEB0F87A2DFF2ADD49A7FDB7EB2554D7344F09C41A76",
|
||||
SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed(
|
||||
"palace glory gospel garment obscure person edge total hunt fix setup uphold\n", ""
|
||||
).toHexString("")
|
||||
|
|
|
@ -160,7 +160,9 @@ class MetadataReaderTest {
|
|||
assertNull(packageMetadata.signatures)
|
||||
}
|
||||
|
||||
private fun getMetadata(packageMetadata: PackageMetadataMap = PackageMetadataMap()): BackupMetadata {
|
||||
private fun getMetadata(
|
||||
packageMetadata: PackageMetadataMap = PackageMetadataMap()
|
||||
): BackupMetadata {
|
||||
return BackupMetadata(
|
||||
version = 1.toByte(),
|
||||
token = Random.nextLong(),
|
||||
|
|
|
@ -110,7 +110,9 @@ internal class MetadataWriterDecoderTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun getMetadata(packageMetadata: HashMap<String, PackageMetadata> = HashMap()): BackupMetadata {
|
||||
private fun getMetadata(
|
||||
packageMetadata: HashMap<String, PackageMetadata> = HashMap()
|
||||
): BackupMetadata {
|
||||
return BackupMetadata(
|
||||
version = Random.nextBytes(1)[0],
|
||||
token = Random.nextLong(),
|
||||
|
|
|
@ -32,7 +32,6 @@ import java.io.OutputStream
|
|||
import java.nio.file.Path
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
internal class ApkBackupTest : BackupTest() {
|
||||
|
||||
|
@ -104,7 +103,9 @@ internal class ApkBackupTest : BackupTest() {
|
|||
@Test
|
||||
fun `do not accept empty signature`() = runBlocking {
|
||||
every { settingsManager.backupApks() } returns true
|
||||
every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns packageMetadata
|
||||
every {
|
||||
metadataManager.getPackageMetadata(packageInfo.packageName)
|
||||
} returns packageMetadata
|
||||
every { sigInfo.hasMultipleSigners() } returns false
|
||||
every { sigInfo.signingCertificateHistory } returns emptyArray()
|
||||
|
||||
|
@ -151,7 +152,9 @@ internal class ApkBackupTest : BackupTest() {
|
|||
|
||||
private fun expectChecks(packageMetadata: PackageMetadata = this.packageMetadata) {
|
||||
every { settingsManager.backupApks() } returns true
|
||||
every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns packageMetadata
|
||||
every {
|
||||
metadataManager.getPackageMetadata(packageInfo.packageName)
|
||||
} returns packageMetadata
|
||||
every { PackageUtils.computeSha256DigestBytes(signatureBytes) } returns signatureHash
|
||||
every { sigInfo.hasMultipleSigners() } returns false
|
||||
every { sigInfo.signingCertificateHistory } returns sigs
|
||||
|
|
|
@ -246,7 +246,9 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
coEvery { full.performFullBackup(packageInfo, fileDescriptor, 0) } returns TRANSPORT_OK
|
||||
expectApkBackupAndMetadataWrite()
|
||||
every { full.getQuota() } returns DEFAULT_QUOTA_FULL_BACKUP
|
||||
every { full.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1) } returns TRANSPORT_QUOTA_EXCEEDED
|
||||
every {
|
||||
full.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1)
|
||||
} returns TRANSPORT_QUOTA_EXCEEDED
|
||||
every { full.getCurrentPackage() } returns packageInfo
|
||||
every {
|
||||
metadataManager.onPackageBackupError(
|
||||
|
@ -347,7 +349,9 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
apkBackup.backupApkIfNecessary(notAllowedPackages[0], NOT_ALLOWED, any())
|
||||
} returns null
|
||||
// check old metadata for state changes, because we won't update it otherwise
|
||||
every { metadataManager.getPackageMetadata(notAllowedPackages[0].packageName) } returns packageMetadata
|
||||
every {
|
||||
metadataManager.getPackageMetadata(notAllowedPackages[0].packageName)
|
||||
} returns packageMetadata
|
||||
every { packageMetadata.state } returns NOT_ALLOWED // no change
|
||||
|
||||
// update notification for second package
|
||||
|
@ -386,10 +390,15 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
val oldPackageMetadata: PackageMetadata = mockk()
|
||||
|
||||
every { packageService.notAllowedPackages } returns listOf(packageInfo)
|
||||
every { notificationManager.onOptOutAppBackup(packageInfo.packageName, 1, 1) } just Runs
|
||||
every {
|
||||
notificationManager.onOptOutAppBackup(packageInfo.packageName, 1, 1)
|
||||
} just Runs
|
||||
coEvery { apkBackup.backupApkIfNecessary(packageInfo, NOT_ALLOWED, any()) } returns null
|
||||
every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns oldPackageMetadata
|
||||
every { oldPackageMetadata.state } returns WAS_STOPPED // state differs now, was stopped before
|
||||
every {
|
||||
metadataManager.getPackageMetadata(packageInfo.packageName)
|
||||
} returns oldPackageMetadata
|
||||
// state differs now, was stopped before
|
||||
every { oldPackageMetadata.state } returns WAS_STOPPED
|
||||
coEvery { plugin.getMetadataOutputStream() } returns metadataOutputStream
|
||||
every {
|
||||
metadataManager.onPackageBackupError(
|
||||
|
|
|
@ -215,7 +215,7 @@ internal class ApkRestoreTest : RestoreTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `test system apps only get reinstalled when older system apps exist`(@TempDir tmpDir: Path) =
|
||||
fun `test system apps only reinstalled when older system apps exist`(@TempDir tmpDir: Path) =
|
||||
runBlocking {
|
||||
val packageMetadata = this@ApkRestoreTest.packageMetadata.copy(system = true)
|
||||
packageMetadataMap[packageName] = packageMetadata
|
||||
|
|
|
@ -165,7 +165,7 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `startRestore() optimized auto-restore with removed storage but no backup shows no notification`() {
|
||||
fun `startRestore() with removed storage shows no notification`() {
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { storage.isUsb } returns true
|
||||
every { storage.getDocumentFile(context) } returns documentFile
|
||||
|
|
Loading…
Reference in a new issue