From b5d1a33cb07dc8c2a448b424a88aee8391a24624 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 28 Feb 2026 17:54:16 -0600 Subject: [PATCH] Swallow and log file deletion errors --- .../external/ExternalContentRepository.kt | 16 ++++++--- .../WhenRemovingTheContent.kt | 36 +++++++++++++++++++ .../GivenContent/WhenRemovingTheContent.kt | 35 ++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/AndContentResolverThrowsException/WhenRemovingTheContent.kt create mode 100644 projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/WhenRemovingTheContent.kt diff --git a/projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/ExternalContentRepository.kt b/projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/ExternalContentRepository.kt index f5bdd3cb45..eda82b750c 100644 --- a/projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/ExternalContentRepository.kt +++ b/projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/ExternalContentRepository.kt @@ -4,6 +4,7 @@ import android.content.ContentResolver import android.content.ContentValues import android.os.Build import android.provider.MediaStore +import com.lasthopesoftware.bluewater.shared.lazyLogger import com.lasthopesoftware.promises.extensions.preparePromise import com.lasthopesoftware.resources.executors.ThreadPools import com.lasthopesoftware.resources.uri.toURI @@ -18,6 +19,10 @@ class ExternalContentRepository( private val publicDirectoryLookup: GetPublicDirectories, ) : HaveExternalContent { + companion object { + private val logger by lazyLogger() + } + override fun promiseNewContentUri(externalContent: ExternalContent): Promise = externalContent .toContentValues() @@ -61,12 +66,15 @@ class ExternalContentRepository( null, null ) - - Unit } override fun removeContent(uri: URI): Promise = ThreadPools.io.preparePromise { - val deletedRecords = contentResolver.delete(uri.toUri(), null, null) - deletedRecords > 0 + try { + val deletedRecords = contentResolver.delete(uri.toUri(), null, null) + deletedRecords > 0 + } catch (e: Throwable) { + logger.error("Unable to delete file at uri $uri.", e) + false + } } } diff --git a/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/AndContentResolverThrowsException/WhenRemovingTheContent.kt b/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/AndContentResolverThrowsException/WhenRemovingTheContent.kt new file mode 100644 index 0000000000..8f181e7ba8 --- /dev/null +++ b/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/AndContentResolverThrowsException/WhenRemovingTheContent.kt @@ -0,0 +1,36 @@ +package com.lasthopesoftware.bluewater.client.stored.library.items.files.external.GivenContent.AndContentResolverThrowsException + +import android.app.RecoverableSecurityException +import com.lasthopesoftware.AndroidContext +import com.lasthopesoftware.bluewater.client.stored.library.items.files.external.ExternalContentRepository +import com.lasthopesoftware.bluewater.shared.promises.extensions.toExpiringFuture +import io.mockk.every +import io.mockk.mockk +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import java.net.URI + +class WhenRemovingTheContent : AndroidContext() { + companion object { + + private val sut by lazy { + ExternalContentRepository( + mockk { + every { delete(any(), null, null) } throws RecoverableSecurityException(Exception(), "whoops", mockk()) + }, + mockk(), + ) + } + + private var isRemoved = false + } + + override fun before() { + isRemoved = sut.removeContent(URI("content://stuff-here")).toExpiringFuture().get() == true + } + + @Test + fun `then isRemoved is false`() { + assertThat(isRemoved).isFalse + } +} diff --git a/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/WhenRemovingTheContent.kt b/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/WhenRemovingTheContent.kt new file mode 100644 index 0000000000..e2fa2039b6 --- /dev/null +++ b/projectBlueWater/src/test/java/com/lasthopesoftware/bluewater/client/stored/library/items/files/external/GivenContent/WhenRemovingTheContent.kt @@ -0,0 +1,35 @@ +package com.lasthopesoftware.bluewater.client.stored.library.items.files.external.GivenContent + +import com.lasthopesoftware.AndroidContext +import com.lasthopesoftware.bluewater.client.stored.library.items.files.external.ExternalContentRepository +import com.lasthopesoftware.bluewater.shared.promises.extensions.toExpiringFuture +import io.mockk.every +import io.mockk.mockk +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import java.net.URI + +class WhenRemovingTheContent : AndroidContext() { + companion object { + + private val sut by lazy { + ExternalContentRepository( + mockk { + every { delete(any(), null, null) } returns 464 + }, + mockk(), + ) + } + + private var isRemoved = false + } + + override fun before() { + isRemoved = sut.removeContent(URI("content://ZqUbxDqDR")).toExpiringFuture().get() == true + } + + @Test + fun `then isRemoved is true`() { + assertThat(isRemoved).isTrue + } +}