runBlocking in test

Ignore warnings
This commit is contained in:
Oupson 2021-03-04 13:45:34 +01:00
parent ffb60346a7
commit 7ca74af4d4
3 changed files with 91 additions and 56 deletions

View File

@ -5,6 +5,7 @@ import android.graphics.drawable.AnimationDrawable
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import junit.framework.TestCase import junit.framework.TestCase
import kotlinx.coroutines.runBlocking
import org.junit.Test import org.junit.Test
import oupson.apng.Utils.Companion.areBitmapSimilar import oupson.apng.Utils.Companion.areBitmapSimilar
import oupson.apng.Utils.Companion.getFrame import oupson.apng.Utils.Companion.getFrame
@ -16,11 +17,13 @@ class ApngDecoderInstrumentedTest {
fun testBtmConfigDecoding() { fun testBtmConfigDecoding() {
val context = InstrumentationRegistry.getInstrumentation().context val context = InstrumentationRegistry.getInstrumentation().context
val input = context.assets.open("sushi.png") val input = context.assets.open("sushi.png")
val anim = ApngDecoder.decodeApng( val anim = runBlocking {
context, ApngDecoder.decodeApng(
input, context,
ApngDecoder.Config(bitmapConfig = Bitmap.Config.RGB_565) input,
) as AnimationDrawable ApngDecoder.Config(bitmapConfig = Bitmap.Config.RGB_565)
) as AnimationDrawable
}
for (i in 0 until anim.numberOfFrames) { for (i in 0 until anim.numberOfFrames) {
TestCase.assertTrue((anim.getFrame(i) as BitmapDrawable).bitmap.config == Bitmap.Config.RGB_565) TestCase.assertTrue((anim.getFrame(i) as BitmapDrawable).bitmap.config == Bitmap.Config.RGB_565)
@ -33,11 +36,13 @@ class ApngDecoderInstrumentedTest {
val list = context.assets.list("bunny")?.map { getFrame(context, "bunny/$it") }!! val list = context.assets.list("bunny")?.map { getFrame(context, "bunny/$it") }!!
val input = context.assets.open("bugbuckbunny.png") val input = context.assets.open("bugbuckbunny.png")
val anim = ApngDecoder.decodeApng( val anim = runBlocking {
context, ApngDecoder.decodeApng(
input, context,
ApngDecoder.Config(bitmapConfig = Bitmap.Config.ARGB_8888, decodeCoverFrame = true) input,
) as ApngDrawable ApngDecoder.Config(bitmapConfig = Bitmap.Config.ARGB_8888, decodeCoverFrame = true)
) as ApngDrawable
}
TestCase.assertTrue(areBitmapSimilar(list[0], anim.coverFrame!!)) TestCase.assertTrue(areBitmapSimilar(list[0], anim.coverFrame!!))
for (i in 0 until anim.numberOfFrames) { for (i in 0 until anim.numberOfFrames) {

View File

@ -5,6 +5,7 @@ import android.graphics.drawable.BitmapDrawable
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import junit.framework.TestCase.assertFalse import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertTrue import junit.framework.TestCase.assertTrue
import kotlinx.coroutines.runBlocking
import org.junit.Test import org.junit.Test
import oupson.apng.Utils.Companion.areBitmapSimilar import oupson.apng.Utils.Companion.areBitmapSimilar
import oupson.apng.Utils.Companion.getFrame import oupson.apng.Utils.Companion.getFrame
@ -57,8 +58,9 @@ class ApngEncoderInstrumentedTest {
val list = context.assets.list("ball")?.map { getFrame(context, "ball/$it") }!! val list = context.assets.list("ball")?.map { getFrame(context, "ball/$it") }!!
val optimisedOutputStream = ByteArrayOutputStream() val optimisedOutputStream = ByteArrayOutputStream()
val optimisedEncoder = ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size) val optimisedEncoder =
.setOptimiseApng(true) ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size)
.setOptimiseApng(true)
list.forEach { list.forEach {
optimisedEncoder.writeFrame(it) optimisedEncoder.writeFrame(it)
@ -70,8 +72,14 @@ class ApngEncoderInstrumentedTest {
val bytes = optimisedOutputStream.toByteArray() val bytes = optimisedOutputStream.toByteArray()
val optimisedInputStream = ByteArrayInputStream(bytes) val optimisedInputStream = ByteArrayInputStream(bytes)
val optimisedApng = val optimisedApng =
ApngDecoder.decodeApng(context, optimisedInputStream) as AnimationDrawable runBlocking {
ApngDecoder.decodeApng(
context,
optimisedInputStream
) as AnimationDrawable
}
optimisedInputStream.close() optimisedInputStream.close()
@ -86,8 +94,9 @@ class ApngEncoderInstrumentedTest {
val nonOptimisedOutputStream = ByteArrayOutputStream() val nonOptimisedOutputStream = ByteArrayOutputStream()
val nonOptimisedEncoder = ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size) val nonOptimisedEncoder =
.setOptimiseApng(false) ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size)
.setOptimiseApng(false)
list.forEach { list.forEach {
nonOptimisedEncoder.writeFrame(it) nonOptimisedEncoder.writeFrame(it)
@ -101,7 +110,12 @@ class ApngEncoderInstrumentedTest {
val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes) val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes)
val nonOptimisedApng = val nonOptimisedApng =
ApngDecoder.decodeApng(context, nonOptimisedInputStream) as AnimationDrawable runBlocking {
ApngDecoder.decodeApng(
context,
nonOptimisedInputStream
) as AnimationDrawable
}
nonOptimisedInputStream.close() nonOptimisedInputStream.close()
for (i in 0 until optimisedApng.numberOfFrames) { for (i in 0 until optimisedApng.numberOfFrames) {
@ -120,8 +134,9 @@ class ApngEncoderInstrumentedTest {
val list = context.assets.list("bunny")?.map { getFrame(context, "bunny/$it") }!! val list = context.assets.list("bunny")?.map { getFrame(context, "bunny/$it") }!!
val optimisedOutputStream = ByteArrayOutputStream() val optimisedOutputStream = ByteArrayOutputStream()
val optimisedEncoder = ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size) val optimisedEncoder =
.setOptimiseApng(true) ApngEncoder(optimisedOutputStream, list[0].width, list[0].height, list.size)
.setOptimiseApng(true)
list.forEach { list.forEach {
optimisedEncoder.writeFrame(it) optimisedEncoder.writeFrame(it)
@ -134,7 +149,12 @@ class ApngEncoderInstrumentedTest {
val optimisedInputStream = ByteArrayInputStream(bytes) val optimisedInputStream = ByteArrayInputStream(bytes)
val optimisedApng = val optimisedApng =
ApngDecoder.decodeApng(context, optimisedInputStream) as AnimationDrawable runBlocking {
ApngDecoder.decodeApng(
context,
optimisedInputStream
) as AnimationDrawable
}
optimisedInputStream.close() optimisedInputStream.close()
@ -149,8 +169,9 @@ class ApngEncoderInstrumentedTest {
val nonOptimisedOutputStream = ByteArrayOutputStream() val nonOptimisedOutputStream = ByteArrayOutputStream()
val nonOptimisedEncoder = ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size) val nonOptimisedEncoder =
.setOptimiseApng(false) ApngEncoder(nonOptimisedOutputStream, list[0].width, list[0].height, list.size)
.setOptimiseApng(false)
list.forEach { list.forEach {
nonOptimisedEncoder.writeFrame(it) nonOptimisedEncoder.writeFrame(it)
@ -164,7 +185,12 @@ class ApngEncoderInstrumentedTest {
val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes) val nonOptimisedInputStream = ByteArrayInputStream(nonOptimisedBytes)
val nonOptimisedApng = val nonOptimisedApng =
ApngDecoder.decodeApng(context, nonOptimisedInputStream) as AnimationDrawable runBlocking {
ApngDecoder.decodeApng(
context,
nonOptimisedInputStream
) as AnimationDrawable
}
nonOptimisedInputStream.close() nonOptimisedInputStream.close()
for (i in 0 until optimisedApng.numberOfFrames) { for (i in 0 until optimisedApng.numberOfFrames) {

View File

@ -49,22 +49,23 @@ class ApngDecoder {
internal var bitmapConfig: Bitmap.Config = Bitmap.Config.ARGB_8888, internal var bitmapConfig: Bitmap.Config = Bitmap.Config.ARGB_8888,
internal var decodeCoverFrame: Boolean = false internal var decodeCoverFrame: Boolean = false
) { ) {
fun getSpeed() : Float = this.speed fun getSpeed(): Float = this.speed
fun setSpeed(speed : Float) : Config { fun setSpeed(speed: Float): Config {
this.speed = speed this.speed = speed
return this return this
} }
fun getBitmapConfig() : Bitmap.Config = this.bitmapConfig fun getBitmapConfig(): Bitmap.Config = this.bitmapConfig
fun setBitmapConfig(config : Bitmap.Config) : Config { fun setBitmapConfig(config: Bitmap.Config): Config {
this.bitmapConfig = config this.bitmapConfig = config
return this return this
} }
fun isDecodingCoverFrame() : Boolean { fun isDecodingCoverFrame(): Boolean {
return this.decodeCoverFrame return this.decodeCoverFrame
} }
fun setIsDecodingCoverFrame(decodeCoverFrame : Boolean) : Config {
fun setIsDecodingCoverFrame(decodeCoverFrame: Boolean): Config {
this.decodeCoverFrame = decodeCoverFrame this.decodeCoverFrame = decodeCoverFrame
return this return this
} }
@ -91,7 +92,10 @@ class ApngDecoder {
* @return [ApngDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable]. * @return [ApngDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable].
*/ */
// TODO DOCUMENT CONFIG // TODO DOCUMENT CONFIG
@Suppress("MemberVisibilityCanBePrivate") @Suppress(
"MemberVisibilityCanBePrivate",
"BlockingMethodInNonBlockingContext"
) // BlockingMethodInNonBlockingContext is a warning generated by java @Throws
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
suspend fun decodeApng( suspend fun decodeApng(
@ -133,23 +137,23 @@ class ApngDecoder {
var byteRead: Int var byteRead: Int
val lengthChunk = ByteArray(4) val lengthChunk = ByteArray(4)
do { do {
val length : Int val length: Int
val chunk : ByteArray val chunk: ByteArray
if (withContext(Dispatchers.IO) { if (withContext(Dispatchers.IO) {
byteRead = inputStream.read(lengthChunk) byteRead = inputStream.read(lengthChunk)
if (byteRead != -1) { if (byteRead != -1) {
length = Utils.uIntFromBytesBigEndian(lengthChunk) length = Utils.uIntFromBytesBigEndian(lengthChunk)
chunk = ByteArray(length + 8) chunk = ByteArray(length + 8)
byteRead = inputStream.read(chunk) byteRead = inputStream.read(chunk)
false false
} else { } else {
chunk = ByteArray(0) chunk = ByteArray(0)
true true
} }
}) { }) {
break break
} }
@ -534,7 +538,7 @@ class ApngDecoder {
inputStream.reset() inputStream.reset()
return@withContext if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { return@withContext if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val bytesRead : ByteArray val bytesRead: ByteArray
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
bytesRead = inputStream.readBytes() bytesRead = inputStream.readBytes()
inputStream.close() inputStream.close()
@ -564,7 +568,7 @@ class ApngDecoder {
* @param config Decoder configuration * @param config Decoder configuration
* @return [ApngDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable]. * @return [ApngDrawable] if successful and an [AnimatedImageDrawable] if the image decoded is not an APNG but a gif. If it is not an animated image, it is a [Drawable].
*/ */
@Suppress("unused") @Suppress("unused", "BlockingMethodInNonBlockingContext")
@JvmStatic @JvmStatic
// TODO DOCUMENT // TODO DOCUMENT
suspend fun decodeApng( suspend fun decodeApng(
@ -574,7 +578,7 @@ class ApngDecoder {
): Drawable = ): Drawable =
decodeApng( decodeApng(
context, context,
FileInputStream(file), config withContext(Dispatchers.IO) { FileInputStream(file) }, config
) )
/** /**
@ -649,7 +653,7 @@ class ApngDecoder {
* @param callback [ApngDecoder.Callback] to handle success and error. * @param callback [ApngDecoder.Callback] to handle success and error.
* @param config Decoder configuration * @param config Decoder configuration
*/ */
@Suppress("unused") @Suppress("unused", "BlockingMethodInNonBlockingContext")
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun decodeApngAsyncInto( fun decodeApngAsyncInto(
@ -658,7 +662,7 @@ class ApngDecoder {
imageView: ImageView, imageView: ImageView,
callback: Callback? = null, callback: Callback? = null,
config: Config = Config(), config: Config = Config(),
scope : CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
) { ) {
scope.launch(Dispatchers.Default) { scope.launch(Dispatchers.Default) {
try { try {
@ -666,8 +670,8 @@ class ApngDecoder {
decodeApng( decodeApng(
context, context,
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
FileInputStream(file) FileInputStream(file)
}, },
config config
) )
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
@ -703,7 +707,7 @@ class ApngDecoder {
imageView: ImageView, imageView: ImageView,
callback: Callback? = null, callback: Callback? = null,
config: Config = Config(), config: Config = Config(),
scope : CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
) { ) {
val inputStream = context.contentResolver.openInputStream(uri)!! val inputStream = context.contentResolver.openInputStream(uri)!!
scope.launch(Dispatchers.Default) { scope.launch(Dispatchers.Default) {
@ -746,7 +750,7 @@ class ApngDecoder {
imageView: ImageView, imageView: ImageView,
callback: Callback? = null, callback: Callback? = null,
config: Config = Config(), config: Config = Config(),
scope : CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
) { ) {
scope.launch(Dispatchers.Default) { scope.launch(Dispatchers.Default) {
try { try {
@ -781,7 +785,7 @@ class ApngDecoder {
* @param callback [ApngDecoder.Callback] to handle success and error. * @param callback [ApngDecoder.Callback] to handle success and error.
* @param config Decoder configuration * @param config Decoder configuration
*/ */
@Suppress("unused") @Suppress("unused", "BlockingMethodInNonBlockingContext")
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun decodeApngAsyncInto( fun decodeApngAsyncInto(
@ -790,7 +794,7 @@ class ApngDecoder {
imageView: ImageView, imageView: ImageView,
callback: Callback? = null, callback: Callback? = null,
config: Config = Config(), config: Config = Config(),
scope : CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
) { ) {
scope.launch(Dispatchers.Default) { scope.launch(Dispatchers.Default) {
try { try {
@ -836,9 +840,9 @@ class ApngDecoder {
imageView: ImageView, imageView: ImageView,
callback: Callback? = null, callback: Callback? = null,
config: Config = Config(), config: Config = Config(),
scope : CoroutineScope = GlobalScope scope: CoroutineScope = GlobalScope
) { ) {
scope.launch(Dispatchers.Default) { scope.launch(Dispatchers.Default) {
try { try {
if (string.startsWith("http://") || string.startsWith("https://")) { if (string.startsWith("http://") || string.startsWith("https://")) {
decodeApngAsyncInto( decodeApngAsyncInto(
@ -877,7 +881,7 @@ class ApngDecoder {
} }
} else { } else {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
callback?.onError(java.lang.Exception("Cannot open string")) callback?.onError(Exception("Cannot open string"))
} }
} }
} catch (e: Exception) { } catch (e: Exception) {