Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.extensions

import android.graphics.Bitmap
import com.nextcloud.utils.extensions.areImageDimensionsSame
import com.owncloud.android.lib.resources.files.model.ImageDimension
import com.owncloud.android.lib.resources.files.model.RemoteFile
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import java.io.File
import java.io.OutputStream
import java.nio.file.Files
import java.nio.file.Path
import kotlin.io.path.exists

class RemoteFileExtensionsImageTest {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we truly need tests for this? Could adding tests lead to test bloat?


private lateinit var tempDir: Path

@Test
fun remoteFileAreImageDimensionsSame_checkForAllConditions() {
val remoteFile = RemoteFile().apply {
mimeType = "image/jpeg"
imageDimension = ImageDimension(IMAGE_WIDTH.toFloat(), IMAGE_HEIGHT.toFloat())
}

// local not an image
assertTrue(
"comparing with non-image",
remoteFile.areImageDimensionsSame(getPath(TEXT_FILENAME).toString())
)

// same dimensions
assertTrue(
"comparing with same-size image",
remoteFile.areImageDimensionsSame(getPath(IMAGE_FILENAME).toString())
)

// different dimensions
val biggerRemoteImage = RemoteFile().apply {
mimeType = "image/jpeg"
imageDimension = ImageDimension((IMAGE_WIDTH * 2).toFloat(), IMAGE_HEIGHT.toFloat())
}
assertFalse(
"comparing with different-size image",
biggerRemoteImage.areImageDimensionsSame(getPath(IMAGE_FILENAME).toString())
)
}

@Test
fun remoteFileAreImageDimensionsSame_checkForEdgeCases() {
val remoteFileWithDimensions = RemoteFile().apply {
mimeType = "image/jpeg"
imageDimension = ImageDimension(IMAGE_WIDTH.toFloat(), IMAGE_HEIGHT.toFloat())
}
val remoteFileWithoutDimensions = RemoteFile().apply {
mimeType = "image/jpeg"
imageDimension = null
}

// local file with null dimensions
assertTrue(
"comparing null-dimensions local file with valid remote file",
remoteFileWithoutDimensions.areImageDimensionsSame(getPath(TEXT_FILENAME).toString())
)

// remote file with null dimensions
assertTrue(
"comparing with null-dimensions remote file",
remoteFileWithoutDimensions.areImageDimensionsSame(getPath(IMAGE_FILENAME).toString())
)

// both files with null dimensions
assertTrue(
"comparing null-dimensions local file with null-dimensions remote file",
remoteFileWithoutDimensions.areImageDimensionsSame(getPath(TEXT_FILENAME).toString())
)
}

@After
fun cleanup() {
val tf = File(getPath(TEXT_FILENAME).toUri())
val imgf = File(getPath(IMAGE_FILENAME).toUri())
tf.delete()
imgf.delete()
}

@Before
fun setup() {
tempDir = Files.createTempDirectory(TMP_DIR)
assertTrue("Temp directory should exist", tempDir.exists())

createImageFile()
createTextFile()
}

private fun getPath(filename: String): Path = tempDir.resolve("test_$filename")

private fun createImageFile() {
val bitmap = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT, Bitmap.Config.ARGB_8888)
val imagePath = getPath(IMAGE_FILENAME)

Files.newOutputStream(imagePath).use { out: OutputStream ->
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
}

assertTrue(imagePath.exists())
}

private fun createTextFile() {
val f = File(getPath(TEXT_FILENAME).toUri())
f.writeText("Lorem ipsum")
}

companion object {
val TMP_DIR = "remoteFileExtensionsTest"
val TEXT_FILENAME = "text.txt"
val IMAGE_FILENAME = "image.jpg"

val IMAGE_WIDTH = 123
val IMAGE_HEIGHT = 45
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@

package com.nextcloud.utils.extensions

import androidx.annotation.VisibleForTesting
import com.nextcloud.utils.TimeConstants
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.lib.resources.shares.ShareeUser
import com.owncloud.android.lib.resources.tags.Tag
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.FileUtil
import com.owncloud.android.utils.MimeTypeUtil

private const val TAG = "RemoteFileExtensions"
fun RemoteFile.isSame(path: String?): Boolean {
val localFile = path?.toFile() ?: return false

Expand Down Expand Up @@ -50,18 +53,25 @@ fun RemoteFile.toAlbumItem(): OCFile = FileStorageUtils.fillOCFile(this).apply {
}

@Suppress("ReturnCount")
private fun RemoteFile.areImageDimensionsSame(path: String): Boolean {
@VisibleForTesting
fun RemoteFile.areImageDimensionsSame(path: String): Boolean {
if (!MimeTypeUtil.isImage(mimeType)) {
// can't compare it's not image
Log_OC.i(TAG, "areImageDimensionsSame: Can't compare: it's not an image")
return true
}

val localFileImageDimension = path.getExifSize() ?: path.getBitmapSize()
if (localFileImageDimension == null) {
// can't compare local file image dimension is not determined
Log_OC.w(TAG, "areImageDimensionsSame: Can't compare: local file image dimension is not determined")
return true
}

return localFileImageDimension.first.toFloat() == imageDimension?.width &&
localFileImageDimension.second.toFloat() == imageDimension?.height
val remoteFileImageDimension = imageDimension
if (remoteFileImageDimension == null) {
Log_OC.w(TAG, "areImageDimensionsSame: Can't compare: remote file image dimension is not determined")
return true
}

return localFileImageDimension.first.toFloat() == remoteFileImageDimension.width &&
localFileImageDimension.second.toFloat() == remoteFileImageDimension.height
}
Loading