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.app.PendingIntent; 25 import android.content.SharedPreferences; 26 import android.database.MatrixCursor; 27 import android.provider.CalendarContract.Attendees; 28 import android.provider.CalendarContract.CalendarAlerts; 29 import android.test.AndroidTestCase; 30 import android.test.suitebuilder.annotation.SmallTest; 31 import android.test.suitebuilder.annotation.Smoke; 32 import android.text.format.DateUtils; 33 import android.text.format.Time; 34 35 import com.android.calendar.GeneralPreferences; 36 import com.android.calendar.alerts.AlertService.NotificationInfo; 37 import com.android.calendar.alerts.AlertService.NotificationWrapper; 38 39 import junit.framework.Assert; 40 41 import java.util.ArrayList; 42 import java.util.Arrays; 43 import java.util.Map; 44 import java.util.Set; 45 46 public class AlertServiceTest extends AndroidTestCase { 47 48 class MockSharedPreferences implements SharedPreferences { 49 50 private Boolean mVibrate; 51 private String mRingtone; 52 private Boolean mPopup; 53 54 // Strict mode will fail if a preference key is queried more than once. 55 private boolean mStrict = false; 56 MockSharedPreferences()57 MockSharedPreferences() { 58 this(false); 59 } 60 MockSharedPreferences(boolean strict)61 MockSharedPreferences(boolean strict) { 62 super(); 63 init(); 64 this.mStrict = strict; 65 } 66 init()67 void init() { 68 mVibrate = true; 69 mRingtone = "/some/cool/ringtone"; 70 mPopup = true; 71 } 72 73 @Override contains(String key)74 public boolean contains(String key) { 75 if (GeneralPreferences.KEY_ALERTS_VIBRATE.equals(key)) { 76 return true; 77 } 78 return false; 79 } 80 81 @Override getBoolean(String key, boolean defValue)82 public boolean getBoolean(String key, boolean defValue) { 83 if (GeneralPreferences.KEY_ALERTS_VIBRATE.equals(key)) { 84 if (mVibrate == null) { 85 Assert.fail(GeneralPreferences.KEY_ALERTS_VIBRATE 86 + " fetched more than once."); 87 } 88 boolean val = mVibrate; 89 if (mStrict) { 90 mVibrate = null; 91 } 92 return val; 93 } 94 if (GeneralPreferences.KEY_ALERTS_POPUP.equals(key)) { 95 if (mPopup == null) { 96 Assert.fail(GeneralPreferences.KEY_ALERTS_POPUP + " fetched more than once."); 97 } 98 boolean val = mPopup; 99 if (mStrict) { 100 mPopup = null; 101 } 102 return val; 103 } 104 throw new IllegalArgumentException(); 105 } 106 107 @Override getString(String key, String defValue)108 public String getString(String key, String defValue) { 109 if (GeneralPreferences.KEY_ALERTS_RINGTONE.equals(key)) { 110 if (mRingtone == null) { 111 Assert.fail(GeneralPreferences.KEY_ALERTS_RINGTONE 112 + " fetched more than once."); 113 } 114 String val = mRingtone; 115 if (mStrict) { 116 mRingtone = null; 117 } 118 return val; 119 } 120 throw new IllegalArgumentException(); 121 } 122 123 @Override getAll()124 public Map<String, ?> getAll() { 125 throw new IllegalArgumentException(); 126 } 127 128 @Override getStringSet(String key, Set<String> defValues)129 public Set<String> getStringSet(String key, Set<String> defValues) { 130 throw new IllegalArgumentException(); 131 } 132 133 @Override getInt(String key, int defValue)134 public int getInt(String key, int defValue) { 135 throw new IllegalArgumentException(); 136 } 137 138 @Override getLong(String key, long defValue)139 public long getLong(String key, long defValue) { 140 throw new IllegalArgumentException(); 141 } 142 143 @Override getFloat(String key, float defValue)144 public float getFloat(String key, float defValue) { 145 throw new IllegalArgumentException(); 146 } 147 148 @Override edit()149 public Editor edit() { 150 throw new IllegalArgumentException(); 151 } 152 153 @Override registerOnSharedPreferenceChangeListener( OnSharedPreferenceChangeListener listener)154 public void registerOnSharedPreferenceChangeListener( 155 OnSharedPreferenceChangeListener listener) { 156 throw new IllegalArgumentException(); 157 } 158 159 @Override unregisterOnSharedPreferenceChangeListener( OnSharedPreferenceChangeListener listener)160 public void unregisterOnSharedPreferenceChangeListener( 161 OnSharedPreferenceChangeListener listener) { 162 throw new IllegalArgumentException(); 163 } 164 165 } 166 167 // Created these constants so the test cases are shorter 168 public static final int SCHEDULED = CalendarAlerts.STATE_SCHEDULED; 169 public static final int FIRED = CalendarAlerts.STATE_FIRED; 170 public static final int DISMISSED = CalendarAlerts.STATE_DISMISSED; 171 172 public static final int ACCEPTED = Attendees.ATTENDEE_STATUS_ACCEPTED; 173 public static final int DECLINED = Attendees.ATTENDEE_STATUS_DECLINED; 174 public static final int INVITED = Attendees.ATTENDEE_STATUS_INVITED; 175 public static final int TENTATIVE = Attendees.ATTENDEE_STATUS_TENTATIVE; 176 177 class NotificationInstance { 178 int mAlertId; 179 int[] mAlertIdsInDigest; 180 int mPriority; 181 NotificationInstance(int alertId, int priority)182 public NotificationInstance(int alertId, int priority) { 183 mAlertId = alertId; 184 mPriority = priority; 185 } 186 NotificationInstance(int[] alertIdsInDigest, int priority)187 public NotificationInstance(int[] alertIdsInDigest, int priority) { 188 mAlertIdsInDigest = alertIdsInDigest; 189 mPriority = priority; 190 } 191 } 192 193 class Alert { 194 long mEventId; 195 int mAlertStatus; 196 int mResponseStatus; 197 int mAllDay; 198 long mBegin; 199 long mEnd; 200 int mMinute; 201 long mAlarmTime; 202 Alert(long eventId, int alertStatus, int responseStatus, int allDay, long begin, long end, int minute, long alarmTime)203 public Alert(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 204 long end, int minute, long alarmTime) { 205 mEventId = eventId; 206 mAlertStatus = alertStatus; 207 mResponseStatus = responseStatus; 208 mAllDay = allDay; 209 mBegin = begin; 210 mEnd = end; 211 mMinute = minute; 212 mAlarmTime = alarmTime; 213 } 214 215 } 216 217 class AlertsTable { 218 219 ArrayList<Alert> mAlerts = new ArrayList<Alert>(); 220 addAlertRow(long eventId, int alertStatus, int responseStatus, int allDay, long begin, long end, long alarmTime)221 int addAlertRow(long eventId, int alertStatus, int responseStatus, int allDay, long begin, 222 long end, long alarmTime) { 223 Alert a = new Alert(eventId, alertStatus, responseStatus, allDay, begin, end, 224 5 /* minute */, alarmTime); 225 int id = mAlerts.size(); 226 mAlerts.add(a); 227 return id; 228 } 229 getAlertCursor()230 public MatrixCursor getAlertCursor() { 231 MatrixCursor alertCursor = new MatrixCursor(AlertService.ALERT_PROJECTION); 232 233 int i = 0; 234 for (Alert a : mAlerts) { 235 Object[] ca = { 236 i++, 237 a.mEventId, 238 a.mAlertStatus, 239 "Title" + a.mEventId + " " + a.mMinute, 240 "Loc" + a.mEventId, 241 a.mResponseStatus, 242 a.mAllDay, 243 a.mAlarmTime > 0 ? a.mAlarmTime : a.mBegin - a.mMinute * 60 * 1000, 244 a.mMinute, 245 a.mBegin, 246 a.mEnd, 247 "Desc: " + a.mAlarmTime 248 }; 249 alertCursor.addRow(ca); 250 } 251 return alertCursor; 252 } 253 254 } 255 256 class NotificationTestManager extends NotificationMgr { 257 // Expected notifications 258 NotificationInstance[] mExpectedNotifications; 259 NotificationWrapper[] mActualNotifications; 260 boolean[] mCancelled; 261 262 // CalendarAlerts table 263 private ArrayList<Alert> mAlerts; 264 NotificationTestManager(ArrayList<Alert> alerts, int maxNotifications)265 public NotificationTestManager(ArrayList<Alert> alerts, int maxNotifications) { 266 assertEquals(0, AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID); 267 mAlerts = alerts; 268 mExpectedNotifications = new NotificationInstance[maxNotifications + 1]; 269 mActualNotifications = new NotificationWrapper[mExpectedNotifications.length]; 270 mCancelled = new boolean[mExpectedNotifications.length]; 271 } 272 expectTestNotification(int notificationId, int alertId, int highPriority)273 public void expectTestNotification(int notificationId, int alertId, int highPriority) { 274 mExpectedNotifications[notificationId] = new NotificationInstance(alertId, 275 highPriority); 276 } 277 expectTestNotification(int notificationId, int[] alertIds, int priority)278 public void expectTestNotification(int notificationId, int[] alertIds, int priority) { 279 mExpectedNotifications[notificationId] = new NotificationInstance(alertIds, priority); 280 } 281 nullContents(T[] array)282 private <T> boolean nullContents(T[] array) { 283 for (T item : array) { 284 if (item != null) { 285 return false; 286 } 287 } 288 return true; 289 } 290 validateNotificationsAndReset()291 public void validateNotificationsAndReset() { 292 if (nullContents(mExpectedNotifications)) { 293 return; 294 } 295 296 String debugStr = printActualNotifications(); 297 for (int id = 0; id < mActualNotifications.length; id++) { 298 NotificationInstance expected = mExpectedNotifications[id]; 299 NotificationWrapper actual = mActualNotifications[id]; 300 if (expected == null) { 301 assertNull("Received unexpected notificationId " + id + debugStr, actual); 302 assertTrue("NotificationId " + id + " should have been cancelled." + debugStr, 303 mCancelled[id]); 304 } else { 305 assertNotNull("Expected notificationId " + id + " but it was not posted." 306 + debugStr, actual); 307 assertFalse("NotificationId " + id + " should not have been cancelled." 308 + debugStr, mCancelled[id]); 309 assertEquals("Priority not as expected for notification " + id + debugStr, 310 expected.mPriority, actual.mNotification.priority); 311 if (expected.mAlertIdsInDigest == null) { 312 Alert a = mAlerts.get(expected.mAlertId); 313 assertEquals("Event ID not expected for notification " + id + debugStr, 314 a.mEventId, actual.mEventId); 315 assertEquals("Begin time not expected for notification " + id + debugStr, 316 a.mBegin, actual.mBegin); 317 assertEquals("End time not expected for notification " + id + debugStr, 318 a.mEnd, actual.mEnd); 319 } else { 320 // Notification should be a digest. 321 assertNotNull("Posted notification not a digest as expected." + debugStr, 322 actual.mNw); 323 assertEquals("Number of notifications in digest not as expected." 324 + debugStr, expected.mAlertIdsInDigest.length, actual.mNw.size()); 325 for (int i = 0; i < actual.mNw.size(); i++) { 326 Alert a = mAlerts.get(expected.mAlertIdsInDigest[i]); 327 assertEquals("Digest item " + i + ": Event ID not as expected" 328 + debugStr, a.mEventId, actual.mNw.get(i).mEventId); 329 assertEquals("Digest item " + i + ": Begin time in digest not expected" 330 + debugStr, a.mBegin, actual.mNw.get(i).mBegin); 331 assertEquals("Digest item " + i + ": End time in digest not expected" 332 + debugStr, a.mEnd, actual.mNw.get(i).mEnd); 333 } 334 } 335 } 336 } 337 338 Arrays.fill(mCancelled, false); 339 Arrays.fill(mExpectedNotifications, null); 340 Arrays.fill(mActualNotifications, null); 341 } 342 printActualNotifications()343 private String printActualNotifications() { 344 StringBuilder s = new StringBuilder(); 345 s.append("\n\nNotifications actually posted:\n"); 346 for (int i = mActualNotifications.length - 1; i >= 0; i--) { 347 NotificationWrapper actual = mActualNotifications[i]; 348 if (actual == null) { 349 continue; 350 } 351 s.append("Notification " + i + " -- "); 352 s.append("priority:" + actual.mNotification.priority); 353 if (actual.mNw == null) { 354 s.append(", eventId:" + actual.mEventId); 355 } else { 356 s.append(", eventIds:{"); 357 for (int digestIndex = 0; digestIndex < actual.mNw.size(); digestIndex++) { 358 s.append(actual.mNw.get(digestIndex).mEventId + ","); 359 } 360 s.append("}"); 361 } 362 s.append("\n"); 363 } 364 return s.toString(); 365 } 366 367 /////////////////////////////// 368 // NotificationMgr methods 369 @Override cancel(int id)370 public void cancel(int id) { 371 assertTrue("id out of bound: " + id, 0 <= id); 372 assertTrue("id out of bound: " + id, id < mCancelled.length); 373 assertNull("id already used", mActualNotifications[id]); 374 assertFalse("id already used", mCancelled[id]); 375 mCancelled[id] = true; 376 assertNull("Unexpected cancel for id " + id, mExpectedNotifications[id]); 377 } 378 379 @Override notify(int id, NotificationWrapper nw)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 expectAlarmTime(int type, long millis)392 public void expectAlarmTime(int type, long millis) { 393 this.expectedAlarmType = type; 394 this.expectedAlarmTime = millis; 395 } 396 397 @Override set(int actualAlarmType, long actualAlarmTime, PendingIntent operation)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 testGenerateAlerts_none()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 testGenerateAlerts_single()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 testGenerateAlerts_multiple()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 testGenerateAlerts_maxAlerts()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 testGenerateAlerts_sharedPreferences()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 testGenerateAlerts_refreshTime()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 createNotificationInfo(long eventId)727 private NotificationInfo createNotificationInfo(long eventId) { 728 return new NotificationInfo("eventName", "location", "description", 100L, 200L, eventId, 729 false, false); 730 } 731 createTimeInMillis(int hour, int minute)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 createTimeInMillis(int second, int minute, int hour, int monthDay, int month, int year, String timezone)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 testProcessQuery_skipDeclinedDismissed()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 testProcessQuery_newAlert()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 testProcessQuery_recurringEvent()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 testProcessQuery_recurringAllDayEvent()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 testRedistributeBuckets_withinLimits()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 testRedistributeBuckets_tooManyHighPriority()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 testRedistributeBuckets_tooManyMediumPriority()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 testRedistributeBuckets_tooManyHighMediumPriority()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