AlertServiceTest.java revision 7a2de3d0ba146217e19d8dba74ff82000b0e676f
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.app.AlarmManager; 24import android.app.PendingIntent; 25import android.content.SharedPreferences; 26import android.database.MatrixCursor; 27import android.provider.CalendarContract.Attendees; 28import android.provider.CalendarContract.CalendarAlerts; 29import android.test.AndroidTestCase; 30import android.test.suitebuilder.annotation.SmallTest; 31import android.test.suitebuilder.annotation.Smoke; 32import android.text.format.DateUtils; 33import android.text.format.Time; 34 35import com.android.calendar.GeneralPreferences; 36import com.android.calendar.alerts.AlertService.NotificationInfo; 37import com.android.calendar.alerts.AlertService.NotificationWrapper; 38 39import junit.framework.Assert; 40 41import java.util.ArrayList; 42import java.util.Arrays; 43import java.util.Map; 44import java.util.Set; 45 46public class AlertServiceTest extends AndroidTestCase { 47 48 class MockSharedPreferences implements SharedPreferences { 49 50 /* "always", "silent", depends on ringer mode */ 51 private String mVibrateWhen; 52 private String mRingtone; 53 private Boolean mPopup; 54 55 // Strict mode will fail if a preference key is queried more than once. 56 private boolean mStrict = false; 57 58 MockSharedPreferences() { 59 this(false); 60 } 61 62 MockSharedPreferences(boolean strict) { 63 super(); 64 init(); 65 this.mStrict = strict; 66 } 67 68 void init() { 69 mVibrateWhen = "always"; 70 mRingtone = "/some/cool/ringtone"; 71 mPopup = true; 72 } 73 74 @Override 75 public boolean contains(String key) { 76 if (GeneralPreferences.KEY_ALERTS_VIBRATE_WHEN.equals(key)) { 77 return true; 78 } 79 return false; 80 } 81 82 @Override 83 public boolean getBoolean(String key, boolean defValue) { 84 if (GeneralPreferences.KEY_ALERTS_POPUP.equals(key)) { 85 if (mPopup == null) { 86 Assert.fail(GeneralPreferences.KEY_ALERTS_POPUP + " fetched more than once."); 87 } 88 boolean val = mPopup; 89 if (mStrict) { 90 mPopup = null; 91 } 92 return val; 93 } 94 throw new IllegalArgumentException(); 95 } 96 97 @Override 98 public String getString(String key, String defValue) { 99 if (GeneralPreferences.KEY_ALERTS_VIBRATE_WHEN.equals(key)) { 100 if (mVibrateWhen == null) { 101 Assert.fail(GeneralPreferences.KEY_ALERTS_VIBRATE_WHEN 102 + " fetched more than once."); 103 } 104 String val = mVibrateWhen; 105 if (mStrict) { 106 mVibrateWhen = null; 107 } 108 return val; 109 } 110 if (GeneralPreferences.KEY_ALERTS_RINGTONE.equals(key)) { 111 if (mRingtone == null) { 112 Assert.fail(GeneralPreferences.KEY_ALERTS_RINGTONE 113 + " fetched more than once."); 114 } 115 String val = mRingtone; 116 if (mStrict) { 117 mRingtone = null; 118 } 119 return val; 120 } 121 throw new IllegalArgumentException(); 122 } 123 124 @Override 125 public Map<String, ?> getAll() { 126 throw new IllegalArgumentException(); 127 } 128 129 @Override 130 public Set<String> getStringSet(String key, Set<String> defValues) { 131 throw new IllegalArgumentException(); 132 } 133 134 @Override 135 public int getInt(String key, int defValue) { 136 throw new IllegalArgumentException(); 137 } 138 139 @Override 140 public long getLong(String key, long defValue) { 141 throw new IllegalArgumentException(); 142 } 143 144 @Override 145 public float getFloat(String key, float defValue) { 146 throw new IllegalArgumentException(); 147 } 148 149 @Override 150 public Editor edit() { 151 throw new IllegalArgumentException(); 152 } 153 154 @Override 155 public void registerOnSharedPreferenceChangeListener( 156 OnSharedPreferenceChangeListener listener) { 157 throw new IllegalArgumentException(); 158 } 159 160 @Override 161 public void unregisterOnSharedPreferenceChangeListener( 162 OnSharedPreferenceChangeListener listener) { 163 throw new IllegalArgumentException(); 164 } 165 166 } 167 168 // Created these constants so the test cases are shorter 169 public static final int SCHEDULED = CalendarAlerts.STATE_SCHEDULED; 170 public static final int FIRED = CalendarAlerts.STATE_FIRED; 171 public static final int DISMISSED = CalendarAlerts.STATE_DISMISSED; 172 173 public static final int ACCEPTED = Attendees.ATTENDEE_STATUS_ACCEPTED; 174 public static final int DECLINED = Attendees.ATTENDEE_STATUS_DECLINED; 175 public static final int INVITED = Attendees.ATTENDEE_STATUS_INVITED; 176 public static final int TENTATIVE = Attendees.ATTENDEE_STATUS_TENTATIVE; 177 178 class NotificationInstance { 179 int mAlertId; 180 int[] mAlertIdsInDigest; 181 int mPriority; 182 183 public NotificationInstance(int alertId, int priority) { 184 mAlertId = alertId; 185 mPriority = priority; 186 } 187 188 public NotificationInstance(int[] alertIdsInDigest, int priority) { 189 mAlertIdsInDigest = alertIdsInDigest; 190 mPriority = priority; 191 } 192 } 193 194 class Alert { 195 long mEventId; 196 int mAlertStatus; 197 int mResponseStatus; 198 int mAllDay; 199 long mBegin; 200 long mEnd; 201 int mMinute; 202 long mAlarmTime; 203 204 public Alert(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 205 long end, int minute, long alarmTime) { 206 mEventId = eventId; 207 mAlertStatus = alertStatus; 208 mResponseStatus = responseStatus; 209 mAllDay = allDay; 210 mBegin = begin; 211 mEnd = end; 212 mMinute = minute; 213 mAlarmTime = alarmTime; 214 } 215 216 } 217 218 class AlertsTable { 219 220 ArrayList<Alert> mAlerts = new ArrayList<Alert>(); 221 222 int addAlertRow(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 223 long end, long alarmTime) { 224 Alert a = new Alert(eventId, alertStatus, responseStatus, allDay, begin, end, 225 5 /* minute */, alarmTime); 226 int id = mAlerts.size(); 227 mAlerts.add(a); 228 return id; 229 } 230 231 public MatrixCursor getAlertCursor() { 232 MatrixCursor alertCursor = new MatrixCursor(AlertService.ALERT_PROJECTION); 233 234 int i = 0; 235 for (Alert a : mAlerts) { 236 Object[] ca = { 237 i++, 238 a.mEventId, 239 a.mAlertStatus, 240 "Title" + a.mEventId + " " + a.mMinute, 241 "Loc" + a.mEventId, 242 a.mResponseStatus, 243 a.mAllDay, 244 a.mAlarmTime > 0 ? a.mAlarmTime : a.mBegin - a.mMinute * 60 * 1000, 245 a.mMinute, 246 a.mBegin, 247 a.mEnd, 248 "Desc: " + a.mAlarmTime 249 }; 250 alertCursor.addRow(ca); 251 } 252 return alertCursor; 253 } 254 255 } 256 257 class NotificationTestManager extends NotificationMgr { 258 // Expected notifications 259 NotificationInstance[] mExpectedNotifications; 260 NotificationWrapper[] mActualNotifications; 261 boolean[] mCancelled; 262 263 // CalendarAlerts table 264 private ArrayList<Alert> mAlerts; 265 266 public NotificationTestManager(ArrayList<Alert> alerts, int maxNotifications) { 267 assertEquals(0, AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID); 268 mAlerts = alerts; 269 mExpectedNotifications = new NotificationInstance[maxNotifications + 1]; 270 mActualNotifications = new NotificationWrapper[mExpectedNotifications.length]; 271 mCancelled = new boolean[mExpectedNotifications.length]; 272 } 273 274 public void expectTestNotification(int notificationId, int alertId, int highPriority) { 275 mExpectedNotifications[notificationId] = new NotificationInstance(alertId, 276 highPriority); 277 } 278 279 public void expectTestNotification(int notificationId, int[] alertIds, int priority) { 280 mExpectedNotifications[notificationId] = new NotificationInstance(alertIds, priority); 281 } 282 283 private <T> boolean nullContents(T[] array) { 284 for (T item : array) { 285 if (item != null) { 286 return false; 287 } 288 } 289 return true; 290 } 291 292 public void validateNotificationsAndReset() { 293 if (nullContents(mExpectedNotifications)) { 294 return; 295 } 296 297 String debugStr = printActualNotifications(); 298 for (int id = 0; id < mActualNotifications.length; id++) { 299 NotificationInstance expected = mExpectedNotifications[id]; 300 NotificationWrapper actual = mActualNotifications[id]; 301 if (expected == null) { 302 assertNull("Received unexpected notificationId " + id + debugStr, actual); 303 assertTrue("NotificationId " + id + " should have been cancelled." + debugStr, 304 mCancelled[id]); 305 } else { 306 assertNotNull("Expected notificationId " + id + " but it was not posted." 307 + debugStr, actual); 308 assertFalse("NotificationId " + id + " should not have been cancelled." 309 + debugStr, mCancelled[id]); 310 assertEquals("Priority not as expected for notification " + id + debugStr, 311 expected.mPriority, actual.mNotification.priority); 312 if (expected.mAlertIdsInDigest == null) { 313 Alert a = mAlerts.get(expected.mAlertId); 314 assertEquals("Event ID not expected for notification " + id + debugStr, 315 a.mEventId, actual.mEventId); 316 assertEquals("Begin time not expected for notification " + id + debugStr, 317 a.mBegin, actual.mBegin); 318 assertEquals("End time not expected for notification " + id + debugStr, 319 a.mEnd, actual.mEnd); 320 } else { 321 // Notification should be a digest. 322 assertNotNull("Posted notification not a digest as expected." + debugStr, 323 actual.mNw); 324 assertEquals("Number of notifications in digest not as expected." 325 + debugStr, expected.mAlertIdsInDigest.length, actual.mNw.size()); 326 for (int i = 0; i < actual.mNw.size(); i++) { 327 Alert a = mAlerts.get(expected.mAlertIdsInDigest[i]); 328 assertEquals("Digest item " + i + ": Event ID not as expected" 329 + debugStr, a.mEventId, actual.mNw.get(i).mEventId); 330 assertEquals("Digest item " + i + ": Begin time in digest not expected" 331 + debugStr, a.mBegin, actual.mNw.get(i).mBegin); 332 assertEquals("Digest item " + i + ": End time in digest not expected" 333 + debugStr, a.mEnd, actual.mNw.get(i).mEnd); 334 } 335 } 336 } 337 } 338 339 Arrays.fill(mCancelled, false); 340 Arrays.fill(mExpectedNotifications, null); 341 Arrays.fill(mActualNotifications, null); 342 } 343 344 private String printActualNotifications() { 345 StringBuilder s = new StringBuilder(); 346 s.append("\n\nNotifications actually posted:\n"); 347 for (int i = mActualNotifications.length - 1; i >= 0; i--) { 348 NotificationWrapper actual = mActualNotifications[i]; 349 if (actual == null) { 350 continue; 351 } 352 s.append("Notification " + i + " -- "); 353 s.append("priority:" + actual.mNotification.priority); 354 if (actual.mNw == null) { 355 s.append(", eventId:" + actual.mEventId); 356 } else { 357 s.append(", eventIds:{"); 358 for (int digestIndex = 0; digestIndex < actual.mNw.size(); digestIndex++) { 359 s.append(actual.mNw.get(digestIndex).mEventId + ","); 360 } 361 s.append("}"); 362 } 363 s.append("\n"); 364 } 365 return s.toString(); 366 } 367 368 /////////////////////////////// 369 // NotificationMgr methods 370 @Override 371 public void cancel(int id) { 372 assertTrue("id out of bound: " + id, 0 <= id); 373 assertTrue("id out of bound: " + id, id < mCancelled.length); 374 assertNull("id already used", mActualNotifications[id]); 375 assertFalse("id already used", mCancelled[id]); 376 mCancelled[id] = true; 377 assertNull("Unexpected cancel for id " + id, mExpectedNotifications[id]); 378 } 379 380 public void notify(int id, NotificationWrapper nw) { 381 assertTrue("id out of bound: " + id, 0 <= id); 382 assertTrue("id out of bound: " + id, id < mExpectedNotifications.length); 383 assertNull("id already used: " + id, mActualNotifications[id]); 384 mActualNotifications[id] = nw; 385 } 386 } 387 388 private class MockAlarmManager implements AlarmManagerInterface { 389 private int expectedAlarmType = -1; 390 private long expectedAlarmTime = -1; 391 392 public void expectAlarmTime(int type, long millis) { 393 this.expectedAlarmType = type; 394 this.expectedAlarmTime = millis; 395 } 396 397 @Override 398 public void set(int actualAlarmType, long actualAlarmTime, PendingIntent operation) { 399 assertNotNull(operation); 400 if (expectedAlarmType != -1) { 401 assertEquals("Alarm type not expected.", expectedAlarmType, actualAlarmType); 402 assertEquals("Alarm time not expected. Expected:" + DateUtils.formatDateTime( 403 mContext, expectedAlarmTime, DateUtils.FORMAT_SHOW_TIME) + ", actual:" 404 + DateUtils.formatDateTime(mContext, actualAlarmTime, 405 DateUtils.FORMAT_SHOW_TIME), expectedAlarmTime, actualAlarmTime); 406 } 407 } 408 } 409 410 // TODO 411 // Catch updates of new state, notify time, and received time 412 // Test ringer, vibrate, 413 // Test intents, action email 414 415 @Smoke 416 @SmallTest 417 public void testGenerateAlerts_none() { 418 MockSharedPreferences prefs = new MockSharedPreferences(); 419 AlertsTable at = new AlertsTable(); 420 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 421 AlertService.MAX_NOTIFICATIONS); 422 423 // Test no alert 424 long currentTime = 1000000; 425 AlertService.generateAlerts(mContext, ntm, new MockAlarmManager(), prefs, 426 at.getAlertCursor(), currentTime, AlertService.MAX_NOTIFICATIONS); 427 ntm.validateNotificationsAndReset(); 428 } 429 430 @Smoke 431 @SmallTest 432 public void testGenerateAlerts_single() { 433 MockSharedPreferences prefs = new MockSharedPreferences(); 434 MockAlarmManager alarmMgr = new MockAlarmManager(); 435 AlertsTable at = new AlertsTable(); 436 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 437 AlertService.MAX_NOTIFICATIONS); 438 439 int id = at.addAlertRow(100, SCHEDULED, ACCEPTED, 0 /* all day */, 1300000, 2300000, 0); 440 441 // Test one up coming alert 442 long currentTime = 1000000; 443 ntm.expectTestNotification(1, id, PRIORITY_HIGH); 444 445 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime, 446 AlertService.MAX_NOTIFICATIONS); 447 ntm.validateNotificationsAndReset(); // This wipes out notification 448 // tests added so far 449 450 // Test half way into an event 451 currentTime = 2300000; 452 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_MIN); 453 454 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime, 455 AlertService.MAX_NOTIFICATIONS); 456 ntm.validateNotificationsAndReset(); 457 458 // Test event ended 459 currentTime = 4300000; 460 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id, PRIORITY_MIN); 461 462 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), currentTime, 463 AlertService.MAX_NOTIFICATIONS); 464 ntm.validateNotificationsAndReset(); 465 } 466 467 @SmallTest 468 public void testGenerateAlerts_multiple() { 469 int maxNotifications = 10; 470 MockSharedPreferences prefs = new MockSharedPreferences(); 471 MockAlarmManager alarmMgr = new MockAlarmManager(); 472 AlertsTable at = new AlertsTable(); 473 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 474 475 // Current time - 5:00 476 long currentTime = createTimeInMillis(5, 0); 477 478 // Set up future alerts. The real query implementation sorts by descending start 479 // time so simulate that here with our order of adds to AlertsTable. 480 int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 481 createTimeInMillis(10, 0), 0); 482 int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0), 483 createTimeInMillis(9, 0), 0); 484 int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0), 485 createTimeInMillis(8, 0), 0); 486 487 // Set up concurrent alerts (that started recently). 488 int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0), 489 createTimeInMillis(5, 40), 0); 490 int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55), 491 createTimeInMillis(7, 30), 0); 492 int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50), 493 createTimeInMillis(4, 50), 0); 494 495 // Set up past alerts. 496 int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0), 497 createTimeInMillis(4, 0), 0); 498 int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0), 499 createTimeInMillis(3, 0), 0); 500 int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0), 501 createTimeInMillis(2, 0), 0); 502 503 // Check posted notifications. The order listed here is the order simulates the 504 // order in the real notification bar (last one posted appears on top), so these 505 // should be lowest start time on top. 506 ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent 507 ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent 508 ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent 509 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 510 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 511 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 512 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 513 new int[] {id3, id2, id1}, PRIORITY_MIN); 514 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 515 currentTime, maxNotifications); 516 ntm.validateNotificationsAndReset(); 517 518 // Increase time by 15 minutes to check that some concurrent events dropped 519 // to the low priority bucket. 520 currentTime = createTimeInMillis(5, 15); 521 ntm.expectTestNotification(4, id5, PRIORITY_HIGH); // concurrent 522 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 523 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 524 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 525 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 526 new int[] {id6, id4, id3, id2, id1}, PRIORITY_MIN); 527 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 528 currentTime, maxNotifications); 529 ntm.validateNotificationsAndReset(); 530 531 // Increase time so some of the previously future ones change state. 532 currentTime = createTimeInMillis(8, 15); 533 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 534 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 535 new int[] {id8, id7, id6, id5, id4, id3, id2, id1}, PRIORITY_MIN); 536 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 537 currentTime, maxNotifications); 538 ntm.validateNotificationsAndReset(); 539 } 540 541 @SmallTest 542 public void testGenerateAlerts_maxAlerts() { 543 MockSharedPreferences prefs = new MockSharedPreferences(); 544 MockAlarmManager alarmMgr = new MockAlarmManager(); 545 AlertsTable at = new AlertsTable(); 546 547 // Current time - 5:00 548 long currentTime = createTimeInMillis(5, 0); 549 550 // Set up future alerts. The real query implementation sorts by descending start 551 // time so simulate that here with our order of adds to AlertsTable. 552 int id9 = at.addAlertRow(9, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 553 createTimeInMillis(10, 0), 0); 554 int id8 = at.addAlertRow(8, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0), 555 createTimeInMillis(9, 0), 0); 556 int id7 = at.addAlertRow(7, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0), 557 createTimeInMillis(8, 0), 0); 558 559 // Set up concurrent alerts (that started recently). 560 int id6 = at.addAlertRow(6, SCHEDULED, ACCEPTED, 0, createTimeInMillis(5, 0), 561 createTimeInMillis(5, 40), 0); 562 int id5 = at.addAlertRow(5, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 55), 563 createTimeInMillis(7, 30), 0); 564 int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, createTimeInMillis(4, 50), 565 createTimeInMillis(4, 50), 0); 566 567 // Set up past alerts. 568 int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(3, 0), 569 createTimeInMillis(4, 0), 0); 570 int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(2, 0), 571 createTimeInMillis(3, 0), 0); 572 int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(1, 0), 573 createTimeInMillis(2, 0), 0); 574 575 // Test when # alerts = max. 576 int maxNotifications = 6; 577 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 578 ntm.expectTestNotification(6, id4, PRIORITY_HIGH); // concurrent 579 ntm.expectTestNotification(5, id5, PRIORITY_HIGH); // concurrent 580 ntm.expectTestNotification(4, id6, PRIORITY_HIGH); // concurrent 581 ntm.expectTestNotification(3, id7, PRIORITY_HIGH); // future 582 ntm.expectTestNotification(2, id8, PRIORITY_HIGH); // future 583 ntm.expectTestNotification(1, id9, PRIORITY_HIGH); // future 584 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 585 new int[] {id3, id2, id1}, PRIORITY_MIN); 586 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 587 currentTime, maxNotifications); 588 ntm.validateNotificationsAndReset(); 589 590 // Test when # alerts > max. 591 maxNotifications = 4; 592 ntm = new NotificationTestManager(at.mAlerts, maxNotifications); 593 ntm.expectTestNotification(4, id4, PRIORITY_HIGH); // concurrent 594 ntm.expectTestNotification(3, id5, PRIORITY_HIGH); // concurrent 595 ntm.expectTestNotification(2, id6, PRIORITY_HIGH); // concurrent 596 ntm.expectTestNotification(1, id7, PRIORITY_HIGH); // future 597 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 598 new int[] {id9, id8, id3, id2, id1}, PRIORITY_MIN); 599 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 600 currentTime, maxNotifications); 601 ntm.validateNotificationsAndReset(); 602 } 603 604 /** 605 * Test that the SharedPreferences are only fetched once for each setting. 606 */ 607 @SmallTest 608 public void testGenerateAlerts_sharedPreferences() { 609 MockSharedPreferences prefs = new MockSharedPreferences(true /* strict mode */); 610 AlertsTable at = new AlertsTable(); 611 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 612 AlertService.MAX_NOTIFICATIONS); 613 614 // Current time - 5:00 615 long currentTime = createTimeInMillis(5, 0); 616 617 // Set up future alerts. The real query implementation sorts by descending start 618 // time so simulate that here with our order of adds to AlertsTable. 619 at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 620 createTimeInMillis(10, 0), 0); 621 at.addAlertRow(2, SCHEDULED, ACCEPTED, 0, createTimeInMillis(8, 0), 622 createTimeInMillis(9, 0), 0); 623 at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, createTimeInMillis(7, 0), 624 createTimeInMillis(8, 0), 0); 625 626 // If this does not result in a failure (MockSharedPreferences fails for duplicate 627 // queries), then test passes. 628 AlertService.generateAlerts(mContext, ntm, new MockAlarmManager(), prefs, 629 at.getAlertCursor(), currentTime, AlertService.MAX_NOTIFICATIONS); 630 } 631 632 public void testGenerateAlerts_refreshTime() { 633 AlertsTable at = new AlertsTable(); 634 MockSharedPreferences prefs = new MockSharedPreferences(); 635 MockAlarmManager alarmMgr = new MockAlarmManager(); 636 NotificationTestManager ntm = new NotificationTestManager(at.mAlerts, 637 AlertService.MAX_NOTIFICATIONS); 638 639 // Since AlertService.processQuery uses DateUtils.isToday instead of checking against 640 // the passed in currentTime (not worth allocating the extra Time objects to do so), use 641 // today's date for this test. 642 Time now = new Time(); 643 now.setToNow(); 644 int day = now.monthDay; 645 int month = now.month; 646 int year = now.year; 647 Time yesterday = new Time(); 648 yesterday.set(System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS); 649 Time tomorrow = new Time(); 650 tomorrow.set(System.currentTimeMillis() + DateUtils.DAY_IN_MILLIS); 651 long allDayStart = createTimeInMillis(0, 0, 0, day, month, year, Time.TIMEZONE_UTC); 652 653 /* today 10am - 10:30am */ 654 int id4 = at.addAlertRow(4, SCHEDULED, ACCEPTED, 0, 655 createTimeInMillis(0, 0, 10, day, month, year, Time.getCurrentTimezone()), 656 createTimeInMillis(0, 30, 10, day, month, year, Time.getCurrentTimezone()), 0); 657 /* today 6am - 6am (0 duration event) */ 658 int id3 = at.addAlertRow(3, SCHEDULED, ACCEPTED, 0, 659 createTimeInMillis(0, 0, 6, day, month, year, Time.getCurrentTimezone()), 660 createTimeInMillis(0, 0, 6, day, month, year, Time.getCurrentTimezone()), 0); 661 /* today allDay */ 662 int id2 = at.addAlertRow(2, SCHEDULED, ACCEPTED, 1, allDayStart, 663 allDayStart + DateUtils.HOUR_IN_MILLIS * 24, 0); 664 /* yesterday 11pm - today 7am (multiday event) */ 665 int id1 = at.addAlertRow(1, SCHEDULED, ACCEPTED, 0, 666 createTimeInMillis(0, 0, 23, yesterday.monthDay, yesterday.month, yesterday.year, 667 Time.getCurrentTimezone()), 668 createTimeInMillis(0, 0, 7, day, month, year, Time.getCurrentTimezone()), 0); 669 670 // Test at midnight - next refresh should be 15 min later (15 min into the all 671 // day event). 672 long currentTime = createTimeInMillis(0, 0, 0, day, month, year, Time.getCurrentTimezone()); 673 alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 15 * DateUtils.MINUTE_IN_MILLIS); 674 ntm.expectTestNotification(4, id1, PRIORITY_HIGH); 675 ntm.expectTestNotification(3, id2, PRIORITY_HIGH); 676 ntm.expectTestNotification(2, id3, PRIORITY_HIGH); 677 ntm.expectTestNotification(1, id4, PRIORITY_HIGH); 678 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 679 currentTime, AlertService.MAX_NOTIFICATIONS); 680 ntm.validateNotificationsAndReset(); 681 682 // Test at 12:30am - next refresh should be 30 min later (1/4 into event 'id1'). 683 currentTime = createTimeInMillis(0, 30, 0, day, month, year, Time.getCurrentTimezone()); 684 alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 30 * DateUtils.MINUTE_IN_MILLIS); 685 ntm.expectTestNotification(3, id1, PRIORITY_HIGH); 686 ntm.expectTestNotification(2, id3, PRIORITY_HIGH); 687 ntm.expectTestNotification(1, id4, PRIORITY_HIGH); 688 ntm.expectTestNotification(4, id2, PRIORITY_DEFAULT); 689 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 690 currentTime, AlertService.MAX_NOTIFICATIONS); 691 ntm.validateNotificationsAndReset(); 692 693 // Test at 5:55am - next refresh should be 20 min later (15 min after 'id3'). 694 currentTime = createTimeInMillis(0, 55, 5, day, month, year, Time.getCurrentTimezone()); 695 alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 20 * DateUtils.MINUTE_IN_MILLIS); 696 ntm.expectTestNotification(2, id3, PRIORITY_HIGH); 697 ntm.expectTestNotification(1, id4, PRIORITY_HIGH); 698 ntm.expectTestNotification(3, id2, PRIORITY_DEFAULT); 699 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, id1, PRIORITY_MIN); 700 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 701 currentTime, AlertService.MAX_NOTIFICATIONS); 702 ntm.validateNotificationsAndReset(); 703 704 // Test at 10:14am - next refresh should be 1 min later (15 min into event 'id4'). 705 currentTime = createTimeInMillis(0, 14, 10, day, month, year, Time.getCurrentTimezone()); 706 alarmMgr.expectAlarmTime(AlarmManager.RTC, currentTime + 1 * DateUtils.MINUTE_IN_MILLIS); 707 ntm.expectTestNotification(1, id4, PRIORITY_HIGH); 708 ntm.expectTestNotification(2, id2, PRIORITY_DEFAULT); 709 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, new int[] {id3, id1}, 710 PRIORITY_MIN); 711 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 712 currentTime, AlertService.MAX_NOTIFICATIONS); 713 ntm.validateNotificationsAndReset(); 714 715 // Test at 10:15am - next refresh should be tomorrow midnight (end of all day event 'id2'). 716 currentTime = createTimeInMillis(0, 15, 10, day, month, year, Time.getCurrentTimezone()); 717 alarmMgr.expectAlarmTime(AlarmManager.RTC, createTimeInMillis(0, 0, 23, tomorrow.monthDay, 718 tomorrow.month, tomorrow.year, Time.getCurrentTimezone())); 719 ntm.expectTestNotification(1, id2, PRIORITY_DEFAULT); 720 ntm.expectTestNotification(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID, 721 new int[] {id4, id3, id1}, PRIORITY_MIN); 722 AlertService.generateAlerts(mContext, ntm, alarmMgr, prefs, at.getAlertCursor(), 723 currentTime, AlertService.MAX_NOTIFICATIONS); 724 ntm.validateNotificationsAndReset(); 725 } 726 727 private NotificationInfo createNotificationInfo(long eventId) { 728 return new NotificationInfo("eventName", "location", "description", 100L, 200L, eventId, 729 false, false); 730 } 731 732 private static long createTimeInMillis(int hour, int minute) { 733 return createTimeInMillis(0 /* second */, minute, hour, 1 /* day */, 1 /* month */, 734 2012 /* year */, Time.getCurrentTimezone()); 735 } 736 737 private static long createTimeInMillis(int second, int minute, int hour, int monthDay, 738 int month, int year, String timezone) { 739 Time t = new Time(timezone); 740 t.set(second, minute, hour, monthDay, month, year); 741 t.normalize(false); 742 return t.toMillis(false); 743 } 744 745 @SmallTest 746 public void testProcessQuery_skipDeclinedDismissed() { 747 int declinedEventId = 1; 748 int dismissedEventId = 2; 749 int acceptedEventId = 3; 750 long acceptedStartTime = createTimeInMillis(10, 0); 751 long acceptedEndTime = createTimeInMillis(10, 30); 752 753 AlertsTable at = new AlertsTable(); 754 at.addAlertRow(declinedEventId, SCHEDULED, DECLINED, 0, createTimeInMillis(9, 0), 755 createTimeInMillis(10, 0), 0); 756 at.addAlertRow(dismissedEventId, SCHEDULED, DISMISSED, 0, createTimeInMillis(9, 30), 757 createTimeInMillis(11, 0), 0); 758 at.addAlertRow(acceptedEventId, SCHEDULED, ACCEPTED, 1, acceptedStartTime, acceptedEndTime, 759 0); 760 761 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 762 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 763 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 764 long currentTime = createTimeInMillis(5, 0); 765 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 766 mediumPriority, lowPriority); 767 768 assertEquals(0, lowPriority.size()); 769 assertEquals(0, mediumPriority.size()); 770 assertEquals(1, highPriority.size()); 771 assertEquals(acceptedEventId, highPriority.get(0).eventId); 772 assertEquals(acceptedStartTime, highPriority.get(0).startMillis); 773 assertEquals(acceptedEndTime, highPriority.get(0).endMillis); 774 assertTrue(highPriority.get(0).allDay); 775 } 776 777 @SmallTest 778 public void testProcessQuery_newAlert() { 779 int scheduledAlertEventId = 1; 780 int firedAlertEventId = 2; 781 782 AlertsTable at = new AlertsTable(); 783 at.addAlertRow(scheduledAlertEventId, SCHEDULED, ACCEPTED, 0, createTimeInMillis(9, 0), 784 createTimeInMillis(10, 0), 0); 785 at.addAlertRow(firedAlertEventId, FIRED, ACCEPTED, 0, createTimeInMillis(10, 0), 786 createTimeInMillis(10, 30), 0); 787 788 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 789 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 790 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 791 long currentTime = createTimeInMillis(5, 0); 792 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 793 mediumPriority, lowPriority); 794 795 assertEquals(0, lowPriority.size()); 796 assertEquals(0, mediumPriority.size()); 797 assertEquals(2, highPriority.size()); 798 assertEquals(scheduledAlertEventId, highPriority.get(0).eventId); 799 assertTrue("newAlert should be ON for scheduled alerts", highPriority.get(0).newAlert); 800 assertEquals(firedAlertEventId, highPriority.get(1).eventId); 801 assertFalse("newAlert should be OFF for fired alerts", highPriority.get(1).newAlert); 802 } 803 804 @SmallTest 805 public void testProcessQuery_recurringEvent() { 806 int eventId = 1; 807 long earlierStartTime = createTimeInMillis(10, 0); 808 long laterStartTime = createTimeInMillis(11, 0); 809 810 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 811 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 812 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 813 814 AlertsTable at = new AlertsTable(); 815 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 0, laterStartTime, 816 laterStartTime + DateUtils.HOUR_IN_MILLIS, 0); 817 at.addAlertRow(eventId, FIRED, ACCEPTED, 0, earlierStartTime, 818 earlierStartTime + DateUtils.HOUR_IN_MILLIS, 0); 819 820 // Both events in the future: the earliest one should be chosen. 821 long currentTime = earlierStartTime - DateUtils.DAY_IN_MILLIS * 5; 822 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 823 mediumPriority, lowPriority); 824 assertEquals(0, lowPriority.size()); 825 assertEquals(0, mediumPriority.size()); 826 assertEquals(1, highPriority.size()); 827 assertEquals("Recurring event with earlier start time expected", earlierStartTime, 828 highPriority.get(0).startMillis); 829 830 // Increment time just past the earlier event: the earlier one should be chosen. 831 highPriority.clear(); 832 currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 10; 833 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 834 mediumPriority, lowPriority); 835 assertEquals(0, lowPriority.size()); 836 assertEquals(0, mediumPriority.size()); 837 assertEquals(1, highPriority.size()); 838 assertEquals("Recurring event with earlier start time expected", earlierStartTime, 839 highPriority.get(0).startMillis); 840 841 // Increment time to 15 min past the earlier event: the later one should be chosen. 842 highPriority.clear(); 843 currentTime = earlierStartTime + DateUtils.MINUTE_IN_MILLIS * 15; 844 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 845 mediumPriority, lowPriority); 846 assertEquals(0, lowPriority.size()); 847 assertEquals(0, mediumPriority.size()); 848 assertEquals(1, highPriority.size()); 849 assertEquals("Recurring event with later start time expected", laterStartTime, 850 highPriority.get(0).startMillis); 851 852 // Both events in the past: the later one should be chosen (in the low priority bucket). 853 highPriority.clear(); 854 currentTime = laterStartTime + DateUtils.DAY_IN_MILLIS * 5; 855 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 856 mediumPriority, lowPriority); 857 assertEquals(0, highPriority.size()); 858 assertEquals(0, mediumPriority.size()); 859 assertEquals(1, lowPriority.size()); 860 assertEquals("Recurring event with later start time expected", laterStartTime, 861 lowPriority.get(0).startMillis); 862 } 863 864 @SmallTest 865 public void testProcessQuery_recurringAllDayEvent() { 866 int eventId = 1; 867 long day1 = createTimeInMillis(0, 0, 0, 1, 5, 2012, Time.TIMEZONE_UTC); 868 long day2 = createTimeInMillis(0, 0, 0, 2, 5, 2012, Time.TIMEZONE_UTC); 869 870 ArrayList<NotificationInfo> highPriority = new ArrayList<NotificationInfo>(); 871 ArrayList<NotificationInfo> mediumPriority = new ArrayList<NotificationInfo>(); 872 ArrayList<NotificationInfo> lowPriority = new ArrayList<NotificationInfo>(); 873 874 AlertsTable at = new AlertsTable(); 875 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day2, day2 + DateUtils.HOUR_IN_MILLIS * 24, 876 0); 877 at.addAlertRow(eventId, SCHEDULED, ACCEPTED, 1, day1, day1 + DateUtils.HOUR_IN_MILLIS * 24, 878 0); 879 880 // Both events in the future: the earliest one should be chosen. 881 long currentTime = day1 - DateUtils.DAY_IN_MILLIS * 3; 882 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 883 mediumPriority, lowPriority); 884 assertEquals(0, lowPriority.size()); 885 assertEquals(0, mediumPriority.size()); 886 assertEquals(1, highPriority.size()); 887 assertEquals("Recurring event with earlier start time expected", day1, 888 highPriority.get(0).startMillis); 889 890 // Increment time just past the earlier event (to 12:10am). The earlier one should 891 // be chosen. 892 highPriority.clear(); 893 currentTime = createTimeInMillis(0, 10, 0, 1, 5, 2012, Time.getCurrentTimezone()); 894 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 895 mediumPriority, lowPriority); 896 assertEquals(0, lowPriority.size()); 897 assertEquals(0, mediumPriority.size()); 898 assertEquals(1, highPriority.size()); 899 assertEquals("Recurring event with earlier start time expected", day1, 900 highPriority.get(0).startMillis); 901 902 // Increment time to 15 min past the earlier event: the later one should be chosen. 903 highPriority.clear(); 904 currentTime = createTimeInMillis(0, 15, 0, 1, 5, 2012, Time.getCurrentTimezone()); 905 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 906 mediumPriority, lowPriority); 907 assertEquals(0, lowPriority.size()); 908 assertEquals(0, mediumPriority.size()); 909 assertEquals(1, highPriority.size()); 910 assertEquals("Recurring event with earlier start time expected", day2, 911 highPriority.get(0).startMillis); 912 913 // Both events in the past: the later one should be chosen (in the low priority bucket). 914 highPriority.clear(); 915 currentTime = day2 + DateUtils.DAY_IN_MILLIS * 1; 916 AlertService.processQuery(at.getAlertCursor(), mContext, currentTime, highPriority, 917 mediumPriority, lowPriority); 918 assertEquals(0, highPriority.size()); 919 assertEquals(0, mediumPriority.size()); 920 assertEquals(1, lowPriority.size()); 921 assertEquals("Recurring event with later start time expected", day2, 922 lowPriority.get(0).startMillis); 923 } 924 925 @SmallTest 926 public void testRedistributeBuckets_withinLimits() throws Exception { 927 int maxNotifications = 3; 928 ArrayList<NotificationInfo> threeItemList = new ArrayList<NotificationInfo>(); 929 threeItemList.add(createNotificationInfo(5)); 930 threeItemList.add(createNotificationInfo(4)); 931 threeItemList.add(createNotificationInfo(3)); 932 933 // Test when max notifications at high priority. 934 ArrayList<NotificationInfo> high = threeItemList; 935 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 936 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 937 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 938 assertEquals(3, high.size()); 939 assertEquals(0, medium.size()); 940 assertEquals(0, low.size()); 941 942 // Test when max notifications at medium priority. 943 high = new ArrayList<NotificationInfo>(); 944 medium = threeItemList; 945 low = new ArrayList<NotificationInfo>(); 946 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 947 assertEquals(0, high.size()); 948 assertEquals(3, medium.size()); 949 assertEquals(0, low.size()); 950 951 // Test when max notifications at high and medium priority 952 high = new ArrayList<NotificationInfo>(threeItemList); 953 medium = new ArrayList<NotificationInfo>(); 954 medium.add(high.remove(1)); 955 low = new ArrayList<NotificationInfo>(); 956 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 957 assertEquals(2, high.size()); 958 assertEquals(1, medium.size()); 959 assertEquals(0, low.size()); 960 } 961 962 @SmallTest 963 public void testRedistributeBuckets_tooManyHighPriority() throws Exception { 964 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 965 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 966 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 967 high.add(createNotificationInfo(5)); 968 high.add(createNotificationInfo(4)); 969 high.add(createNotificationInfo(3)); 970 high.add(createNotificationInfo(2)); 971 high.add(createNotificationInfo(1)); 972 973 // Invoke the method under test. 974 int maxNotifications = 3; 975 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 976 977 // Verify some high priority were kicked out. 978 assertEquals(3, high.size()); 979 assertEquals(3, high.get(0).eventId); 980 assertEquals(2, high.get(1).eventId); 981 assertEquals(1, high.get(2).eventId); 982 983 // Verify medium priority untouched. 984 assertEquals(0, medium.size()); 985 986 // Verify the extras went to low priority. 987 assertEquals(2, low.size()); 988 assertEquals(5, low.get(0).eventId); 989 assertEquals(4, low.get(1).eventId); 990 } 991 992 @SmallTest 993 public void testRedistributeBuckets_tooManyMediumPriority() throws Exception { 994 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 995 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 996 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 997 high.add(createNotificationInfo(5)); 998 high.add(createNotificationInfo(4)); 999 medium.add(createNotificationInfo(3)); 1000 medium.add(createNotificationInfo(2)); 1001 medium.add(createNotificationInfo(1)); 1002 1003 // Invoke the method under test. 1004 int maxNotifications = 3; 1005 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 1006 1007 // Verify high priority untouched. 1008 assertEquals(2, high.size()); 1009 assertEquals(5, high.get(0).eventId); 1010 assertEquals(4, high.get(1).eventId); 1011 1012 // Verify some medium priority were kicked out (the ones near the end of the 1013 // list). 1014 assertEquals(1, medium.size()); 1015 assertEquals(3, medium.get(0).eventId); 1016 1017 // Verify the extras went to low priority. 1018 assertEquals(2, low.size()); 1019 assertEquals(2, low.get(0).eventId); 1020 assertEquals(1, low.get(1).eventId); 1021 } 1022 1023 @SmallTest 1024 public void testRedistributeBuckets_tooManyHighMediumPriority() throws Exception { 1025 ArrayList<NotificationInfo> high = new ArrayList<NotificationInfo>(); 1026 ArrayList<NotificationInfo> medium = new ArrayList<NotificationInfo>(); 1027 ArrayList<NotificationInfo> low = new ArrayList<NotificationInfo>(); 1028 high.add(createNotificationInfo(8)); 1029 high.add(createNotificationInfo(7)); 1030 high.add(createNotificationInfo(6)); 1031 high.add(createNotificationInfo(5)); 1032 high.add(createNotificationInfo(4)); 1033 medium.add(createNotificationInfo(3)); 1034 medium.add(createNotificationInfo(2)); 1035 medium.add(createNotificationInfo(1)); 1036 1037 // Invoke the method under test. 1038 int maxNotifications = 3; 1039 AlertService.redistributeBuckets(high, medium, low, maxNotifications); 1040 1041 // Verify high priority. 1042 assertEquals(3, high.size()); 1043 assertEquals(6, high.get(0).eventId); 1044 assertEquals(5, high.get(1).eventId); 1045 assertEquals(4, high.get(2).eventId); 1046 1047 // Verify some medium priority. 1048 assertEquals(0, medium.size()); 1049 1050 // Verify low priority. 1051 assertEquals(5, low.size()); 1052 assertEquals(8, low.get(0).eventId); 1053 assertEquals(7, low.get(1).eventId); 1054 assertEquals(3, low.get(2).eventId); 1055 assertEquals(2, low.get(3).eventId); 1056 assertEquals(1, low.get(4).eventId); 1057 } 1058} 1059