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