Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 8c8c9fb4 authored by Marten Gajda's avatar Marten Gajda Committed by GitHub
Browse files

Tolerate floating time mismatch, fixes #850 (#853)

This commit (temporarily) allows tasks with floating start or due and absolute until part in the RRULE and vice versa.
Apparently such tasks exist and we didn't validate this condition. So for now we tolerate this issue until we can be sure
the database won't contain such tasks.
parent d0fd159e
Loading
Loading
Loading
Loading
+126 −0
Original line number Diff line number Diff line
@@ -200,6 +200,69 @@ public class TaskProviderRecurrenceTest
    }


    /**
     * Test if instances of a task with a timed DTSTART, DUE and a floating RRULE UNTIL.
     * <p>
     * Note, this combination should not be accepted by the provider. For the time being, however, it should be tolerated instead of causing a crash.
     */
    @Test
    public void testRRuleWithFloatingMismatch() throws InvalidRecurrenceRuleException
    {
        RowSnapshot<TaskLists> taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority));
        Table<Instances> instancesTable = new InstanceTable(mAuthority);
        RowSnapshot<Tasks> task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));

        Duration hour = new Duration(1, 0, 3600 /* 1 hour */);
        DateTime start = DateTime.parse("20180104T123456Z");
        DateTime due = start.addDuration(hour);
        DateTime localStart = start.shiftTimeZone(TimeZone.getDefault());

        Duration day = new Duration(1, 1, 0);

        DateTime second = localStart.addDuration(day);
        DateTime third = second.addDuration(day);
        DateTime fourth = third.addDuration(day);
        DateTime fifth = fourth.addDuration(day);

        DateTime localDue = due.shiftTimeZone(TimeZone.getDefault());

        assertThat(new Seq<>(
                        new Put<>(taskList, new EmptyRowData<>()),
                        new Put<>(task,
                                new Composite<>(
                                        new TimeData<>(start, due),
                                        new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106", RecurrenceRule.RfcMode.RFC2445_LAX))))

                ), resultsIn(mClient,
                new Assert<>(task,
                        new Composite<>(
                                new TimeData<>(start, due),
                                new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106"))),
//                new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)),
                new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)),
                // 1st instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(localStart, localDue, new Present<>(start), 0),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*,
                // 2nd instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())),
                // 3rd instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())),
                // 4th instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())),
                // 5th instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */)
        );
    }


    /**
     * Test if instances of a task with an all-day DTSTART, DUE and an RRULE.
@@ -263,6 +326,69 @@ public class TaskProviderRecurrenceTest
    }


    /**
     * Test if instances of a task with an all-day DTSTART, DUE and an RRULE with an absolute UNTIL
     * <p>
     * Note, this combination should not be accepted by the provider. For the time being, however, it should be tolerated instead of causing a crash.
     */
    @Test
    public void testAllDayRRuleFloatingMismatch() throws InvalidRecurrenceRuleException
    {
        RowSnapshot<TaskLists> taskList = new VirtualRowSnapshot<>(new LocalTaskListsTable(mAuthority));
        Table<Instances> instancesTable = new InstanceTable(mAuthority);
        RowSnapshot<Tasks> task = new VirtualRowSnapshot<>(new TaskListScoped(taskList, new TasksTable(mAuthority)));

        Duration days = new Duration(1, 2, 0);
        DateTime start = DateTime.parse("20180104");
        DateTime due = start.addDuration(days);
        DateTime localStart = start;

        Duration day = new Duration(1, 1, 0);

        DateTime second = localStart.addDuration(day);
        DateTime third = second.addDuration(day);
        DateTime fourth = third.addDuration(day);
        DateTime fifth = fourth.addDuration(day);

        DateTime localDue = due;

        assertThat(new Seq<>(
                        new Put<>(taskList, new EmptyRowData<>()),
                        new Put<>(task,
                                new Composite<>(
                                        new TimeData<>(start, due),
                                        new RRuleTaskData(new RecurrenceRule("FREQ=DAILY;UNTIL=20180106T120000Z", RecurrenceRule.RfcMode.RFC2445_LAX))))

                ), resultsIn(mClient,
                new Assert<>(task,
                        new Composite<>(
                                new TimeData<>(start, due),
                                new CharSequenceRowData<>(Tasks.RRULE, "FREQ=DAILY;UNTIL=20180106T120000Z"))),
//                new Counted<>(5, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)),
                new Counted<>(1, new AssertRelated<>(instancesTable, Instances.TASK_ID, task)),
                // 1st instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(localStart, localDue, new Present<>(start), 0),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, start.getTimestamp()))/*,
                // 2nd instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(second, second.addDuration(hour), new Present<>(second), 1),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, second.getTimestamp())),
                // 3rd instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(third, third.addDuration(hour), new Present<>(third), 2),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, third.getTimestamp())),
                // 4th instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(fourth, fourth.addDuration(hour), new Present<>(fourth), 3),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, fourth.getTimestamp())),
                // 5th instance:
                new AssertRelated<>(instancesTable, Instances.TASK_ID, task,
                        new InstanceTestData(fifth, fifth.addDuration(hour), new Present<>(fifth), 4),
                        new EqArg(Instances.INSTANCE_ORIGINAL_TIME, fifth.getTimestamp())) */)
        );
    }


    /**
     * Test if instances of a task with a DUE and an RRULE but no DTSTART.
+16 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import org.dmfs.rfc5545.recurrenceset.RecurrenceSet;
import org.dmfs.rfc5545.recurrenceset.RecurrenceSetIterator;

import java.util.Iterator;
import java.util.TimeZone;


/**
@@ -54,6 +55,21 @@ public final class TaskInstanceIterable implements Iterable<DateTime>
        RecurrenceRule rule = mTaskAdapter.valueOf(TaskAdapter.RRULE);
        if (rule != null)
        {
            if (rule.getUntil() != null && dtstart.isFloating() != rule.getUntil().isFloating())
            {
                // rule UNTIL date mismatches start. This is merely a workaround for existing users. In future we should make sure
                // such tasks don't exist
                if (dtstart.isFloating())
                {
                    // make until floating too by making it floating in the current time zone
                    rule.setUntil(rule.getUntil().shiftTimeZone(TimeZone.getDefault()).swapTimeZone(null));
                }
                else
                {
                    // anchor UNTIL in the current time zone
                    rule.setUntil(new DateTime(null, rule.getUntil().getTimestamp()).swapTimeZone(TimeZone.getDefault()));
                }
            }
            set.addInstances(new RecurrenceRuleAdapter(rule));
        }