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
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([])
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)
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)
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)
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:])
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:])