1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.email.activity; 18 19 import com.android.email.activity.ContactStatusLoader.Result; 20 import com.android.mail.utils.MatrixCursorWithCachedColumns; 21 22 import android.content.Context; 23 import android.content.pm.ProviderInfo; 24 import android.database.Cursor; 25 import android.database.MatrixCursor; 26 import android.graphics.Bitmap; 27 import android.net.Uri; 28 import android.provider.ContactsContract; 29 import android.provider.ContactsContract.StatusUpdates; 30 import android.test.ProviderTestCase2; 31 import android.test.mock.MockContentProvider; 32 33 import java.io.ByteArrayOutputStream; 34 import java.util.ArrayList; 35 import java.util.Queue; 36 import java.util.concurrent.LinkedBlockingQueue; 37 38 import junit.framework.Assert; 39 40 /** 41 * Test for {@link ContactStatusLoader} 42 * 43 * Unfortunately this doesn't check {@link ContactStatusLoader.Result#mLookupUri}, because we don't 44 * (shouldn't) know how {@link android.provider.ContactsContract.Data#getContactLookupUri} is 45 * implemented. 46 */ 47 public class ContactStatusLoaderTest 48 extends ProviderTestCase2<ContactStatusLoaderTest.MockContactProvider> { 49 private static final String EMAIL = "a (at) b.c"; 50 51 private MockContactProvider mProvider; 52 53 public ContactStatusLoaderTest() { 54 super(MockContactProvider.class, ContactsContract.AUTHORITY); 55 } 56 57 @Override 58 protected void setUp() throws Exception { 59 super.setUp(); 60 mProvider = getProvider(); 61 } 62 63 // Contact doesn't exist 64 public void brokentestContactNotFound() { 65 // Insert empty cursor 66 mProvider.mCursors.offer(new MatrixCursorWithCachedColumns( 67 ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE)); 68 69 // Load! 70 ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL); 71 Result r = l.loadInBackground(); 72 73 // Check input to the provider 74 assertEquals(1, mProvider.mUris.size()); 75 assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c", 76 mProvider.mUris.get(0)); 77 78 // Check result 79 assertNull(r.mPhoto); 80 assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId); 81 } 82 83 // Contact doesn't exist -- provider returns null for the first query 84 public void brokentestNull() { 85 // No cursor prepared. (Mock provider will return null) 86 87 // Load! 88 ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL); 89 Result r = l.loadInBackground(); 90 91 // Check result 92 assertNull(r.mPhoto); 93 assertEquals(ContactStatusLoader.PRESENCE_UNKNOWN_RESOURCE_ID, r.mPresenceResId); 94 } 95 96 // Contact exists, but no photo 97 public void brokentestNoPhoto() { 98 // Result for the first query (the one for photo-id) 99 MatrixCursor cursor1 = 100 new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE); 101 cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY}); 102 mProvider.mCursors.offer(cursor1); 103 104 // Empty cursor for the second query 105 mProvider.mCursors.offer( 106 new MatrixCursorWithCachedColumns(ContactStatusLoader.PHOTO_PROJECTION)); 107 108 // Load! 109 ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL); 110 Result r = l.loadInBackground(); 111 112 // Check input to the provider 113 // We should have had at least two queries from loadInBackground. 114 // There can be extra queries from getContactLookupUri(), but this test shouldn't know 115 // the details, so use ">= 2". 116 assertTrue(mProvider.mUris.size() >= 2); 117 assertEquals("content://com.android.contacts/data/emails/lookup/a%40b.c", 118 mProvider.mUris.get(0)); 119 assertEquals("content://com.android.contacts/data/12345", 120 mProvider.mUris.get(1)); 121 122 // Check result 123 assertNull(r.mPhoto); // no photo 124 assertEquals(android.R.drawable.presence_away, r.mPresenceResId); 125 } 126 127 // Contact exists, but no photo (provider returns null for the second query) 128 public void brokentestNull2() { 129 // Result for the first query (the one for photo-id) 130 MatrixCursor cursor1 = 131 new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE); 132 cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY}); 133 mProvider.mCursors.offer(cursor1); 134 135 // No cursor for the second query 136 137 // Load! 138 ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL); 139 Result r = l.loadInBackground(); 140 141 // Check result 142 assertNull(r.mPhoto); // no photo 143 assertEquals(android.R.drawable.presence_away, r.mPresenceResId); 144 } 145 146 // Contact exists, with a photo 147 public void brokentestWithPhoto() { 148 // Result for the first query (the one for photo-id) 149 MatrixCursor cursor1 = 150 new MatrixCursorWithCachedColumns(ContactStatusLoader.PROJECTION_PHOTO_ID_PRESENCE); 151 cursor1.addRow(new Object[]{12345, StatusUpdates.AWAY}); 152 mProvider.mCursors.offer(cursor1); 153 154 // Prepare for the second query. 155 MatrixCursor cursor2 = new PhotoCursor(createJpegData(10, 20)); 156 mProvider.mCursors.offer(cursor2); 157 158 // Load! 159 ContactStatusLoader l = new ContactStatusLoader(getMockContext(), EMAIL); 160 Result r = l.loadInBackground(); 161 162 // Check result 163 assertNotNull(r.mPhoto); 164 assertEquals(10, r.mPhoto.getWidth()); 165 assertEquals(android.R.drawable.presence_away, r.mPresenceResId); 166 } 167 168 private static byte[] createJpegData(int width, int height) { 169 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); 170 ByteArrayOutputStream out = new ByteArrayOutputStream(); 171 bitmap.compress(Bitmap.CompressFormat.JPEG, 50, out); 172 return out.toByteArray(); 173 } 174 175 // MatrixCursor doesn't support getBlob, so use this... 176 private static class PhotoCursor extends MatrixCursorWithCachedColumns { 177 private final byte[] mBlob; 178 179 public PhotoCursor(byte[] blob) { 180 super(ContactStatusLoader.PHOTO_PROJECTION); 181 mBlob = blob; 182 addRow(new Object[] {null}); // Add dummy row 183 } 184 185 @Override 186 public byte[] getBlob(int column) { 187 Assert.assertEquals(0, column); 188 return mBlob; 189 } 190 } 191 192 public static class MockContactProvider extends MockContentProvider { 193 public ArrayList<String> mUris = new ArrayList<String>(); 194 195 public final Queue<Cursor> mCursors = new LinkedBlockingQueue<Cursor>(); 196 197 @Override 198 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 199 String sortOrder) { 200 mUris.add(uri.toString()); 201 return mCursors.poll(); 202 } 203 204 @Override 205 public void attachInfo(Context context, ProviderInfo info) { 206 } 207 } 208 } 209