def migrate(self, txn, mapIDsCallback): """ See L{ScheduleWork.migrate} """ # Try to find a mapping new_home, new_resource = yield mapIDsCallback(self.resourceID) # If we previously had a resource ID and now don't, then don't create work if self.resourceID is not None and new_resource is None: returnValue(False) if self.icalendarTextOld: calendar_old = Component.fromString(self.icalendarTextOld) uid = calendar_old.resourceUID() else: calendar_new = Component.fromString(self.icalendarTextNew) uid = calendar_new.resourceUID() # Insert new work - in paused state yield ScheduleOrganizerWork.schedule( txn, uid, scheduleActionFromSQL[self.scheduleAction], new_home, new_resource, self.icalendarTextOld, self.icalendarTextNew, new_home.uid(), self.attendeeCount, self.smartMerge, pause=1 ) returnValue(True)
def test_twoSimpleEvents(self): """ Exporting a calendar with two events in it will result in a VCALENDAR component with both VEVENTs in it. """ yield populateCalendarsFrom( { "home1": { "calendar1": { "valentines-day.ics": (valentines, {}), "new-years-day.ics": (newYears, {}) } } }, self.store ) expected = Component.newCalendar() a = Component.fromString(valentines) b = Component.fromString(newYears) for comp in a, b: for sub in comp.subcomponents(): expected.addComponent(sub) io = StringIO() yield exportToFile( [(yield self.txn().calendarHomeWithUID("home1")) .calendarWithName("calendar1")], io ) self.assertEquals(Component.fromString(io.getvalue()), expected)
def test_vcalendar_no_effect(self): data = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ORGANIZER;CN=User 01:mailto:[email protected] END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") no_effect = CalendarData( CalendarComponent( name="VCALENDAR" ) ) for item in (data, Component.fromString(data),): self.assertEqual(str(CalendarDataFilter(no_effect).filter(item)), data) no_effect = CalendarData( CalendarComponent( AllComponents(), AllProperties(), name="VCALENDAR" ) ) for item in (data, Component.fromString(data),): self.assertEqual(str(CalendarDataFilter(no_effect).filter(item)), data)
def test_oneEventCalendar(self): """ Exporting an calendar with one event in it will result in just that event. """ yield populateCalendarsFrom( { "home1": { "calendar1": { "valentines-day.ics": (valentines, {}) } } }, self.store ) expected = Component.newCalendar() [theComponent] = Component.fromString(valentines).subcomponents() expected.addComponent(theComponent) io = StringIO() yield exportToFile( [(yield self.txn().calendarHomeWithUID("home1")) .calendarWithName("calendar1")], io ) self.assertEquals(Component.fromString(io.getvalue()), expected)
def doWork(self): try: home = (yield self.transaction.calendarHomeWithResourceID(self.homeResourceID)) resource = (yield home.objectResourceWithID(self.resourceID)) organizerAddress = yield calendarUserFromCalendarUserUID(home.uid(), self.transaction) organizer = organizerAddress.record.canonicalCalendarUserAddress() calendar_old = Component.fromString(self.icalendarTextOld) if self.icalendarTextOld else None calendar_new = Component.fromString(self.icalendarTextNew) if self.icalendarTextNew else None log.debug("ScheduleOrganizerWork - running for ID: {id}, UID: {uid}, organizer: {org}", id=self.workID, uid=self.icalendarUid, org=organizer) # We need to get the UID lock for implicit processing. yield NamedLock.acquire(self.transaction, "ImplicitUIDLock:%s" % (hashlib.md5(self.icalendarUid).hexdigest(),)) from txdav.caldav.datastore.scheduling.implicit import ImplicitScheduler scheduler = ImplicitScheduler() yield scheduler.queuedOrganizerProcessing( self.transaction, scheduleActionFromSQL[self.scheduleAction], home, resource, self.icalendarUid, calendar_old, calendar_new, self.smartMerge ) self._dequeued() except Exception, e: log.debug("ScheduleOrganizerWork - exception ID: {id}, UID: '{uid}', {err}", id=self.workID, uid=self.icalendarUid, err=str(e)) log.debug(traceback.format_exc()) raise
def test_full(self): """ Running C{calendarserver_export} on the command line exports an ics file. (Almost-full integration test, starting from the main point, using as few test fakes as possible.) Note: currently the only test for directory interaction. """ yield populateCalendarsFrom( { "user02": { # TODO: more direct test for skipping inbox "inbox": { "inbox-item.ics": (valentines, {}) }, "calendar1": { "peruser.ics": (dataForTwoUsers, {}), # EST } } }, self.store ) output = FilePath(self.mktemp()) main(['calendarserver_export', '--output', output.path, '--user', 'user02'], reactor=self) yield self.waitToStop self.assertEquals( Component.fromString(resultForUser2), Component.fromString(output.getContent()) )
def test_listobjects(self): """ Test that action=listobjects works. """ yield self.createShare("user01", "puser01") shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") objects = yield shared.listObjectResources() self.assertEqual(set(objects), set()) yield self.commitTransaction(1) calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield calendar1.createCalendarObjectWithName("2.ics", Component.fromString(self.caldata2)) objects = yield calendar1.listObjectResources() self.assertEqual(set(objects), set(("1.ics", "2.ics",))) yield self.commitTransaction(0) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") objects = yield shared.listObjectResources() self.assertEqual(set(objects), set(("1.ics", "2.ics",))) yield self.commitTransaction(1) calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") yield object1.remove() objects = yield calendar1.listObjectResources() self.assertEqual(set(objects), set(("2.ics",))) yield self.commitTransaction(0) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") objects = yield shared.listObjectResources() self.assertEqual(set(objects), set(("2.ics",))) yield self.commitTransaction(1)
def test_setcomponent(self): """ Test that action=setcomponent works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) shared_object = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", calendar_name="shared-calendar", name="1.ics") ical = yield shared_object.component() self.assertTrue(isinstance(ical, Component)) self.assertEqual(normalize_iCalStr(str(ical)), normalize_iCalStr(self.caldata1)) yield self.commitTransaction(1) shared_object = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", calendar_name="shared-calendar", name="1.ics") changed = yield shared_object.setComponent(Component.fromString(self.caldata1_changed)) self.assertFalse(changed) ical = yield shared_object.component() self.assertTrue(isinstance(ical, Component)) self.assertEqual(normalize_iCalStr(str(ical)), normalize_iCalStr(self.caldata1_changed)) yield self.commitTransaction(1) object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") ical = yield object1.component() self.assertTrue(isinstance(ical, Component)) self.assertEqual(normalize_iCalStr(str(ical)), normalize_iCalStr(self.caldata1_changed)) yield self.commitTransaction(0)
def test_objectresource_component(self): """ Test that a remote object resource L{component} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") yield calendar01.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield calendar01.createCalendarObjectWithName("2.ics", Component.fromString(self.caldata2)) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") caldata = yield resource.component() self.assertEqual(str(caldata), self.caldata1) resource = yield calendar.objectResourceWithName("2.ics") caldata = yield resource.component() self.assertEqual(str(caldata), self.caldata2) yield self.commitTransaction(1)
def test_objectresource_resourceuidforname(self): """ Test that a remote home child L{resourceUIDForName} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") yield calendar01.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield calendar01.createCalendarObjectWithName("2.ics", Component.fromString(self.caldata2)) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") uid = yield calendar.resourceUIDForName("1.ics") self.assertEqual(uid, "uid1") uid = yield calendar.resourceUIDForName("2.ics") self.assertEqual(uid, "uid2") uid = yield calendar.resourceUIDForName("foo.ics") self.assertEqual(uid, None) yield self.commitTransaction(1)
def test_objectresource_objectwith(self): """ Test that a remote home child L{objectResourceWithName} and L{objectResourceWithUID} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") resource01 = yield calendar01.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield calendar01.createCalendarObjectWithName("2.ics", Component.fromString(self.caldata2)) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("2.ics") self.assertEqual(resource.name(), "2.ics") resource = yield calendar.objectResourceWithName("foo.ics") self.assertEqual(resource, None) resource = yield calendar.objectResourceWithUID("uid1") self.assertEqual(resource.name(), "1.ics") resource = yield calendar.objectResourceWithUID("foo") self.assertEqual(resource, None) resource = yield calendar.objectResourceWithID(resource01.id()) self.assertEqual(resource.name(), "1.ics") resource = yield calendar.objectResourceWithID(12345) self.assertEqual(resource, None) yield self.commitTransaction(1)
def test_full(self): """ Running C{calendarserver_export} on the command line exports an ics file. (Almost-full integration test, starting from the main point, using as few test fakes as possible.) Note: currently the only test for directory interaction. """ yield populateCalendarsFrom( { "user02": { # TODO: more direct test for skipping inbox "inbox": { "inbox-item.ics": (valentines, {}) }, "calendar1": { "peruser.ics": (dataForTwoUsers, {}), # EST } } }, self.store ) augmentsData = """ <augments> <record> <uid>Default</uid> <enable>true</enable> <enable-calendar>true</enable-calendar> <enable-addressbook>true</enable-addressbook> </record> </augments> """ augments = FilePath(self.mktemp()) augments.setContent(augmentsData) accountsData = """ <accounts realm="Test Realm"> <user> <uid>user-under-test</uid> <guid>user02</guid> <name>Not Interesting</name> <password>very-secret</password> </user> </accounts> """ accounts = FilePath(self.mktemp()) accounts.setContent(accountsData) output = FilePath(self.mktemp()) self.accountsFile = accounts.path self.augmentsFile = augments.path main(['calendarserver_export', '--output', output.path, '--user', 'user-under-test'], reactor=self) yield self.waitToStop self.assertEquals( Component.fromString(resultForUser2), Component.fromString(output.getContent()) )
def test_validation_preserveOrganizerPrivateComments(self): """ Test that organizer private comments are restored. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-organizer DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:x-uid:user01"; X-CALENDARSERVER-DTSTAMP=20131101T100000Z:Someone else's comment END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName( "test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-organizer DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VEVENT END:VCALENDAR """ txn = self.transactionUnderTest() txn._authz_uid = "user01" calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar = Component.fromString(data2) yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue( "X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF=\"urn:x-uid:user01\";X-CALENDARSERVER-DTSTAMP=20131101T100000Z:Someone else's comment" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) yield self.commit()
def test_validation_replaceMissingToDoProperties_OrganizerAttendee(self): """ Test that missing scheduling properties in VTODOs are recovered. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VTODO UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VTODO END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName( "test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VTODO UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VTODO END:VCALENDAR """ txn = self.transactionUnderTest() txn._authz_uid = "user01" calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar = Component.fromString(data2) yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue("ORGANIZER" in calendar1) self.assertTrue("ATTENDEE" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) yield self.commit()
def assertEqualCalendarData(self, cal1, cal2): if isinstance(cal1, str): cal1 = Component.fromString(cal1) if isinstance(cal2, str): cal2 = Component.fromString(cal2) ncal1 = normalize_iCalStr(cal1) ncal2 = normalize_iCalStr(cal2) self.assertEqual(ncal1, ncal2, msg=diff_iCalStrs(ncal1, ncal2))
def test_validation_noPreservePrivateComments(self): """ Test that attendee private comments are no longer restored. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z X-CALENDARSERVER-PRIVATE-COMMENT:My Comment END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName( "test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VEVENT END:VCALENDAR """ txn = self.transactionUnderTest() txn._authz_uid = "user01" calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar = Component.fromString(data2) yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertFalse( "X-CALENDARSERVER-PRIVATE-COMMENT:My Comment" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) yield self.commit()
def test_validation_replaceMissingToDoProperties_Completed(self): """ Test that VTODO completed status is fixed. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VTODO UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VTODO END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName("test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VTODO UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed COMPLETED:20080601T140000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VTODO END:VCALENDAR """ calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar = Component.fromString(data2) txn = self.transactionUnderTest() txn._authz_uid = "user01" yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue("ORGANIZER" in calendar1) self.assertTrue("ATTENDEE" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) self.assertTrue("PARTSTAT=COMPLETED" in calendar1) yield self.commit()
def test_validation_maxResourceSize(self): """ Test that various types of invalid calendar data are rejected when creating a resource. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z END:VEVENT END:VCALENDAR """ data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VEVENT END:VCALENDAR """ self.patch(config, "MaxResourceSize", 100) calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar1 = Component.fromString(data1) yield self.failUnlessFailure( calendar_collection.createCalendarObjectWithName( "test.ics", calendar1), ObjectResourceTooBigError) yield self.commit() self.patch(config, "MaxResourceSize", 10000) calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar1 = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName( "test.ics", calendar1) yield self.commit() self.patch(config, "MaxResourceSize", 100) calendar_resource = (yield self.calendarObjectUnderTest( name="test.ics", home="user01", )) calendar2 = Component.fromString(data2) yield self.failUnlessFailure(calendar_resource.setComponent(calendar2), ObjectResourceTooBigError) yield self.commit()
def test_objectresource_create(self): """ Test that a remote object resource L{create} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) yield home01.childWithName("calendar") yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.createCalendarObjectWithName( "1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(1) home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") resource01 = yield calendar01.objectResourceWithName("1.ics") self.assertEqual(resource01.id(), resource.id()) caldata = yield resource01.component() self.assertEqual(str(caldata), self.caldata1) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") caldata = yield resource.component() self.assertEqual(str(caldata), self.caldata1) yield self.commitTransaction(1) # Recreate fails home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") self.assertFailure( calendar.createCalendarObjectWithName( "1.ics", Component.fromString(self.caldata1)), ObjectResourceNameAlreadyExistsError, ) yield self.abortTransaction(1)
def test_testImplicitSchedulingPUT_FixScheduleState(self): """ Test that testImplicitSchedulingPUT will fix an old cached schedule object state by re-evaluating the calendar data. """ calendarOld = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calendarNew = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calendar_collection = (yield self.calendarUnderTest(home="user01")) calresource = (yield calendar_collection.createCalendarObjectWithName( "1.ics", calendarOld )) calresource.isScheduleObject = False scheduler = ImplicitScheduler() try: doAction, isScheduleObject = (yield scheduler.testImplicitSchedulingPUT(calendar_collection, calresource, calendarNew, False)) except Exception as e: print e self.fail("Exception must not be raised") self.assertTrue(doAction) self.assertTrue(isScheduleObject)
def test_validation_preserveOrganizerPrivateComments(self): """ Test that organizer private comments are restored. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-organizer DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:x-uid:user01"; X-CALENDARSERVER-DTSTAMP=20131101T100000Z:Someone else's comment END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName("test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-organizer DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VEVENT END:VCALENDAR """ txn = self.transactionUnderTest() txn._authz_uid = "user01" calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar = Component.fromString(data2) yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue("X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF=\"urn:x-uid:user01\";X-CALENDARSERVER-DTSTAMP=20131101T100000Z:Someone else's comment" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) yield self.commit()
def test_objectresource_setcomponent(self): """ Test that a remote object resource L{setComponent} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") yield calendar01.createCalendarObjectWithName( "1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") changed = yield resource.setComponent( Component.fromString(self.caldata1_changed)) self.assertFalse(changed) caldata = yield resource.component() self.assertEqual(normalize_iCalStr(str(caldata)), normalize_iCalStr(self.caldata1_changed)) yield self.commitTransaction(1) home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") resource01 = yield calendar01.objectResourceWithName("1.ics") caldata = yield resource01.component() self.assertEqual(normalize_iCalStr(str(caldata)), normalize_iCalStr(self.caldata1_changed)) yield self.commitTransaction(0) # Fail to set with different UID home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") self.assertFailure( resource.setComponent(Component.fromString(self.caldata1_failed)), InvalidUIDError, ) yield self.commitTransaction(1)
def test_testImplicitSchedulingPUT_FixScheduleState(self): """ Test that testImplicitSchedulingPUT will fix an old cached schedule object state by re-evaluating the calendar data. """ request = SimpleRequest(self.site, "PUT", "/calendar/1.ics") calresource = yield request.locateResource("/calendar/1.ics") self.assertEqual(calresource.isScheduleObject, None) calresource.isScheduleObject = False calendarOld = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 02":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calendarNew = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 02":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calresource.exists = lambda : True calresource.iCalendarForUser = lambda request: succeed(calendarOld) scheduler = ImplicitScheduler() try: doAction, isScheduleObject = (yield scheduler.testImplicitSchedulingPUT(request, calresource, "/calendars/users/user01/calendar/1.ics", calendarNew, False)) except: self.fail("Exception must not be raised") self.assertTrue(doAction) self.assertTrue(isScheduleObject)
def test_validation_noPreservePrivateComments(self): """ Test that attendee private comments are no longer restored. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z X-CALENDARSERVER-PRIVATE-COMMENT:My Comment END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName("test.ics", calendar) yield self.commit() data2 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z SUMMARY:Changed END:VEVENT END:VCALENDAR """ txn = self.transactionUnderTest() txn._authz_uid = "user01" calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar = Component.fromString(data2) yield calendar_resource.setComponent(calendar) yield self.commit() calendar_resource = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar1 = (yield calendar_resource.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertFalse("X-CALENDARSERVER-PRIVATE-COMMENT:My Comment" in calendar1) self.assertTrue("SUMMARY:Changed" in calendar1) yield self.commit()
def test_testImplicitSchedulingPUT_NoChangeScheduleState(self): """ Test that testImplicitSchedulingPUT will prevent attendees from changing the schedule object state. """ request = SimpleRequest(self.site, "PUT", "/calendar/1.ics") calresource = yield request.locateResource("/calendar/1.ics") self.assertEqual(calresource.isScheduleObject, None) calresource.isScheduleObject = False calendarOld = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z END:VEVENT END:VCALENDAR """) calendarNew = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 02":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calresource.exists = lambda : True calresource.iCalendarForUser = lambda request: succeed(calendarOld) scheduler = ImplicitScheduler() try: yield scheduler.testImplicitSchedulingPUT(request, calresource, "/calendars/users/user01/calendar/1.ics", calendarNew, False) except HTTPError: pass except: self.fail("HTTPError exception must be raised") else: self.fail("Exception must be raised") request._newStoreTransaction.abort()
def test_testImplicitSchedulingPUT_NoChangeScheduleState(self): """ Test that testImplicitSchedulingPUT will prevent attendees from changing the schedule object state. """ calendarOld = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z END:VEVENT END:VCALENDAR """) calendarNew = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 02":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """) calendar_collection = (yield self.calendarUnderTest(home="user01")) calresource = (yield calendar_collection.createCalendarObjectWithName( "1.ics", calendarOld )) calresource.isScheduleObject = False scheduler = ImplicitScheduler() try: yield scheduler.testImplicitSchedulingPUT(calendar_collection, calresource, calendarNew, False) except HTTPError: pass except: self.fail("HTTPError exception must be raised") else: self.fail("Exception must be raised")
def test_doCreateResource(self): """ Test that resource creation works. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar1 = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName("test.ics", calendar1) yield self.commit() calendar_resource1 = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar1 = (yield calendar_resource1.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue("urn:uuid:user01" in calendar1) self.assertTrue("urn:uuid:user02" in calendar1) self.assertTrue("CN=" in calendar1) yield self.commit()
def test_doCreateResource(self): """ Test that resource creation works. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """ calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar1 = Component.fromString(data1) yield calendar_collection.createCalendarObjectWithName("test.ics", calendar1) yield self.commit() calendar_resource1 = (yield self.calendarObjectUnderTest(name="test.ics", home="user01",)) calendar1 = (yield calendar_resource1.component()) calendar1 = str(calendar1).replace("\r\n ", "") self.assertTrue("urn:x-uid:user01" in calendar1) self.assertTrue("urn:x-uid:user02" in calendar1) self.assertTrue("CN=" in calendar1) yield self.commit()
def test_cancelAsAttendeeMultipleOccurrences(self): # Multiple meeting occurrences with no master, where purged CUA is # an attendee event = Component.fromString(INVITED_TO_MULTIPLE_OCCURRENCES_ICS) action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)), "urn:uuid:9DC04A71-E6DD-11DF-9492-0800200C9A66") self.assertEquals(action, PurgePrincipalService.CANCELEVENT_SHOULD_DELETE)
def test_validation_validAttendeeListSizeCheck(self): """ Test that resource with too many attendees are rejected. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """ self.patch(config, "MaxAttendeesPerInstance", 2) calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield self.failUnlessFailure(calendar_collection.createCalendarObjectWithName("test.ics", calendar), TooManyAttendeesError) yield self.commit()
def test_no_freebusy(self): data = """BEGIN:VCALENDAR VERSION:2.0 METHOD:REQUEST PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VFREEBUSY UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VFREEBUSY END:VCALENDAR """ scheduler = iMIPProcessing.FakeSchedule( LocalCalendarUser("mailto:[email protected]", None), Component.fromString(data) ) recipients = (RemoteCalendarUser("mailto:[email protected]"),) responses = ScheduleResponseQueue("REQUEST", responsecode.OK) delivery = ScheduleViaIMip(scheduler, recipients, responses, True) yield delivery.generateSchedulingResponses() self.assertEqual(len(responses.responses), 1) self.assertEqual(str(responses.responses[0].reqstatus), iTIPRequestStatus.SERVICE_UNAVAILABLE)
def test_no_freebusy(self): data = """BEGIN:VCALENDAR VERSION:2.0 METHOD:REQUEST PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VFREEBUSY UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VFREEBUSY END:VCALENDAR """ scheduler = iMIPProcessing.FakeSchedule(Component.fromString(data)) recipients = (RemoteCalendarUser("mailto:[email protected]"),) responses = ScheduleResponseQueue("REQUEST", responsecode.OK) delivery = ScheduleViaIMip(scheduler, recipients, responses, True) yield delivery.generateSchedulingResponses() self.assertEqual(len(responses.responses), 1) self.assertEqual(str(responses.responses[0].children[1]), iTIPRequestStatus.SERVICE_UNAVAILABLE)
def test_queueAttendeeUpdate_no_refresh(self): self.patch(config.Scheduling.Options, "AttendeeRefreshBatch", 5) calendar = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER:urn:uuid:user01 ATTENDEE:urn:uuid:user01 ATTENDEE:urn:uuid:user02 END:VEVENT END:VCALENDAR """) processor = FakeImplicitProcessor() processor.txn = "" processor.uid = "12345-67890" processor.recipient_calendar_resource = FakeResource() processor.recipient_calendar = calendar yield processor.queueAttendeeUpdate(( "urn:uuid:user02", "urn:uuid:user01", )) self.assertEqual(processor.batches, 0)
def populateOneObject(self, objectName, objectText): """ Populate one calendar object in the test user's calendar. @param objectName: The name of a calendar object. @type objectName: str @param objectText: Some iCalendar text to populate it with. @type objectText: str """ record = self.directoryService.recordWithShortName("users", "wsanchez") uid = record.uid # XXX there should be a more test-friendly way to ensure the directory # actually exists try: self.calendarCollection._newStore._path.createDirectory() except: pass txn = self.calendarCollection._newStore.newTransaction() home = yield txn.calendarHomeWithUID(uid, True) cal = yield home.calendarWithName("calendar") yield cal.createCalendarObjectWithName( objectName, VComponent.fromString(objectText) ) yield txn.commit()
def test_changeEventAttendeePreconditionFailed(self): """ If the attempt to accept an invitation fails because of an unmet precondition (412), the event is re-retrieved and the PUT is re-issued with the new data. """ clock = Clock() userNumber = 2 client = StubClient(userNumber, self.mktemp()) randomDelay = 3 calendarURL = '/some/calendar/' calendar = Calendar( caldavxml.calendar, set(('VEVENT',)), u'calendar', calendarURL, None) client._calendars[calendarURL] = calendar vevent = Component.fromString(INVITED_EVENT) event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._setEvent(event.url, event) accepter = Accepter(clock, self.sim, client, userNumber) accepter.setParameters(acceptDelayDistribution=Deterministic(randomDelay)) client.rescheduled.add(event.url) accepter.eventChanged(event.url) clock.advance(randomDelay)
def test_get_attachment_links(self): """ Test that action=get-attachment-links works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") cobj1 = yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) calobjID = cobj1.id() yield self.commitTransaction(0) object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") attachment, _ignore_location = yield object1.addAttachment(None, MimeType.fromString("text/plain"), "test.txt", MemoryStream("Here is some text.")) attID = attachment.id() managedID = attachment.managedID() yield self.commitTransaction(0) shared_object = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", calendar_name="shared-calendar", name="1.ics") links = yield shared_object.ownerHome().getAttachmentLinks() self.assertEqual(len(links), 1) self.assertTrue(isinstance(links[0], AttachmentLink)) self.assertEqual(links[0]._attachmentID, attID) self.assertEqual(links[0]._managedID, managedID) self.assertEqual(links[0]._calendarObjectID, calobjID) yield self.commitTransaction(1)
def test_remove_attachment(self): """ Test that action=remove-attachment works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") resourceID = object1.id() attachment, _ignore_location = yield object1.addAttachment(None, MimeType.fromString("text/plain"), "test.txt", MemoryStream("Here is some text.")) managedID = attachment.managedID() yield self.commitTransaction(0) shared_object = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", calendar_name="shared-calendar", name="1.ics") yield shared_object.removeAttachment(None, managedID) yield self.commitTransaction(1) cobjs = yield ManagedAttachment.referencesTo(self.theTransactionUnderTest(0), managedID) self.assertEqual(cobjs, set()) attachment = yield ManagedAttachment.load(self.theTransactionUnderTest(0), resourceID, managedID) self.assertTrue(attachment is None) yield self.commitTransaction(0)
def test_countobjects(self): """ Test that action=countobjects works. """ yield self.createShare("user01", "puser01") shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") count = yield shared.countObjectResources() self.assertEqual(count, 0) yield self.commitTransaction(1) calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) count = yield calendar1.countObjectResources() self.assertEqual(count, 1) yield self.commitTransaction(0) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") count = yield shared.countObjectResources() self.assertEqual(count, 1) yield self.commitTransaction(1) calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") yield object1.remove() count = yield calendar1.countObjectResources() self.assertEqual(count, 0) yield self.commitTransaction(0) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") count = yield shared.countObjectResources() self.assertEqual(count, 0) yield self.commitTransaction(1)
def test_freebusy(self): """ Test that action=component works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) fbstart = "{now:04d}0102T000000Z".format(**self.nowYear) fbend = "{now:04d}0103T000000Z".format(**self.nowYear) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") fbinfo = FreebusyQuery.FBInfo([], [], []) timerange = Period(DateTime.parseText(fbstart), DateTime.parseText(fbend)) organizer = recipient = (yield calendarUserFromCalendarUserAddress("mailto:[email protected]", self.theTransactionUnderTest(1))) freebusy = FreebusyQuery(organizer=organizer, recipient=recipient, timerange=timerange) matchtotal = (yield freebusy.generateFreeBusyInfo([shared, ], fbinfo)) self.assertEqual(matchtotal, 1) self.assertEqual(fbinfo[0], [Period.parseText("{now:04d}0102T140000Z/PT1H".format(**self.nowYear)), ]) self.assertEqual(len(fbinfo[1]), 0) self.assertEqual(len(fbinfo[2]), 0) yield self.commitTransaction(1)
def test_create(self): """ Test that action=create works. """ yield self.createShare("user01", "puser01") shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") resource = yield shared.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) resource_id = resource.id() self.assertTrue(resource is not None) self.assertEqual(resource.name(), "1.ics") self.assertEqual(resource.uid(), "uid1") self.assertFalse(resource._componentChanged) yield self.commitTransaction(1) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") resource = yield shared.objectResourceWithUID("uid1") self.assertTrue(resource is not None) self.assertEqual(resource.name(), "1.ics") self.assertEqual(resource.uid(), "uid1") self.assertEqual(resource.id(), resource_id) yield self.commitTransaction(1) object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") self.assertTrue(object1 is not None) self.assertEqual(object1.name(), "1.ics") self.assertEqual(object1.uid(), "uid1") self.assertEqual(object1.id(), resource_id) yield self.commitTransaction(0)
def calendar(self): """ Returns a calendar component derived from this element, which contains exactly one VEVENT with the VALARM embedded component, or C{None} if empty. """ valarm = str(self) return iComponent.fromString(self.calendartxt % str(self)) if valarm else None
def test_objectresource_remove(self): """ Test that a remote object resource L{component} works. """ home01 = yield self.homeUnderTest(txn=self.theTransactionUnderTest(0), name="user01", create=True) self.assertTrue(home01 is not None) calendar01 = yield home01.childWithName("calendar") yield calendar01.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") yield resource.remove() yield self.commitTransaction(1) resource01 = yield self.calendarObjectUnderTest( txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics", ) self.assertTrue(resource01 is None) yield self.commitTransaction(0) home = yield self._remoteHome(self.theTransactionUnderTest(1), "user01") self.assertTrue(home is not None) calendar = yield home.childWithName("calendar") resource = yield calendar.objectResourceWithName("1.ics") self.assertTrue(resource is None) yield self.commitTransaction(1)
def test_confidential(self): data = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN X-CALENDARSERVER-ACCESS:CONFIDENTIAL BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] DESCRIPTION:In confidence LOCATION:My office ORGANIZER;CN=User 01:mailto:[email protected] SUMMARY:Confidential END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") filtered = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN X-CALENDARSERVER-ACCESS:CONFIDENTIAL BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") for item in (data, Component.fromString(data),): self.assertEqual(str(PrivateEventFilter(Component.ACCESS_CONFIDENTIAL, True).filter(item)), data) self.assertEqual(str(PrivateEventFilter(Component.ACCESS_CONFIDENTIAL, False).filter(item)), filtered)
def parseCalendarData(self): """ Check the calendar data for valid iCalendar data. """ result = True message = "" try: component = Component.fromString(self.input.read()) # Do underlying iCalendar library validation with data fix fixed, unfixed = component._pycalendar.validate(doFix=True) if unfixed: raise InvalidICalendarDataError( "Calendar data had unfixable problems:\n %s" % ("\n ".join(unfixed), )) if fixed: print("Calendar data had fixable problems:\n %s" % ("\n ".join(fixed), )) except ValueError, e: result = False message = str(e) if message.startswith(errorPrefix): message = message[len(errorPrefix):]
def test_validation_validAccess_invalidValue(self): """ Test that resource access mode changes are rejected. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN X-CALENDARSERVER-ACCESS:BOGUS BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z END:VEVENT END:VCALENDAR """ self.patch(config, "EnablePrivateEvents", True) calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield self.failUnlessFailure( calendar_collection.createCalendarObjectWithName( "test.ics", calendar), InvalidCalendarAccessError) yield self.commit()
def test_cancelAllDayRepeating(self): # A repeating All Day event where purged CUA is organizer event = Component.fromString(REPEATING_2_ICS_BEFORE) action = PurgePrincipalService._cancelEvent(event, PyCalendarDateTime(2010, 12, 6, 12, 0, 0, PyCalendarTimezone(utc=True)), "urn:uuid:0F168477-CF3D-45D3-AE60-9875EA02C4D1") self.assertEquals(action, PurgePrincipalService.CANCELEVENT_MODIFIED) self.assertEquals(str(event), REPEATING_2_ICS_AFTER)
def test_ignoreAlreadyAccepting(self): """ If the client sees an event change a second time before responding to an invitation found on it during the first change notification, the second change notification does not generate another accept attempt. """ clock = Clock() randomDelay = 7 vevent = Component.fromString(INVITED_EVENT) attendees = tuple(vevent.mainComponent().properties('ATTENDEE')) userNumber = int(attendees[1].parameterValue('CN').split(None, 1)[1]) calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[calendarURL] = calendar event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._events[event.url] = event accepter = Accepter(clock, self.sim, client, userNumber) accepter.random = Deterministic() accepter.random.gauss = lambda mu, sigma: randomDelay accepter.eventChanged(event.url) accepter.eventChanged(event.url) clock.advance(randomDelay)
def test_queueAttendeeUpdate_with_refresh(self): self.patch(config.Scheduling.Options, "AttendeeRefreshBatch", 5) calendar = Component.fromString("""BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER:urn:uuid:user01 ATTENDEE:urn:uuid:user01 ATTENDEE:urn:uuid:user02 ATTENDEE:urn:uuid:user03 END:VEVENT END:VCALENDAR """) processor = FakeImplicitProcessor() processor.txn = "" processor.uid = "12345-67890" processor.recipient_calendar_resource = FakeResource() processor.recipient_calendar = calendar yield processor.queueAttendeeUpdate(("urn:uuid:user02", "urn:uuid:user01",)) self.assertEqual(processor.batches, 1)
def test_inboxReplyFailedDelete(self): """ When an inbox item that contains a reply is seen by the client, it deletes it immediately. If the delete fails, the appropriate response code is returned. """ userNumber = 1 clock = Clock() inboxURL = '/some/inbox/' vevent = Component.fromString(INBOX_REPLY) inbox = Calendar(caldavxml.schedule_inbox, set(), u'the inbox', inboxURL, None) client = StubClient(userNumber, self.mktemp()) client._calendars[inboxURL] = inbox inboxEvent = Event(client.serializeLocation(), inboxURL + u'4321.ics', None, vevent) client._setEvent(inboxEvent.url, inboxEvent) client._failDeleteWithObject( inboxEvent.url, IncorrectResponseCode( NO_CONTENT, Response(('HTTP', 1, 1), PRECONDITION_FAILED, 'Precondition Failed', None, None))) accepter = Accepter(clock, self.sim, client, userNumber) accepter.eventChanged(inboxEvent.url) clock.advance(3) self.assertNotIn(inboxEvent.url, client._events) self.assertNotIn('4321.ics', inbox.events)
def test_public(self): data = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN X-CALENDARSERVER-ACCESS:PUBLIC BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ORGANIZER;CN=User 01:mailto:[email protected] END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") for item in ( data, Component.fromString(data), ): self.assertEqual( str( PrivateEventFilter(Component.ACCESS_PUBLIC, True).filter(item)), data) self.assertEqual( str( PrivateEventFilter(Component.ACCESS_PUBLIC, False).filter(item)), data)
def test_changeEventAttendeePreconditionFailed(self): """ If the attempt to accept an invitation fails because of an unmet precondition (412), the event is re-retrieved and the PUT is re-issued with the new data. """ clock = Clock() userNumber = 2 client = StubClient(userNumber, self.mktemp()) randomDelay = 3 calendarURL = '/some/calendar/' calendar = Calendar(caldavxml.calendar, set(('VEVENT', )), u'calendar', calendarURL, None) client._calendars[calendarURL] = calendar vevent = Component.fromString(INVITED_EVENT) event = Event(client.serializeLocation(), calendarURL + u'1234.ics', None, vevent) client._setEvent(event.url, event) accepter = Accepter(clock, self.sim, client, userNumber) accepter.setParameters( acceptDelayDistribution=Deterministic(randomDelay)) client.rescheduled.add(event.url) accepter.eventChanged(event.url) clock.advance(randomDelay)
def test_vevent_other_component(self): data = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890 DTSTART:20080601T120000Z DTEND:20080601T130000Z ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ORGANIZER;CN=User 01:mailto:[email protected] END:VEVENT END:VCALENDAR """.replace("\n", "\r\n") result = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN END:VCALENDAR """.replace("\n", "\r\n") other_component = CalendarData( CalendarComponent(CalendarComponent(name="VTODO"), AllProperties(), name="VCALENDAR")) for item in ( data, Component.fromString(data), ): self.assertEqual( str(CalendarDataFilter(other_component).filter(item)), result)
def migrate(self, txn, mapIDsCallback): """ See L{ScheduleWork.migrate} """ # Try to find a mapping new_home, new_resource = yield mapIDsCallback(self.resourceID) # If we previously had a resource ID and now don't, then don't create work if self.resourceID is not None and new_resource is None: returnValue(False) if self.itipMsg: itipmsg = Component.fromString(self.itipMsg) # Insert new work - in paused state yield ScheduleOrganizerSendWork.schedule( txn, scheduleActionFromSQL[self.scheduleAction], new_home, new_resource, new_home.uid(), self.attendee, itipmsg, self.noRefresh, 0, pause=1) returnValue(True)
def test_validation_validAttendeeListSizeCheck(self): """ Test that resource with too many attendees are rejected. """ data1 = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CALENDARSERVER.ORG//NONSGML Version 1//EN BEGIN:VEVENT UID:12345-67890-attendee-reply DTSTAMP:20080601T120000Z DTSTART:20080601T120000Z DTEND:20080601T130000Z ORGANIZER;CN="User 01":mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] ATTENDEE:mailto:[email protected] END:VEVENT END:VCALENDAR """ self.patch(config, "MaxAttendeesPerInstance", 2) calendar_collection = (yield self.calendarUnderTest(home="user01")) calendar = Component.fromString(data1) yield self.failUnlessFailure( calendar_collection.createCalendarObjectWithName( "test.ics", calendar), TooManyAttendeesError) yield self.commit()
def test_search(self): """ Test that action=resourcenameforuid works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) filter = caldavxml.Filter( caldavxml.ComponentFilter( *[caldavxml.ComponentFilter( **{"name": ("VEVENT", "VFREEBUSY", "VAVAILABILITY")} )], **{"name": "VCALENDAR"} ) ) filter = Filter(filter) calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") names = [item[0] for item in (yield calendar1.search(filter))] self.assertEqual(names, ["1.ics", ]) yield self.commitTransaction(0) shared = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", name="shared-calendar") names = [item[0] for item in (yield shared.search(filter))] self.assertEqual(names, ["1.ics", ]) yield self.commitTransaction(1)
def test_update_attachment(self): """ Test that action=update-attachment works. """ yield self.createShare("user01", "puser01") calendar1 = yield self.calendarUnderTest(txn=self.theTransactionUnderTest(0), home="user01", name="calendar") yield calendar1.createCalendarObjectWithName("1.ics", Component.fromString(self.caldata1)) yield self.commitTransaction(0) object1 = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(0), home="user01", calendar_name="calendar", name="1.ics") resourceID = object1.id() attachment, _ignore_location = yield object1.addAttachment(None, MimeType.fromString("text/plain"), "test.txt", MemoryStream("Here is some text.")) managedID = attachment.managedID() yield self.commitTransaction(0) shared_object = yield self.calendarObjectUnderTest(txn=self.theTransactionUnderTest(1), home="puser01", calendar_name="shared-calendar", name="1.ics") data = "Here is some more text." attachment, location = yield shared_object.updateAttachment(managedID, MimeType.fromString("text/plain"), "test.txt", MemoryStream(data)) managedID = attachment.managedID() from txdav.caldav.datastore.sql_external import ManagedAttachmentExternal self.assertTrue(isinstance(attachment, ManagedAttachmentExternal)) self.assertEqual(attachment.size(), len(data)) self.assertTrue("user01/dropbox/" in location) yield self.commitTransaction(1) cobjs = yield ManagedAttachment.referencesTo(self.theTransactionUnderTest(0), managedID) self.assertEqual(cobjs, set((resourceID,))) attachment = yield ManagedAttachment.load(self.transactionUnderTest(), resourceID, managedID) self.assertEqual(attachment.name(), "test.txt") data = yield self.attachmentToString(attachment) self.assertEqual(data, "Here is some more text.") yield self.commitTransaction(0)
def doWork(self): calendar = Component.fromString(self.icalendarText) try: yield injectMessage(self.transaction, self.organizer, self.attendee, calendar) except: log.error("Unable to process reply")