Ejemplo n.º 1
0
class SharedSandboxTestCase(SingleRepositoryTestCase):
    """
    This test case class uses a single repository view, which is left
    in place across invocation of individual tests. At the start of each
    test case (i.e. in C{setUp}) an Item is created at the path '//sandbox',
    and this is destroyed afterwards (i.e. in C{tearDown}). This means that
    if you specify itsParent=self.sandbox when creating persistent items
    in your test code, these items will be cleaned up after each test.
    
    @ivar sandbox: The poarent for items you want cleaned up in the test
    @type sandbox: C{Item}
    """

    view = None

    def setUp(self):
        if SharedSandboxTestCase.view is None:
            super(SharedSandboxTestCase,self).setUp()
            SharedSandboxTestCase.view = self.view
            del self.view
            
        self.sandbox = Item("sandbox", SharedSandboxTestCase.view, None)
        
    def tearDown(self):
        self.sandbox.delete(recursive=True)
        self.sandbox.itsView.commit()
        self.sandbox = None
        
    def reopenRepository(self):
        self.view = self.sandbox.itsView
        path = self.sandbox.itsPath
        super(SharedSandboxTestCase, self).reopenRepository()
        self.sandbox = self.view.findPath(path)
        del self.view
Ejemplo n.º 2
0
class SharedSandboxTestCase(SingleRepositoryTestCase):
    """
    This test case class uses a single repository view, which is left
    in place across invocation of individual tests. At the start of each
    test case (i.e. in C{setUp}) an Item is created at the path '//sandbox',
    and this is destroyed afterwards (i.e. in C{tearDown}). This means that
    if you specify itsParent=self.sandbox when creating persistent items
    in your test code, these items will be cleaned up after each test.
    
    @ivar sandbox: The poarent for items you want cleaned up in the test
    @type sandbox: C{Item}
    """

    view = None

    def setUp(self):
        if SharedSandboxTestCase.view is None:
            super(SharedSandboxTestCase, self).setUp()
            SharedSandboxTestCase.view = self.view
            del self.view

        self.sandbox = Item("sandbox", SharedSandboxTestCase.view, None)

    def tearDown(self):
        self.sandbox.delete(recursive=True)
        self.sandbox.itsView.commit()
        self.sandbox = None

    def reopenRepository(self):
        self.view = self.sandbox.itsView
        path = self.sandbox.itsPath
        super(SharedSandboxTestCase, self).reopenRepository()
        self.sandbox = self.view.findPath(path)
        del self.view
class RecurrenceConflictTestCase(NRVTestCase):
    def setUp(self):

        if not hasattr(RecurrenceConflictTestCase, 'view'):
            super(RecurrenceConflictTestCase, self).setUp()
            RecurrenceConflictTestCase.view = self.view
            del self.view

        view = RecurrenceConflictTestCase.view
        self.sandbox = Item("sandbox", view, None)

        self.pacific = self.view.tzinfo.getInstance("America/Los_Angeles")
        self.floating = self.view.tzinfo.floating
        self.utc = self.view.tzinfo.UTC

        self.start = datetime.datetime(2007, 4, 10, 9, tzinfo=self.floating)

        self.master = Calendar.CalendarEvent(None, itsParent=self.sandbox)
        self.uuid = self.master.itsItem.itsUUID.str16()
        self.master.startTime = self.start
        self.master.anyTime = self.master.allDay = False

        # create a baseline dictionary with keywords for creating an EventRecord
        names = (i.name for i in EventRecord.__fields__ if i.name != 'uuid')
        # default values to NoChange
        self.kwds = dict.fromkeys(names, sharing.NoChange)

    def tearDown(self):
        self.master.deleteAll()
        self.sandbox.delete(recursive=True)
        self.sandbox = None

    def _makeRecurrenceRuleSet(self, until=None, freq='daily'):
        ruleItem = RecurrenceRule(None, itsParent=self.sandbox)
        ruleItem.freq = freq
        if until is not None:
            ruleItem.until = until
        ruleSetItem = RecurrenceRuleSet(None, itsParent=self.sandbox)
        ruleSetItem.addRule(ruleItem)
        return ruleSetItem

    def _getAliases(self, uuid, dtlist, allDay=False):
        view = self.view
        aliases = []
        for dt in dtlist:
            if allDay or dt.tzinfo == self.floating:
                real_dt = formatDateTime(self.view, dt, allDay, False)
            else:
                real_dt = formatDateTime(self.view, dt.astimezone(self.utc),
                                         False, False)
            aliases.append(uuid + ":" + real_dt)
        return aliases

    def _getConflicts(self, diff, aliases):
        return findRecurrenceConflicts(self.view, self.uuid, diff, aliases)

    def testUntilChange(self):
        """
        Inbound changes to Until should work.
        """
        # set up master to recur
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')

        # create a diff
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070425T170000Z'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # get a sample set of aliases to test
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_week for n in range(5)])

        # the first three come before April 25
        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testNoRecurrenceChange(self):
        """
        If recurrence fields weren't changed, empty list should be returned.
        """

        emptyDiff = sharing.Diff(set(), set())
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_week for n in range(5)])

        # No conflicts when master isn't recurring
        self.assertEqual(self._getConflicts(emptyDiff, aliases), [])

        # create a diff with an EventRecord, but no recurrence changes
        self.kwds['dtstart'] = ';VALUE=DATE-TIME:20070301T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # No conflicts
        self.assertEqual(self._getConflicts(diff, aliases), [])

        # try again when master is recurring
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')

        conflicts = findRecurrenceConflicts(self.view, self.uuid, emptyDiff,
                                            aliases)
        # No conflicts with an empty diff
        self.assertEqual(self._getConflicts(emptyDiff, aliases), [])
        # A start time change should give conflicts
        self.assertNotEqual(self._getConflicts(diff, aliases), [])

    def testRemoveRecurrence(self):
        """All modifications should be returned if recurrence was removed."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_week for n in range(5)])

        # create a diff with all recurrence fields empty
        recurrence_fields = ('exdate', 'rdate', 'rrule', 'exrule')
        self.kwds.update(dict.fromkeys(recurrence_fields))
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), aliases)

    def testUnstamping(self):
        """If EventRecord is removed, it will be in exclusions."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_week for n in range(5)])

        # create a diff with an EventRecord in exclusions.  The EventRecord
        # can't be empty or it'll be seen as NoChange, so make a small change
        self.kwds['exdate'] = None
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set(), set([record]))

        self.assertEqual(self._getConflicts(diff, aliases), aliases)

    def testExdate(self):
        """If an EXDATE is added, it should conflict."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_week for n in range(5)])

        # create a diff with an EventRecord in exclusions.  The EventRecord
        # can't be empty or it'll be seen as NoChange, so make a small change
        self.kwds['exdate'] = ';VALUE=DATE-TIME:20070417T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), aliases[1:2])

        # choose an exdate that doesn't conflict with anything (changed time)
        self.kwds['exdate'] = ';VALUE=DATE-TIME:20070417T000000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), [])

    def testFrequencyChange(self):
        """
        Currently, Chandler leaves off-rule modifications after recurrence rule
        changes (there's no pending deletion).  For now, remote rule changes
        that leave the event recurring *do* conflict with local off-rule
        modifications for sharing.
        
        """
        # set up master to recur
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='daily')

        # create a diff changing frequency to weekly
        self.kwds['rrule'] = 'FREQ=WEEKLY'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # get a sample set of aliases to test that don't overlap with seven day
        # intervals
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_day for n in range(0, 30, 5)])

        self.assertEqual(self._getConflicts(diff, aliases), aliases[1:])

    def testRemoveRrruleLeaveRdate(self):
        """
        Removing an RRULE shouldn't cause everything to conflict if there are
        still RDATEs.
        
        """
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.master.rruleset.rdates = [
            self.start + n * one_day for n in range(1, 3)
        ]

        # create a diff removing the RRULE
        self.kwds['rrule'] = None
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # get a sample set of aliases to test that don't overlap with seven day
        # intervals
        aliases = self._getAliases(
            self.uuid, [self.start + n * one_day for n in range(5)])

        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testAllDay(self):
        self.master.allDay = True

        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070424'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        aliases = self._getAliases(
            self.uuid,
            [self.master.effectiveStartTime + n * one_week for n in range(5)])

        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testTimezonedEvent(self):
        self.master.startTime = self.start.replace(tzinfo=self.pacific)

        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070424T160000Z'
        self.kwds[
            'exdate'] = ';VALUE=DATE-TIME;TZID=America/Los_Angeles:20070417T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        aliases = self._getAliases(
            self.uuid,
            [self.master.startTime + n * one_week for n in range(5)])

        self.assertEqual(self._getConflicts(diff, aliases),
                         aliases[1:2] + aliases[3:])
Ejemplo n.º 4
0
class RecurrenceConflictTestCase(NRVTestCase):

    def setUp(self):

        if not hasattr(RecurrenceConflictTestCase, 'view'):
            super(RecurrenceConflictTestCase,self).setUp()
            RecurrenceConflictTestCase.view = self.view
            del self.view
            
        view = RecurrenceConflictTestCase.view
        self.sandbox = Item("sandbox", view, None)

        self.pacific = self.view.tzinfo.getInstance("America/Los_Angeles")
        self.floating = self.view.tzinfo.floating
        self.utc = self.view.tzinfo.UTC
        
        self.start = datetime.datetime(2007,4,10,9, tzinfo = self.floating)
        
        self.master = Calendar.CalendarEvent(None, itsParent=self.sandbox)
        self.uuid = self.master.itsItem.itsUUID.str16()
        self.master.startTime = self.start
        self.master.anyTime = self.master.allDay = False
        
        # create a baseline dictionary with keywords for creating an EventRecord
        names = (i.name for i in EventRecord.__fields__ if i.name != 'uuid')
        # default values to NoChange
        self.kwds = dict.fromkeys(names, sharing.NoChange)

    def tearDown(self):
        self.master.deleteAll()
        self.sandbox.delete(recursive=True)
        self.sandbox = None

    def _makeRecurrenceRuleSet(self, until=None, freq='daily'):
        ruleItem = RecurrenceRule(None, itsParent=self.sandbox)
        ruleItem.freq = freq
        if until is not None:
            ruleItem.until = until
        ruleSetItem = RecurrenceRuleSet(None, itsParent=self.sandbox)
        ruleSetItem.addRule(ruleItem)
        return ruleSetItem

    def _getAliases(self, uuid, dtlist, allDay=False):
        view = self.view
        aliases = []
        for dt in dtlist:
            if allDay or dt.tzinfo == self.floating:
                real_dt = formatDateTime(self.view, dt, allDay, False)
            else:
                real_dt = formatDateTime(self.view, dt.astimezone(self.utc),
                                         False, False)
            aliases.append(uuid + ":" + real_dt)
        return aliases

    def _getConflicts(self, diff, aliases):
        return findRecurrenceConflicts(self.view, self.uuid, diff, aliases)

    def testUntilChange(self):
        """
        Inbound changes to Until should work.
        """
        # set up master to recur
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        
        # create a diff
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070425T170000Z'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())
        
        # get a sample set of aliases to test
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_week for n in range(5)])
        
        # the first three come before April 25
        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testNoRecurrenceChange(self):
        """
        If recurrence fields weren't changed, empty list should be returned.
        """

        emptyDiff = sharing.Diff(set(), set())
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_week for n in range(5)])

        # No conflicts when master isn't recurring
        self.assertEqual(self._getConflicts(emptyDiff, aliases), [])
        
        # create a diff with an EventRecord, but no recurrence changes
        self.kwds['dtstart'] = ';VALUE=DATE-TIME:20070301T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # No conflicts
        self.assertEqual(self._getConflicts(diff, aliases), [])

        # try again when master is recurring
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        
        conflicts = findRecurrenceConflicts(self.view, self.uuid, emptyDiff,
                                            aliases)
        # No conflicts with an empty diff
        self.assertEqual(self._getConflicts(emptyDiff, aliases), [])
        # A start time change should give conflicts
        self.assertNotEqual(self._getConflicts(diff, aliases), [])

    def testRemoveRecurrence(self):
        """All modifications should be returned if recurrence was removed."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_week for n in range(5)])

        # create a diff with all recurrence fields empty
        recurrence_fields = ('exdate', 'rdate', 'rrule', 'exrule')
        self.kwds.update(dict.fromkeys(recurrence_fields))
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), aliases)

    def testUnstamping(self):
        """If EventRecord is removed, it will be in exclusions."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_week for n in range(5)])

        # create a diff with an EventRecord in exclusions.  The EventRecord
        # can't be empty or it'll be seen as NoChange, so make a small change
        self.kwds['exdate'] = None
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set(), set([record]))

        self.assertEqual(self._getConflicts(diff, aliases), aliases)

    def testExdate(self):
        """If an EXDATE is added, it should conflict."""
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_week for n in range(5)])

        # create a diff with an EventRecord in exclusions.  The EventRecord
        # can't be empty or it'll be seen as NoChange, so make a small change
        self.kwds['exdate'] = ';VALUE=DATE-TIME:20070417T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), aliases[1:2])

        # choose an exdate that doesn't conflict with anything (changed time)
        self.kwds['exdate'] = ';VALUE=DATE-TIME:20070417T000000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        self.assertEqual(self._getConflicts(diff, aliases), [])

    def testFrequencyChange(self):
        """
        Currently, Chandler leaves off-rule modifications after recurrence rule
        changes (there's no pending deletion).  For now, remote rule changes
        that leave the event recurring *do* conflict with local off-rule
        modifications for sharing.
        
        """
        # set up master to recur
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='daily')
        
        # create a diff changing frequency to weekly
        self.kwds['rrule'] = 'FREQ=WEEKLY'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())
        
        # get a sample set of aliases to test that don't overlap with seven day
        # intervals
        aliases = self._getAliases(self.uuid,
                              [self.start + n*one_day for n in range(0, 30, 5)])
        
        self.assertEqual(self._getConflicts(diff, aliases), aliases[1:])

    def testRemoveRrruleLeaveRdate(self):
        """
        Removing an RRULE shouldn't cause everything to conflict if there are
        still RDATEs.
        
        """
        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.master.rruleset.rdates = [self.start + n*one_day for n in range(1,3)]

        # create a diff removing the RRULE
        self.kwds['rrule'] = None
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        # get a sample set of aliases to test that don't overlap with seven day
        # intervals
        aliases = self._getAliases(self.uuid,
                                   [self.start + n*one_day for n in range(5)])
        
        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testAllDay(self):
        self.master.allDay = True

        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070424'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        aliases = self._getAliases(self.uuid,
                                   [self.master.effectiveStartTime + n*one_week
                                    for n in range(5)])
        
        self.assertEqual(self._getConflicts(diff, aliases), aliases[3:])

    def testTimezonedEvent(self):
        self.master.startTime = self.start.replace(tzinfo=self.pacific)

        self.master.rruleset = self._makeRecurrenceRuleSet(freq='weekly')
        self.kwds['rrule'] = 'FREQ=WEEKLY;UNTIL=20070424T160000Z'
        self.kwds['exdate'] = ';VALUE=DATE-TIME;TZID=America/Los_Angeles:20070417T090000'
        record = sharing.model.EventRecord(self.uuid, **self.kwds)
        diff = sharing.Diff(set([record]), set())

        aliases = self._getAliases(self.uuid,
                                   [self.master.startTime + n*one_week
                                    for n in range(5)])
        
        self.assertEqual(self._getConflicts(diff, aliases),
                         aliases[1:2] + aliases[3:])