[CalendarServer-changes] [13683] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Jun 24 19:26:01 PDT 2014


Revision: 13683
          http://trac.calendarserver.org//changeset/13683
Author:   sagen at apple.com
Date:     2014-06-24 19:26:01 -0700 (Tue, 24 Jun 2014)
Log Message:
-----------
Groups' disappearance from the directory affects their extant value

Modified Paths:
--------------
    CalendarServer/trunk/calendarserver/tools/principals.py
    CalendarServer/trunk/calendarserver/tools/test/deprovision/caldavd.plist
    CalendarServer/trunk/calendarserver/tools/test/gateway/caldavd.plist
    CalendarServer/trunk/calendarserver/tools/test/principals/caldavd.plist
    CalendarServer/trunk/conf/resources/caldavd-resources.plist
    CalendarServer/trunk/txdav/caldav/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/who/delegates.py
    CalendarServer/trunk/txdav/who/groups.py
    CalendarServer/trunk/txdav/who/test/test_delegates.py
    CalendarServer/trunk/txdav/who/test/test_group_attendees.py
    CalendarServer/trunk/txdav/who/test/test_groups.py
    CalendarServer/trunk/txdav/who/util.py

Modified: CalendarServer/trunk/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/principals.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/calendarserver/tools/principals.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -787,7 +787,9 @@
     txn = store.newTransaction()
     groupUIDs = yield txn.allGroupDelegates()
     for groupUID in groupUIDs:
-        groupID, name, _ignore_membershipHash, modified = yield txn.groupByUID(
+        (
+            groupID, name, _ignore_membershipHash, modified, extant
+        ) = yield txn.groupByUID(
             groupUID
         )
         print("Group: \"{name}\" ({uid})".format(name=name, uid=groupUID))

Modified: CalendarServer/trunk/calendarserver/tools/test/deprovision/caldavd.plist
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/deprovision/caldavd.plist	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/calendarserver/tools/test/deprovision/caldavd.plist	2014-06-25 02:26:01 UTC (rev 13683)
@@ -115,12 +115,6 @@
     <key>MaxAttendeesPerInstance</key>
     <integer>100</integer>
 
-    <!-- Maximum number of instances allowed for a single RRULE -->
-    <!-- 0 for no limit -->
-    <key>MaxInstancesForRRULE</key>
-    <integer>400</integer>
-
-
     <!--
         Directory service
 
@@ -135,7 +129,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFile</key>
@@ -155,7 +149,7 @@
       <true/>
       <key>type</key>
       <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFile</key>
@@ -167,14 +161,14 @@
         </array>
       </dict>
     </dict>
-    
+
     <!-- Open Directory Service (Mac OS X) -->
     <!--
     <key>DirectoryService</key>
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.appleopendirectory.OpenDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>node</key>
@@ -198,7 +192,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFiles</key>
@@ -207,14 +201,14 @@
         </array>
       </dict>
     </dict>
-    
+
     <!-- Sqlite Augment Service -->
     <!--
     <key>AugmentService</key>
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>dbpath</key>
@@ -229,7 +223,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentPostgreSQLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>host</key>
@@ -245,7 +239,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.calendaruserproxy.ProxySqliteDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>dbpath</key>
@@ -259,7 +253,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.calendaruserproxy.ProxyPostgreSQLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>host</key>
@@ -687,7 +681,7 @@
     <!-- Support for Content-Encoding compression options as specified in RFC2616 Section 3.5 -->
     <key>ResponseCompression</key>
     <false/>
-    
+
     <!-- The retry-after value (in seconds) to return with a 503 error. -->
     <key>HTTPRetryAfter</key>
     <integer>180</integer>

Modified: CalendarServer/trunk/calendarserver/tools/test/gateway/caldavd.plist
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/gateway/caldavd.plist	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/calendarserver/tools/test/gateway/caldavd.plist	2014-06-25 02:26:01 UTC (rev 13683)
@@ -127,12 +127,6 @@
     <key>MaxAttendeesPerInstance</key>
     <integer>100</integer>
 
-    <!-- Maximum number of instances allowed for a single RRULE -->
-    <!-- 0 for no limit -->
-    <key>MaxInstancesForRRULE</key>
-    <integer>400</integer>
-
-
     <!--
         Directory service
 

Modified: CalendarServer/trunk/calendarserver/tools/test/principals/caldavd.plist
===================================================================
--- CalendarServer/trunk/calendarserver/tools/test/principals/caldavd.plist	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/calendarserver/tools/test/principals/caldavd.plist	2014-06-25 02:26:01 UTC (rev 13683)
@@ -119,12 +119,6 @@
     <key>MaxAttendeesPerInstance</key>
     <integer>100</integer>
 
-    <!-- Maximum number of instances allowed for a single RRULE -->
-    <!-- 0 for no limit -->
-    <key>MaxInstancesForRRULE</key>
-    <integer>400</integer>
-
-
     <!--
         Directory service
 

Modified: CalendarServer/trunk/conf/resources/caldavd-resources.plist
===================================================================
--- CalendarServer/trunk/conf/resources/caldavd-resources.plist	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/conf/resources/caldavd-resources.plist	2014-06-25 02:26:01 UTC (rev 13683)
@@ -99,12 +99,6 @@
     <key>MaxAttendeesPerInstance</key>
     <integer>100</integer>
 
-    <!-- Maximum number of instances allowed for a single RRULE -->
-    <!-- 0 for no limit -->
-    <key>MaxInstancesForRRULE</key>
-    <integer>400</integer>
-
-
     <!--
         Directory service
 
@@ -119,7 +113,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFile</key>
@@ -131,14 +125,14 @@
         </array>
       </dict>
     </dict>
-    
+
     <key>ResourceService</key>
     <dict>
       <key>Enabled</key>
       <true/>
       <key>type</key>
       <string>twistedcaldav.directory.xmlfile.XMLDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFile</key>
@@ -150,14 +144,14 @@
         </array>
       </dict>
     </dict>
-    
+
     <!-- Open Directory Service (Mac OS X) -->
     <!--
     <key>DirectoryService</key>
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.appleopendirectory.OpenDirectoryService</string>
-      
+
       <key>params</key>
       <dict>
         <key>node</key>
@@ -181,7 +175,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentXMLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>xmlFiles</key>
@@ -190,14 +184,14 @@
         </array>
       </dict>
     </dict>
-    
+
     <!-- Sqlite Augment Service -->
     <!--
     <key>AugmentService</key>
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentSqliteDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>dbpath</key>
@@ -212,7 +206,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.augment.AugmentPostgreSQLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>host</key>
@@ -228,7 +222,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.calendaruserproxy.ProxySqliteDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>dbpath</key>
@@ -242,7 +236,7 @@
     <dict>
       <key>type</key>
       <string>twistedcaldav.directory.calendaruserproxy.ProxyPostgreSQLDB</string>
-      
+
       <key>params</key>
       <dict>
         <key>host</key>
@@ -672,7 +666,7 @@
     <!-- Support for Content-Encoding compression -->
     <key>ResponseCompression</key>
     <false/>
-    
+
     <!-- The retry-after value (in seconds) to return with a 503 error. -->
     <key>HTTPRetryAfter</key>
     <integer>180</integer>

Modified: CalendarServer/trunk/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/sql.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/caldav/datastore/sql.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -1996,7 +1996,10 @@
                 groupUID = groupRecord.uid
             else:
                 groupUID = uidFromCalendarUserAddress(groupCUA)
-            groupID, _ignore_name, membershipHash, _ignore_modDate = yield self._txn.groupByUID(groupUID)
+            (
+                groupID, _ignore_name, membershipHash, _ignore_modDate,
+                _ignore_extant
+            ) = yield self._txn.groupByUID(groupUID)
 
             if groupID in groupIDToMembershipHashMap:
                 if groupIDToMembershipHashMap[groupID] != membershipHash:

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -1033,8 +1033,8 @@
             {
                 gr.MEMBERSHIP_HASH: Parameter("membershipHash"),
                 gr.NAME: Parameter("name"),
-                gr.MODIFIED:
-                Parameter("timestamp")
+                gr.MODIFIED: Parameter("timestamp"),
+                gr.EXTANT: Parameter("extant"),
             },
             Where=(gr.GROUP_UID == Parameter("groupUID"))
         )
@@ -1044,7 +1044,7 @@
     def _groupByUID(cls):
         gr = schema.GROUPS
         return Select(
-            [gr.GROUP_ID, gr.NAME, gr.MEMBERSHIP_HASH, gr.MODIFIED],
+            [gr.GROUP_ID, gr.NAME, gr.MEMBERSHIP_HASH, gr.MODIFIED, gr.EXTANT],
             From=gr,
             Where=(gr.GROUP_UID == Parameter("groupUID"))
         )
@@ -1054,7 +1054,7 @@
     def _groupByID(cls):
         gr = schema.GROUPS
         return Select(
-            [gr.GROUP_UID, gr.NAME, gr.MEMBERSHIP_HASH],
+            [gr.GROUP_UID, gr.NAME, gr.MEMBERSHIP_HASH, gr.EXTANT],
             From=gr,
             Where=(gr.GROUP_ID == Parameter("groupID"))
         )
@@ -1083,11 +1083,12 @@
         )
 
 
-    def updateGroup(self, groupUID, name, membershipHash):
+    def updateGroup(self, groupUID, name, membershipHash, extant=True):
         """
         @type groupUID: C{unicode}
         @type name: C{unicode}
         @type membershipHash: C{str}
+        @type extant: C{boolean}
         """
         timestamp = datetime.datetime.utcnow()
         return self._updateGroupQuery.on(
@@ -1095,7 +1096,8 @@
             name=name.encode("utf-8"),
             groupUID=groupUID.encode("utf-8"),
             timestamp=timestamp,
-            membershipHash=membershipHash
+            membershipHash=membershipHash,
+            extant=(1 if extant else 0)
         )
 
 
@@ -1107,7 +1109,8 @@
         @type groupUID: C{unicode}
 
         @return: Deferred firing with tuple of group ID C{str}, group name
-            C{unicode}, membership hash C{str}, and modified timestamp
+            C{unicode}, membership hash C{str}, modified timestamp, and
+            extant C{boolean}
         """
         results = (
             yield self._groupByUID.on(
@@ -1120,6 +1123,7 @@
                 results[0][1].decode("utf-8"),  # name
                 results[0][2],  # membership hash
                 results[0][3],  # modified timestamp
+                bool(results[0][4]),  # extant
             ))
         elif create:
             savepoint = SavepointAction("groupByUID")
@@ -1139,6 +1143,7 @@
                         results[0][1].decode("utf-8"),  # name
                         results[0][2],  # membership hash
                         results[0][3],  # modified timestamp
+                        bool(results[0][4]),  # extant
                     ))
                 else:
                     raise
@@ -1155,11 +1160,12 @@
                         results[0][1].decode("utf-8"),  # name
                         results[0][2],  # membership hash
                         results[0][3],  # modified timestamp
+                        bool(results[0][4]),  # extant
                     ))
                 else:
                     raise
         else:
-            returnValue((None, None, None, None))
+            returnValue((None, None, None, None, None))
 
 
     @inlineCallbacks
@@ -1169,7 +1175,7 @@
 
         @type groupID: C{str}
         @return: Deferred firing with a tuple of group UID C{unicode},
-            group name C{unicode}, and membership hash C{str}
+            group name C{unicode}, membership hash C{str}, and extant C{boolean}
         """
         try:
             results = (yield self._groupByID.on(self, groupID=groupID))[0]
@@ -1177,7 +1183,8 @@
                 results = (
                     results[0].decode("utf-8"),
                     results[1].decode("utf-8"),
-                    results[2]
+                    results[2],
+                    bool(results[3])
                 )
             returnValue(results)
         except IndexError:

Modified: CalendarServer/trunk/txdav/who/delegates.py
===================================================================
--- CalendarServer/trunk/txdav/who/delegates.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/delegates.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -236,7 +236,10 @@
     """
     if delegate.recordType == BaseRecordType.group:
         # find the groupID
-        groupID, _ignore_name, _ignore_membershipHash, _ignore_modified = yield txn.groupByUID(
+        (
+            groupID, _ignore_name, _ignore_membershipHash, _ignore_modified,
+            _ignore_extant
+        ) = yield txn.groupByUID(
             delegate.uid
         )
         yield txn.addDelegateGroup(delegator.uid, groupID, readWrite)
@@ -260,7 +263,10 @@
     """
     if delegate.recordType == BaseRecordType.group:
         # find the groupID
-        groupID, _ignore_name, _ignore_membershipHash, _ignore_modified = yield txn.groupByUID(
+        (
+            groupID, _ignore_name, _ignore_membershipHash, _ignore_modified,
+            _ignore_extant
+        ) = yield txn.groupByUID(
             delegate.uid
         )
         yield txn.removeDelegateGroup(delegator.uid, groupID, readWrite)

Modified: CalendarServer/trunk/txdav/who/groups.py
===================================================================
--- CalendarServer/trunk/txdav/who/groups.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/groups.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -157,12 +157,14 @@
             if (component.masterComponent() is None or not component.isRecurring()):
 
                 # skip non-recurring old events, no instances
-                if (yield calendarObject.removeOldEventGroupLink(
-                    component,
-                    instances=None,
-                    inserting=False,
-                    txn=self.transaction
-                )):
+                if (
+                    yield calendarObject.removeOldEventGroupLink(
+                        component,
+                        instances=None,
+                        inserting=False,
+                        txn=self.transaction
+                    )
+                ):
                     returnValue(None)
             else:
                 # skip recurring old events
@@ -180,12 +182,14 @@
                     lowerLimit=truncateLowerLimit,
                     ignoreInvalidInstances=True
                 )
-                if (yield calendarObject.removeOldEventGroupLink(
-                    component,
-                    instances=instances,
-                    inserting=False,
-                    txn=self.transaction
-                )):
+                if (
+                    yield calendarObject.removeOldEventGroupLink(
+                        component,
+                        instances=instances,
+                        inserting=False,
+                        txn=self.transaction
+                    )
+                ):
                     returnValue(None)
 
                 # split spanning events and only update present-future split result
@@ -310,11 +314,17 @@
             ) in changed:
                 readDelegateGroupID = writeDelegateGroupID = None
                 if readDelegateUID:
-                    readDelegateGroupID, _ignore_name, hash, _ignore_modified = (
+                    (
+                        readDelegateGroupID, _ignore_name, hash,
+                        _ignore_modified, _ignore_extant
+                    ) = (
                         yield txn.groupByUID(readDelegateUID)
                     )
                 if writeDelegateUID:
-                    writeDelegateGroupID, _ignore_name, hash, _ignore_modified = (
+                    (
+                        writeDelegateGroupID, _ignore_name, hash,
+                        _ignore_modified, _ignore_extant
+                    ) = (
                         yield txn.groupByUID(writeDelegateUID)
                     )
                 yield txn.assignExternalDelegates(
@@ -344,20 +354,24 @@
         else:
             self.log.debug("Got group record: {u}", u=record.uid)
 
-        groupID, cachedName, cachedMembershipHash, _ignore_modified = (
-            yield txn.groupByUID(
-                groupUID,
-                create=(record is not None)
-            )
+        (
+            groupID, cachedName, cachedMembershipHash, _ignore_modified,
+            extant
+        ) = yield txn.groupByUID(
+            groupUID,
+            create=(record is not None)
         )
+
         wps = tuple()
         if groupID:
             if record is not None:
                 members = yield record.expandedMembers()
-                name = record.fullNames[0]
+                name = record.displayName
+                extant = True
             else:
                 members = frozenset()
                 name = cachedName
+                extant = False
 
             membershipHashContent = hashlib.md5()
             members = list(members)
@@ -376,7 +390,9 @@
 
             if membershipChanged or record is not None:
                 # also updates group mod date
-                yield txn.updateGroup(groupUID, name, membershipHash)
+                yield txn.updateGroup(
+                    groupUID, name, membershipHash, extant=extant
+                )
 
             if membershipChanged:
                 newMemberUIDs = set()
@@ -461,7 +477,7 @@
             "There are {count} group delegates", count=len(delegatedUIDs)
         )
 
-        # Get groupUIDs for aoo group attendees
+        # Get groupUIDs for all group attendees
         groupAttendee = schema.GROUP_ATTENDEE
         gr = schema.GROUPS
         rows = yield Select(

Modified: CalendarServer/trunk/txdav/who/test/test_delegates.py
===================================================================
--- CalendarServer/trunk/txdav/who/test/test_delegates.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/test/test_delegates.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -207,7 +207,10 @@
                 yield self.directory.recordWithShortName(RecordType.user, name)
             )
             newSet.add(record.uid)
-        groupID, name, _ignore_membershipHash, _ignore_modified = (yield txn.groupByUID(group1.uid))
+        (
+            groupID, name, _ignore_membershipHash, _ignore_modified,
+            _ignore_extant
+        ) = (yield txn.groupByUID(group1.uid))
         _ignore_numAdded, _ignore_numRemoved = (
             yield self.groupCacher.synchronizeMembers(txn, groupID, newSet)
         )

Modified: CalendarServer/trunk/txdav/who/test/test_group_attendees.py
===================================================================
--- CalendarServer/trunk/txdav/who/test/test_group_attendees.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/test/test_group_attendees.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -868,7 +868,10 @@
         #finally, simulate an event that has become old
         self.patch(CalendarDirectoryRecordMixin, "expandedMembers", unpatchedExpandedMembers)
 
-        groupID, _ignore_name, _ignore_membershipHash, _ignore_modDate = yield self.transactionUnderTest().groupByUID("20000000-0000-0000-0000-000000000001")
+        (
+            groupID, _ignore_name, _ignore_membershipHash, _ignore_modDate,
+            _ignore_extant
+        ) = yield self.transactionUnderTest().groupByUID("20000000-0000-0000-0000-000000000001")
         ga = schema.GROUP_ATTENDEE
         yield Insert({
                 ga.RESOURCE_ID: cobj._resourceID,
@@ -1029,7 +1032,10 @@
         #finally, simulate an event that has become old
         self.patch(CalendarDirectoryRecordMixin, "expandedMembers", unpatchedExpandedMembers)
 
-        groupID, _ignore_name, _ignore_membershipHash, _ignore_modDate = yield self.transactionUnderTest().groupByUID("20000000-0000-0000-0000-000000000001")
+        (
+            groupID, _ignore_name, _ignore_membershipHash, _ignore_modDate,
+            _ignore_extant
+        ) = yield self.transactionUnderTest().groupByUID("20000000-0000-0000-0000-000000000001")
         ga = schema.GROUP_ATTENDEE
         yield Insert({
                 ga.RESOURCE_ID: cobj._resourceID,

Modified: CalendarServer/trunk/txdav/who/test/test_groups.py
===================================================================
--- CalendarServer/trunk/txdav/who/test/test_groups.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/test/test_groups.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -18,11 +18,12 @@
 Group membership caching implementation tests
 """
 
-from txdav.who.groups import GroupCacher, diffAssignments
 from twext.who.idirectory import RecordType
 from twisted.internet.defer import inlineCallbacks
 from twistedcaldav.test.util import StoreTestCase
 from txdav.common.icommondatastore import NotFoundError
+from txdav.who.groups import GroupCacher, diffAssignments
+from txdav.who.test.support import TestRecord, CalendarInMemoryDirectoryService
 
 
 
@@ -44,8 +45,8 @@
         txn = store.newTransaction()
 
         record = yield self.directory.recordWithUID(u"__top_group_1__")
-        _ignore_groupID, _ignore_name, _ignore_membershipHash, _ignore_modified = (yield txn.groupByUID(record.uid))
-        _ignore_groupID, _ignore_name, _ignore_membershipHash, _ignore_modified = (yield txn.groupByUID(record.uid))
+        yield txn.groupByUID(record.uid)
+        yield txn.groupByUID(record.uid)
 
         yield txn.commit()
 
@@ -63,14 +64,19 @@
         record = yield self.directory.recordWithUID(u"__top_group_1__")
         yield self.groupCacher.refreshGroup(txn, record.uid)
 
-        groupID, _ignore_name, membershipHash, _ignore_modified = (yield txn.groupByUID(record.uid))
+        (
+            groupID, _ignore_name, membershipHash, _ignore_modified,
+            extant
+        ) = (yield txn.groupByUID(record.uid))
 
+        self.assertEquals(extant, True)
         self.assertEquals(membershipHash, "553eb54e3bbb26582198ee04541dbee4")
 
-        groupUID, name, membershipHash = (yield txn.groupByID(groupID))
+        groupUID, name, membershipHash, extant = (yield txn.groupByID(groupID))
         self.assertEquals(groupUID, record.uid)
         self.assertEquals(name, u"Top Group 1")
         self.assertEquals(membershipHash, "553eb54e3bbb26582198ee04541dbee4")
+        self.assertEquals(extant, True)
 
         members = (yield txn.membersOfGroup(groupID))
         self.assertEquals(
@@ -107,7 +113,10 @@
         # Refresh the group so it's assigned a group_id
         uid = u"__top_group_1__"
         yield self.groupCacher.refreshGroup(txn, uid)
-        groupID, name, _ignore_membershipHash, _ignore_modified = (yield txn.groupByUID(uid))
+        (
+            groupID, name, _ignore_membershipHash, _ignore_modified,
+            _ignore_extant
+        ) = yield txn.groupByUID(uid)
 
         # Remove two members, and add one member
         newSet = set()
@@ -156,9 +165,12 @@
         uid = u"__top_group_1__"
         hash = "553eb54e3bbb26582198ee04541dbee4"
         yield self.groupCacher.refreshGroup(txn, uid)
-        groupID, _ignore_name, _ignore_membershipHash, _ignore_modified = yield txn.groupByUID(uid)
-        results = (yield txn.groupByID(groupID))
-        self.assertEquals((uid, u"Top Group 1", hash), results)
+        (
+            groupID, _ignore_name, _ignore_membershipHash, _ignore_modified,
+            extant
+        ) = yield txn.groupByUID(uid)
+        results = yield txn.groupByID(groupID)
+        self.assertEquals((uid, u"Top Group 1", hash, True), results)
 
         yield txn.commit()
 
@@ -414,3 +426,125 @@
                 {"D": ("7", "8"), "C": ("4", "5"), "A": ("1", "2")},
             )
         )
+
+
+class DynamicGroupTest(StoreTestCase):
+
+
+    @inlineCallbacks
+    def setUp(self):
+        yield super(DynamicGroupTest, self).setUp()
+
+        self.directory = CalendarInMemoryDirectoryService(None)
+        self.store.setDirectoryService(self.directory)
+        self.groupCacher = GroupCacher(self.directory)
+
+        self.numUsers = 100
+
+        # Add users
+        records = []
+        fieldName = self.directory.fieldName
+        for i in xrange(self.numUsers):
+            records.append(
+                TestRecord(
+                    self.directory,
+                    {
+                        fieldName.uid: u"foo{ctr:05d}".format(ctr=i),
+                        fieldName.shortNames: (u"foo{ctr:05d}".format(ctr=i),),
+                        fieldName.fullNames: (u"foo{ctr:05d}".format(ctr=i),),
+                        fieldName.recordType: RecordType.user,
+                    }
+                )
+            )
+
+        # Add a group
+        records.append(
+            TestRecord(
+                self.directory,
+                {
+                    fieldName.uid: u"testgroup",
+                    fieldName.recordType: RecordType.group,
+                }
+            )
+        )
+
+        yield self.directory.updateRecords(records, create=True)
+
+        group = yield self.directory.recordWithUID(u"testgroup")
+        members = yield self.directory.recordsWithRecordType(RecordType.user)
+        yield group.setMembers(members)
+
+
+    @inlineCallbacks
+    def test_extant(self):
+        """
+        Verify that once a group is removed from the directory, the next call
+        to refreshGroup() will set the "extent" to False.  Add the group back
+        to the directory and "extent" becomes True.
+        """
+        store = self.storeUnderTest()
+
+        txn = store.newTransaction()
+        yield self.groupCacher.refreshGroup(txn, u"testgroup")
+        (
+            groupID, _ignore_name, membershipHash, _ignore_modified,
+            extant
+        ) = (yield txn.groupByUID(u"testgroup"))
+        yield txn.commit()
+
+        self.assertTrue(extant)
+
+        # Remove the group
+        yield self.directory.removeRecords([u"testgroup"])
+
+        txn = store.newTransaction()
+        yield self.groupCacher.refreshGroup(txn, u"testgroup")
+        (
+            groupID, _ignore_name, membershipHash, _ignore_modified,
+            extant
+        ) = (yield txn.groupByUID(u"testgroup"))
+        yield txn.commit()
+
+        # Extant = False
+        self.assertFalse(extant)
+
+        # The list of members stored in the DB for this group is now empty
+        txn = store.newTransaction()
+        members = yield txn.membersOfGroup(groupID)
+        yield txn.commit()
+        self.assertEquals(members, set())
+
+        # Add the group back into the directory
+        fieldName = self.directory.fieldName
+        yield self.directory.updateRecords(
+            (
+                TestRecord(
+                    self.directory,
+                    {
+                        fieldName.uid: u"testgroup",
+                        fieldName.recordType: RecordType.group,
+                    }
+                ),
+            ),
+            create=True
+        )
+        group = yield self.directory.recordWithUID(u"testgroup")
+        members = yield self.directory.recordsWithRecordType(RecordType.user)
+        yield group.setMembers(members)
+
+        txn = store.newTransaction()
+        yield self.groupCacher.refreshGroup(txn, u"testgroup")
+        (
+            groupID, _ignore_name, membershipHash, _ignore_modified,
+            extant
+        ) = (yield txn.groupByUID(u"testgroup"))
+        yield txn.commit()
+
+        # Extant = True
+        self.assertTrue(extant)
+
+        # The list of members stored in the DB for this group has 100 users
+        txn = store.newTransaction()
+        members = yield txn.membersOfGroup(groupID)
+        yield txn.commit()
+        self.assertEquals(len(members), 100)

Modified: CalendarServer/trunk/txdav/who/util.py
===================================================================
--- CalendarServer/trunk/txdav/who/util.py	2014-06-25 02:24:15 UTC (rev 13682)
+++ CalendarServer/trunk/txdav/who/util.py	2014-06-25 02:26:01 UTC (rev 13683)
@@ -172,8 +172,8 @@
             )
 
         elif "inmemory" in directoryType:
-            from txdav.who.test.support import InMemoryDirectoryService
-            directory = InMemoryDirectoryService()
+            from txdav.who.test.support import CalendarInMemoryDirectoryService
+            directory = CalendarInMemoryDirectoryService()
 
         else:
             log.error("Invalid DirectoryType: {dt}", dt=directoryType)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140624/18d90ca6/attachment-0001.html>


More information about the calendarserver-changes mailing list