• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.dialer.calllog;
18 
19 import static com.google.common.collect.Lists.newArrayList;
20 
21 import android.database.MatrixCursor;
22 import android.test.AndroidTestCase;
23 import android.test.suitebuilder.annotation.SmallTest;
24 
25 import com.android.contacts.common.compat.CompatUtils;
26 import com.android.dialer.util.AppCompatConstants;
27 
28 import java.util.List;
29 
30 /**
31  * Unit tests for {@link CallLogGroupBuilder}
32  */
33 @SmallTest
34 public class CallLogGroupBuilderTest extends AndroidTestCase {
35     /** A phone number for testing. */
36     private static final String TEST_NUMBER1 = "14125551234";
37     /** A phone number for testing. */
38     private static final String TEST_NUMBER2 = "14125555555";
39     /** A post-dial string for testing */
40     private static final String TEST_POST_DIAL_DIGITS = ";12435;0987";
41 
42     /** The object under test. */
43     private CallLogGroupBuilder mBuilder;
44     /** Records the created groups. */
45     private FakeGroupCreator mFakeGroupCreator;
46     /** Cursor to store the values. */
47     private MatrixCursor mCursor;
48 
49     @Override
setUp()50     protected void setUp() throws Exception {
51         super.setUp();
52         mFakeGroupCreator = new FakeGroupCreator();
53         mBuilder = new CallLogGroupBuilder(mFakeGroupCreator);
54         createCursor();
55     }
56 
57     @Override
tearDown()58     protected void tearDown() throws Exception {
59         mCursor = null;
60         mBuilder = null;
61         mFakeGroupCreator = null;
62         super.tearDown();
63     }
64 
testAddGroups_NoCalls()65     public void testAddGroups_NoCalls() {
66         mBuilder.addGroups(mCursor);
67         assertEquals(0, mFakeGroupCreator.groups.size());
68     }
69 
testAddGroups_OneCall()70     public void testAddGroups_OneCall() {
71         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
72         mBuilder.addGroups(mCursor);
73         assertEquals(1, mFakeGroupCreator.groups.size());
74     }
75 
testAddGroups_TwoCallsNotMatching()76     public void testAddGroups_TwoCallsNotMatching() {
77         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
78         addCallLogEntry(TEST_NUMBER2, AppCompatConstants.CALLS_INCOMING_TYPE);
79         mBuilder.addGroups(mCursor);
80         assertEquals(2, mFakeGroupCreator.groups.size());
81     }
82 
testAddGroups_ThreeCallsMatching()83     public void testAddGroups_ThreeCallsMatching() {
84         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
85         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
86         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
87         mBuilder.addGroups(mCursor);
88         assertEquals(1, mFakeGroupCreator.groups.size());
89         assertGroupIs(0, 3, mFakeGroupCreator.groups.get(0));
90     }
91 
testAddGroups_WithPostDialMatching()92     public void testAddGroups_WithPostDialMatching() {
93         addCallLogEntryWithPostDialDigits(TEST_NUMBER1, TEST_POST_DIAL_DIGITS,
94                 AppCompatConstants.CALLS_OUTGOING_TYPE);
95         addCallLogEntryWithPostDialDigits(TEST_NUMBER1, TEST_POST_DIAL_DIGITS,
96                 AppCompatConstants.CALLS_OUTGOING_TYPE);
97         addCallLogEntryWithPostDialDigits(TEST_NUMBER1, "",
98                 AppCompatConstants.CALLS_OUTGOING_TYPE);
99 
100         mBuilder.addGroups(mCursor);
101 
102         if (CompatUtils.isNCompatible()) {
103             assertEquals(2, mFakeGroupCreator.groups.size());
104             assertGroupIs(0, 2, mFakeGroupCreator.groups.get(0));
105             assertGroupIs(2, 1, mFakeGroupCreator.groups.get(1));
106         } else {
107             assertEquals(1, mFakeGroupCreator.groups.size());
108             assertGroupIs(0, 3, mFakeGroupCreator.groups.get(0));
109         }
110     }
111 
testAddGroups_WithViaNumberMatching()112     public void testAddGroups_WithViaNumberMatching() {
113         addCallLogEntryWithViaNumber(TEST_NUMBER1, TEST_NUMBER2,
114                 AppCompatConstants.CALLS_OUTGOING_TYPE);
115         addCallLogEntryWithViaNumber(TEST_NUMBER1, TEST_NUMBER2,
116                 AppCompatConstants.CALLS_OUTGOING_TYPE);
117         addCallLogEntryWithViaNumber(TEST_NUMBER1, "",
118                 AppCompatConstants.CALLS_OUTGOING_TYPE);
119 
120         mBuilder.addGroups(mCursor);
121 
122         if (CompatUtils.isNCompatible()) {
123             assertEquals(2, mFakeGroupCreator.groups.size());
124             assertGroupIs(0, 2, mFakeGroupCreator.groups.get(0));
125             assertGroupIs(2, 1, mFakeGroupCreator.groups.get(1));
126         } else {
127             assertEquals(1, mFakeGroupCreator.groups.size());
128             assertGroupIs(0, 3, mFakeGroupCreator.groups.get(0));
129         }
130     }
131 
testAddGroups_MatchingIncomingAndOutgoing()132     public void testAddGroups_MatchingIncomingAndOutgoing() {
133         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
134         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_OUTGOING_TYPE);
135         addCallLogEntry(TEST_NUMBER1, AppCompatConstants.CALLS_INCOMING_TYPE);
136         mBuilder.addGroups(mCursor);
137         assertEquals(1, mFakeGroupCreator.groups.size());
138         assertGroupIs(0, 3, mFakeGroupCreator.groups.get(0));
139     }
140 
testGrouping_Voicemail()141     public void testGrouping_Voicemail() {
142         // Does not group with other types of calls, include voicemail themselves.
143         assertCallsAreNotGrouped(
144                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
145         assertCallsAreNotGrouped(
146                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_VOICEMAIL_TYPE);
147         assertCallsAreNotGrouped(
148                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
149         assertCallsAreNotGrouped(
150                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
151     }
152 
testGrouping_VoicemailArchive()153     public void testGrouping_VoicemailArchive() {
154         // Does not group with other types of calls, include voicemail themselves.
155         assertVoicemailsAreNotGrouped(
156                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
157         assertVoicemailsAreNotGrouped(
158                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_VOICEMAIL_TYPE);
159         assertVoicemailsAreNotGrouped(
160                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
161         assertVoicemailsAreNotGrouped(
162                 AppCompatConstants.CALLS_VOICEMAIL_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
163     }
164 
testGrouping_Missed()165     public void testGrouping_Missed() {
166         // Groups with one or more missed calls.
167         assertCallsAreGrouped(
168                 AppCompatConstants.CALLS_MISSED_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
169         assertCallsAreGrouped(
170                 AppCompatConstants.CALLS_MISSED_TYPE,
171                 AppCompatConstants.CALLS_MISSED_TYPE,
172                 AppCompatConstants.CALLS_MISSED_TYPE);
173         // Does not group with other types of calls.
174         assertCallsAreNotGrouped(
175                 AppCompatConstants.CALLS_MISSED_TYPE, AppCompatConstants.CALLS_VOICEMAIL_TYPE);
176         assertCallsAreGrouped(
177                 AppCompatConstants.CALLS_MISSED_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
178         assertCallsAreGrouped(
179                 AppCompatConstants.CALLS_MISSED_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
180     }
181 
testGrouping_Incoming()182     public void testGrouping_Incoming() {
183         // Groups with one or more incoming or outgoing.
184         assertCallsAreGrouped(
185                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
186         assertCallsAreGrouped(
187                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
188         assertCallsAreGrouped(
189                 AppCompatConstants.CALLS_INCOMING_TYPE,
190                 AppCompatConstants.CALLS_INCOMING_TYPE,
191                 AppCompatConstants.CALLS_OUTGOING_TYPE);
192         assertCallsAreGrouped(
193                 AppCompatConstants.CALLS_INCOMING_TYPE,
194                 AppCompatConstants.CALLS_OUTGOING_TYPE,
195                 AppCompatConstants.CALLS_INCOMING_TYPE);
196         assertCallsAreGrouped(
197                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
198         // Does not group with voicemail and missed calls.
199         assertCallsAreNotGrouped(
200                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_VOICEMAIL_TYPE);
201     }
202 
testGrouping_Outgoing()203     public void testGrouping_Outgoing() {
204         // Groups with one or more incoming or outgoing.
205         assertCallsAreGrouped(
206                 AppCompatConstants.CALLS_OUTGOING_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
207         assertCallsAreGrouped(
208                 AppCompatConstants.CALLS_OUTGOING_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
209         assertCallsAreGrouped(
210                 AppCompatConstants.CALLS_OUTGOING_TYPE,
211                 AppCompatConstants.CALLS_INCOMING_TYPE,
212                 AppCompatConstants.CALLS_OUTGOING_TYPE);
213         assertCallsAreGrouped(
214                 AppCompatConstants.CALLS_OUTGOING_TYPE,
215                 AppCompatConstants.CALLS_OUTGOING_TYPE,
216                 AppCompatConstants.CALLS_INCOMING_TYPE);
217         assertCallsAreGrouped(
218                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
219         // Does not group with voicemail and missed calls.
220         assertCallsAreNotGrouped(
221                 AppCompatConstants.CALLS_INCOMING_TYPE, AppCompatConstants.CALLS_VOICEMAIL_TYPE);
222     }
223 
testGrouping_Blocked()224     public void testGrouping_Blocked() {
225         assertCallsAreNotGrouped(
226                 AppCompatConstants.CALLS_BLOCKED_TYPE, AppCompatConstants.CALLS_INCOMING_TYPE);
227         assertCallsAreNotGrouped(
228                 AppCompatConstants.CALLS_BLOCKED_TYPE, AppCompatConstants.CALLS_OUTGOING_TYPE);
229         assertCallsAreNotGrouped(
230                 AppCompatConstants.CALLS_BLOCKED_TYPE, AppCompatConstants.CALLS_MISSED_TYPE);
231 
232     }
233 
testAddGroups_Separate()234     public void testAddGroups_Separate() {
235         addMultipleCallLogEntries(TEST_NUMBER1,
236                 AppCompatConstants.CALLS_VOICEMAIL_TYPE,    // Group 1: 0
237                 AppCompatConstants.CALLS_INCOMING_TYPE,     // Group 2: 1
238                 AppCompatConstants.CALLS_OUTGOING_TYPE,     // Group 3: 2
239                 AppCompatConstants.CALLS_MISSED_TYPE);      // Group 4: 3
240         mBuilder.addVoicemailGroups(mCursor);
241 
242         assertEquals(4, mFakeGroupCreator.groups.size());
243         assertGroupIs(0, 1, mFakeGroupCreator.groups.get(0));
244         assertGroupIs(1, 1, mFakeGroupCreator.groups.get(1));
245         assertGroupIs(2, 1, mFakeGroupCreator.groups.get(2));
246         assertGroupIs(3, 1, mFakeGroupCreator.groups.get(3));
247     }
248 
testAddGroups_Mixed()249     public void testAddGroups_Mixed() {
250         addMultipleCallLogEntries(TEST_NUMBER1,
251                 AppCompatConstants.CALLS_VOICEMAIL_TYPE,   // Group 1: 0
252                 AppCompatConstants.CALLS_INCOMING_TYPE,    // Group 2: 1-4
253                 AppCompatConstants.CALLS_OUTGOING_TYPE,
254                 AppCompatConstants.CALLS_MISSED_TYPE,
255                 AppCompatConstants.CALLS_MISSED_TYPE,
256                 AppCompatConstants.CALLS_VOICEMAIL_TYPE,   // Group 3: 5
257                 AppCompatConstants.CALLS_INCOMING_TYPE,    // Group 4: 6
258                 AppCompatConstants.CALLS_VOICEMAIL_TYPE,   // Group 5: 7
259                 AppCompatConstants.CALLS_MISSED_TYPE,      // Group 6: 8-10
260                 AppCompatConstants.CALLS_MISSED_TYPE,
261                 AppCompatConstants.CALLS_OUTGOING_TYPE);
262         mBuilder.addGroups(mCursor);
263 
264         assertEquals(6, mFakeGroupCreator.groups.size());
265         assertGroupIs(0, 1, mFakeGroupCreator.groups.get(0));
266         assertGroupIs(1, 4, mFakeGroupCreator.groups.get(1));
267         assertGroupIs(5, 1, mFakeGroupCreator.groups.get(2));
268         assertGroupIs(6, 1, mFakeGroupCreator.groups.get(3));
269         assertGroupIs(7, 1, mFakeGroupCreator.groups.get(4));
270         assertGroupIs(8, 3, mFakeGroupCreator.groups.get(5));
271     }
272 
testAddGroups_Blocked()273     public void testAddGroups_Blocked() {
274         addMultipleCallLogEntries(TEST_NUMBER1,
275                 AppCompatConstants.CALLS_INCOMING_TYPE,     // Group 1: 0-1
276                 AppCompatConstants.CALLS_OUTGOING_TYPE,
277                 AppCompatConstants.CALLS_BLOCKED_TYPE,      // Group 2: 2
278                 AppCompatConstants.CALLS_MISSED_TYPE,       // Group 3: 3
279                 AppCompatConstants.CALLS_BLOCKED_TYPE,      // Group 4: 4-5
280                 AppCompatConstants.CALLS_BLOCKED_TYPE);
281         mBuilder.addGroups(mCursor);
282 
283         assertEquals(4, mFakeGroupCreator.groups.size());
284         assertGroupIs(0, 2, mFakeGroupCreator.groups.get(0));
285         assertGroupIs(2, 1, mFakeGroupCreator.groups.get(1));
286         assertGroupIs(3, 1, mFakeGroupCreator.groups.get(2));
287         assertGroupIs(4, 2, mFakeGroupCreator.groups.get(3));
288     }
289 
testEqualPhoneNumbers()290     public void testEqualPhoneNumbers() {
291         // Identical.
292         assertTrue(mBuilder.equalNumbers("6505555555", "6505555555"));
293         assertTrue(mBuilder.equalNumbers("650 555 5555", "650 555 5555"));
294         // Formatting.
295         assertTrue(mBuilder.equalNumbers("6505555555", "650 555 5555"));
296         assertTrue(mBuilder.equalNumbers("6505555555", "(650) 555-5555"));
297         assertTrue(mBuilder.equalNumbers("650 555 5555", "(650) 555-5555"));
298         // Short codes.
299         assertTrue(mBuilder.equalNumbers("55555", "55555"));
300         assertTrue(mBuilder.equalNumbers("55555", "555 55"));
301         // Different numbers.
302         assertFalse(mBuilder.equalNumbers("6505555555", "650555555"));
303         assertFalse(mBuilder.equalNumbers("6505555555", "6505555551"));
304         assertFalse(mBuilder.equalNumbers("650 555 5555", "650 555 555"));
305         assertFalse(mBuilder.equalNumbers("650 555 5555", "650 555 5551"));
306         assertFalse(mBuilder.equalNumbers("55555", "5555"));
307         assertFalse(mBuilder.equalNumbers("55555", "55551"));
308         // SIP addresses.
309         assertTrue(mBuilder.equalNumbers("6505555555@host.com", "6505555555@host.com"));
310         assertTrue(mBuilder.equalNumbers("6505555555@host.com", "6505555555@HOST.COM"));
311         assertTrue(mBuilder.equalNumbers("user@host.com", "user@host.com"));
312         assertTrue(mBuilder.equalNumbers("user@host.com", "user@HOST.COM"));
313         assertFalse(mBuilder.equalNumbers("USER@host.com", "user@host.com"));
314         assertFalse(mBuilder.equalNumbers("user@host.com", "user@host1.com"));
315         // SIP address vs phone number.
316         assertFalse(mBuilder.equalNumbers("6505555555@host.com", "6505555555"));
317         assertFalse(mBuilder.equalNumbers("6505555555", "6505555555@host.com"));
318         assertFalse(mBuilder.equalNumbers("user@host.com", "6505555555"));
319         assertFalse(mBuilder.equalNumbers("6505555555", "user@host.com"));
320         // Nulls.
321         assertTrue(mBuilder.equalNumbers(null, null));
322         assertFalse(mBuilder.equalNumbers(null, "6505555555"));
323         assertFalse(mBuilder.equalNumbers("6505555555", null));
324         assertFalse(mBuilder.equalNumbers(null, "6505555555@host.com"));
325         assertFalse(mBuilder.equalNumbers("6505555555@host.com", null));
326     }
327 
testCompareSipAddresses()328     public void testCompareSipAddresses() {
329         // Identical.
330         assertTrue(mBuilder.compareSipAddresses("6505555555@host.com", "6505555555@host.com"));
331         assertTrue(mBuilder.compareSipAddresses("user@host.com", "user@host.com"));
332         // Host is case insensitive.
333         assertTrue(mBuilder.compareSipAddresses("6505555555@host.com", "6505555555@HOST.COM"));
334         assertTrue(mBuilder.compareSipAddresses("user@host.com", "user@HOST.COM"));
335         // Userinfo is case sensitive.
336         assertFalse(mBuilder.compareSipAddresses("USER@host.com", "user@host.com"));
337         // Different hosts.
338         assertFalse(mBuilder.compareSipAddresses("user@host.com", "user@host1.com"));
339         // Different users.
340         assertFalse(mBuilder.compareSipAddresses("user1@host.com", "user@host.com"));
341         // Nulls.
342         assertTrue(mBuilder.compareSipAddresses(null, null));
343         assertFalse(mBuilder.compareSipAddresses(null, "6505555555@host.com"));
344         assertFalse(mBuilder.compareSipAddresses("6505555555@host.com", null));
345     }
346 
347     /** Creates (or recreates) the cursor used to store the call log content for the tests. */
createCursor()348     private void createCursor() {
349         mCursor = new MatrixCursor(CallLogQuery._PROJECTION);
350     }
351 
352     /** Clears the content of the {@link FakeGroupCreator} used in the tests. */
clearFakeGroupCreator()353     private void clearFakeGroupCreator() {
354         mFakeGroupCreator.groups.clear();
355     }
356 
357     /** Asserts that calls of the given types are grouped together into a single group. */
assertCallsAreGrouped(int... types)358     private void assertCallsAreGrouped(int... types) {
359         createCursor();
360         clearFakeGroupCreator();
361         addMultipleCallLogEntries(TEST_NUMBER1, types);
362         mBuilder.addGroups(mCursor);
363         assertEquals(1, mFakeGroupCreator.groups.size());
364         assertGroupIs(0, types.length, mFakeGroupCreator.groups.get(0));
365 
366     }
367 
368     /** Asserts that calls of the given types are not grouped together at all. */
assertCallsAreNotGrouped(int... types)369     private void assertCallsAreNotGrouped(int... types) {
370         createCursor();
371         clearFakeGroupCreator();
372         addMultipleCallLogEntries(TEST_NUMBER1, types);
373         mBuilder.addGroups(mCursor);
374         assertEquals(types.length, mFakeGroupCreator.groups.size());
375     }
376 
377     /** Asserts that voicemails are not grouped together with other types at all. */
assertVoicemailsAreNotGrouped(int... types)378     private void assertVoicemailsAreNotGrouped(int... types) {
379         createCursor();
380         clearFakeGroupCreator();
381         addMultipleCallLogEntries(TEST_NUMBER1, types);
382         mBuilder.addVoicemailGroups(mCursor);
383         assertEquals(types.length, mFakeGroupCreator.groups.size());
384     }
385 
386     /** Adds a set of calls with the given types, all from the same number, in the old section. */
addMultipleCallLogEntries(String number, int... types)387     private void addMultipleCallLogEntries(String number, int... types) {
388         for (int type : types) {
389             addCallLogEntry(number, type);
390         }
391     }
392     /** Adds a call log entry with the given number and type to the cursor. */
addCallLogEntry(String number, int type)393     private void addCallLogEntry(String number, int type) {
394         addCallLogEntryWithPostDialDigits(number, "", type);
395     }
396 
397     /** Adds a call log entry with the given number, post-dial digits, and type to the cursor. */
addCallLogEntryWithPostDialDigits(String number, String postDialDigits, int type)398     private void addCallLogEntryWithPostDialDigits(String number, String postDialDigits, int type) {
399         mCursor.moveToNext();
400         Object[] values = CallLogQueryTestUtils.createTestValues();
401         values[CallLogQuery.ID] = mCursor.getPosition();
402         values[CallLogQuery.NUMBER] = number;
403         values[CallLogQuery.CALL_TYPE] = type;
404         if (CompatUtils.isNCompatible()) {
405             values[CallLogQuery.POST_DIAL_DIGITS] = postDialDigits;
406         }
407         mCursor.addRow(values);
408     }
409 
410     /** Adds a call log entry with the given number, post-dial digits, and type to the cursor. */
addCallLogEntryWithViaNumber(String number, String viaNumber, int type)411     private void addCallLogEntryWithViaNumber(String number, String viaNumber, int type) {
412         mCursor.moveToNext();
413         Object[] values = CallLogQueryTestUtils.createTestValues();
414         values[CallLogQuery.ID] = mCursor.getPosition();
415         values[CallLogQuery.NUMBER] = number;
416         values[CallLogQuery.CALL_TYPE] = type;
417         if (CompatUtils.isNCompatible()) {
418             values[CallLogQuery.VIA_NUMBER] = viaNumber;
419         }
420         mCursor.addRow(values);
421     }
422 
423     /** Adds a call log entry with a header to the cursor. */
addCallLogHeader(int section)424     private void addCallLogHeader(int section) {
425         mCursor.moveToNext();
426         Object[] values = CallLogQueryTestUtils.createTestValues();
427         values[CallLogQuery.ID] = mCursor.getPosition();
428         mCursor.addRow(values);
429     }
430 
431     /** Asserts that the group matches the given values. */
assertGroupIs(int cursorPosition, int size, GroupSpec group)432     private void assertGroupIs(int cursorPosition, int size, GroupSpec group) {
433         assertEquals(cursorPosition, group.cursorPosition);
434         assertEquals(size, group.size);
435     }
436 
437     /** Defines an added group. Used by the {@link FakeGroupCreator}. */
438     private static class GroupSpec {
439         /** The starting position of the group. */
440         public final int cursorPosition;
441         /** The number of elements in the group. */
442         public final int size;
443 
GroupSpec(int cursorPosition, int size)444         public GroupSpec(int cursorPosition, int size) {
445             this.cursorPosition = cursorPosition;
446             this.size = size;
447         }
448     }
449 
450     /** Fake implementation of a GroupCreator which stores the created groups in a member field. */
451     private static class FakeGroupCreator implements CallLogGroupBuilder.GroupCreator {
452         /** The list of created groups. */
453         public final List<GroupSpec> groups = newArrayList();
454 
455         @Override
addGroup(int cursorPosition, int size)456         public void addGroup(int cursorPosition, int size) {
457             groups.add(new GroupSpec(cursorPosition, size));
458         }
459 
460         @Override
setDayGroup(long rowId, int dayGroup)461         public void setDayGroup(long rowId, int dayGroup) {
462             //No-op
463         }
464 
465         @Override
clearDayGroups()466         public void clearDayGroups() {
467             //No-op
468         }
469     }
470 }
471