Example #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
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
    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 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 setUp(self):
        if self.sandbox is None:
            super(ProxyTestCase, self).setUp()
            type(self).sandbox = Item("sandbox", self.view, None)
            del self.view
        view = self.sandbox.itsView

        self.event = pim.calendar.Calendar.CalendarEvent(
            itsParent=self.sandbox,
            displayName=u"An event",
            startTime=datetime.datetime(
                2007,
                3,
                16,
                11,
                30,
                tzinfo=view.tzinfo.getInstance("America/New_York")),
            duration=datetime.timedelta(minutes=15),
            anyTime=False,
            read=False,
        )
        self.rruleset = self.makeRuleset('daily')
        self.one = pim.SmartCollection(itsParent=self.sandbox,
                                       displayName=u"One")
        self.two = pim.SmartCollection(itsParent=self.sandbox,
                                       displayName=u"Two")
        return view
Example #6
0
    def packStart(self, attrs):

        if attrs.has_key('cwd'):
            cwd = attrs['cwd']
            if isinstance(cwd, unicode):
                cwd = cwd.encode(self.fsenc)

            self.cwd[-1] = os.path.join(self.cwd[-1], cwd)

        if attrs.has_key('file'):
            if not self.view.find(Path('//', 'Packs', attrs['name'])):
                try:
                    file = attrs['file']
                    if isinstance(file, unicode):
                        file = file.encode(self.fsenc)

                    self.view.loadPack(os.path.join(self.cwd[-1], file),
                                       self.parent[-1], self.package)
                except:
                    self.saveException()
                    return

        else:
            self.name = attrs['name']
            self.pack = Item(self.name, self.packs, None)
            self.hooks.append([])
Example #7
0
 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 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)
Example #9
0
    def testSubAttributes(self):
        """Test attributes which have sub attributes (subAttributes and superAttribute attributes)"""
        view = self.view
        itemKind = view.findPath('//Schema/Core/Item')
        attrKind = view.findPath('//Schema/Core/Attribute')
        self.assert_(itemKind is not None)

        attr = Attribute('references', view.findPath('//Schema/Core'), attrKind,
                         cardinality='list', otherName='item')
        itemKind.attributes.append(attr, alias='references')
        
        attr_name = 'references'
        
        item = Item('item1', view, itemKind)
        attrKind = itemKind.itsParent['Attribute']

        # subattributes are created by assigning the "parent" attribute
        # to the superAttribute attribute of the "child" attribute
        testAttr = itemKind.getAttribute(attr_name)
        criticalSubAttr = Attribute('critical', testAttr, attrKind)
        criticalSubAttr.superAttribute = testAttr
        self.assert_(criticalSubAttr.superAttribute is testAttr)
        self.assert_(criticalSubAttr in testAttr.subAttributes)

        # now do it by assigning to the subAttributes list to ensure that
        # the bidirectional ref is getting updated.
        normalSubAttr = Attribute('normal', testAttr, attrKind)
        testAttr.subAttributes.append(normalSubAttr)
        self.assert_(normalSubAttr.superAttribute is testAttr)
        self.assert_(normalSubAttr in testAttr.subAttributes)
        
        # now do it by callin addValue on the Attribute item
        minorSubAttr = Attribute('minor', testAttr, attrKind)
        testAttr.addValue('subAttributes', minorSubAttr)
        self.assert_(minorSubAttr.superAttribute is testAttr)
        self.assert_(minorSubAttr in testAttr.subAttributes)

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//item1')
        itemKind = item.itsKind
        testAttr = itemKind.getAttribute(attr_name)

        attMap = {}
        for i in testAttr.subAttributes:
            attMap[i.itsName] = i 
            
        criticalSubAttr = attMap['critical']
        normalSubAttr = attMap['normal']
        minorSubAttr = attMap['minor']
        self.assert_(criticalSubAttr.superAttribute is testAttr)
        self.assert_(criticalSubAttr in testAttr.subAttributes)
        self.assert_(normalSubAttr.superAttribute is testAttr)
        self.assert_(normalSubAttr in testAttr.subAttributes)
        self.assert_(minorSubAttr.superAttribute is testAttr)
        self.assert_(minorSubAttr in testAttr.subAttributes)
Example #10
0
    def prepareTestData(self):

        # Make sure these are initialized, otherwise they won't be tracking
        # icalUIDs
        schema.ns('osaf.sharing', self.views[0]).uid_map
        schema.ns('osaf.sharing', self.views[1]).uid_map

        view = self.views[0]
        # create a sandbox root
        Item("sandbox", view, None)

        sandbox = view.findPath("//sandbox")
        coll = pim.ListCollection("testCollection",
                                  sandbox,
                                  displayName="Test Collection")

        names = [
            (u"Morgen", u"Sagen", u"*****@*****.**"),
            (u"Ted", u"Leung", u"*****@*****.**"),
            (u"Andi", u"Vajda", u"*****@*****.**"),
        ]

        contacts = []

        for name in names:
            c = pim.Contact(None, sandbox)
            c.contactName = pim.ContactName(None, sandbox)
            c.contactName.firstName = name[0]
            c.contactName.lastName = name[1]
            c.emailAddress = name[2]
            c.displayName = u"%s %s" % (name[0], name[1])
            contacts.append(c)

        events = [
            u"breakfast",
            u"lunch",
            u"dinner",
            u"meeting",
            u"movie",
            u'\u8fd1\u85e4\u6df3\u4e5f\u306e\u65b0\u30cd\u30c3\u30c8\u30b3\u30df\u30e5\u30cb\u30c6\u30a3\u8ad6',
        ]

        self.uuids = {}

        tzinfo = sandbox.itsView.tzinfo.default
        for i in xrange(6):
            c = pim.CalendarEvent(None, sandbox)
            c.summary = events[i % 6]
            c.organizer = contacts[0]
            c.participants = [contacts[1], contacts[2]]
            c.startTime = datetime.datetime(2005, 10, 31, 12, 0, 0, 0, tzinfo)
            c.duration = datetime.timedelta(minutes=60)
            c.anyTime = False
            self.uuids[c.itsItem.itsUUID] = c.summary
            coll.add(c.itsItem)
    def testLiteralAttributes(self):
        view = self.view
        """Test basic features of literal attributes"""
        kind = view.findPath('//Schema/Core/Kind')
        itemKind = view.findPath('//Schema/Core/Item')
        self.assert_(itemKind is not None)
        attrKind = view.findPath('//Schema/Core/Attribute')
        self.assert_(attrKind is not None)
        stringType = view.findPath('//Schema/Core/String')
        self.assert_(stringType is not None)

        attr = attrKind.newItem('testAttr', itemKind, type=stringType)
        itemKind.attributes.add(attr, 'testAttr')
        self.assert_(itemKind.getAttribute('testAttr', True) is not None)

        kind1 = Kind('kind1', view, kind)
        self.assert_(kind1 is not None)

        item1 = Item('item1', view, itemKind)
        self.assert_(item1 is not None)

        #Test hasAttributeAspect and getAttributeAspect
        self.assert_(
            kind1.hasAttributeAspect('attributes', 'cardinality') and
            kind1.getAttributeAspect('attributes', 'cardinality') == 'list')

        self.assert_(
            kind1.hasAttributeAspect('superKinds', 'cardinality') and
            kind1.getAttributeAspect('superKinds', 'cardinality') == 'list')

        self.assert_(
            kind1.hasAttributeAspect('classes', 'cardinality')
            and kind1.getAttributeAspect('classes', 'cardinality') == 'dict')

        # up to here testAttr is an unset Chandler attribute
        self.failUnlessRaises(AttributeError, lambda: item1.testAttr)
        # now set the attribute
        item1.setAttributeValue('testAttr', u'myName')
        self.assertEquals(item1.testAttr, u'myName')
        #test __getattr__ and getAttributeValue() access
        self.assertEquals(item1.testAttr, item1.getAttributeValue('testAttr'))
        # now remove attribute value
        item1.removeAttributeValue('testAttr')
        self.failUnlessRaises(AttributeError, lambda: item1.testAttr)
        #TODO need a test for list valued literal attribute

        # test dict valued literal attribute
        self.assert_(kind.classes['python'] is not None)
Example #12
0
    def __init__(self, path, parent, package, view):

        ContentHandler.__init__(self)

        self.path = path
        self.package = package
        self.cwd = [os.path.dirname(path)]
        self.parent = [parent]
        self.view = view
        self.hooks = []

        # the xml parser may return unicode for non-ascii paths or names
        # which need to be encoded to utf8
        self.fsenc = 'utf8'

        packs = view.getRoot('Packs')
        if packs is None:
            packs = Item('Packs', view, None)
        self.packs = packs
    def testLiteralAttributes(self):
        view = self.view
        """Test basic features of literal attributes"""
        kind = view.findPath('//Schema/Core/Kind')
        itemKind = view.findPath('//Schema/Core/Item')
        self.assert_(itemKind is not None)
        attrKind = view.findPath('//Schema/Core/Attribute')
        self.assert_(attrKind is not None)
        stringType = view.findPath('//Schema/Core/String')
        self.assert_(stringType is not None)

        attr = attrKind.newItem('testAttr', itemKind, type=stringType)
        itemKind.attributes.add(attr, 'testAttr')
        self.assert_(itemKind.getAttribute('testAttr', True) is not None)

        kind1 = Kind('kind1', view, kind)
        self.assert_(kind1 is not None)

        item1 = Item('item1', view, itemKind)
        self.assert_(item1 is not None)

        #Test hasAttributeAspect and getAttributeAspect
        self.assert_(kind1.hasAttributeAspect('attributes','cardinality') and
                     kind1.getAttributeAspect('attributes','cardinality') == 'list')

        self.assert_(kind1.hasAttributeAspect('superKinds','cardinality') and
                     kind1.getAttributeAspect('superKinds','cardinality') == 'list')

        self.assert_(kind1.hasAttributeAspect('classes','cardinality') and
                     kind1.getAttributeAspect('classes','cardinality') == 'dict')

        # up to here testAttr is an unset Chandler attribute
        self.failUnlessRaises(AttributeError, lambda: item1.testAttr)
        # now set the attribute
        item1.setAttributeValue('testAttr', u'myName')
        self.assertEquals(item1.testAttr, u'myName')
        #test __getattr__ and getAttributeValue() access
        self.assertEquals(item1.testAttr, item1.getAttributeValue('testAttr'))
        # now remove attribute value
        item1.removeAttributeValue('testAttr')
        self.failUnlessRaises(AttributeError, lambda: item1.testAttr)
        #TODO need a test for list valued literal attribute

        # test dict valued literal attribute
        self.assert_(kind.classes['python'] is not None)
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:])
Example #15
0
    def testItemParentChild(self):
        """Test basic attribute functionality, focusing on parent-child relationships"""
        view = self.view
        # Test find()
        kind = view.findPath('//Schema/Core/Item')
        self.assert_(kind is not None)

        # Test itsName
        self.assertEquals(kind.itsName, 'Item')

        # Test itsPath
        self.assertEquals(str(kind.itsPath), '//Schema/Core/Item')

        # Test simple item construction
        item = Item('test', view, kind)
        self.assert_(item is not None)
        self.assert_(item.isItemOf(kind))
        self.failIf(item.isRemote())
        self.failIf(item.hasChildren())
        self.assertEquals(item.itsName, 'test')
        self.assertItemPathEqual(item, '//test')
        self.assertEquals(item.refCount(), 0)
        self.assert_(item.isNew())
        self.assert_(item.isDirty())
        self.failIf(item.isDeleted())
        self.failIf(item.isStale())
        self.assertEquals(view, item.itsView)

#TODO test toXML
        out = StringIO()
        generator = XMLPrettyGenerator(XMLGenerator(out))
        itemWriter = XMLItemWriter(generator)
        generator.startDocument()
        itemWriter.writeItem(item, item.getVersion())
        generator.endDocument()
        xml = out.getvalue()
        out.close()

        self.failIf(xml is None)

        # Test to see that item became a respository root
        view.commit()
        roots = list(view.iterRoots())
        self.assert_(item in roots)
        self.failIf(item.isDirty())

        # Test placing children
        child1 = Item('child1', item, kind)
        self.assertEquals(child1.itsName, 'child1')
        self.assertItemPathEqual(child1, '//test/child1')
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        item.placeChild(child1, None)
        self.assert_(item.hasChild('child1'))
        self.failIf(item.isNew())
        self.assert_(item.isDirty())

        child2 = Item('child2', item, kind)
        self.assertEquals(child2.itsName, 'child2')
        self.assertItemPathEqual(child2, '//test/child2')
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        self.assert_(item.hasChild('child2'))

        item.placeChild(child2, child1)
        self.assert_(item.hasChild('child2'))
        self.failIf(item.isNew())
        self.assert_(item.isDirty())

        self.assertEqual(item.getItemChild('child1'), child1)
        self.assertEqual(item.getItemChild('child2'), child2)
        self.assertEqual(child1.itsParent, item)
        self.assertEqual(child2.itsParent, item)

        # Test iterating over child items
        iter = item.iterChildren()
        self.assertEqual(item.getItemChild('child1'), iter.next())
        self.assertEqual(item.getItemChild('child2'), iter.next())

#        self.failUnlessRaises(StopIteration, lambda: iter.next())

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        self.assertIsRoot(item)
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        self.assert_(item.hasChild('child2'))

        # Test item renaming, itsName
        kind = view.findPath('//Schema/Core/Item')
        child3 = Item('busted', item, kind)
        self.assertEqual(child3.itsName, 'busted')
        child3.itsName = 'busted'
        self.assertEqual(child3.itsName, 'busted')
        child3.itsName = 'child3'
        self.assertEqual(child3.itsName, 'child3')

        # Test that placing affects iteration order
        item.placeChild(child3, child1)
        iter = item.iterChildren()
        iter.next()
        self.assertEqual(child3, iter.next())
        self.assertItemPathEqual(child3, '//test/child3')
        self.assertIsRoot(child3.itsRoot)

        # Test item movement to same parent
        oldParent = child3.itsParent
        child3.itsParent = child3.itsParent
        self.assertEqual(oldParent, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child3')
        self.assertIsRoot(child3.itsRoot)
        
        # Test item movement to leaf item
        child3.itsParent = child2
        self.assertEqual(child2, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child2/child3')
        self.assertIsRoot(child3.itsRoot)

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        child3 = child2['child3']

        self.assertEqual(child2, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child2/child3')
        self.assertIsRoot(child3.itsRoot)

        # Test item movement to root
        child3.itsParent = view
        self.assertIsRoot(child3)
        self.assertItemPathEqual(child3, '//child3')
        self.assertIsRoot(child3.itsRoot)
        
        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        child3 = view['child3']

        self.assert_(child3 in list(view.iterRoots()))
        self.assertItemPathEqual(child3, '//child3')
        self.assertIsRoot(child3.itsRoot)
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:])
Example #17
0
    def testItemParentChild(self):
        """Test basic attribute functionality, focusing on parent-child relationships"""
        view = self.view
        # Test find()
        kind = view.findPath('//Schema/Core/Item')
        self.assert_(kind is not None)

        # Test itsName
        self.assertEquals(kind.itsName, 'Item')

        # Test itsPath
        self.assertEquals(str(kind.itsPath), '//Schema/Core/Item')

        # Test simple item construction
        item = Item('test', view, kind)
        self.assert_(item is not None)
        self.assert_(item.isItemOf(kind))
        self.failIf(item.isRemote())
        self.failIf(item.hasChildren())
        self.assertEquals(item.itsName, 'test')
        self.assertItemPathEqual(item, '//test')
        self.assertEquals(item.refCount(), 0)
        self.assert_(item.isNew())
        self.assert_(item.isDirty())
        self.failIf(item.isDeleted())
        self.failIf(item.isStale())
        self.assertEquals(view, item.itsView)

        #TODO test toXML
        out = StringIO()
        generator = XMLPrettyGenerator(XMLGenerator(out))
        itemWriter = XMLItemWriter(generator)
        generator.startDocument()
        itemWriter.writeItem(item, item.getVersion())
        generator.endDocument()
        xml = out.getvalue()
        out.close()

        self.failIf(xml is None)

        # Test to see that item became a respository root
        view.commit()
        roots = list(view.iterRoots())
        self.assert_(item in roots)
        self.failIf(item.isDirty())

        # Test placing children
        child1 = Item('child1', item, kind)
        self.assertEquals(child1.itsName, 'child1')
        self.assertItemPathEqual(child1, '//test/child1')
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        item.placeChild(child1, None)
        self.assert_(item.hasChild('child1'))
        self.failIf(item.isNew())
        self.assert_(item.isDirty())

        child2 = Item('child2', item, kind)
        self.assertEquals(child2.itsName, 'child2')
        self.assertItemPathEqual(child2, '//test/child2')
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        self.assert_(item.hasChild('child2'))

        item.placeChild(child2, child1)
        self.assert_(item.hasChild('child2'))
        self.failIf(item.isNew())
        self.assert_(item.isDirty())

        self.assertEqual(item.getItemChild('child1'), child1)
        self.assertEqual(item.getItemChild('child2'), child2)
        self.assertEqual(child1.itsParent, item)
        self.assertEqual(child2.itsParent, item)

        # Test iterating over child items
        iter = item.iterChildren()
        self.assertEqual(item.getItemChild('child1'), iter.next())
        self.assertEqual(item.getItemChild('child2'), iter.next())

        #        self.failUnlessRaises(StopIteration, lambda: iter.next())

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        self.assertIsRoot(item)
        self.assert_(item.hasChildren())
        self.assert_(item.hasChild('child1'))
        self.assert_(item.hasChild('child2'))

        # Test item renaming, itsName
        kind = view.findPath('//Schema/Core/Item')
        child3 = Item('busted', item, kind)
        self.assertEqual(child3.itsName, 'busted')
        child3.itsName = 'busted'
        self.assertEqual(child3.itsName, 'busted')
        child3.itsName = 'child3'
        self.assertEqual(child3.itsName, 'child3')

        # Test that placing affects iteration order
        item.placeChild(child3, child1)
        iter = item.iterChildren()
        iter.next()
        self.assertEqual(child3, iter.next())
        self.assertItemPathEqual(child3, '//test/child3')
        self.assertIsRoot(child3.itsRoot)

        # Test item movement to same parent
        oldParent = child3.itsParent
        child3.itsParent = child3.itsParent
        self.assertEqual(oldParent, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child3')
        self.assertIsRoot(child3.itsRoot)

        # Test item movement to leaf item
        child3.itsParent = child2
        self.assertEqual(child2, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child2/child3')
        self.assertIsRoot(child3.itsRoot)

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        child3 = child2['child3']

        self.assertEqual(child2, child3.itsParent)
        self.assertItemPathEqual(child3, '//test/child2/child3')
        self.assertIsRoot(child3.itsRoot)

        # Test item movement to root
        child3.itsParent = view
        self.assertIsRoot(child3)
        self.assertItemPathEqual(child3, '//child3')
        self.assertIsRoot(child3.itsRoot)

        # now write what we've done and read it back
        self._reopenRepository()
        view = self.view
        item = view.findPath('//test')
        child1 = item['child1']
        child2 = item['child2']
        child3 = view['child3']

        self.assert_(child3 in list(view.iterRoots()))
        self.assertItemPathEqual(child3, '//child3')
        self.assertIsRoot(child3.itsRoot)