0

I'm jUnit testing my android application. On setUp() I create 3 contacts, where two of them have a photo. The first inserted and the last contact inserted have a photo. The contact's info are received in a JSON Object, where the images comes in base64 encoded.

I'm 95% sure the 2 images are the same, I just decoded it using an online decoder and I got the image I was expecting.

On tearDown() I'm deleting the contacts.

I'm stuck at a particular method. This one:

public void testGetContactPhotoInputStream() {

    try {
        String photoBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeIAAAC2CAIAAACK4xmhAAAABmJLR0Q(...)";
        String rawContactId = getAllRawContactIds().get(0);

        photo.setRawContactId(rawContactId);

        InputStream isExpected = photo.getContactPhotoInputStream();

        InputStream isActual = new ByteArrayInputStream(Base64.decode(photoBase64.getBytes(), Base64.DEFAULT));

        assertTrue(IOUtils.contentEquals(isExpected, isActual));

    } catch (IOException e) {
        e.printStackTrace();
        fail("Exception: " + e.getMessage());
    } 
}

Which is testing this method from Photo class.

public InputStream getContactPhotoInputStream() throws IOException {
    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(mRawContactId));
    InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, uri);

    return is;
}

I'm sure the photos are the same, as that base64 encoding the is the string inside the received JSON.

I've tried with:

String photoBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeIAAAC2CAIAAACK4xmhAAAABmJLR0QA/wD/AP(...)";

And without the initial part of "data:image/png...", as like this:

String photoBase64 = "iVBORw0KGgoAAAANSUhEUgAAAeIAAAC2CAIAAACK4xmhAAAABmJLR0QA/wD/AP(...)";

Still get the failed assertion.

Here is my assertion ouput:

junit.framework.AssertionFailedError
at com.pedro.notesquirrel.test.PhotoTest.testGetContactPhotoInputStream(PhotoTest.java:178)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)

I think the problem is on the conversion to InputStream but I don't see any reason why the assertion fails.

Any help?

PS; I removed most part of the photoBase64 String for easy reading.

/////////////////////////// EDIT ////////////////////////////////

Following Joop Eggen comment, here's my code:

public void testGetContactPhotoInputStream() {
try {

    String photoBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeIAAAC2CAIAAACK4xmhAAA(...)";
    String contactId = getAllContactIds().get(0);
    String rawContactId = contact.getAllRawContactIdsBelongingToGivenContactId(contactId).get(0);

    photo.setRawContactId(rawContactId);

    photoBase64 = photoBase64.replaceFirst("^.*;base64,", "");
    Log.d(TAG, "Data: " + photoBase64);
    byte[] bytes = Base64.decode(photoBase64, Base64.DEFAULT);

    InputStream isActual = new ByteArrayInputStream(bytes);
    InputStream isExpected = photo.getContactPhotoInputStream();

    assertTrue(IOUtils.contentEquals(isExpected, isActual));

    } catch (IOException e) {
        e.printStackTrace();
        fail("Exception: " + e.getMessage());
    }       
}
dazito
  • 7,740
  • 15
  • 75
  • 117
  • 1
    http://stackoverflow.com/questions/9388264/jeditorpane-with-inline-image does this conversion. – Joop Eggen Apr 04 '14 at 07:16
  • @JoopEggen I've tried following your advise but still getting assertation failure. I've edited my question with the code I'm using from your comment. Android doesn't have the class `DatatypeConverter`, it has the `Base64` class. – dazito Apr 04 '14 at 09:07
  • 1. Check the metainformation stored in the image, maybe they were changed. 2. Make a hex dump and compare those. – Joop Eggen Apr 04 '14 at 11:16
  • Yup, you are right. Android does change the image. It lowers the image quality, making it not match the original image. – dazito Apr 04 '14 at 12:07

2 Answers2

1

The part "data:image/png;base64," does not belong to the real Base64 data.

String base64Text = photoBase64.replaceFirst("^.*,", "");
byte[] bytes = Base64.decode(base64Text , Base64.DEFAULT);
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I know that, In both situations and to peace out my mind I tested with and without "data:image/png;base64," and not working. I ended up getting my `InputStream isExpected` encoded to base64 and analyse it. I concluded that the `InputStream isExpected` is not what I should get, so the test fails as expected. Thanks for you help and input, rep given! – dazito Apr 04 '14 at 10:38
1

Well, the images to our "eyes" are equal (well not exactly equal as you can see some foggy pixels) but Android internally does lower the image quality making it not match the original image. Therefore the unit test fails.

dazito
  • 7,740
  • 15
  • 75
  • 117