def test_oneEventCalendar(self): """ Exporting an calendar with one event in it will result in just that event. """ yield populateCalendarsFrom( { "user01": { "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("user01")) .calendarWithName("calendar1")], io ) self.assertEquals(Component.fromString(io.getvalue()), expected)
def createConflicted(self, c1=None, c2=None): """ Create two calendar homes with calendars with the same names within them. Parameters are both a mapping of calendar object names to 2-tuples of (iCalendar data, metadata). @param c1: the calendar data for conflict1/conflicted/* @param c2: the calendar data for conflict2/conflicted/* """ if c1 is None: c1 = {"1.ics": self.sampleEvent("uid1")} if c2 is None: c2 = {"2.ics": self.sampleEvent("uid2")} defaults = {"calendar": {}, "inbox": {}, "tasks": {}, "polls": {}} def conflicted(caldata): d = defaults.copy() d.update(conflicted=caldata) return d yield populateCalendarsFrom( { "conflict1": conflicted(c1), "conflict2": conflicted(c2), }, self.storeUnderTest())
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( { "user01": { "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("user01") ).calendarWithName("calendar1")], io) self.assertEquals(Component.fromString(io.getvalue()), expected)
def test_migrateEmptyHome(self): """ Migrating an empty home into an existing home should destroy all the existing home's calendars. """ yield populateCalendarsFrom({ "empty_home": { # Some of the upgrade logic will ensure that sufficient default # calendars exist for basic usage, so this home is actually only # *mostly* empty; the important thing is that the default # calendar is removed. "other-default-calendar": {} }, "non_empty_home": { "calendar": {}, "inbox": {}, # XXX: implementation is configuration-sensitive regarding the # 'tasks' calendar and it shouldn't be. "tasks": {}, "polls": {}, } }, self.storeUnderTest()) txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") self.assertIdentical((yield emptyHome.calendarWithName("calendar")), None) nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") yield migrateHome(emptyHome, nonEmpty) yield self.commit() txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") self.assertIdentical((yield nonEmpty.calendarWithName("calendar")), None) self.assertNotIdentical((yield nonEmpty.calendarWithName("inbox")), None) self.assertNotIdentical((yield nonEmpty.calendarWithName("other-default-calendar")), None)
def test_exportAll(self): """ Run the export with --all to get a directory of calendars from all calendar homes in the database. """ yield populateCalendarsFrom( { "user01": { "calendar1": { "valentines-day.ics": (valentines, {}), "new-years-day.ics": (newYears, {}) } }, "user02": { "calendar1": { "valentines-day.ics": (valentines, {}) }, "calendar2": { "new-years-day.ics": (newYears, {}) } } }, self.store) outputDir = FilePath(self.mktemp()) outputDir.makedirs() main([ 'calendarserver_export', '--directory', outputDir.path, '--all' ], reactor=self) yield self.waitToStop self.assertEquals( set([ "user01_calendar1.ics", "user02_calendar1.ics", "user02_calendar2.ics" ]), set([child.basename() for child in outputDir.children()]))
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_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 setUp(self): """ Set up two stores to migrate between. """ # Add some files to the file store. self.filesPath = CachingFilePath(self.mktemp()) self.filesPath.createDirectory() fileStore = self.fileStore = CommonDataStore( self.filesPath, {"push": StubNotifierFactory()}, TestStoreDirectoryService(), True, True ) self.sqlStore = yield theStoreBuilder.buildStore( self, StubNotifierFactory() ) self.upgrader = UpgradeToDatabaseStep(self.fileStore, self.sqlStore) requirements = CommonTests.requirements extras = deriveValue(self, "extraRequirements", lambda t: {}) requirements = self.mergeRequirements(requirements, extras) yield populateCalendarsFrom(requirements, fileStore) md5s = CommonTests.md5s yield resetCalendarMD5s(md5s, fileStore) self.filesPath.child("calendars").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data") requirements = ABCommonTests.requirements yield populateAddressBooksFrom(requirements, fileStore) md5s = ABCommonTests.md5s yield resetAddressBookMD5s(md5s, fileStore) self.filesPath.child("addressbooks").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra 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 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 setUp(self): """ Set up two stores to migrate between. """ # Add some files to the file store. self.filesPath = CachingFilePath(self.mktemp()) self.filesPath.createDirectory() fileStore = self.fileStore = CommonDataStore( self.filesPath, {"push": StubNotifierFactory()}, TestStoreDirectoryService(), True, True ) self.sqlStore = yield theStoreBuilder.buildStore( self, StubNotifierFactory() ) self.upgrader = UpgradeToDatabaseStep(self.fileStore, self.sqlStore) requirements = CommonTests.requirements extras = deriveValue(self, "extraRequirements", lambda t: {}) requirements = self.mergeRequirements(requirements, extras) yield populateCalendarsFrom(requirements, fileStore) md5s = CommonTests.md5s yield resetCalendarMD5s(md5s, fileStore) self.filesPath.child("calendars").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data") requirements = ABCommonTests.requirements yield populateAddressBooksFrom(requirements, fileStore) md5s = ABCommonTests.md5s yield resetAddressBookMD5s(md5s, fileStore) self.filesPath.child("addressbooks").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data") # Add some properties we want to check get migrated over txn = self.fileStore.newTransaction() home = yield txn.calendarHomeWithUID("home_defaults") cal = yield home.calendarWithName("calendar_1") props = cal.properties() props[PropertyName.fromElement(caldavxml.SupportedCalendarComponentSet)] = caldavxml.SupportedCalendarComponentSet( caldavxml.CalendarComponent(name="VEVENT"), caldavxml.CalendarComponent(name="VTODO"), ) props[PropertyName.fromElement(element.ResourceType)] = element.ResourceType( element.Collection(), caldavxml.Calendar(), ) props[PropertyName.fromElement(customxml.GETCTag)] = customxml.GETCTag.fromString("foobar") inbox = yield home.calendarWithName("inbox") props = inbox.properties() props[PropertyName.fromElement(customxml.CalendarAvailability)] = customxml.CalendarAvailability.fromString(str(self.av1)) props[PropertyName.fromElement(caldavxml.ScheduleDefaultCalendarURL)] = caldavxml.ScheduleDefaultCalendarURL( element.HRef.fromString("/calendars/__uids__/home_defaults/calendar_1"), ) yield txn.commit()
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 setUp(self): """ Set up two stores to migrate between. """ # Add some files to the file store. self.filesPath = CachingFilePath(self.mktemp()) self.filesPath.createDirectory() fileStore = self.fileStore = CommonDataStore( self.filesPath, StubNotifierFactory(), True, True ) self.sqlStore = yield theStoreBuilder.buildStore( self, StubNotifierFactory() ) subStarted = self.subStarted = Deferred() class StubService(Service, object): def startService(self): super(StubService, self).startService() if not subStarted.called: subStarted.callback(None) from twisted.python import log def justOnce(evt): if evt.get('isError') and not hasattr(subStarted, 'result'): subStarted.errback( evt.get('failure', RuntimeError("error starting up (see log)")) ) log.addObserver(justOnce) def cleanObserver(): try: log.removeObserver(justOnce) except ValueError: pass # x not in list, I don't care. self.addCleanup(cleanObserver) self.stubService = StubService() self.topService = MultiService() self.upgrader = self.createUpgradeService() self.upgrader.setServiceParent(self.topService) requirements = CommonTests.requirements extras = deriveValue(self, "extraRequirements", lambda t: {}) requirements = self.mergeRequirements(requirements, extras) yield populateCalendarsFrom(requirements, fileStore) md5s = CommonTests.md5s yield resetCalendarMD5s(md5s, fileStore) self.filesPath.child("calendars").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data") requirements = ABCommonTests.requirements yield populateAddressBooksFrom(requirements, fileStore) md5s = ABCommonTests.md5s yield resetAddressBookMD5s(md5s, fileStore) self.filesPath.child("addressbooks").child( "__uids__").child("ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data")
def populate(self): yield populateCalendarsFrom(self.requirements, self.storeUnderTest()) self.notifierFactory.reset() txn = self._sqlCalendarStore.newTransaction() Delete( From=schema.ATTACHMENT, Where=None ).on(txn) (yield txn.commit())
def test_mailto(self): """ Verify the conversion of non-mailto: CUAs to mailto: CUAs """ yield populateCalendarsFrom( {"user01": { "calendar1": { "peruser.ics": (dataWithUIDs, {}), } }}, self.store) io = StringIO() yield exportToFile([(yield self.txn().calendarHomeWithUID("user01") ).calendarWithName("calendar1")], io, convertToMailto=True) self.assertEquals(Component.fromString(resultWithMailtos), Component.fromString(io.getvalue()))
def test_onlyOneVTIMEZONE(self): """ C{VTIMEZONE} subcomponents with matching TZIDs in multiple event calendar objects should only be rendered in the resulting output once. (Note that the code to suppor this is actually in PyCalendar, not the export tool itself.) """ yield populateCalendarsFrom( { "user01": { "calendar1": { "1.ics": (one, {}), # EST "2.ics": (another, {}), # EST "3.ics": (third, {}) # PST } } }, self.store ) io = StringIO() yield exportToFile( [(yield self.txn().calendarHomeWithUID("user01")) .calendarWithName("calendar1")], io ) result = Component.fromString(io.getvalue()) def filtered(name): for c in result.subcomponents(): if c.name() == name: yield c timezones = list(filtered("VTIMEZONE")) events = list(filtered("VEVENT")) # Sanity check to make sure we picked up all three events: self.assertEquals(len(events), 3) self.assertEquals(len(timezones), 2) self.assertEquals(set([tz.propertyValue("TZID") for tz in timezones]), # Use an intentionally wrong TZID in order to make # sure we don't depend on caching effects elsewhere. set(["America/New_Yrok", "US/Pacific"]))
def test_onlyOneVTIMEZONE(self): """ C{VTIMEZONE} subcomponents with matching TZIDs in multiple event calendar objects should only be rendered in the resulting output once. (Note that the code to suppor this is actually in PyCalendar, not the export tool itself.) """ yield populateCalendarsFrom( { "home1": { "calendar1": { "1.ics": (one, {}), # EST "2.ics": (another, {}), # EST "3.ics": (third, {}) # PST } } }, self.store ) io = StringIO() yield exportToFile( [(yield self.txn().calendarHomeWithUID("home1")) .calendarWithName("calendar1")], io ) result = Component.fromString(io.getvalue()) def filtered(name): for c in result.subcomponents(): if c.name() == name: yield c timezones = list(filtered("VTIMEZONE")) events = list(filtered("VEVENT")) # Sanity check to make sure we picked up all three events: self.assertEquals(len(events), 3) self.assertEquals(len(timezones), 2) self.assertEquals(set([tz.propertyValue("TZID") for tz in timezones]), # Use an intentionally wrong TZID in order to make # sure we don't depend on caching effects elsewhere. set(["America/New_Yrok", "US/Pacific"]))
def test_perUserFiltering(self): """ L{exportToFile} performs per-user component filtering based on the owner of that calendar. """ yield populateCalendarsFrom( { "user02": { "calendar1": { "peruser.ics": (dataForTwoUsers, {}), # EST } } }, self.store) io = StringIO() yield exportToFile([(yield self.txn().calendarHomeWithUID("user02") ).calendarWithName("calendar1")], io) self.assertEquals(Component.fromString(resultForUser2), Component.fromString(io.getvalue()))
def test_migrateMergeDontDeleteDefault(self): """ If we're doing a merge migration, it's quite possible that the user has scheduled events onto their default calendar already. In fact the whole point of a merge migration is to preserve data that might have been created there. So, let's make sure that we I{don't} delete any data from the default calendars in the case that we're merging. """ yield populateCalendarsFrom( { "empty_home": { # see test_migrateEmptyHome above. "other-default-calendar": {} }, "non_empty_home": { "calendar": { "some-name": self.sampleEvent("some-uid", "some summary"), }, "inbox": {}, "tasks": {} } }, self.storeUnderTest()) txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") self.assertIdentical((yield emptyHome.calendarWithName("calendar")), None) nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") yield migrateHome(emptyHome, nonEmpty, merge=True) yield self.commit() txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") self.assertNotIdentical((yield nonEmpty.calendarWithName("inbox")), None) defaultCal = (yield nonEmpty.calendarWithName("calendar")) self.assertNotIdentical( (yield defaultCal.calendarObjectWithName("some-name")), None)
def test_perUserFiltering(self): """ L{exportToFile} performs per-user component filtering based on the owner of that calendar. """ yield populateCalendarsFrom( { "user02": { "calendar1": { "peruser.ics": (dataForTwoUsers, {}), # EST } } }, self.store ) io = StringIO() yield exportToFile( [(yield self.txn().calendarHomeWithUID("user02")) .calendarWithName("calendar1")], io ) self.assertEquals( Component.fromString(resultForUser2), Component.fromString(io.getvalue()) )
def populate(self): populateTxn = self.storeUnderTest().newTransaction() addressookRequirements = self.requirements["addressbook"] for homeUID in addressookRequirements: addressbooks = addressookRequirements[homeUID] if addressbooks is not None: home = yield populateTxn.addressbookHomeWithUID(homeUID, True) addressbook = home.addressbook() addressbookObjNames = addressbooks[addressbook.name()] if addressbookObjNames is not None: for objectName in addressbookObjNames: objData = addressbookObjNames[objectName] yield addressbook.createAddressBookObjectWithName( objectName, VCard.fromString(objData) ) yield populateTxn.commit() calendarRequirements = self.requirements["calendar"] yield populateCalendarsFrom(calendarRequirements, self.storeUnderTest()) self.notifierFactory.reset()
def createConflicted(self, c1=None, c2=None): """ Create two calendar homes with calendars with the same names within them. Parameters are both a mapping of calendar object names to 2-tuples of (iCalendar data, metadata). @param c1: the calendar data for conflict1/conflicted/* @param c2: the calendar data for conflict2/conflicted/* """ if c1 is None: c1 = {"1.ics": self.sampleEvent("uid1")} if c2 is None: c2 = {"2.ics": self.sampleEvent("uid2")} defaults = {"calendar": {}, "inbox": {}, "tasks": {}, "polls": {}} def conflicted(caldata): d = defaults.copy() d.update(conflicted=caldata) return d yield populateCalendarsFrom({ "conflict1": conflicted(c1), "conflict2": conflicted(c2), }, self.storeUnderTest())
def populate(self): populateTxn = self.storeUnderTest().newTransaction() addressookRequirements = self.requirements["addressbook"] for homeUID in addressookRequirements: addressbooks = addressookRequirements[homeUID] if addressbooks is not None: home = yield populateTxn.addressbookHomeWithUID(homeUID, True) addressbook = home.addressbook() addressbookObjNames = addressbooks[addressbook.name()] if addressbookObjNames is not None: for objectName in addressbookObjNames: objData = addressbookObjNames[objectName] yield addressbook.createAddressBookObjectWithName( objectName, VCard.fromString(objData)) yield populateTxn.commit() calendarRequirements = self.requirements["calendar"] yield populateCalendarsFrom(calendarRequirements, self.storeUnderTest()) self.notifierFactory.reset()
def test_migrateMergeDontDeleteDefault(self): """ If we're doing a merge migration, it's quite possible that the user has scheduled events onto their default calendar already. In fact the whole point of a merge migration is to preserve data that might have been created there. So, let's make sure that we I{don't} delete any data from the default calendars in the case that we're merging. """ yield populateCalendarsFrom({ "empty_home": { # see test_migrateEmptyHome above. "other-default-calendar": {} }, "non_empty_home": { "calendar": { "some-name": self.sampleEvent("some-uid", "some summary"), }, "inbox": {}, "tasks": {} } }, self.storeUnderTest()) txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") self.assertIdentical((yield emptyHome.calendarWithName("calendar")), None) nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") yield migrateHome(emptyHome, nonEmpty, merge=True) yield self.commit() txn = self.transactionUnderTest() emptyHome = yield txn.calendarHomeWithUID("empty_home") nonEmpty = yield txn.calendarHomeWithUID("non_empty_home") self.assertNotIdentical( (yield nonEmpty.calendarWithName("inbox")), None ) defaultCal = (yield nonEmpty.calendarWithName("calendar")) self.assertNotIdentical( (yield defaultCal.calendarObjectWithName("some-name")), None )
def populate(self): yield populateCalendarsFrom(self.requirements, self.storeUnderTest()) self.notifierFactory.reset()
def populate(self): yield populateCalendarsFrom(self.requirements, self.storeUnderTest()) yield populateAddressBooksFrom(self.requirements, self.storeUnderTest())
def populate(self): # Need to bypass normal validation inside the store yield populateCalendarsFrom(self.requirements, self.storeUnderTest()) self.notifierFactory.reset()
def populate(self): yield populateCalendarsFrom(self.requirements0, self.theStoreUnderTest(0)) yield populateCalendarsFrom(self.requirements1, self.theStoreUnderTest(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) 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())) @inlineCallbacks def test_exportAll(self): """ Run the export with --all to get a directory of calendars from all calendar homes in the database. """ yield populateCalendarsFrom( { "user01": { "calendar1": { "valentines-day.ics": (valentines, {}), "new-years-day.ics": (newYears, {}) } }, "user02": { "calendar1": { "valentines-day.ics": (valentines, {}) }, "calendar2": { "new-years-day.ics": (newYears, {}) } } }, self.store) outputDir = FilePath(self.mktemp()) outputDir.makedirs() main([ 'calendarserver_export', '--directory', outputDir.path, '--all' ], reactor=self) yield self.waitToStop self.assertEquals( set([ "user01_calendar1.ics", "user02_calendar1.ics", "user02_calendar2.ics" ]), set([child.basename() for child in outputDir.children()]))
def test_exportMixAndMatch(self): """ Run the export with some calendars and some addressbooks """ yield populateAddressBooksFrom( { "user01": { "addressbook": { "1.vcf": adbk1Root.child("1.vcf").getContent(), "2.vcf": adbk1Root.child("2.vcf").getContent(), "3.vcf": adbk1Root.child("3.vcf").getContent(), } }, "user02": { "addressbook": { "1.vcf": adbk1Root.child("1.vcf").getContent(), }, } }, self.store) yield populateCalendarsFrom( { "user01": { "calendar1": { "valentines-day.ics": (valentines, {}), "new-years-day.ics": (newYears, {}) } }, "user02": { "calendar1": { "valentines-day.ics": (valentines, {}) }, "calendar2": { "new-years-day.ics": (newYears, {}) } } }, self.store) outputDir = FilePath(self.mktemp()) outputDir.makedirs() main([ 'calendarserver_export', '--directory', outputDir.path, '--uid', 'user01', '--contacts', '--uid', 'user01', '--calendars', '--uid', 'user02', '--collection=calendar1', '--uid', 'user02', '--contacts', ], reactor=self) yield self.waitToStop self.assertEquals( set([ "user01_addressbook.vcf", "user01_calendar1.ics", "user02_calendar1.ics", "user02_addressbook.vcf" ]), set([child.basename() for child in outputDir.children()]))
def setUp(self): """ Set up two stores to migrate between. """ yield super(HomeMigrationTests, self).setUp() yield self.buildStoreAndDirectory(extraUids=( u"home1", u"home2", u"home3", u"home_defaults", u"home_no_splits", u"home_splits", u"home_splits_shared", )) self.sqlStore = self.store # Add some files to the file store. self.filesPath = CachingFilePath(self.mktemp()) self.filesPath.createDirectory() fileStore = self.fileStore = CommonDataStore( self.filesPath, {"push": StubNotifierFactory()}, self.directory, True, True) self.upgrader = UpgradeToDatabaseStep(self.fileStore, self.sqlStore) requirements = CommonTests.requirements extras = deriveValue(self, "extraRequirements", lambda t: {}) requirements = self.mergeRequirements(requirements, extras) yield populateCalendarsFrom(requirements, fileStore) md5s = CommonTests.md5s yield resetCalendarMD5s(md5s, fileStore) self.filesPath.child("calendars").child("__uids__").child("ho").child( "me").child("home1").child(".some-extra-data").setContent( "some extra data") requirements = ABCommonTests.requirements yield populateAddressBooksFrom(requirements, fileStore) md5s = ABCommonTests.md5s yield resetAddressBookMD5s(md5s, fileStore) self.filesPath.child("addressbooks").child("__uids__").child( "ho").child("me").child("home1").child( ".some-extra-data").setContent("some extra data") # Add some properties we want to check get migrated over txn = self.fileStore.newTransaction() home = yield txn.calendarHomeWithUID("home_defaults") cal = yield home.calendarWithName("calendar_1") props = cal.properties() props[PropertyName.fromElement( caldavxml.SupportedCalendarComponentSet )] = caldavxml.SupportedCalendarComponentSet( caldavxml.CalendarComponent(name="VEVENT"), caldavxml.CalendarComponent(name="VTODO"), ) props[PropertyName.fromElement( element.ResourceType)] = element.ResourceType( element.Collection(), caldavxml.Calendar(), ) props[PropertyName.fromElement( customxml.GETCTag)] = customxml.GETCTag.fromString("foobar") inbox = yield home.calendarWithName("inbox") props = inbox.properties() props[PropertyName.fromElement( customxml.CalendarAvailability )] = customxml.CalendarAvailability.fromString(str(self.av1)) props[PropertyName.fromElement( caldavxml.ScheduleDefaultCalendarURL )] = caldavxml.ScheduleDefaultCalendarURL( element.HRef.fromString( "/calendars/__uids__/home_defaults/calendar_1"), ) yield txn.commit()