AlertServiceTest.java revision bce26a2a19499790595e48ca36b43eb130e4a3fb
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17package com.android.calendar.alerts; 18 19import static android.app.Notification.PRIORITY_DEFAULT; 20import static android.app.Notification.PRIORITY_HIGH; 21import static android.app.Notification.PRIORITY_MIN; 22 23import android.content.SharedPreferences; 24import android.database.MatrixCursor; 25import android.provider.CalendarContract.Attendees; 26import android.provider.CalendarContract.CalendarAlerts; 27import android.test.AndroidTestCase; 28import android.test.suitebuilder.annotation.SmallTest; 29import android.test.suitebuilder.annotation.Smoke; 30import android.text.format.DateUtils; 31import android.text.format.Time; 32 33import com.android.calendar.GeneralPreferences; 34import com.android.calendar.alerts.AlertService.NotificationInfo; 35import com.android.calendar.alerts.AlertService.NotificationWrapper; 36 37import java.util.ArrayList; 38import java.util.Arrays; 39import java.util.Map; 40import java.util.Set; 41 42public class AlertServiceTest extends AndroidTestCase { 43 44 class MockSharedPreferences implements SharedPreferences { 45 46 /* "always", "silent", depends on ringer mode */ 47 private String mVibrateWhen = "always"; 48 private String mRingtone = "/some/cool/ringtone"; 49 private boolean mPopup = true; 50 51 @Override 52 public boolean contains(String key) { 53 if (GeneralPreferences.KEY_ALERTS_VIBRATE_WHEN.equals(key)) { 54 return true; 55 } 56 return false; 57 } 58 59 @Override 60 public boolean getBoolean(String key, boolean defValue) { 61 if (GeneralPreferences.KEY_ALERTS_POPUP.equals(key)) { 62 return mPopup; 63 } 64 throw new IllegalArgumentException(); 65 } 66 67 @Override 68 public String getString(String key, String defValue) { 69 if (GeneralPreferences.KEY_ALERTS_VIBRATE_WHEN.equals(key)) { 70 return mVibrateWhen; 71 } 72 if (GeneralPreferences.KEY_ALERTS_RINGTONE.equals(key)) { 73 return mRingtone; 74 } 75 throw new IllegalArgumentException(); 76 } 77 78 @Override 79 public Map<String, ?> getAll() { 80 throw new IllegalArgumentException(); 81 } 82 83 @Override 84 public Set<String> getStringSet(String key, Set<String> defValues) { 85 throw new IllegalArgumentException(); 86 } 87 88 @Override 89 public int getInt(String key, int defValue) { 90 throw new IllegalArgumentException(); 91 } 92 93 @Override 94 public long getLong(String key, long defValue) { 95 throw new IllegalArgumentException(); 96 } 97 98 @Override 99 public float getFloat(String key, float defValue) { 100 throw new IllegalArgumentException(); 101 } 102 103 @Override 104 public Editor edit() { 105 throw new IllegalArgumentException(); 106 } 107 108 @Override 109 public void registerOnSharedPreferenceChangeListener( 110 OnSharedPreferenceChangeListener listener) { 111 throw new IllegalArgumentException(); 112 } 113 114 @Override 115 public void unregisterOnSharedPreferenceChangeListener( 116 OnSharedPreferenceChangeListener listener) { 117 throw new IllegalArgumentException(); 118 } 119 120 } 121 122 // Created these constants so the test cases are shorter 123 public static final int SCHEDULED = CalendarAlerts.STATE_SCHEDULED; 124 public static final int FIRED = CalendarAlerts.STATE_FIRED; 125 public static final int DISMISSED = CalendarAlerts.STATE_DISMISSED; 126 127 public static final int ACCEPTED = Attendees.ATTENDEE_STATUS_ACCEPTED; 128 public static final int DECLINED = Attendees.ATTENDEE_STATUS_DECLINED; 129 public static final int INVITED = Attendees.ATTENDEE_STATUS_INVITED; 130 public static final int TENTATIVE = Attendees.ATTENDEE_STATUS_TENTATIVE; 131 132 class NotificationInstance { 133 int mAlertId; 134 int[] mAlertIdsInDigest; 135 int mPriority; 136 137 public NotificationInstance(int alertId, int priority) { 138 mAlertId = alertId; 139 mPriority = priority; 140 } 141 142 public NotificationInstance(int[] alertIdsInDigest, int priority) { 143 mAlertIdsInDigest = alertIdsInDigest; 144 mPriority = priority; 145 } 146 } 147 148 class Alert { 149 long mEventId; 150 int mAlertStatus; 151 int mResponseStatus; 152 int mAllDay; 153 long mBegin; 154 long mEnd; 155 int mMinute; 156 long mAlarmTime; 157 158 public Alert(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 159 long end, int minute, long alarmTime) { 160 mEventId = eventId; 161 mAlertStatus = alertStatus; 162 mResponseStatus = responseStatus; 163 mAllDay = allDay; 164 mBegin = begin; 165 mEnd = end; 166 mMinute = minute; 167 mAlarmTime = alarmTime; 168 } 169 170 } 171 172 class AlertsTable { 173 174 ArrayList<Alert> mAlerts = new ArrayList<Alert>(); 175 176 int addAlertRow(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 177 long end, long alarmTime) { 178 Alert a = new Alert(eventId, alertStatus, responseStatus, allDay, begin, end, 179 5 /* minute */, alarmTime); 180 int id = mAlerts.size(); 181 mAlerts.add(a); 182 return id; 183 } 184 185 public MatrixCursor getAlertCursor() { 186 MatrixCursor alertCursor = new MatrixCursor(AlertService.ALERT_PROJECTION); 187 188 int i = 0; 189 for (Alert a : mAlerts) { 190 Object[] ca = { 191 i++, 192 a.mEventId, 193 a.mAlertStatus, 194 "Title" + a.mEventId + " " + a.mMinute, 195 "Loc" + a.mEventId, 196 a.mResponseStatus, 197 a.mAllDay, 198 a.mAlarmTime > 0 ? a.mAlarmTime : a.mBegin - a.mMinute * 60 * 1000, 199 a.mMinute, 200 a.mBegin, 201 a.mEnd, 202 "Desc: " + a.mAlarmTime 203 }; 204 alertCursor.addRow(ca); 205 } 206 return alertCursor; 207 } 208 209 } 210 211 class NotificationTestManager implements NotificationMgr { 212 // Expected notifications 213 NotificationInstance[] mNotifications; 214 215 // Flag to know which notification has been posted or canceled 216 boolean[] mDone; 217 218 // CalendarAlerts table 219 private ArrayList<Alert> mAlerts; 220 221 public NotificationTestManager(ArrayList<Alert> alerts, int maxNotifications) { 222 assertEquals(0, AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID); 223 mAlerts = alerts; 224 mNotifications = new NotificationInstance[maxNotifications + 1]; 225 } 226 227 public void expectTestNotification(int notificationId, int alertId, int highPriority) { 228 mNotifications[notificationId] = new NotificationInstance(alertId, highPriority); 229 } 230 231 public void expectTestNotification(int notificationId, int[] alertIds, int priority) { 232 mNotifications[notificationId] = new NotificationInstance(alertIds, priority); 233 } 234 235 private void verifyNotification(int id, NotificationWrapper nw) { 236 assertEquals(mNotifications[id].mPriority, nw.mNotification.priority); 237 238 NotificationInstance expected = mNotifications[id]; 239 if (expected.mAlertIdsInDigest == null) { 240 Alert a = mAlerts.get(expected.mAlertId); 241 assertEquals("Event ID", a.mEventId, nw.mEventId); 242 assertEquals("Begin time", a.mBegin, nw.mBegin); 243 assertEquals("End time", a.mEnd, nw.mEnd); 244 } else { 245 // Notification should be a digest. 246 assertNotNull("Posted notification not a digest as expected.", nw.mNw); 247 assertEquals("Number of notifications in digest not as expected.", 248 expected.mAlertIdsInDigest.length, nw.mNw.size()); 249 for (int i = 0; i < nw.mNw.size(); i++) { 250 Alert a = mAlerts.get(expected.mAlertIdsInDigest[i]); 251 assertEquals("Digest item " + i + ": Event ID not as expected", 252 a.mEventId, nw.mNw.get(i).mEventId); 253 assertEquals("Digest item " + i + ": Begin time in digest", 254 a.mBegin, nw.mNw.get(i).mBegin); 255 assertEquals("Digest item " + i + ": End time in digest", 256 a.mEnd, nw.mNw.get(i).mEnd); 257 } 258 } 259 } 260 261 public void validateNotificationsAndReset() { 262 for (int i = 0; i < mDone.length; i++) { 263 assertTrue("Notification id " + i + " has not been posted", mDone[i]); 264 } 265 Arrays.fill(mDone, false); 266 Arrays.fill(mNotifications, null); 267 } 268 269 /////////////////////////////// 270 // NotificationMgr methods 271 @Override 272 public void cancel(int id) { 273 if (mDone == null) { 274 mDone = new boolean[mNotifications.length]; 275 } 276 assertTrue("id out of bound: " + id, 0 <= id); 277 assertTrue("id out of bound: " + id, id < mDone.length); 278 assertFalse("id already used", mDone[id]); 279 mDone[id] = true; 280 assertNull("Unexpected cancel for id " + id, mNotifications[id]); 281 } 282 283 @Override 284 public void cancel(String tag, int id) { 285 throw new IllegalArgumentException(); 286 } 287 288 @Override 289 public void cancelAll() { 290 for (int i = 0; i < mNotifications.length; i++) { 291 assertNull("Expecting notification id " + i + ". Got cancelAll", mNotifications[i]); 292 293 if (mDone != null) { 294 assertFalse("Notification id " + i + " is done but got cancelAll", mDone[i]); 295 } 296 } 297 298 assertNull(mDone); // this should have been null since nothing 299 // should have been posted 300 mDone = new boolean[mNotifications.length]; 301 Arrays.fill(mDone, true); 302 } 303 304 @Override 305 public void notify(int id, NotificationWrapper nw) { 306 if (mDone == null) { 307 mDone = new boolean[mNotifications.length]; 308 } 309 assertTrue("id out of bound: " + id, 0 <= id); 310 assertTrue("id out of bound: " + id, id < mDone.length); 311 assertFalse("id already used", mDone[id]); 312 mDone[id] = true; 313 314 assertNotNull("Unexpected notify for id " + id, mNotifications[id]); 315 316 verifyNotification(id, nw); 317 } 318 319 @Override 320 public void notify(String tag, int id, NotificationWrapper nw) { 321 throw new IllegalArgumentException(); 322 } 323 } 324 325 // TODO 326 // Catch updates of new state, notify time, and received time 327 // Test ringer, vibrate, 328 // Test digest notifications 329 // Test intents, action email 330 // Catch alarmmgr calls 331 332 @Smoke 333 @SmallTest 334 public void testNoAlerts() { 335 MockSharedPreferences prefs = new MockSharedPreferences(); 336 AlertsTable at = new AlertsTable(); 337 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 338 AlertService.MAX_NOTIFICATIONS); 339 340 // Test no alert 341 long currentTime = 1000000; 342 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 343 AlertService.MAX_NOTIFICATIONS); 344 ntm.validateNotificationsAndReset(); 345 } 346 347 @Smoke 348 @SmallTest 349 public void testSingleAlert() { 350 MockSharedPreferences prefs = new MockSharedPreferences(); 351 AlertsTable at = new AlertsTable(); 352 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 353 AlertService.MAX_NOTIFICATIONS); 354 355 int id = at.addAlertRow(100, SCHEDULED, ACCEPTED, 0 /* all day */, 1300000, 2300000, 0); 356 357 // Test one up coming alert 358 long currentTime = 1000000; 359 ntm.expectTestNotification(1, id, PRIORITY_HIGH); 360 361 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 362 AlertService.MAX_NOTIFICATIONS); 363 ntm.validateNotificationsAndReset(); // This wipes out notification 364 // tests added so far 365 366 // Test half way into an event 367 currentTime = 2300000; 368 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_DEFAULT); 369 370 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 371 AlertService.MAX_NOTIFICATIONS); 372 ntm.validateNotificationsAndReset(); 373 374 // Test event ended 375 currentTime = 4300000; 376 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_MIN); 377 378 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 379 AlertService.MAX_NOTIFICATIONS); 380 ntm.validateNotificationsAndReset(); 381 } 382 383 @SmallTest 384 public void testMultipleAlerts() { 385 int maxNotifications = 10; 386 MockSharedPreferences prefs = new MockSharedPreferences(); 387 AlertsTable at = new AlertsTable(); 388 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 389 390 // Current time - 5:00 391 long currentTime = createTimeInMillis(5, 0); 392 393 // Set up future alerts. The real query implementation sorts by descending start 394 // time so simulate that here with our order of adds to AlertsTable. 395 int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 396 createTimeInMillis(10, 0), 0); 397 int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0), 398 createTimeInMillis(9, 0), 0); 399 int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0), 400 createTimeInMillis(8, 0), 0); 401 402 // Set up concurrent alerts (that started recently). 403 int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0), 404 createTimeInMillis(5, 40), 0); 405 int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55), 406 createTimeInMillis(7, 30), 0); 407 int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50), 408 createTimeInMillis(4, 50), 0); 409 410 // Set up past alerts. 411 int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0), 412 createTimeInMillis(4, 0), 0); 413 int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0), 414 createTimeInMillis(3, 0), 0); 415 int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0), 416 createTimeInMillis(2, 0), 0); 417 418 // Check posted notifications. The order listed here is the order simulates the 419 // order in the real notification bar (last one posted appears on top), so these 420 // should be lowest start time on top. 421 ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent 422 ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent 423 ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent 424 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 425 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 426 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 427 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 428 new int[] {id3, id2, id1}, PRIORITY_MIN); 429 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 430 maxNotifications); 431 ntm.validateNotificationsAndReset(); 432 433 // Increase time by 15 minutes to check that some concurrent events dropped 434 // to the low priority bucket. 435 currentTime = createTimeInMillis(5, 15); 436 ntm.expectTestNotification(4, id5, PRIORITY_HIGH); // concurrent 437 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 438 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 439 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 440 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 441 new int[] {id6, id4, id3, id2, id1}, PRIORITY_MIN); 442 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 443 maxNotifications); 444 ntm.validateNotificationsAndReset(); 445 446 // Increase time so some of the previously future ones change state. 447 currentTime = createTimeInMillis(8, 15); 448 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 449 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 450 new int[] {id8, id7, id6, id5, id4, id3, id2, id1}, PRIORITY_MIN); 451 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 452 maxNotifications); 453 ntm.validateNotificationsAndReset(); 454 } 455 456 @SmallTest 457 public void testMultipleAlerts_max() { 458 MockSharedPreferences prefs = new MockSharedPreferences(); 459 AlertsTable at = new AlertsTable(); 460 461 // Current time - 5:00 462 long currentTime = createTimeInMillis(5, 0); 463 464 // Set up future alerts. The real query implementation sorts by descending start 465 // time so simulate that here with our order of adds to AlertsTable. 466 int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 467 createTimeInMillis(10, 0), 0); 468 int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0), 469 createTimeInMillis(9, 0), 0); 470 int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0), 471 createTimeInMillis(8, 0), 0); 472 473 // Set up concurrent alerts (that started recently). 474 int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0), 475 createTimeInMillis(5, 40), 0); 476 int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55), 477 createTimeInMillis(7, 30), 0); 478 int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50), 479 createTimeInMillis(4, 50), 0); 480 481 // Set up past alerts. 482 int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0), 483 createTimeInMillis(4, 0), 0); 484 int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0), 485 createTimeInMillis(3, 0), 0); 486 int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0), 487 createTimeInMillis(2, 0), 0); 488 489 // Test when # alerts = max. 490 int maxNotifications = 6; 491 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 492 ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent 493 ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent 494 ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent 495 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 496 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 497 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 498 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 499 new int[] {id3, id2, id1}, PRIORITY_MIN); 500 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 501 maxNotifications); 502 ntm.validateNotificationsAndReset(); 503 504 // Test when # alerts > max. 505 maxNotifications = 4; 506 ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 507 ntm.expectTestNotification(4, id4, PRIORITY_HIGH); // concurrent 508 ntm.expectTestNotification(3, id5, PRIORITY_HIGH); // concurrent 509 ntm.expectTestNotification(2, id6, PRIORITY_HIGH); // concurrent 510 ntm.expectTestNotification(1, id7, PRIORITY_HIGH); // future 511 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 512 new int[] {id9, id8, id3, id2, id1}, PRIORITY_MIN); 513 AlertService.generateAlerts(mContext, ntm, prefs, at.getAlertCursor(), currentTime, 514 maxNotifications); 515 ntm.validateNotificationsAndReset(); 516 } 517 518 private NotificationInfo createNotificationInfo(long eventId) { 519 return new NotificationInfo("eventName", "location", "description", 100L, 200L, eventId, 520 false, false); 521 } 522 523 private static long createTimeInMillis(int hour, int minute) { 524 return createTimeInMillis(0 /* second */, minute, hour, 1 /* day */, 1 /* month */, 525 2012 /* year */, Time.getCurrentTimezone()); 526 } 527 528 private static long createTimeInMillis(int second, int minute, int hour, int monthDay, 529 int month, int year, String timezone) { 530 Time t = new Time(timezone); 531 t.set(second, minute, hour, monthDay, month, year); 532 t.normalize(false); 533 return t.toMillis(false); 534 } 535 536 @SmallTest 537 public void testProcessQuery_skipDeclinedDismissed() { 538 int declinedEventId = 1; 539 int dismissedEventId = 2; 540 int acceptedEventId = 3; 541 long acceptedStartTime = createTimeInMillis(10, 0); 542 long acceptedEndTime = createTimeInMillis(10, 30); 543 544 AlertsTable at = new AlertsTable(); 545 at.addAlertRow(declinedEventId, SCHEDULED, DECLINED, 0, createTimeInMillis(9, 0), 546 createTimeInMillis(10, 0), 0); 547 at.addAlertRow(dismissedEventId, SCHEDULED, DISMISSED, 0, createTimeInMillis(9, 30), 548 createTimeInMillis(11, 0), 0); 549 at.addAlertRow(acceptedEventId, SCHEDULED, ACCEPTED, 1, acceptedStartTime, acceptedEndTime, 550 0); 551 552 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 553 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 554 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 555 long currentTime = createTimeInMillis(5, 0); 556 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 557 mediumPriority, lowPriority); 558 559 assertEquals(0, lowPriority.size()); 560 assertEquals(0, mediumPriority.size()); 561 assertEquals(1, highPriority.size()); 562 assertEquals(acceptedEventId, highPriority.get(0).eventId); 563 assertEquals(acceptedStartTime, highPriority.get(0).startMillis); 564 assertEquals(acceptedEndTime, highPriority.get(0).endMillis); 565 assertTrue(highPriority.get(0).allDay); 566 } 567 568 @SmallTest 569 public void testProcessQuery_newAlert() { 570 int scheduledAlertEventId = 1; 571 int firedAlertEventId = 2; 572 573 AlertsTable at = new AlertsTable(); 574 at.addAlertRow(scheduledAlertEventId, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 575 createTimeInMillis(10, 0), 0); 576 at.addAlertRow(firedAlertEventId, FIRED, ACCEPTED, 0, createTimeInMillis(10, 0), 577 createTimeInMillis(10, 30), 0); 578 579 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 580 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 581 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 582 long currentTime = createTimeInMillis(5, 0); 583 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 584 mediumPriority, lowPriority); 585 586 assertEquals(0, lowPriority.size()); 587 assertEquals(0, mediumPriority.size()); 588 assertEquals(2, highPriority.size()); 589 assertEquals(scheduledAlertEventId, highPriority.get(0).eventId); 590 assertTrue("newAlert should be ON for scheduled alerts", highPriority.get(0).newAlert); 591 assertEquals(firedAlertEventId, highPriority.get(1).eventId); 592 assertFalse("newAlert should be OFF for fired alerts", highPriority.get(1).newAlert); 593 } 594 595 @SmallTest 596 public void testProcessQuery_recurringEvent() { 597 int eventId = 1; 598 long earlierStartTime = createTimeInMillis(10, 0); 599 long laterStartTime = createTimeInMillis(11, 0); 600 601 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 602 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 603 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 604 605 AlertsTable at = new AlertsTable(); 606 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 0, laterStartTime, 607 laterStartTime + DateUtils.HOUR_IN_MILLIS, 0); 608 at.addAlertRow(eventId, FIRED, ACCEPTED, 0, earlierStartTime, 609 earlierStartTime + DateUtils.HOUR_IN_MILLIS, 0); 610 611 // Both events in the future: the earliest one should be chosen. 612 long currentTime = earlierStartTime - DateUtils.DAY_IN_MILLIS * 5; 613 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 614 mediumPriority, lowPriority); 615 assertEquals(0, lowPriority.size()); 616 assertEquals(0, mediumPriority.size()); 617 assertEquals(1, highPriority.size()); 618 assertEquals("Recurring event with earlier start time expected", earlierStartTime, 619 highPriority.get(0).startMillis); 620 621 // Increment time just past the earlier event: the earlier one should be chosen. 622 highPriority.clear(); 623 currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 10; 624 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 625 mediumPriority, lowPriority); 626 assertEquals(0, lowPriority.size()); 627 assertEquals(0, mediumPriority.size()); 628 assertEquals(1, highPriority.size()); 629 assertEquals("Recurring event with earlier start time expected", earlierStartTime, 630 highPriority.get(0).startMillis); 631 632 // Increment time to 15 min past the earlier event: the later one should be chosen. 633 highPriority.clear(); 634 currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 15; 635 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 636 mediumPriority, lowPriority); 637 assertEquals(0, lowPriority.size()); 638 assertEquals(0, mediumPriority.size()); 639 assertEquals(1, highPriority.size()); 640 assertEquals("Recurring event with later start time expected", laterStartTime, 641 highPriority.get(0).startMillis); 642 643 // Both events in the past: the later one should be chosen (in the low priority bucket). 644 highPriority.clear(); 645 currentTime = laterStartTime + DateUtils.DAY_IN_MILLIS * 5; 646 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 647 mediumPriority, lowPriority); 648 assertEquals(0, highPriority.size()); 649 assertEquals(0, mediumPriority.size()); 650 assertEquals(1, lowPriority.size()); 651 assertEquals("Recurring event with later start time expected", laterStartTime, 652 lowPriority.get(0).startMillis); 653 } 654 655 @SmallTest 656 public void testProcessQuery_recurringAllDayEvent() { 657 int eventId = 1; 658 long day1 = createTimeInMillis(0, 0, 0, 1, 5, 2012, Time.TIMEZONE_UTC); 659 long day2 = createTimeInMillis(0, 0, 0, 2, 5, 2012, Time.TIMEZONE_UTC); 660 661 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 662 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 663 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 664 665 AlertsTable at = new AlertsTable(); 666 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day2, day2 + DateUtils.HOUR_IN_MILLIS * 24, 667 0); 668 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day1, day1 + DateUtils.HOUR_IN_MILLIS * 24, 669 0); 670 671 // Both events in the future: the earliest one should be chosen. 672 long currentTime = day1 - DateUtils.DAY_IN_MILLIS * 3; 673 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 674 mediumPriority, lowPriority); 675 assertEquals(0, lowPriority.size()); 676 assertEquals(0, mediumPriority.size()); 677 assertEquals(1, highPriority.size()); 678 assertEquals("Recurring event with earlier start time expected", day1, 679 highPriority.get(0).startMillis); 680 681 // Increment time just past the earlier event (to 12:10am). The earlier one should 682 // be chosen. 683 highPriority.clear(); 684 currentTime = createTimeInMillis(0, 10, 0, 1, 5, 2012, Time.getCurrentTimezone()); 685 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 686 mediumPriority, lowPriority); 687 assertEquals(0, lowPriority.size()); 688 assertEquals(0, mediumPriority.size()); 689 assertEquals(1, highPriority.size()); 690 assertEquals("Recurring event with earlier start time expected", day1, 691 highPriority.get(0).startMillis); 692 693 // Increment time to 15 min past the earlier event: the later one should be chosen. 694 highPriority.clear(); 695 currentTime = createTimeInMillis(0, 15, 0, 1, 5, 2012, Time.getCurrentTimezone()); 696 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 697 mediumPriority, lowPriority); 698 assertEquals(0, lowPriority.size()); 699 assertEquals(0, mediumPriority.size()); 700 assertEquals(1, highPriority.size()); 701 assertEquals("Recurring event with earlier start time expected", day2, 702 highPriority.get(0).startMillis); 703 704 // Both events in the past: the later one should be chosen (in the low priority bucket). 705 highPriority.clear(); 706 currentTime = day2 + DateUtils.DAY_IN_MILLIS * 1; 707 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 708 mediumPriority, lowPriority); 709 assertEquals(0, highPriority.size()); 710 assertEquals(0, mediumPriority.size()); 711 assertEquals(1, lowPriority.size()); 712 assertEquals("Recurring event with later start time expected", day2, 713 lowPriority.get(0).startMillis); 714 } 715 716 @SmallTest 717 public void testRedistributeBuckets_withinLimits() throws Exception { 718 int maxNotifications = 3; 719 ArrayList<NotificationInfo> threeItemList = new ArrayList<NotificationInfo>(); 720 threeItemList.add(createNotificationInfo(5)); 721 threeItemList.add(createNotificationInfo(4)); 722 threeItemList.add(createNotificationInfo(3)); 723 724 // Test when max notifications at high priority. 725 ArrayList<NotificationInfo> high = threeItemList; 726 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 727 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 728 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 729 assertEquals(3, high.size()); 730 assertEquals(0, medium.size()); 731 assertEquals(0, low.size()); 732 733 // Test when max notifications at medium priority. 734 high = new ArrayList<NotificationInfo>(); 735 medium = threeItemList; 736 low = new ArrayList<NotificationInfo>(); 737 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 738 assertEquals(0, high.size()); 739 assertEquals(3, medium.size()); 740 assertEquals(0, low.size()); 741 742 // Test when max notifications at high and medium priority 743 high = new ArrayList<NotificationInfo>(threeItemList); 744 medium = new ArrayList<NotificationInfo>(); 745 medium.add(high.remove(1)); 746 low = new ArrayList<NotificationInfo>(); 747 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 748 assertEquals(2, high.size()); 749 assertEquals(1, medium.size()); 750 assertEquals(0, low.size()); 751 } 752 753 @SmallTest 754 public void testRedistributeBuckets_tooManyHighPriority() throws Exception { 755 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 756 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 757 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 758 high.add(createNotificationInfo(5)); 759 high.add(createNotificationInfo(4)); 760 high.add(createNotificationInfo(3)); 761 high.add(createNotificationInfo(2)); 762 high.add(createNotificationInfo(1)); 763 764 // Invoke the method under test. 765 int maxNotifications = 3; 766 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 767 768 // Verify some high priority were kicked out. 769 assertEquals(3, high.size()); 770 assertEquals(3, high.get(0).eventId); 771 assertEquals(2, high.get(1).eventId); 772 assertEquals(1, high.get(2).eventId); 773 774 // Verify medium priority untouched. 775 assertEquals(0, medium.size()); 776 777 // Verify the extras went to low priority. 778 assertEquals(2, low.size()); 779 assertEquals(5, low.get(0).eventId); 780 assertEquals(4, low.get(1).eventId); 781 } 782 783 @SmallTest 784 public void testRedistributeBuckets_tooManyMediumPriority() throws Exception { 785 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 786 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 787 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 788 high.add(createNotificationInfo(5)); 789 high.add(createNotificationInfo(4)); 790 medium.add(createNotificationInfo(3)); 791 medium.add(createNotificationInfo(2)); 792 medium.add(createNotificationInfo(1)); 793 794 // Invoke the method under test. 795 int maxNotifications = 3; 796 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 797 798 // Verify high priority untouched. 799 assertEquals(2, high.size()); 800 assertEquals(5, high.get(0).eventId); 801 assertEquals(4, high.get(1).eventId); 802 803 // Verify some medium priority were kicked out (the ones near the end of the 804 // list). 805 assertEquals(1, medium.size()); 806 assertEquals(3, medium.get(0).eventId); 807 808 // Verify the extras went to low priority. 809 assertEquals(2, low.size()); 810 assertEquals(2, low.get(0).eventId); 811 assertEquals(1, low.get(1).eventId); 812 } 813 814 @SmallTest 815 public void testRedistributeBuckets_tooManyHighMediumPriority() throws Exception { 816 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 817 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 818 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 819 high.add(createNotificationInfo(8)); 820 high.add(createNotificationInfo(7)); 821 high.add(createNotificationInfo(6)); 822 high.add(createNotificationInfo(5)); 823 high.add(createNotificationInfo(4)); 824 medium.add(createNotificationInfo(3)); 825 medium.add(createNotificationInfo(2)); 826 medium.add(createNotificationInfo(1)); 827 828 // Invoke the method under test. 829 int maxNotifications = 3; 830 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 831 832 // Verify high priority. 833 assertEquals(3, high.size()); 834 assertEquals(6, high.get(0).eventId); 835 assertEquals(5, high.get(1).eventId); 836 assertEquals(4, high.get(2).eventId); 837 838 // Verify some medium priority. 839 assertEquals(0, medium.size()); 840 841 // Verify low priority. 842 assertEquals(5, low.size()); 843 assertEquals(8, low.get(0).eventId); 844 assertEquals(7, low.get(1).eventId); 845 assertEquals(3, low.get(2).eventId); 846 assertEquals(2, low.get(3).eventId); 847 assertEquals(1, low.get(4).eventId); 848 } 849} 850