Home | History | Annotate | Download | only in calllog
      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
     44     protected void setUp() throws Exception {
     45         super.setUp();
     46         mFakeGroupCreator = new FakeGroupCreator();
     47         mBuilder = new CallLogGroupBuilder(mFakeGroupCreator);
     48         createCursor();
     49     }
     50 
     51     @Override
     52     protected void tearDown() throws Exception {
     53         mCursor = null;
     54         mBuilder = null;
     55         mFakeGroupCreator = null;
     56         super.tearDown();
     57     }
     58 
     59     public void testAddGroups_NoCalls() {
     60         mBuilder.addGroups(mCursor);
     61         assertEquals(0, mFakeGroupCreator.groups.size());
     62     }
     63 
     64     public void testAddGroups_OneCall() {
     65         addOldCallLogEntry(TEST_NUMBER1, Calls.INCOMING_TYPE);
     66         mBuilder.addGroups(mCursor);
     67         assertEquals(0, mFakeGroupCreator.groups.size());
     68     }
     69 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 (at) host.com", "6505555555 (at) host.com"));
    190         assertTrue(mBuilder.equalNumbers("6505555555 (at) host.com", "6505555555 (at) HOST.COM"));
    191         assertTrue(mBuilder.equalNumbers("user (at) host.com", "user (at) host.com"));
    192         assertTrue(mBuilder.equalNumbers("user (at) host.com", "user (at) HOST.COM"));
    193         assertFalse(mBuilder.equalNumbers("USER (at) host.com", "user (at) host.com"));
    194         assertFalse(mBuilder.equalNumbers("user (at) host.com", "user (at) host1.com"));
    195         // SIP address vs phone number.
    196         assertFalse(mBuilder.equalNumbers("6505555555 (at) host.com", "6505555555"));
    197         assertFalse(mBuilder.equalNumbers("6505555555", "6505555555 (at) host.com"));
    198         assertFalse(mBuilder.equalNumbers("user (at) host.com", "6505555555"));
    199         assertFalse(mBuilder.equalNumbers("6505555555", "user (at) 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 (at) host.com"));
    205         assertFalse(mBuilder.equalNumbers("6505555555 (at) host.com", null));
    206     }
    207 
    208     public void testCompareSipAddresses() {
    209         // Identical.
    210         assertTrue(mBuilder.compareSipAddresses("6505555555 (at) host.com", "6505555555 (at) host.com"));
    211         assertTrue(mBuilder.compareSipAddresses("user (at) host.com", "user (at) host.com"));
    212         // Host is case insensitive.
    213         assertTrue(mBuilder.compareSipAddresses("6505555555 (at) host.com", "6505555555 (at) HOST.COM"));
    214         assertTrue(mBuilder.compareSipAddresses("user (at) host.com", "user (at) HOST.COM"));
    215         // Userinfo is case sensitive.
    216         assertFalse(mBuilder.compareSipAddresses("USER (at) host.com", "user (at) host.com"));
    217         // Different hosts.
    218         assertFalse(mBuilder.compareSipAddresses("user (at) host.com", "user (at) host1.com"));
    219         // Different users.
    220         assertFalse(mBuilder.compareSipAddresses("user1 (at) host.com", "user (at) host.com"));
    221         // Nulls.
    222         assertTrue(mBuilder.compareSipAddresses(null, null));
    223         assertFalse(mBuilder.compareSipAddresses(null, "6505555555 (at) host.com"));
    224         assertFalse(mBuilder.compareSipAddresses("6505555555 (at) host.com", null));
    225     }
    226 
    227     /** Creates (or recreates) the cursor used to store the call log content for the tests. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    290     private void addOldCallLogHeader() {
    291         addCallLogHeader(CallLogQuery.SECTION_OLD_HEADER);
    292     }
    293 
    294     /** Adds the new section header to the call log. */
    295     private void addNewCallLogHeader() {
    296         addCallLogHeader(CallLogQuery.SECTION_NEW_HEADER);
    297     }
    298 
    299     /** Adds a call log entry with a header to the cursor. */
    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. */
    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 
    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
    341         public void addGroup(int cursorPosition, int size, boolean expanded) {
    342             groups.add(new GroupSpec(cursorPosition, size, expanded));
    343         }
    344     }
    345 }
    346