More reminder service tests

pull/127/merge
Alex Baker 8 years ago
parent 4aa3326245
commit d164fdb3fc

@ -6,9 +6,9 @@ import com.todoroo.astrid.data.Task;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.tasks.Snippet;
import org.tasks.injection.InjectingTestCase;
@ -16,29 +16,30 @@ import org.tasks.injection.TestComponent;
import org.tasks.jobs.JobQueue;
import org.tasks.jobs.Reminder;
import org.tasks.preferences.Preferences;
import org.tasks.reminders.Random;
import org.tasks.time.DateTime;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import static com.natpryce.makeiteasy.MakeItEasy.with;
import static com.todoroo.andlib.utility.DateUtilities.ONE_HOUR;
import static com.todoroo.andlib.utility.DateUtilities.ONE_WEEK;
import static com.todoroo.astrid.data.Task.NOTIFY_AFTER_DEADLINE;
import static com.todoroo.astrid.data.Task.NOTIFY_AT_DEADLINE;
import static com.todoroo.astrid.reminders.ReminderService.TYPE_RANDOM;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.tasks.Freeze.freezeClock;
import static org.tasks.date.DateTimeUtils.newDateTime;
import static org.tasks.makers.TaskMaker.COMPLETION_TIME;
import static org.tasks.makers.TaskMaker.CREATION_TIME;
import static org.tasks.makers.TaskMaker.DELETION_TIME;
import static org.tasks.makers.TaskMaker.DUE_DATE;
import static org.tasks.makers.TaskMaker.DUE_TIME;
import static org.tasks.makers.TaskMaker.ID;
import static org.tasks.makers.TaskMaker.PRIORITY;
import static org.tasks.makers.TaskMaker.RANDOM_REMINDER_PERIOD;
import static org.tasks.makers.TaskMaker.REMINDERS;
import static org.tasks.makers.TaskMaker.REMINDER_LAST;
@ -52,12 +53,15 @@ public class ReminderServiceTest extends InjectingTestCase {
@Inject Preferences preferences;
private ReminderService service;
private Random random;
private JobQueue<Reminder> jobs;
@Before
public void before() {
jobs = mock(JobQueue.class);
service = new ReminderService(preferences, jobs);
random = mock(Random.class);
when(random.nextFloat()).thenReturn(1.0f);
service = new ReminderService(preferences, jobs, random);
}
@After
@ -164,23 +168,6 @@ public class ReminderServiceTest extends InjectingTestCase {
verify(jobs).cancel(1);
}
@Test
public void snoozeOverridesAll() {
DateTime now = newDateTime();
Task task = newTask(
with(ID, 1L),
with(DUE_TIME, now),
with(SNOOZE_TIME, now.plusMonths(12)),
with(REMINDERS, NOTIFY_AT_DEADLINE | NOTIFY_AFTER_DEADLINE),
with(RANDOM_REMINDER_PERIOD, TimeUnit.HOURS.toMillis(1)));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1, now.plusMonths(12).getMillis(), ReminderService.TYPE_SNOOZE));
}
@Test
public void ignoreLapsedSnoozeTime() {
Task task = newTask(
@ -197,119 +184,170 @@ public class ReminderServiceTest extends InjectingTestCase {
}
@Test
public void scheduleRandomReminder() {
public void scheduleInitialRandomReminder() {
freezeClock().thawAfter(new Snippet() {{
DateTime now = newDateTime();
when(random.nextFloat()).thenReturn(0.3865f);
Task task = newTask(
with(ID, 1L),
with(REMINDER_LAST, (DateTime) null),
with(CREATION_TIME, now.minusDays(1)),
with(RANDOM_REMINDER_PERIOD, ONE_WEEK));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, now.minusDays(1).getMillis() + 584206592, ReminderService.TYPE_RANDOM));
}});
}
@Test
public void scheduleNextRandomReminder() {
freezeClock().thawAfter(new Snippet() {{
DateTime now = newDateTime();
when(random.nextFloat()).thenReturn(0.3865f);
Task task = newTask(
with(ID, 1L),
with(REMINDER_LAST, now.minusDays(1)),
with(CREATION_TIME, now.minusDays(30)),
with(RANDOM_REMINDER_PERIOD, ONE_WEEK));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, now.minusDays(1).getMillis() + 584206592, ReminderService.TYPE_RANDOM));
}});
}
@Test
public void scheduleOverdueRandomReminder() {
freezeClock().thawAfter(new Snippet() {{
DateTime now = newDateTime();
when(random.nextFloat()).thenReturn(0.3865f);
Task task = newTask(
with(ID, 1L),
with(REMINDER_LAST, now.minusDays(14)),
with(CREATION_TIME, now.minusDays(30)),
with(RANDOM_REMINDER_PERIOD, ONE_WEEK));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, now.getMillis() + 10148400, ReminderService.TYPE_RANDOM));
}});
}
@Test
public void scheduleOverdueForFutureDueDate() {
freezeClock().thawAfter(new Snippet() {{
when(random.nextFloat()).thenReturn(0.3865f);
Task task = newTask(
with(ID, 1L),
with(DUE_TIME, newDateTime().plusMinutes(5)),
with(REMINDERS, NOTIFY_AFTER_DEADLINE));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, task.getDueDate() + 4582800, ReminderService.TYPE_OVERDUE));
}});
}
@Test
public void scheduleOverdueForPastDueDateWithNoReminderPastDueDate() {
freezeClock().thawAfter(new Snippet() {{
DateTime now = newDateTime();
Task task = newTask(
with(ID, 1L),
with(DUE_TIME, now.minusMinutes(5)),
with(REMINDERS, NOTIFY_AFTER_DEADLINE));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, currentTimeMillis(), ReminderService.TYPE_OVERDUE));
}});
}
@Test
public void scheduleOverdueForPastDueDateLastReminderSixHoursAgo() {
freezeClock().thawAfter(new Snippet() {{
Task task = newTask(
with(ID, 1L),
with(RANDOM_REMINDER_PERIOD, TimeUnit.DAYS.toMillis(7)));
with(DUE_TIME, newDateTime().minusHours(12)),
with(REMINDER_LAST, newDateTime().minusHours(6)),
with(REMINDERS, NOTIFY_AFTER_DEADLINE));
service.scheduleAlarm(null, task);
ArgumentCaptor<Reminder> captor = ArgumentCaptor.forClass(Reminder.class);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(captor.capture());
order.verify(jobs).add(new Reminder(1L, currentTimeMillis(), ReminderService.TYPE_OVERDUE));
}});
}
Reminder reminder = captor.getValue();
assertTrue(reminder.getTime() > currentTimeMillis());
assertTrue(reminder.getTime() < currentTimeMillis() + 1.2 * TimeUnit.DAYS.toMillis(7));
assertEquals(TYPE_RANDOM, reminder.getType());
@Test
public void scheduleOverdueForPastDueDateLastReminderWithinSixHours() {
freezeClock().thawAfter(new Snippet() {{
when(random.nextFloat()).thenReturn(0.3865f);
Task task = newTask(
with(ID, 1L),
with(DUE_TIME, newDateTime().minusHours(12)),
with(PRIORITY, 2),
with(REMINDER_LAST, newDateTime().minusHours(3)),
with(REMINDERS, NOTIFY_AFTER_DEADLINE));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1L, currentTimeMillis() + 22748400, ReminderService.TYPE_OVERDUE));
}});
}
// @Test
// public void testOverdue() {
// // test due date in the future
// reminderService.setScheduler(new AlarmExpected() {
// @Override
// public void createAlarm(Task task, long time, int type) {
// if (time == ReminderService.NO_ALARM)
// return;
// super.createAlarm(task, time, type);
// assertTrue(time > task.getDueDate());
// assertTrue(time < task.getDueDate() + DateUtilities.ONE_DAY);
// assertEquals(type, ReminderService.TYPE_OVERDUE);
// }
// });
// final Task task = new Task();
// task.setTitle("water");
// task.setDueDate(DateUtilities.now() + DateUtilities.ONE_DAY);
// task.setReminderFlags(Task.NOTIFY_AFTER_DEADLINE);
// taskDao.save(task);
//
// // test due date in the past
// task.setDueDate(DateUtilities.now() - DateUtilities.ONE_DAY);
// reminderService.setScheduler(new AlarmExpected() {
// @Override
// public void createAlarm(Task task, long time, int type) {
// if (time == ReminderService.NO_ALARM)
// return;
// super.createAlarm(task, time, type);
// assertTrue(time > DateUtilities.now() - 1000L);
// assertTrue(time < DateUtilities.now() + 2 * DateUtilities.ONE_DAY);
// assertEquals(type, ReminderService.TYPE_OVERDUE);
// }
// });
// taskDao.save(task);
// assertTrue(((AlarmExpected) reminderService.getScheduler()).alarmCreated);
//
// // test due date in the past, but recently notified
// task.setReminderLast(DateUtilities.now());
// reminderService.setScheduler(new AlarmExpected() {
// @Override
// public void createAlarm(Task task, long time, int type) {
// if (time == ReminderService.NO_ALARM)
// return;
// super.createAlarm(task, time, type);
// assertTrue(time > DateUtilities.now() + DateUtilities.ONE_HOUR);
// assertTrue(time < DateUtilities.now() + DateUtilities.ONE_DAY);
// assertEquals(type, ReminderService.TYPE_OVERDUE);
// }
// });
// taskDao.save(task);
// assertTrue(((AlarmExpected) reminderService.getScheduler()).alarmCreated);
// }
//
// @Test
// public void testMultipleReminders() {
// // test due date in the future, enable random
// final Task task = new Task();
// task.setTitle("water");
// task.setDueDate(DateUtilities.now() + DateUtilities.ONE_WEEK);
// task.setReminderFlags(Task.NOTIFY_AT_DEADLINE);
// task.setReminderPeriod(DateUtilities.ONE_HOUR);
// reminderService.setScheduler(new AlarmExpected() {
// @Override
// public void createAlarm(Task task, long time, int type) {
// if (time == ReminderService.NO_ALARM)
// return;
// super.createAlarm(task, time, type);
// assertTrue(time > DateUtilities.now());
// assertTrue(time < DateUtilities.now() + DateUtilities.ONE_DAY);
// assertEquals(type, ReminderService.TYPE_RANDOM);
// }
// });
// taskDao.save(task);
// assertTrue(((AlarmExpected) reminderService.getScheduler()).alarmCreated);
//
// // now set the due date in the past
// task.setDueDate(DateUtilities.now() - DateUtilities.ONE_WEEK);
// ((AlarmExpected) reminderService.getScheduler()).alarmCreated = false;
// reminderService.scheduleAlarm(taskDao, task);
// assertTrue(((AlarmExpected) reminderService.getScheduler()).alarmCreated);
//
// // now set the due date before the random
// task.setDueDate(DateUtilities.now() + DateUtilities.ONE_HOUR);
// reminderService.setScheduler(new AlarmExpected() {
// @Override
// public void createAlarm(Task task, long time, int type) {
// if (time == ReminderService.NO_ALARM)
// return;
// super.createAlarm(task, time, type);
// assertEquals((long) task.getDueDate(), time);
// assertEquals(type, ReminderService.TYPE_DUE);
// }
// });
// taskDao.save(task);
// assertTrue(((AlarmExpected) reminderService.getScheduler()).alarmCreated);
// }
@Test
public void snoozeOverridesAll() {
DateTime now = newDateTime();
Task task = newTask(
with(ID, 1L),
with(DUE_TIME, now),
with(SNOOZE_TIME, now.plusMonths(12)),
with(REMINDERS, NOTIFY_AT_DEADLINE | NOTIFY_AFTER_DEADLINE),
with(RANDOM_REMINDER_PERIOD, ONE_HOUR));
service.scheduleAlarm(null, task);
InOrder order = inOrder(jobs);
order.verify(jobs).cancel(1);
order.verify(jobs).add(new Reminder(1, now.plusMonths(12).getMillis(), ReminderService.TYPE_SNOOZE));
}
@Test
@Ignore
public void randomReminderBeforeDueAndOverdue() {
}
@Test
@Ignore
public void randomReminderAfterDue() {
}
@Test
@Ignore
public void randomReminderAfterOverdue() {
}
@Test
@Ignore
public void dueDateBeforeOverdue() {
}
}

@ -9,8 +9,8 @@ import com.todoroo.astrid.data.Task;
import org.tasks.time.DateTime;
import static com.natpryce.makeiteasy.Property.newProperty;
import static org.tasks.date.DateTimeUtils.newDateTime;
import static org.tasks.makers.Maker.make;
import static org.tasks.time.DateTimeUtils.currentTimeMillis;
public class TaskMaker {
@ -18,10 +18,12 @@ public class TaskMaker {
public static Property<Task, String> TITLE = newProperty();
public static Property<Task, DateTime> DUE_DATE = newProperty();
public static Property<Task, DateTime> DUE_TIME = newProperty();
public static Property<Task, Integer> PRIORITY = newProperty();
public static Property<Task, DateTime> REMINDER_LAST = newProperty();
public static Property<Task, Long> RANDOM_REMINDER_PERIOD = newProperty();
public static Property<Task, Integer> HIDE_TYPE = newProperty();
public static Property<Task, Integer> REMINDERS = newProperty();
public static Property<Task, DateTime> CREATION_TIME = newProperty();
public static Property<Task, DateTime> COMPLETION_TIME = newProperty();
public static Property<Task, DateTime> DELETION_TIME = newProperty();
public static Property<Task, DateTime> SNOOZE_TIME = newProperty();
@ -44,6 +46,11 @@ public class TaskMaker {
task.setId(id);
}
int priority = lookup.valueOf(PRIORITY, -1);
if (priority >= 0) {
task.setImportance(priority);
}
DateTime dueDate = lookup.valueOf(DUE_DATE, (DateTime) null);
if (dueDate != null) {
task.setDueDate(Task.createDueDate(Task.URGENCY_SPECIFIC_DAY, dueDate.getMillis()));
@ -89,7 +96,8 @@ public class TaskMaker {
task.setReminderPeriod(randomReminderPeriod);
}
task.setCreationDate(currentTimeMillis());
DateTime creationTime = lookup.valueOf(CREATION_TIME, newDateTime());
task.setCreationDate(creationTime.getMillis());
return task;
};

@ -19,10 +19,10 @@ import org.tasks.jobs.JobManager;
import org.tasks.jobs.JobQueue;
import org.tasks.jobs.Reminder;
import org.tasks.preferences.Preferences;
import org.tasks.reminders.Random;
import org.tasks.time.DateTime;
import java.util.List;
import java.util.Random;
import javax.inject.Inject;
@ -57,22 +57,23 @@ public final class ReminderService {
/** flag for an alarm reminder */
public static final int TYPE_ALARM = 4;
private static final Random random = new Random();
private static final long NO_ALARM = Long.MAX_VALUE;
private final JobQueue<Reminder> jobs;
private final Random random;
private final Preferences preferences;
private long now = -1; // For tracking when reminders might be scheduled all at once
@Inject
ReminderService(Preferences preferences, JobManager jobManager) {
this(preferences, JobQueue.newReminderQueue(preferences, jobManager));
this(preferences, JobQueue.newReminderQueue(preferences, jobManager), new Random());
}
ReminderService(Preferences preferences, JobQueue<Reminder> jobs) {
ReminderService(Preferences preferences, JobQueue<Reminder> jobs, Random random) {
this.preferences = preferences;
this.jobs = jobs;
this.random = random;
}
private static final int MILLIS_PER_HOUR = 60 * 60 * 1000;
@ -139,7 +140,6 @@ public final class ReminderService {
// notifications at due date
long whenDueDate = calculateNextDueDateReminder(task);
// notifications after due date
long whenOverdue = calculateNextOverdueReminder(task);

@ -0,0 +1,10 @@
package org.tasks.reminders;
public class Random {
private static final java.util.Random random = new java.util.Random();
public float nextFloat() {
return random.nextFloat();
}
}

@ -189,6 +189,10 @@ public class DateTime {
return subtract(Calendar.DATE, days);
}
public DateTime minusHours(int hours) {
return subtract(Calendar.HOUR, hours);
}
public DateTime minusMinutes(int minutes) {
return subtract(Calendar.MINUTE, minutes);
}

Loading…
Cancel
Save