1 /* 2 * Copyright (C) 2011 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.contacts.calllog; 18 19 import static com.google.android.collect.Lists.newArrayList; 20 21 import android.database.MatrixCursor; 22 import android.provider.CallLog.Calls; 23 import android.test.AndroidTestCase; 24 25 import java.util.List; 26 27 /** 28 * Unit tests for {@link CallLogGroupBuilder} 29 */ 30 public class CallLogGroupBuilderTest extends AndroidTestCase { 31 /** A phone number for testing. */ 32 private static final String TEST_NUMBER1 = "14125551234"; 33 /** A phone number for testing. */ 34 private static final String TEST_NUMBER2 = "14125555555"; 35 36 /** The object under test. */ 37 private CallLogGroupBuilder mBuilder; 38 /** Records the created groups. */ 39 private FakeGroupCreator mFakeGroupCreator; 40 /** Cursor to store the values. */ 41 private MatrixCursor mCursor; 42 43 @Override setUp()44 protected void setUp() throws Exception { 45 super.setUp(); 46 mFakeGroupCreator = new FakeGroupCreator(); 47 mBuilder = new CallLogGroupBuilder(mFakeGroupCreator); 48 createCursor(); 49 } 50 51 @Override tearDown()52 protected void tearDown() throws Exception { 53 mCursor = null; 54 mBuilder = null; 55 mFakeGroupCreator = null; 56 super.tearDown(); 57 } 58 testAddGroups_NoCalls()59 public void testAddGroups_NoCalls() { 60 mBuilder.addGroups(mCursor); 61 assertEquals(0, mFakeGroupCreator.groups.size()); 62 } 63 testAddGroups_OneCall()64 public void testAddGroups_OneCall() { 65 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 66 mBuilder.addGroups(mCursor); 67 assertEquals(0, mFakeGroupCreator.groups.size()); 68 } 69 testAddGroups_TwoCallsNotMatching()70 public void testAddGroups_TwoCallsNotMatching() { 71 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 72 addOldCallLogEntry(TEST_NUMBER2, Calls.INCOMING_TYPE); 73 mBuilder.addGroups(mCursor); 74 assertEquals(0, mFakeGroupCreator.groups.size()); 75 } 76 testAddGroups_ThreeCallsMatching()77 public void testAddGroups_ThreeCallsMatching() { 78 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 79 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 80 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 81 mBuilder.addGroups(mCursor); 82 assertEquals(1, mFakeGroupCreator.groups.size()); 83 assertGroupIs(0, 3, false, mFakeGroupCreator.groups.get(0)); 84 } 85 testAddGroups_MatchingIncomingAndOutgoing()86 public void testAddGroups_MatchingIncomingAndOutgoing() { 87 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 88 addOldCallLogEntry(TEST_NUMBER1, Calls.OUTGOING_TYPE); 89 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 90 mBuilder.addGroups(mCursor); 91 assertEquals(1, mFakeGroupCreator.groups.size()); 92 assertGroupIs(0, 3, false, mFakeGroupCreator.groups.get(0)); 93 } 94 testAddGroups_HeaderSplitsGroups()95 public void testAddGroups_HeaderSplitsGroups() { 96 addNewCallLogHeader(); 97 addNewCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 98 addNewCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 99 addOldCallLogHeader(); 100 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 101 addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE); 102 mBuilder.addGroups(mCursor); 103 assertEquals(2, mFakeGroupCreator.groups.size()); 104 assertGroupIs(1, 2, false, mFakeGroupCreator.groups.get(0)); 105 assertGroupIs(4, 2, false, mFakeGroupCreator.groups.get(1)); 106 } 107 testAddGroups_Voicemail()108 public void testAddGroups_Voicemail() { 109 // Groups with one or more missed calls. 110 assertCallsAreGrouped(Calls.VOICEMAIL_TYPE, Calls.MISSED_TYPE); 111 assertCallsAreGrouped(Calls.VOICEMAIL_TYPE, Calls.MISSED_TYPE, Calls.MISSED_TYPE); 112 // Does not group with other types of calls, include voicemail themselves. 113 assertCallsAreNotGrouped(Calls.VOICEMAIL_TYPE, Calls.VOICEMAIL_TYPE); 114 assertCallsAreNotGrouped(Calls.VOICEMAIL_TYPE, Calls.INCOMING_TYPE); 115 assertCallsAreNotGrouped(Calls.VOICEMAIL_TYPE, Calls.OUTGOING_TYPE); 116 } 117 testAddGroups_Missed()118 public void testAddGroups_Missed() { 119 // Groups with one or more missed calls. 120 assertCallsAreGrouped(Calls.MISSED_TYPE, Calls.MISSED_TYPE); 121 assertCallsAreGrouped(Calls.MISSED_TYPE, Calls.MISSED_TYPE, Calls.MISSED_TYPE); 122 // Does not group with other types of calls. 123 assertCallsAreNotGrouped(Calls.MISSED_TYPE, Calls.VOICEMAIL_TYPE); 124 assertCallsAreNotGrouped(Calls.MISSED_TYPE, Calls.INCOMING_TYPE); 125 assertCallsAreNotGrouped(Calls.MISSED_TYPE, Calls.OUTGOING_TYPE); 126 } 127 testAddGroups_Incoming()128 public void testAddGroups_Incoming() { 129 // Groups with one or more incoming or outgoing. 130 assertCallsAreGrouped(Calls.INCOMING_TYPE, Calls.INCOMING_TYPE); 131 assertCallsAreGrouped(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); 132 assertCallsAreGrouped(Calls.INCOMING_TYPE, Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); 133 assertCallsAreGrouped(Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE, Calls.INCOMING_TYPE); 134 // Does not group with voicemail and missed calls. 135 assertCallsAreNotGrouped(Calls.INCOMING_TYPE, Calls.VOICEMAIL_TYPE); 136 assertCallsAreNotGrouped(Calls.INCOMING_TYPE, Calls.MISSED_TYPE); 137 } 138 testAddGroups_Outgoing()139 public void testAddGroups_Outgoing() { 140 // Groups with one or more incoming or outgoing. 141 assertCallsAreGrouped(Calls.OUTGOING_TYPE, Calls.INCOMING_TYPE); 142 assertCallsAreGrouped(Calls.OUTGOING_TYPE, Calls.OUTGOING_TYPE); 143 assertCallsAreGrouped(Calls.OUTGOING_TYPE, Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE); 144 assertCallsAreGrouped(Calls.OUTGOING_TYPE, Calls.OUTGOING_TYPE, Calls.INCOMING_TYPE); 145 // Does not group with voicemail and missed calls. 146 assertCallsAreNotGrouped(Calls.INCOMING_TYPE, Calls.VOICEMAIL_TYPE); 147 assertCallsAreNotGrouped(Calls.INCOMING_TYPE, Calls.MISSED_TYPE); 148 } 149 testAddGroups_Mixed()150 public void testAddGroups_Mixed() { 151 addMultipleOldCallLogEntries(TEST_NUMBER1, 152 Calls.VOICEMAIL_TYPE, // Stand-alone 153 Calls.INCOMING_TYPE, // Group 1: 1-2 154 Calls.OUTGOING_TYPE, 155 Calls.MISSED_TYPE, // Group 2: 3-4 156 Calls.MISSED_TYPE, 157 Calls.VOICEMAIL_TYPE, // Stand-alone 158 Calls.INCOMING_TYPE, // Stand-alone 159 Calls.VOICEMAIL_TYPE, // Group 3: 7-9 160 Calls.MISSED_TYPE, 161 Calls.MISSED_TYPE, 162 Calls.OUTGOING_TYPE); // Stand-alone 163 mBuilder.addGroups(mCursor); 164 assertEquals(3, mFakeGroupCreator.groups.size()); 165 assertGroupIs(1, 2, false, mFakeGroupCreator.groups.get(0)); 166 assertGroupIs(3, 2, false, mFakeGroupCreator.groups.get(1)); 167 assertGroupIs(7, 3, false, mFakeGroupCreator.groups.get(2)); 168 } 169 testEqualPhoneNumbers()170 public void testEqualPhoneNumbers() { 171 // Identical. 172 assertTrue(mBuilder.equalNumbers("6505555555", "6505555555")); 173 assertTrue(mBuilder.equalNumbers("650 555 5555", "650 555 5555")); 174 // Formatting. 175 assertTrue(mBuilder.equalNumbers("6505555555", "650 555 5555")); 176 assertTrue(mBuilder.equalNumbers("6505555555", "(650) 555-5555")); 177 assertTrue(mBuilder.equalNumbers("650 555 5555", "(650) 555-5555")); 178 // Short codes. 179 assertTrue(mBuilder.equalNumbers("55555", "55555")); 180 assertTrue(mBuilder.equalNumbers("55555", "555 55")); 181 // Different numbers. 182 assertFalse(mBuilder.equalNumbers("6505555555", "650555555")); 183 assertFalse(mBuilder.equalNumbers("6505555555", "6505555551")); 184 assertFalse(mBuilder.equalNumbers("650 555 5555", "650 555 555")); 185 assertFalse(mBuilder.equalNumbers("650 555 5555", "650 555 5551")); 186 assertFalse(mBuilder.equalNumbers("55555", "5555")); 187 assertFalse(mBuilder.equalNumbers("55555", "55551")); 188 // SIP addresses. 189 assertTrue(mBuilder.equalNumbers("6505555555@host.com", "6505555555@host.com")); 190 assertTrue(mBuilder.equalNumbers("6505555555@host.com", "6505555555@HOST.COM")); 191 assertTrue(mBuilder.equalNumbers("user@host.com", "user@host.com")); 192 assertTrue(mBuilder.equalNumbers("user@host.com", "user@HOST.COM")); 193 assertFalse(mBuilder.equalNumbers("USER@host.com", "user@host.com")); 194 assertFalse(mBuilder.equalNumbers("user@host.com", "user@host1.com")); 195 // SIP address vs phone number. 196 assertFalse(mBuilder.equalNumbers("6505555555@host.com", "6505555555")); 197 assertFalse(mBuilder.equalNumbers("6505555555", "6505555555@host.com")); 198 assertFalse(mBuilder.equalNumbers("user@host.com", "6505555555")); 199 assertFalse(mBuilder.equalNumbers("6505555555", "user@host.com")); 200 // Nulls. 201 assertTrue(mBuilder.equalNumbers(null, null)); 202 assertFalse(mBuilder.equalNumbers(null, "6505555555")); 203 assertFalse(mBuilder.equalNumbers("6505555555", null)); 204 assertFalse(mBuilder.equalNumbers(null, "6505555555@host.com")); 205 assertFalse(mBuilder.equalNumbers("6505555555@host.com", null)); 206 } 207 testCompareSipAddresses()208 public void testCompareSipAddresses() { 209 // Identical. 210 assertTrue(mBuilder.compareSipAddresses("6505555555@host.com", "6505555555@host.com")); 211 assertTrue(mBuilder.compareSipAddresses("user@host.com", "user@host.com")); 212 // Host is case insensitive. 213 assertTrue(mBuilder.compareSipAddresses("6505555555@host.com", "6505555555@HOST.COM")); 214 assertTrue(mBuilder.compareSipAddresses("user@host.com", "user@HOST.COM")); 215 // Userinfo is case sensitive. 216 assertFalse(mBuilder.compareSipAddresses("USER@host.com", "user@host.com")); 217 // Different hosts. 218 assertFalse(mBuilder.compareSipAddresses("user@host.com", "user@host1.com")); 219 // Different users. 220 assertFalse(mBuilder.compareSipAddresses("user1@host.com", "user@host.com")); 221 // Nulls. 222 assertTrue(mBuilder.compareSipAddresses(null, null)); 223 assertFalse(mBuilder.compareSipAddresses(null, "6505555555@host.com")); 224 assertFalse(mBuilder.compareSipAddresses("6505555555@host.com", null)); 225 } 226 227 /** Creates (or recreates) the cursor used to store the call log content for the tests. */ createCursor()228 private void createCursor() { 229 mCursor = new MatrixCursor(CallLogQuery.EXTENDED_PROJECTION); 230 } 231 232 /** Clears the content of the {@link FakeGroupCreator} used in the tests. */ clearFakeGroupCreator()233 private void clearFakeGroupCreator() { 234 mFakeGroupCreator.groups.clear(); 235 } 236 237 /** Asserts that calls of the given types are grouped together into a single group. */ assertCallsAreGrouped(int... types)238 private void assertCallsAreGrouped(int... types) { 239 createCursor(); 240 clearFakeGroupCreator(); 241 addMultipleOldCallLogEntries(TEST_NUMBER1, types); 242 mBuilder.addGroups(mCursor); 243 assertEquals(1, mFakeGroupCreator.groups.size()); 244 assertGroupIs(0, types.length, false, mFakeGroupCreator.groups.get(0)); 245 246 } 247 248 /** Asserts that calls of the given types are not grouped together at all. */ assertCallsAreNotGrouped(int... types)249 private void assertCallsAreNotGrouped(int... types) { 250 createCursor(); 251 clearFakeGroupCreator(); 252 addMultipleOldCallLogEntries(TEST_NUMBER1, types); 253 mBuilder.addGroups(mCursor); 254 assertEquals(0, mFakeGroupCreator.groups.size()); 255 } 256 257 /** Adds a set of calls with the given types, all from the same number, in the old section. */ addMultipleOldCallLogEntries(String number, int... types)258 private void addMultipleOldCallLogEntries(String number, int... types) { 259 for (int type : types) { 260 addOldCallLogEntry(number, type); 261 } 262 } 263 264 /** Adds a call with the given number and type to the old section of the call log. */ addOldCallLogEntry(String number, int type)265 private void addOldCallLogEntry(String number, int type) { 266 addCallLogEntry(number, type, CallLogQuery.SECTION_OLD_ITEM); 267 } 268 269 /** Adds a call with the given number and type to the new section of the call log. */ addNewCallLogEntry(String number, int type)270 private void addNewCallLogEntry(String number, int type) { 271 addCallLogEntry(number, type, CallLogQuery.SECTION_NEW_ITEM); 272 } 273 274 /** Adds a call log entry with the given number and type to the cursor. */ addCallLogEntry(String number, int type, int section)275 private void addCallLogEntry(String number, int type, int section) { 276 if (section != CallLogQuery.SECTION_NEW_ITEM 277 && section != CallLogQuery.SECTION_OLD_ITEM) { 278 throw new IllegalArgumentException("not an item section: " + section); 279 } 280 mCursor.moveToNext(); 281 Object[] values = CallLogQueryTestUtils.createTestExtendedValues(); 282 values[CallLogQuery.ID] = mCursor.getPosition(); 283 values[CallLogQuery.NUMBER] = number; 284 values[CallLogQuery.CALL_TYPE] = type; 285 values[CallLogQuery.SECTION] = section; 286 mCursor.addRow(values); 287 } 288 289 /** Adds the old section header to the call log. */ addOldCallLogHeader()290 private void addOldCallLogHeader() { 291 addCallLogHeader(CallLogQuery.SECTION_OLD_HEADER); 292 } 293 294 /** Adds the new section header to the call log. */ addNewCallLogHeader()295 private void addNewCallLogHeader() { 296 addCallLogHeader(CallLogQuery.SECTION_NEW_HEADER); 297 } 298 299 /** Adds a call log entry with a header to the cursor. */ addCallLogHeader(int section)300 private void addCallLogHeader(int section) { 301 if (section != CallLogQuery.SECTION_NEW_HEADER 302 && section != CallLogQuery.SECTION_OLD_HEADER) { 303 throw new IllegalArgumentException("not a header section: " + section); 304 } 305 mCursor.moveToNext(); 306 Object[] values = CallLogQueryTestUtils.createTestExtendedValues(); 307 values[CallLogQuery.ID] = mCursor.getPosition(); 308 values[CallLogQuery.SECTION] = section; 309 mCursor.addRow(values); 310 } 311 312 /** Asserts that the group matches the given values. */ assertGroupIs(int cursorPosition, int size, boolean expanded, GroupSpec group)313 private void assertGroupIs(int cursorPosition, int size, boolean expanded, GroupSpec group) { 314 assertEquals(cursorPosition, group.cursorPosition); 315 assertEquals(size, group.size); 316 assertEquals(expanded, group.expanded); 317 } 318 319 /** Defines an added group. Used by the {@link FakeGroupCreator}. */ 320 private static class GroupSpec { 321 /** The starting position of the group. */ 322 public final int cursorPosition; 323 /** The number of elements in the group. */ 324 public final int size; 325 /** Whether the group should be initially expanded. */ 326 public final boolean expanded; 327 GroupSpec(int cursorPosition, int size, boolean expanded)328 public GroupSpec(int cursorPosition, int size, boolean expanded) { 329 this.cursorPosition = cursorPosition; 330 this.size = size; 331 this.expanded = expanded; 332 } 333 } 334 335 /** Fake implementation of a GroupCreator which stores the created groups in a member field. */ 336 private static class FakeGroupCreator implements CallLogGroupBuilder.GroupCreator { 337 /** The list of created groups. */ 338 public final List<GroupSpec> groups = newArrayList(); 339 340 @Override addGroup(int cursorPosition, int size, boolean expanded)341 public void addGroup(int cursorPosition, int size, boolean expanded) { 342 groups.add(new GroupSpec(cursorPosition, size, expanded)); 343 } 344 } 345 } 346