Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawable comparison test failing #7180

Closed
nak411 opened this issue Mar 24, 2022 · 5 comments
Closed

Drawable comparison test failing #7180

nak411 opened this issue Mar 24, 2022 · 5 comments

Comments

@nak411
Copy link

nak411 commented Mar 24, 2022

Description

I have a test that sets a drawable on an image view and then retrieves the drawable and compares its bytes with the expected drawable. In robolectric 4.3.1 this test passed, however I'm now upgrading to robolectric 4.7.2 which is causing the test to fail.

The main issue I'm noticing is that
myImageView.setImageResource(resId) changes the size of the retrieved bytes when compared with the same drawable in using context.getDrawable(resid). This was not the case in 4.3.1

Was there any modification made to drawable/bitmaps between 4.7.2 and 4.3.1 that would cause this test to fail?

Steps to Reproduce

@RunWith(RobolectricTestRunner::class)
class ExampleUnitTest {

    private lateinit var myImageView: ImageView

    @Before
    fun setup() {
        val app = ApplicationProvider.getApplicationContext<Application>()
        myImageView = ImageView(app)
    }

    @Test
    fun checkImage() {
        val resId = android.R.drawable.btn_plus
        val drawable = myImageView.context.getDrawable(resId)!!
        myImageView.setImageResource(resId)
        val drawable2 = myImageView.drawable
        assertEquals(drawable.toBytes().size, drawable2.toBytes().size)
    }

    private fun Drawable.toBytes(): ByteArray {
        val bitmap = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        setBounds(0, 0, canvas.width, canvas.height)
        draw(canvas)
        return ByteArrayOutputStream().use { stream ->
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
            stream.toByteArray()
        }
    }
}

Robolectric & Android Version

Robolectric Version: 4.7.2
Android Target SDK: 30

Link to a public git repo demonstrating the problem:

The entire issue is reproducible in the linked code.

@hoisie
Copy link
Contributor

hoisie commented Mar 25, 2022

@nak411 can you print out the contents of those byte arrays in Robolectric 4.3? I suspect they will all be zeros.

There were massive improvements to bitmap fidelity, primarily #6147 by @utzcoz. I think this failure is expected behavior on real Android.

I copied this test to an emulator, and it also fails: https://gist.github.com/hoisie/bbd9d6cf9f28129030dbd88a8e61c854

I think when you compress something as JPEG, it encodes some transient metadata (maybe date/time?).

@nak411
Copy link
Author

nak411 commented Mar 25, 2022

I printed out the bytes in 4.3 and they do have content in them, however the byte array size is the same for both drawables.

In 4.7.2, it seems like the call to myImageView.setImageResource(...) is increasing the drawable size. The drawable from the ImageView has some extra data in it when compared with the drawable that is obtained using context.getDrawable(...)

I understand that the test is correctly failing but I was just wondering what that extra data was and why calling setImageResource would add that extra data to the drawable.

@utzcoz
Copy link
Member

utzcoz commented Mar 25, 2022

@nak411 Does those two Drawable have the same state? The android.R.drawable.btn_plus is a selector drawable: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/drawable/btn_plus.xml?q=btn_plus.xml&ss=android%2Fplatform%2Fsuperproject.

@hoisie
Copy link
Contributor

hoisie commented Mar 25, 2022

@nak411 could you update that code sample to get to the point where it passes in an emulator but fails in Robolectric?

@nak411
Copy link
Author

nak411 commented Mar 25, 2022

@utzcoz Thank you for your input. It seems like the issue is with the state. The drawable has a state enabled when it is added to the image view but does not have any state when obtained from context.getDrawable. This is causing the difference in the object size. Using a stateless image seems to work fine.

@hoisie Greatly appreciate the help. The robolectric behavior is consistent with android behavior so this can be closed as a nonissue. The test was actually asserting the wrong thing and was incorrectly passing in the older version of robolectric.

@nak411 nak411 closed this as completed Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants