13a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting/* 23a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Copyright (C) 2012 The Android Open Source Project 33a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * 43a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Licensed under the Apache License, Version 2.0 (the "License"); you may not 53a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * use this file except in compliance with the License. You may obtain a copy of 63a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * the License at 73a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * 83a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * http://www.apache.org/licenses/LICENSE-2.0 93a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * 103a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Unless required by applicable law or agreed to in writing, software 113a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 123a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 133a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * License for the specific language governing permissions and limitations under 143a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * the License. 153a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 163a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 173a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingpackage com.android.calendar.alerts; 183a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 193a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.app.AlarmManager; 203a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.database.Cursor; 213a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.database.MatrixCursor; 223a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.net.Uri; 233a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.provider.CalendarContract; 243a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.provider.CalendarContract.Instances; 253a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.provider.CalendarContract.Reminders; 263a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.test.AndroidTestCase; 273a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.test.IsolatedContext; 283a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.test.mock.MockContentProvider; 293a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.test.mock.MockContentResolver; 303a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.test.suitebuilder.annotation.SmallTest; 313a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.text.format.DateUtils; 323a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.text.format.Time; 333a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport android.util.Log; 343a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 353a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport junit.framework.Assert; 363a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 373a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport java.util.ArrayList; 383a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport java.util.Arrays; 393a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingimport java.util.HashSet; 403a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 413a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting@SmallTest 423a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Tingpublic class AlarmSchedulerTest extends AndroidTestCase { 433a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private static final int BATCH_SIZE = 50; 443a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private MockProvider mMockProvider; 453a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private MockAlarmManager mMockAlarmManager; 463a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private IsolatedContext mIsolatedContext; 473a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 483a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting /** 493a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * A helper class to mock query results from the test data. 503a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 513a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private static class MockProvider extends MockContentProvider { 523a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private ArrayList<EventInfo> mEvents = new ArrayList<EventInfo>(); 533a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private ArrayList<String> mExpectedRemindersQueries = new ArrayList<String>(); 543a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private int mCurrentReminderQueryIndex = 0; 553a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 563a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting /** 573a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Contains info for a test event and its reminder. 583a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 593a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private static class EventInfo { 603a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long mEventId; 613a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long mBegin; 623a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting boolean mAllDay; 633a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int mReminderMinutes; 643a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 653a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public EventInfo(long eventId, boolean allDay, long begin, int reminderMinutes) { 663a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mEventId = eventId; 673a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mAllDay = allDay; 683a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mBegin = begin; 693a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mReminderMinutes = reminderMinutes; 703a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 713a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 723a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 733a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 743a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting /** 753a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Adds event/reminder data for testing. These will always be returned in the mocked 763a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * query result cursors. 773a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 783a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting void addEventInfo(long eventId, boolean allDay, long begin, int reminderMinutes) { 793a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mEvents.add(new EventInfo(eventId, allDay, begin, reminderMinutes)); 803a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 813a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 823a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private MatrixCursor getInstancesCursor() { 833a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting MatrixCursor instancesCursor = new MatrixCursor(AlarmScheduler.INSTANCES_PROJECTION); 843a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int i = 0; 853a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting HashSet<Long> eventIds = new HashSet<Long>(); 863a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting for (EventInfo event : mEvents) { 873a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting if (!eventIds.contains(event.mEventId)) { 883a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting Object[] ca = { 893a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting event.mEventId, 903a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting event.mBegin, 913a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting event.mAllDay ? 1 : 0, 923a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting }; 933a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting instancesCursor.addRow(ca); 943a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting eventIds.add(event.mEventId); 953a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 963a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 973a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting return instancesCursor; 983a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 993a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1003a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private MatrixCursor getRemindersCursor() { 1013a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting MatrixCursor remindersCursor = new MatrixCursor(AlarmScheduler.REMINDERS_PROJECTION); 1023a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int i = 0; 1033a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting for (EventInfo event : mEvents) { 1043a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting Object[] ca = { 1053a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting event.mEventId, 1063a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting event.mReminderMinutes, 1073a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1, 1083a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting }; 1093a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting remindersCursor.addRow(ca); 1103a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1113a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting return remindersCursor; 1123a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1133a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1143a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting @Override 1153a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 1163a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting String sortOrder) { 1173a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting if (uri.toString().startsWith(Instances.CONTENT_URI.toString())) { 1183a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting return getInstancesCursor(); 1193a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } else if (Reminders.CONTENT_URI.equals(uri)) { 1203a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting if (mExpectedRemindersQueries.size() > 0) { 1213a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting if (mExpectedRemindersQueries.size() <= mCurrentReminderQueryIndex || 1223a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting !mExpectedRemindersQueries.get(mCurrentReminderQueryIndex).equals( 1233a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting selection)) { 1243a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting String msg = "Reminders query not as expected.\n"; 1253a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting msg += " Expected:"; 1263a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting msg += Arrays.deepToString(mExpectedRemindersQueries.toArray()); 1273a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting msg += "\n Got in position " + mCurrentReminderQueryIndex + ": "; 1283a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting msg += selection; 1293a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting fail(msg); 1303a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1313a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mCurrentReminderQueryIndex++; 1323a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1333a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting return getRemindersCursor(); 1343a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } else { 1353a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting return super.query(uri, projection, selection, selectionArgs, sortOrder); 1363a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1373a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1383a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1393a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting /** 1403a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Optionally set up expectation for the reminders query selection. 1413a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 1423a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void addExpectedRemindersQuery(String expectedRemindersQuery) { 1433a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting this.mExpectedRemindersQueries.add(expectedRemindersQuery); 1443a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1453a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1463a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1473a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting /** 1483a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting * Expect an alarm for the specified time. 1493a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting */ 1503a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting private void expectAlarmAt(long millis) { 1513a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // AlarmScheduler adds a slight delay to the alarm so account for that here. 1523a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockAlarmManager.expectAlarmTime(AlarmManager.RTC_WAKEUP, 1533a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting millis + AlarmScheduler.ALARM_DELAY_MS); 1543a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1553a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1563a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting @Override 1573a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting protected void setUp() throws Exception { 1583a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting super.setUp(); 1593a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1603a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider = new MockProvider(); 1613a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockAlarmManager = new MockAlarmManager(mContext); 1623a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting MockContentResolver mockResolver = new MockContentResolver(); 1633a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mockResolver.addProvider(CalendarContract.AUTHORITY, mMockProvider); 1643a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mIsolatedContext = new IsolatedContext(mockResolver, mContext); 1653a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1663a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1673a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testNoEvents() { 1683a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, 1693a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting BATCH_SIZE, System.currentTimeMillis()); 1703a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertFalse(mMockAlarmManager.isAlarmSet()); 1713a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1723a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1733a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testNonAllDayEvent() { 1743a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock test data. 1753a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 1763a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillis = currentMillis + DateUtils.HOUR_IN_MILLIS; 1773a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int reminderMin = 10; 1783a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, startMillis, reminderMin); 1793a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(startMillis - reminderMin * DateUtils.MINUTE_IN_MILLIS); 1803a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1813a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 1823a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 1833a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 1843a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 1853a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 1863a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1873a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testAllDayEvent() { 1883a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock allday data. 1893a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillisUtc = Utils.createTimeInMillis(0, 0, 0, 1, 5, 2012, Time.TIMEZONE_UTC); 1903a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillisLocal = Utils.createTimeInMillis(0, 0, 0, 1, 5, 2012, 1913a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting Time.getCurrentTimezone()); 1923a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = startMillisLocal - DateUtils.DAY_IN_MILLIS; 1933a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int reminderMin = 15; 1943a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, true, startMillisUtc, reminderMin); 1953a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(startMillisLocal - reminderMin * DateUtils.MINUTE_IN_MILLIS); 1963a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 1973a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 1983a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 1993a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2003a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2013a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2023a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2033a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testAllDayAndNonAllDayEvents() { 2043a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock test data. 2053a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillisUtc = Utils.createTimeInMillis(0, 0, 0, 1, 5, 2012, Time.TIMEZONE_UTC); 2063a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillisLocal = Utils.createTimeInMillis(0, 0, 0, 1, 5, 2012, 2073a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting Time.getCurrentTimezone()); 2083a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = startMillisLocal - DateUtils.DAY_IN_MILLIS; 2093a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, true, startMillisUtc, 15); 2103a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, startMillisLocal, 10); 2113a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(startMillisLocal - 15 * DateUtils.MINUTE_IN_MILLIS); 2123a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2133a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 2143a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2153a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2163a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2173a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2183a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2193a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testExpiredReminder() { 2203a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock test data. 2213a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 2223a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillis = currentMillis + DateUtils.HOUR_IN_MILLIS; 2233a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int reminderMin = 61; 2243a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, startMillis, reminderMin); 2253a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2263a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify no alarm was set. 2273a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2283a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2293a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertFalse(mMockAlarmManager.isAlarmSet()); 2303a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2313a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2323a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testAlarmMax() { 2333a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock test data for a reminder greater than 1 day in the future. 2343a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // This will be maxed out to 1 day out. 2353a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 2363a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long startMillis = currentMillis + DateUtils.DAY_IN_MILLIS * 3; 2373a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int reminderMin = (int) DateUtils.DAY_IN_MILLIS / (1000 * 60); 2383a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, startMillis, reminderMin); 2393a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(currentMillis + DateUtils.DAY_IN_MILLIS); 2403a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2413a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 2423a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2433a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2443a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2453a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2463a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2473a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testMultipleEvents() { 2483a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up multiple events where a later event time has an earlier reminder time. 2493a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 2503a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS, 0); 2513a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(2, false, currentMillis + DateUtils.MINUTE_IN_MILLIS * 60, 45); 2523a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(3, false, currentMillis + DateUtils.MINUTE_IN_MILLIS * 30, 10); 2533a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2543a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Expect event 2's reminder. 2553a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(currentMillis + DateUtils.MINUTE_IN_MILLIS * 15); 2563a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2573a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 2583a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2593a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2603a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2613a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2623a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2633a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testRecurringEvents() { 2643a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 2653a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2663a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Event in 3 days, with a 2 day reminder 2673a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS * 3, 2683a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting (int) DateUtils.DAY_IN_MILLIS * 2 / (1000 * 60) /* 2 day reminder */); 2693a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Event for tomorrow, with a 2 day reminder 2703a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS, 2713a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting (int) DateUtils.DAY_IN_MILLIS * 2 / (1000 * 60) /* 2 day reminder */); 2723a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2733a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Expect the reminder for the top event because the reminder time for the bottom 2743a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // one already passed. 2753a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(currentMillis + DateUtils.DAY_IN_MILLIS); 2763a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2773a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 2783a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2793a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2803a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2813a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2823a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2833a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testMultipleRemindersForEvent() { 2843a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up mock test data. 2853a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 2863a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS, 10); 2873a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS, 20); 2883a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(1, false, currentMillis + DateUtils.DAY_IN_MILLIS, 15); 2893a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2903a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Expect earliest reminder. 2913a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(currentMillis + DateUtils.DAY_IN_MILLIS - DateUtils.MINUTE_IN_MILLIS * 20); 2923a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2933a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm was set at the expected time. 2943a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, BATCH_SIZE, 2953a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 2963a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting assertTrue(mMockAlarmManager.isAlarmSet()); 2973a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 2983a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 2993a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting public void testLargeBatch() { 3003a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Add enough events to require several batches. 3013a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting long currentMillis = System.currentTimeMillis(); 3023a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting int batchSize = 5; 3033a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting for (int i = 19; i > 0; i--) { 3043a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addEventInfo(i, false, currentMillis + DateUtils.HOUR_IN_MILLIS * i, 3053a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 10); 3063a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 3073a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 3083a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Set up expectations for the batch queries. 3093a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting expectAlarmAt(currentMillis + DateUtils.MINUTE_IN_MILLIS * 50); 3103a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addExpectedRemindersQuery("method=1 AND event_id IN (19,18,17,16,15)"); 3113a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addExpectedRemindersQuery("method=1 AND event_id IN (14,13,12,11,10)"); 3123a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addExpectedRemindersQuery("method=1 AND event_id IN (9,8,7,6,5)"); 3133a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting mMockProvider.addExpectedRemindersQuery("method=1 AND event_id IN (4,3,2,1)"); 3143a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting 3153a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting // Invoke scheduleNextAlarm and verify alarm and reminder query batches. 3163a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting AlarmScheduler.scheduleNextAlarm(mIsolatedContext, mMockAlarmManager, batchSize, 3173a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting currentMillis); 3183a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting } 3193a07a68da6460c36a5dbec5b8828baa4355dbe04Sara Ting} 320