<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[13079] CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/13079">13079</a></dd>
<dt>Author</dt> <dd>wsanchez@apple.com</dd>
<dt>Date</dt> <dd>2014-03-31 18:41:25 -0700 (Mon, 31 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>obsolete</pre>

<h3>Removed Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytesttest_ldapdirectorypy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_ldapdirectory.py</a></li>
<li><a href="#CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytesttest_livedirectorypy">CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_livedirectory.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytesttest_ldapdirectorypy"></a>
<div class="delfile"><h4>Deleted: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_ldapdirectory.py (13078 => 13079)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_ldapdirectory.py        2014-04-01 01:41:02 UTC (rev 13078)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_ldapdirectory.py        2014-04-01 01:41:25 UTC (rev 13079)
</span><span class="lines">@@ -1,1856 +0,0 @@
</span><del>-##
-# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-from __future__ import print_function
-
-try:
-    from twistedcaldav.directory.ldapdirectory import (
-        buildFilter, buildFilterFromTokens, LdapDirectoryService,
-        MissingGuidException, MissingRecordNameException,
-        normalizeDNstr, dnContainedIn
-    )
-    from twistedcaldav.directory.util import splitIntoBatches
-    from twistedcaldav.test.util import proxiesFile
-    from twistedcaldav.directory.calendaruserproxyloader import (
-        XMLCalendarUserProxyLoader
-    )
-    from twistedcaldav.directory import calendaruserproxy
-    from twistedcaldav.directory.directory import (
-        GroupMembershipCache, GroupMembershipCacheUpdater
-    )
-    from twisted.internet.defer import inlineCallbacks
-    from string import maketrans
-    import ldap
-except ImportError:
-    print(&quot;Skipping because ldap module not installed&quot;)
-else:
-    from twistedcaldav.test.util import TestCase
-
-    class BuildFilterTestCase(TestCase):
-
-        def test_buildFilter(self):
-            mapping = {
-                &quot;recordName&quot;: &quot;uid&quot;,
-                &quot;fullName&quot;: &quot;cn&quot;,
-                &quot;emailAddresses&quot;: &quot;mail&quot;,
-                &quot;firstName&quot;: &quot;givenName&quot;,
-                &quot;lastName&quot;: &quot;sn&quot;,
-                &quot;guid&quot;: &quot;generateduid&quot;,
-                &quot;memberIDAttr&quot;: &quot;generateduid&quot;,
-            }
-
-            entries = [
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;)
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(cn=mor*)(mail=mor*)(givenName=mor*)(sn=mor*)))&quot;,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor(&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor)&quot;, True, u&quot;contains&quot;),
-                        (&quot;firstName&quot;, &quot;mor*&quot;, True, u&quot;exact&quot;),
-                        (&quot;lastName&quot;, &quot;mor\\&quot;, True, u&quot;starts-with&quot;)
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(cn=mor\\28*)(mail=*mor\\29*)(givenName=mor\\2a)(sn=mor\\5c*)))&quot;,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(cn=mor*))&quot;,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;contains&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor&quot;, True, u&quot;equals&quot;),
-                        (&quot;invalid&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;and&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(&amp;(cn=*mor*)(mail=mor)))&quot;,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;invalid&quot;, &quot;mor&quot;, True, u&quot;contains&quot;),
-                        (&quot;invalid&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;and&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: None,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [],
-                    &quot;operand&quot;: &quot;and&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: None,
-                    &quot;optimize&quot;: False,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;fullName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;users&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(&amp;(givenName=mor*)(sn=sag*))(&amp;(givenName=sag*)(sn=mor*))))&quot;,
-                    &quot;optimize&quot;: True,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;fullName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;groups&quot;,
-                    &quot;expected&quot;: None,
-                    &quot;optimize&quot;: True,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;fullName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;emailAddresses&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;firstName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;mor&quot;, True, u&quot;starts-with&quot;),
-                        (&quot;lastName&quot;, &quot;sag&quot;, True, u&quot;starts-with&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;groups&quot;,
-                    &quot;expected&quot;: None,
-                    &quot;optimize&quot;: True,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;guid&quot;, &quot;xyzzy&quot;, True, u&quot;equals&quot;),
-                        (&quot;guid&quot;, &quot;plugh&quot;, True, u&quot;equals&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;groups&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(generateduid=xyzzy)(generateduid=plugh)))&quot;,
-                    &quot;optimize&quot;: True,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;contains&quot;),
-                        (&quot;fullName&quot;, &quot;sag&quot;, True, u&quot;contains&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;locations&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))&quot;,
-                    &quot;optimize&quot;: True,
-                },
-                {
-                    &quot;fields&quot;: [
-                        (&quot;fullName&quot;, &quot;mor&quot;, True, u&quot;contains&quot;),
-                        (&quot;fullName&quot;, &quot;sag&quot;, True, u&quot;contains&quot;),
-                    ],
-                    &quot;operand&quot;: &quot;or&quot;,
-                    &quot;recordType&quot;: &quot;resources&quot;,
-                    &quot;expected&quot;: &quot;(&amp;(uid=*)(generateduid=*)(|(cn=*mor*)(cn=*sag*)))&quot;,
-                    &quot;optimize&quot;: True,
-                },
-            ]
-            for entry in entries:
-                self.assertEquals(
-                    buildFilter(entry[&quot;recordType&quot;], mapping, entry[&quot;fields&quot;],
-                                operand=entry[&quot;operand&quot;], optimizeMultiName=entry[&quot;optimize&quot;]),
-                    entry[&quot;expected&quot;]
-                )
-
-
-    class BuildFilterFromTokensTestCase(TestCase):
-
-        def test_buildFilterFromTokens(self):
-
-            entries = [
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(a=b)(|(cn=*foo*)(mail=foo*)))&quot;,
-                    &quot;extra&quot;: &quot;(a=b)&quot;,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;foo&quot;, &quot;oo&quot;, &quot;fo&quot;, &quot;bar&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(a=b)(|(cn=*bar*)(mail=bar*))(|(cn=*foo*)(mail=foo*)))&quot;,
-                    &quot;extra&quot;: &quot;(a=b)&quot;,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;fo&quot;, &quot;foo&quot;, &quot;foooo&quot;, &quot;ooo&quot;, &quot;fooo&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(a=b)(|(cn=*foooo*)(mail=foooo*)))&quot;,
-                    &quot;extra&quot;: &quot;(a=b)&quot;,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;mailAliases&quot;],
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(a=b)(|(cn=*foo*)(mail=foo*)(mailAliases=foo*)))&quot;,
-                    &quot;extra&quot;: &quot;(a=b)&quot;,
-                },
-                {
-                    &quot;tokens&quot;: [],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: None,
-                    &quot;extra&quot;: None,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;bar&quot;],
-                    &quot;mapping&quot;: {},
-                    &quot;expected&quot;: None,
-                    &quot;extra&quot;: None,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;bar&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(mail=bar*)(mail=foo*))&quot;,
-                    &quot;extra&quot;: None,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;bar&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(|(cn=*bar*)(mail=bar*))(|(cn=*foo*)(mail=foo*)))&quot;,
-                    &quot;extra&quot;: None,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;bar&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;mailAliases&quot;],
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(|(cn=*bar*)(mail=bar*)(mailAliases=bar*))(|(cn=*foo*)(mail=foo*)(mailAliases=foo*)))&quot;,
-                    &quot;extra&quot;: None,
-                },
-                {
-                    &quot;tokens&quot;: [&quot;foo&quot;, &quot;bar&quot;, &quot;baz(&quot;],
-                    &quot;mapping&quot;: {
-                        &quot;fullName&quot;: &quot;cn&quot;,
-                        &quot;emailAddresses&quot;: &quot;mail&quot;,
-                    },
-                    &quot;expected&quot;: &quot;(&amp;(|(cn=*bar*)(mail=bar*))(|(cn=*baz\\28*)(mail=baz\\28*))(|(cn=*foo*)(mail=foo*)))&quot;,
-                    &quot;extra&quot;: None,
-                },
-            ]
-            for entry in entries:
-                self.assertEquals(
-                    buildFilterFromTokens(None, entry[&quot;mapping&quot;], entry[&quot;tokens&quot;], extra=entry[&quot;extra&quot;]),
-                    entry[&quot;expected&quot;]
-                )
-
-
-    class StubList(object):
-        def __init__(self, wrapper):
-            self.ldap = wrapper
-
-        def startSearch(self, base, scope, filterstr, attrList=None,
-                        timeout=-1, sizelimit=0):
-            self.base = base
-            self.scope = scope
-            self.filterstr = filterstr
-            self.attrList = attrList
-            self.timeout = timeout
-            self.sizelimit = sizelimit
-
-        def processResults(self):
-            self.allResults = self.ldap.search_s(self.base, self.scope,
-                                                 self.filterstr,
-                                                 attrlist=self.attrList)
-
-
-    class StubAsync(object):
-        def List(self, wrapper):
-            return StubList(wrapper)
-
-
-    class LdapDirectoryTestWrapper(object):
-        &quot;&quot;&quot;
-        A test stub which replaces search_s( ) with a version that will return
-        whatever you have previously called addTestResults( ) with.
-        &quot;&quot;&quot;
-
-        def __init__(self, actual, records):
-            self.actual = actual
-            self.async = StubAsync()
-
-            # Test data returned from search_s.
-            # Note that some DNs have various extra whitespace added and mixed
-            # up case since LDAP is pretty loose about these.
-            self.records = records
-
-
-        def search_s(self, base, scope, filterstr=&quot;(objectClass=*)&quot;,
-                     attrlist=None):
-            &quot;&quot;&quot; A simple implementation of LDAP search filter processing &quot;&quot;&quot;
-
-            base = normalizeDNstr(base)
-            results = []
-            for dn, attrs in self.records:
-                dn = normalizeDNstr(dn)
-                if dn == base:
-                    results.append((&quot;ignored&quot;, (dn, attrs)))
-                elif dnContainedIn(ldap.dn.str2dn(dn), ldap.dn.str2dn(base)):
-                    if filterstr in (&quot;(objectClass=*)&quot;, &quot;(!(objectClass=organizationalUnit))&quot;):
-                        results.append((&quot;ignored&quot;, (dn, attrs)))
-                    else:
-                        trans = maketrans(&quot;&amp;(|)&quot;, &quot;   |&quot;)
-                        fragments = filterstr.encode(&quot;utf-8&quot;).translate(trans).split(&quot;|&quot;)
-                        for fragment in fragments:
-                            if not fragment:
-                                continue
-                            fragment = fragment.strip()
-                            key, value = fragment.split(&quot;=&quot;)
-                            if value in attrs.get(key, []):
-                                results.append((&quot;ignored&quot;, (dn, attrs)))
-                                break
-                            elif value == &quot;*&quot; and key in attrs:
-                                results.append((&quot;ignored&quot;, (dn, attrs)))
-                                break
-
-            return results
-
-
-    class LdapDirectoryServiceTestCase(TestCase):
-
-        nestedUsingDifferentAttributeUsingDN = (
-            (
-                (
-                    &quot;cn=Recursive1_coasts, cn=gROUps,dc=example, dc=com&quot;,
-                    {
-                        'cn': ['recursive1_coasts'],
-                        'apple-generateduid': ['recursive1_coasts'],
-                        'uniqueMember': [
-                            'uid=wsanchez ,cn=users, dc=eXAMple,dc=com',
-                        ],
-                        'nestedGroups': [
-                            'cn=recursive2_coasts,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    &quot;cn=recursive2_coasts,cn=groups,dc=example,dc=com&quot;,
-                    {
-                        'cn': ['recursive2_coasts'],
-                        'apple-generateduid': ['recursive2_coasts'],
-                        'uniqueMember': [
-                            'uid=cdaboo,cn=users,dc=example,dc=com',
-                        ],
-                        'nestedGroups': [
-                            'cn=recursive1_coasts,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=both_coasts,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['both_coasts'],
-                        'apple-generateduid': ['both_coasts'],
-                        'nestedGroups': [
-                            'cn=right_coast,cn=groups,dc=example,dc=com',
-                            'cn=left_coast,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=right_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['right_coast'],
-                        'apple-generateduid': ['right_coast'],
-                        'uniqueMember': [
-                            'uid=cdaboo,cn=users,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=left_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['left_coast'],
-                        'apple-generateduid': ['left_coast'],
-                        'uniqueMember': [
-                            'uid=wsanchez, cn=users,dc=example,dc=com',
-                            'uid=lecroy,cn=users,dc=example,dc=com',
-                            'uid=dreid,cn=users,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestamanda'],
-                        # purposely throw in an un-normalized GUID
-                        'apple-generateduid': ['9dc04a70-e6dd-11df-9492-0800200c9a66'],
-                        'sn': ['Test'],
-                        'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                        'givenName': ['Amanda'],
-                        'cn': ['Amanda Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestbetty,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestbetty'],
-                        'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
-                        'sn': ['Test'],
-                        'mail': ['odtestbetty@example.com'],
-                        'givenName': ['Betty'],
-                        'cn': ['Betty Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestcarlene,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestcarlene'],
-                        # Note: no guid here, to test this record is skipped
-                        'sn': ['Test'],
-                        'mail': ['odtestcarlene@example.com'],
-                        'givenName': ['Carlene'],
-                        'cn': ['Carlene Test']
-                    }
-                ),
-                (
-                    &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['cdaboo'],
-                        'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                        'sn': ['Daboo'],
-                        'mail': ['daboo@example.com'],
-                        'givenName': ['Cyrus'],
-                        'cn': ['Cyrus Daboo']
-                    }
-                ),
-                (
-                    &quot;uid=wsanchez  ,  cn=users  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['wsanchez'],
-                        'apple-generateduid': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
-                        'sn': ['Sanchez'],
-                        'mail': ['wsanchez@example.com'],
-                        'givenName': ['Wilfredo'],
-                        'cn': ['Wilfredo Sanchez']
-                    }
-                ),
-                (
-                    &quot;uid=testresource  ,  cn=resources  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['testresource'],
-                        'apple-generateduid': ['D91B21B9-B856-495A-8E36-0E5AD54EFB3A'],
-                        'sn': ['Resource'],
-                        'givenName': ['Test'],
-                        'cn': ['Test Resource'],
-                        # purposely throw in an un-normalized GUID
-                        'read-write-proxy': ['6423f94a-6b76-4a3a-815b-d52cfd77935d'],
-                        'read-only-proxy': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                    }
-                ),
-                (
-                    &quot;uid=testresource2  ,  cn=resources  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['testresource2'],
-                        'apple-generateduid': ['753E5A60-AFFD-45E4-BF2C-31DAB459353F'],
-                        'sn': ['Resource2'],
-                        'givenName': ['Test'],
-                        'cn': ['Test Resource2'],
-                        'read-write-proxy': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
-                    }
-                ),
-            ),
-            {
-                &quot;augmentService&quot;: None,
-                &quot;groupMembershipCache&quot;: None,
-                &quot;cacheTimeout&quot;: 1,  # Minutes
-                &quot;negativeCaching&quot;: False,
-                &quot;warningThresholdSeconds&quot;: 3,
-                &quot;batchSize&quot;: 500,
-                &quot;queryLocationsImplicitly&quot;: True,
-                &quot;restrictEnabledRecords&quot;: True,
-                &quot;restrictToGroup&quot;: &quot;both_coasts&quot;,
-                &quot;recordTypes&quot;: (&quot;users&quot;, &quot;groups&quot;, &quot;locations&quot;, &quot;resources&quot;),
-                &quot;uri&quot;: &quot;ldap://localhost/&quot;,
-                &quot;tls&quot;: False,
-                &quot;tlsCACertFile&quot;: None,
-                &quot;tlsCACertDir&quot;: None,
-                &quot;tlsRequireCert&quot;: None,  # never, allow, try, demand, hard
-                &quot;credentials&quot;: {
-                    &quot;dn&quot;: None,
-                    &quot;password&quot;: None,
-                },
-                &quot;authMethod&quot;: &quot;LDAP&quot;,
-                &quot;rdnSchema&quot;: {
-                    &quot;base&quot;: &quot;dc=example,dc=com&quot;,
-                    &quot;guidAttr&quot;: &quot;apple-generateduid&quot;,
-                    &quot;users&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Users&quot;,
-                        &quot;attr&quot;: &quot;uid&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;loginEnabledAttr&quot;: &quot;&quot;,  # attribute controlling login
-                        &quot;loginEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;calendarEnabledAttr&quot;: &quot;enable-calendar&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;uid&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;groups&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Groups&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                        },
-                    },
-                    &quot;locations&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Places&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;associatedAddressAttr&quot;: &quot;assocAddr&quot;,
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: &quot;&quot;,  # old style, single string
-                        },
-                    },
-                    &quot;resources&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Resources&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [],  # new style, array
-                        },
-                    },
-                    &quot;addresses&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Buildings&quot;,
-                        &quot;geoAttr&quot;: &quot;coordinates&quot;,
-                        &quot;streetAddressAttr&quot;: &quot;postal&quot;,
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                        },
-                    },
-                },
-                &quot;groupSchema&quot;: {
-                    &quot;membersAttr&quot;: &quot;uniqueMember&quot;,  # how members are specified
-                    &quot;nestedGroupsAttr&quot;: &quot;nestedGroups&quot;,  # how nested groups are specified
-                    &quot;memberIdAttr&quot;: &quot;&quot;,  # which attribute the above refer to
-                },
-                &quot;resourceSchema&quot;: {
-                    &quot;resourceInfoAttr&quot;: &quot;apple-resource-info&quot;,  # contains location/resource info
-                    &quot;autoScheduleAttr&quot;: None,
-                    &quot;proxyAttr&quot;: &quot;read-write-proxy&quot;,
-                    &quot;readOnlyProxyAttr&quot;: &quot;read-only-proxy&quot;,
-                    &quot;autoAcceptGroupAttr&quot;: None,
-                },
-                &quot;poddingSchema&quot;: {
-                    &quot;serverIdAttr&quot;: &quot;server-id&quot;,  # maps to augments server-id
-                },
-            }
-        )
-        nestedUsingSameAttributeUsingDN = (
-            (
-                (
-                    &quot;cn=Recursive1_coasts, cn=gROUps,dc=example, dc=com&quot;,
-                    {
-                        'cn': ['recursive1_coasts'],
-                        'apple-generateduid': ['recursive1_coasts'],
-                        'uniqueMember': [
-                            'uid=wsanchez ,cn=users, dc=eXAMple,dc=com',
-                            'cn=recursive2_coasts,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    &quot;cn=recursive2_coasts,cn=groups,dc=example,dc=com&quot;,
-                    {
-                        'cn': ['recursive2_coasts'],
-                        'apple-generateduid': ['recursive2_coasts'],
-                        'uniqueMember': [
-                            'uid=cdaboo,cn=users,dc=example,dc=com',
-                            'cn=recursive1_coasts,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=both_coasts,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['both_coasts'],
-                        'apple-generateduid': ['both_coasts'],
-                        'uniqueMember': [
-                            'cn=right_coast,cn=groups,dc=example,dc=com',
-                            'cn=left_coast,cn=groups,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=right_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['right_coast'],
-                        'apple-generateduid': ['right_coast'],
-                        'uniqueMember': [
-                            'uid=cdaboo,cn=users,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    'cn=left_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['left_coast'],
-                        'apple-generateduid': ['left_coast'],
-                        'uniqueMember': [
-                            'uid=wsanchez, cn=users,dc=example,dc=com',
-                            'uid=lecroy,cn=users,dc=example,dc=com',
-                            'uid=dreid,cn=users,dc=example,dc=com',
-                        ],
-                    }
-                ),
-                (
-                    &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestamanda'],
-                        'apple-generateduid': ['9DC04A70-E6DD-11DF-9492-0800200C9A66'],
-                        'sn': ['Test'],
-                        'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                        'givenName': ['Amanda'],
-                        'cn': ['Amanda Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestbetty,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestbetty'],
-                        'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
-                        'sn': ['Test'],
-                        'mail': ['odtestbetty@example.com'],
-                        'givenName': ['Betty'],
-                        'cn': ['Betty Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestcarlene,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestcarlene'],
-                        # Note: no guid here, to test this record is skipped
-                        'sn': ['Test'],
-                        'mail': ['odtestcarlene@example.com'],
-                        'givenName': ['Carlene'],
-                        'cn': ['Carlene Test']
-                    }
-                ),
-                (
-                    &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['cdaboo'],
-                        'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                        'sn': ['Daboo'],
-                        'mail': ['daboo@example.com'],
-                        'givenName': ['Cyrus'],
-                        'cn': ['Cyrus Daboo']
-                    }
-                ),
-                (
-                    &quot;uid=wsanchez  ,  cn=users  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['wsanchez'],
-                        'apple-generateduid': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
-                        'sn': ['Sanchez'],
-                        'mail': ['wsanchez@example.com'],
-                        'givenName': ['Wilfredo'],
-                        'cn': ['Wilfredo Sanchez']
-                    }
-                ),
-            ),
-            {
-                &quot;augmentService&quot;: None,
-                &quot;groupMembershipCache&quot;: None,
-                &quot;cacheTimeout&quot;: 1,  # Minutes
-                &quot;negativeCaching&quot;: False,
-                &quot;warningThresholdSeconds&quot;: 3,
-                &quot;batchSize&quot;: 500,
-                &quot;queryLocationsImplicitly&quot;: True,
-                &quot;restrictEnabledRecords&quot;: True,
-                &quot;restrictToGroup&quot;: &quot;both_coasts&quot;,
-                &quot;recordTypes&quot;: (&quot;users&quot;, &quot;groups&quot;, &quot;locations&quot;, &quot;resources&quot;),
-                &quot;uri&quot;: &quot;ldap://localhost/&quot;,
-                &quot;tls&quot;: False,
-                &quot;tlsCACertFile&quot;: None,
-                &quot;tlsCACertDir&quot;: None,
-                &quot;tlsRequireCert&quot;: None,  # never, allow, try, demand, hard
-                &quot;credentials&quot;: {
-                    &quot;dn&quot;: None,
-                    &quot;password&quot;: None,
-                },
-                &quot;authMethod&quot;: &quot;LDAP&quot;,
-                &quot;rdnSchema&quot;: {
-                    &quot;base&quot;: &quot;dc=example,dc=com&quot;,
-                    &quot;guidAttr&quot;: &quot;apple-generateduid&quot;,
-                    &quot;users&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Users&quot;,
-                        &quot;attr&quot;: &quot;uid&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;loginEnabledAttr&quot;: &quot;&quot;,  # attribute controlling login
-                        &quot;loginEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;calendarEnabledAttr&quot;: &quot;enable-calendar&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;uid&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;groups&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Groups&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;locations&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Places&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: &quot;&quot;,  # old style, single string
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;resources&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Resources&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [],  # new style, array
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                },
-                &quot;groupSchema&quot;: {
-                    &quot;membersAttr&quot;: &quot;uniqueMember&quot;,  # how members are specified
-                    &quot;nestedGroupsAttr&quot;: &quot;&quot;,  # how nested groups are specified
-                    &quot;memberIdAttr&quot;: &quot;&quot;,  # which attribute the above refer to
-                },
-                &quot;resourceSchema&quot;: {
-                    &quot;resourceInfoAttr&quot;: &quot;apple-resource-info&quot;,  # contains location/resource info
-                    &quot;autoScheduleAttr&quot;: None,
-                    &quot;proxyAttr&quot;: None,
-                    &quot;readOnlyProxyAttr&quot;: None,
-                    &quot;autoAcceptGroupAttr&quot;: None,
-                },
-                &quot;poddingSchema&quot;: {
-                    &quot;serverIdAttr&quot;: &quot;server-id&quot;,  # maps to augments server-id
-                },
-            }
-        )
-        nestedUsingDifferentAttributeUsingGUID = (
-            (
-                (
-                    &quot;cn=Recursive1_coasts, cn=gROUps,dc=example, dc=com&quot;,
-                    {
-                        'cn': ['recursive1_coasts'],
-                        'apple-generateduid': ['recursive1_coasts'],
-                        'uniqueMember': [
-                            '6423F94A-6B76-4A3A-815B-D52CFD77935D',
-                        ],
-                        'nestedGroups': [
-                            'recursive2_coasts',
-                        ],
-                    }
-                ),
-                (
-                    &quot;cn=recursive2_coasts,cn=groups,dc=example,dc=com&quot;,
-                    {
-                        'cn': ['recursive2_coasts'],
-                        'apple-generateduid': ['recursive2_coasts'],
-                        'uniqueMember': [
-                            '5A985493-EE2C-4665-94CF-4DFEA3A89500',
-                        ],
-                        'nestedGroups': [
-                            'recursive1_coasts',
-                        ],
-                    }
-                ),
-                (
-                    'cn=both_coasts,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['both_coasts'],
-                        'apple-generateduid': ['both_coasts'],
-                        'nestedGroups': [
-                            'right_coast',
-                            'left_coast',
-                        ],
-                    }
-                ),
-                (
-                    'cn=right_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['right_coast'],
-                        'apple-generateduid': ['right_coast'],
-                        'uniqueMember': [
-                            '5A985493-EE2C-4665-94CF-4DFEA3A89500',
-                        ],
-                    }
-                ),
-                (
-                    'cn=left_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['left_coast'],
-                        'apple-generateduid': ['left_coast'],
-                        'uniqueMember': [
-                            '6423F94A-6B76-4A3A-815B-D52CFD77935D',
-                        ],
-                    }
-                ),
-                (
-                    &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestamanda'],
-                        'apple-generateduid': ['9DC04A70-E6DD-11DF-9492-0800200C9A66'],
-                        'sn': ['Test'],
-                        'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                        'givenName': ['Amanda'],
-                        'cn': ['Amanda Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestbetty,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestbetty'],
-                        'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
-                        'sn': ['Test'],
-                        'mail': ['odtestbetty@example.com'],
-                        'givenName': ['Betty'],
-                        'cn': ['Betty Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestcarlene,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestcarlene'],
-                        # Note: no guid here, to test this record is skipped
-                        'sn': ['Test'],
-                        'mail': ['odtestcarlene@example.com'],
-                        'givenName': ['Carlene'],
-                        'cn': ['Carlene Test']
-                    }
-                ),
-                (
-                    &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['cdaboo'],
-                        'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                        'sn': ['Daboo'],
-                        'mail': ['daboo@example.com'],
-                        'givenName': ['Cyrus'],
-                        'cn': ['Cyrus Daboo']
-                    }
-                ),
-                (
-                    &quot;uid=wsanchez  ,  cn=users  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['wsanchez'],
-                        'apple-generateduid': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
-                        'sn': ['Sanchez'],
-                        'mail': ['wsanchez@example.com'],
-                        'givenName': ['Wilfredo'],
-                        'cn': ['Wilfredo Sanchez']
-                    }
-                ),
-            ),
-            {
-                &quot;augmentService&quot;: None,
-                &quot;groupMembershipCache&quot;: None,
-                &quot;cacheTimeout&quot;: 1,  # Minutes
-                &quot;negativeCaching&quot;: False,
-                &quot;warningThresholdSeconds&quot;: 3,
-                &quot;batchSize&quot;: 500,
-                &quot;queryLocationsImplicitly&quot;: True,
-                &quot;restrictEnabledRecords&quot;: True,
-                &quot;restrictToGroup&quot;: &quot;both_coasts&quot;,
-                &quot;recordTypes&quot;: (&quot;users&quot;, &quot;groups&quot;, &quot;locations&quot;, &quot;resources&quot;),
-                &quot;uri&quot;: &quot;ldap://localhost/&quot;,
-                &quot;tls&quot;: False,
-                &quot;tlsCACertFile&quot;: None,
-                &quot;tlsCACertDir&quot;: None,
-                &quot;tlsRequireCert&quot;: None,  # never, allow, try, demand, hard
-                &quot;credentials&quot;: {
-                    &quot;dn&quot;: None,
-                    &quot;password&quot;: None,
-                },
-                &quot;authMethod&quot;: &quot;LDAP&quot;,
-                &quot;rdnSchema&quot;: {
-                    &quot;base&quot;: &quot;dc=example,dc=com&quot;,
-                    &quot;guidAttr&quot;: &quot;apple-generateduid&quot;,
-                    &quot;users&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Users&quot;,
-                        &quot;attr&quot;: &quot;uid&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;loginEnabledAttr&quot;: &quot;&quot;,  # attribute controlling login
-                        &quot;loginEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;calendarEnabledAttr&quot;: &quot;enable-calendar&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;uid&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;groups&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Groups&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;locations&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Places&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: &quot;&quot;,  # old style, single string
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;resources&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Resources&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [],  # new style, array
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                },
-                &quot;groupSchema&quot;: {
-                    &quot;membersAttr&quot;: &quot;uniqueMember&quot;,  # how members are specified
-                    &quot;nestedGroupsAttr&quot;: &quot;nestedGroups&quot;,  # how nested groups are specified
-                    &quot;memberIdAttr&quot;: &quot;apple-generateduid&quot;,  # which attribute the above refer to
-                },
-                &quot;resourceSchema&quot;: {
-                    &quot;resourceInfoAttr&quot;: &quot;apple-resource-info&quot;,  # contains location/resource info
-                    &quot;autoScheduleAttr&quot;: None,
-                    &quot;proxyAttr&quot;: None,
-                    &quot;readOnlyProxyAttr&quot;: None,
-                    &quot;autoAcceptGroupAttr&quot;: None,
-                },
-                &quot;poddingSchema&quot;: {
-                    &quot;serverIdAttr&quot;: &quot;server-id&quot;,  # maps to augments server-id
-                },
-            }
-        )
-        nestedUsingSameAttributeUsingGUID = (
-            (
-                (
-                    &quot;cn=Recursive1_coasts, cn=gROUps,dc=example, dc=com&quot;,
-                    {
-                        'cn': ['recursive1_coasts'],
-                        'apple-generateduid': ['recursive1_coasts'],
-                        'uniqueMember': [
-                            '6423F94A-6B76-4A3A-815B-D52CFD77935D',
-                            'recursive2_coasts',
-                        ],
-                    }
-                ),
-                (
-                    &quot;cn=recursive2_coasts,cn=groups,dc=example,dc=com&quot;,
-                    {
-                        'cn': ['recursive2_coasts'],
-                        'apple-generateduid': ['recursive2_coasts'],
-                        'uniqueMember': [
-                            '5A985493-EE2C-4665-94CF-4DFEA3A89500',
-                            'recursive1_coasts',
-                        ],
-                    }
-                ),
-                (
-                    'cn=both_coasts,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['both_coasts'],
-                        'apple-generateduid': ['both_coasts'],
-                        'uniqueMember': [
-                            'right_coast',
-                            'left_coast',
-                        ],
-                    }
-                ),
-                (
-                    'cn=right_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['right_coast'],
-                        'apple-generateduid': ['right_coast'],
-                        'uniqueMember': [
-                            '5A985493-EE2C-4665-94CF-4DFEA3A89500',
-                        ],
-                    }
-                ),
-                (
-                    'cn=left_coast,cn=groups,dc=example,dc=com',
-                    {
-                        'cn': ['left_coast'],
-                        'apple-generateduid': ['left_coast'],
-                        'uniqueMember': [
-                            '6423F94A-6B76-4A3A-815B-D52CFD77935D',
-                        ],
-                    }
-                ),
-                (
-                    &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestamanda'],
-                        'apple-generateduid': ['9DC04A70-E6DD-11DF-9492-0800200C9A66'],
-                        'sn': ['Test'],
-                        'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                        'givenName': ['Amanda'],
-                        'cn': ['Amanda Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestbetty,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestbetty'],
-                        'apple-generateduid': ['93A8F5C5-49D8-4641-840F-CD1903B0394C'],
-                        'sn': ['Test'],
-                        'mail': ['odtestbetty@example.com'],
-                        'givenName': ['Betty'],
-                        'cn': ['Betty Test']
-                    }
-                ),
-                (
-                    &quot;uid=odtestcarlene,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['odtestcarlene'],
-                        # Note: no guid here, to test this record is skipped
-                        'sn': ['Test'],
-                        'mail': ['odtestcarlene@example.com'],
-                        'givenName': ['Carlene'],
-                        'cn': ['Carlene Test']
-                    }
-                ),
-                (
-                    &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;,
-                    {
-                        'uid': ['cdaboo'],
-                        'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                        'sn': ['Daboo'],
-                        'mail': ['daboo@example.com'],
-                        'givenName': ['Cyrus'],
-                        'cn': ['Cyrus Daboo']
-                    }
-                ),
-                (
-                    &quot;uid=wsanchez  ,  cn=users  , dc=example,dc=com&quot;,
-                    {
-                        'uid': ['wsanchez'],
-                        'apple-generateduid': ['6423F94A-6B76-4A3A-815B-D52CFD77935D'],
-                        'sn': ['Sanchez'],
-                        'mail': ['wsanchez@example.com'],
-                        'givenName': ['Wilfredo'],
-                        'cn': ['Wilfredo Sanchez']
-                    }
-                ),
-            ),
-            {
-                &quot;augmentService&quot;: None,
-                &quot;groupMembershipCache&quot;: None,
-                &quot;cacheTimeout&quot;: 1,  # Minutes
-                &quot;negativeCaching&quot;: False,
-                &quot;warningThresholdSeconds&quot;: 3,
-                &quot;batchSize&quot;: 500,
-                &quot;queryLocationsImplicitly&quot;: True,
-                &quot;restrictEnabledRecords&quot;: True,
-                &quot;restrictToGroup&quot;: &quot;both_coasts&quot;,
-                &quot;recordTypes&quot;: (&quot;users&quot;, &quot;groups&quot;, &quot;locations&quot;, &quot;resources&quot;),
-                &quot;uri&quot;: &quot;ldap://localhost/&quot;,
-                &quot;tls&quot;: False,
-                &quot;tlsCACertFile&quot;: None,
-                &quot;tlsCACertDir&quot;: None,
-                &quot;tlsRequireCert&quot;: None,  # never, allow, try, demand, hard
-                &quot;credentials&quot;: {
-                    &quot;dn&quot;: None,
-                    &quot;password&quot;: None,
-                },
-                &quot;authMethod&quot;: &quot;LDAP&quot;,
-                &quot;rdnSchema&quot;: {
-                    &quot;base&quot;: &quot;dc=example,dc=com&quot;,
-                    &quot;guidAttr&quot;: &quot;apple-generateduid&quot;,
-                    &quot;users&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Users&quot;,
-                        &quot;attr&quot;: &quot;uid&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;loginEnabledAttr&quot;: &quot;&quot;,  # attribute controlling login
-                        &quot;loginEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;calendarEnabledAttr&quot;: &quot;enable-calendar&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;uid&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;groups&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Groups&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;&quot;,  # additional filter for this type
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [&quot;mail&quot;, &quot;emailAliases&quot;],
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;locations&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Places&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: &quot;&quot;,  # old style, single string
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                    &quot;resources&quot;: {
-                        &quot;rdn&quot;: &quot;cn=Resources&quot;,
-                        &quot;attr&quot;: &quot;cn&quot;,  # used only to synthesize email address
-                        &quot;emailSuffix&quot;: None,  # used only to synthesize email address
-                        &quot;filter&quot;: &quot;(objectClass=apple-resource)&quot;,  # additional filter for this type
-                        &quot;calendarEnabledAttr&quot;: &quot;&quot;,  # attribute controlling calendaring
-                        &quot;calendarEnabledValue&quot;: &quot;yes&quot;,  # &quot;True&quot; value of above attribute
-                        &quot;mapping&quot;: {  # maps internal record names to LDAP
-                            &quot;recordName&quot;: &quot;cn&quot;,
-                            &quot;fullName&quot;: &quot;cn&quot;,
-                            &quot;emailAddresses&quot;: [],  # new style, array
-                            &quot;firstName&quot;: &quot;givenName&quot;,
-                            &quot;lastName&quot;: &quot;sn&quot;,
-                        },
-                    },
-                },
-                &quot;groupSchema&quot;: {
-                    &quot;membersAttr&quot;: &quot;uniqueMember&quot;,  # how members are specified
-                    &quot;nestedGroupsAttr&quot;: &quot;&quot;,  # how nested groups are specified
-                    &quot;memberIdAttr&quot;: &quot;apple-generateduid&quot;,  # which attribute the above refer to
-                },
-                &quot;resourceSchema&quot;: {
-                    &quot;resourceInfoAttr&quot;: &quot;apple-resource-info&quot;,  # contains location/resource info
-                    &quot;autoScheduleAttr&quot;: None,
-                    &quot;proxyAttr&quot;: None,
-                    &quot;readOnlyProxyAttr&quot;: None,
-                    &quot;autoAcceptGroupAttr&quot;: None,
-                },
-                &quot;poddingSchema&quot;: {
-                    &quot;serverIdAttr&quot;: &quot;server-id&quot;,  # maps to augments server-id
-                },
-            }
-        )
-
-
-        def setupService(self, scenario):
-            self.service = LdapDirectoryService(scenario[1])
-            self.service.ldap = LdapDirectoryTestWrapper(self.service.ldap, scenario[0])
-            self.patch(ldap, &quot;async&quot;, StubAsync())
-
-
-        def test_ldapWrapper(self):
-            &quot;&quot;&quot;
-            Exercise the fake search_s implementation
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            # Get all groups
-            self.assertEquals(
-                len(self.service.ldap.search_s(&quot;cn=groups,dc=example,dc=com&quot;, 0, &quot;(objectClass=*)&quot;, [])), 5)
-
-            self.assertEquals(
-                len(self.service.ldap.search_s(&quot;cn=recursive1_coasts,cn=groups,dc=example,dc=com&quot;, 2, &quot;(objectClass=*)&quot;, [])), 1)
-
-            self.assertEquals(
-                len(self.service.ldap.search_s(&quot;cn=groups,dc=example,dc=com&quot;, 0, &quot;(|(apple-generateduid=right_coast)(apple-generateduid=left_coast))&quot;, [])), 2)
-
-
-        def test_ldapRecordCreation(self):
-            &quot;&quot;&quot;
-            Exercise _ldapResultToRecord(), which converts a dictionary
-            of LDAP attributes into an LdapDirectoryRecord
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            # User without enabled-for-calendaring specified
-
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            guid = '9DC04A70-E6DD-11DF-9492-0800200C9A66'
-            attrs = {
-                'uid': ['odtestamanda'],
-                'apple-generateduid': [guid],
-                'sn': ['Test'],
-                'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                'givenName': ['Amanda'],
-                'cn': ['Amanda Test']
-            }
-
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_users
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(
-                record.emailAddresses,
-                set(['alternate@example.com', 'odtestamanda@example.com'])
-            )
-            self.assertEquals(record.shortNames, ('odtestamanda',))
-            self.assertEquals(record.fullName, 'Amanda Test')
-            self.assertEquals(record.firstName, 'Amanda')
-            self.assertEquals(record.lastName, 'Test')
-            self.assertEquals(record.serverID, None)
-            self.assertFalse(record.enabledForCalendaring)
-
-            # User with enabled-for-calendaring specified
-
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            guid = '9DC04A70-E6DD-11DF-9492-0800200C9A66'
-            attrs = {
-                'uid': ['odtestamanda'],
-                'apple-generateduid': [guid],
-                'enable-calendar': [&quot;yes&quot;],
-                'sn': ['Test'],
-                'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                'givenName': ['Amanda'],
-                'cn': ['Amanda Test']
-            }
-
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_users
-            )
-            self.assertTrue(record.enabledForCalendaring)
-
-            # User with &quot;podding&quot; info
-
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            guid = '9DC04A70-E6DD-11DF-9492-0800200C9A66'
-            attrs = {
-                'uid': ['odtestamanda'],
-                'apple-generateduid': [guid],
-                'cn': ['Amanda Test'],
-                'server-id': [&quot;test-server-id&quot;],
-            }
-
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_users
-            )
-            self.assertEquals(record.serverID, &quot;test-server-id&quot;)
-
-            # User missing guidAttr
-
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            attrs = {
-                'uid': ['odtestamanda'],
-                'cn': ['Amanda Test'],
-            }
-
-            self.assertRaises(
-                MissingGuidException,
-                self.service._ldapResultToRecord, dn, attrs,
-                self.service.recordType_users
-            )
-
-            # User missing record name
-
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            attrs = {
-                'apple-generateduid': ['9ABDD881-B3A4-4065-9DA7-12095F40A898'],
-                'cn': ['Amanda Test'],
-            }
-
-            self.assertRaises(
-                MissingRecordNameException,
-                self.service._ldapResultToRecord, dn, attrs,
-                self.service.recordType_users
-            )
-
-            # Group with direct user members and nested group
-
-            dn = &quot;cn=odtestgrouptop,cn=groups,dc=example,dc=com&quot;
-            guid = '6C6CD280-E6E3-11DF-9492-0800200C9A66'
-            attrs = {
-                'apple-generateduid': [guid],
-                'uniqueMember': [
-                    'uid=odtestamanda,cn=users,dc=example,dc=com',
-                    'uid=odtestbetty,cn=users,dc=example,dc=com',
-                    'cn=odtestgroupb,cn=groups,dc=example,dc=com',
-                ],
-                'cn': ['odtestgrouptop']
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_groups
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(
-                record.memberGUIDs(),
-                set(
-                    [
-                        'cn=odtestgroupb,cn=groups,dc=example,dc=com',
-                        'uid=odtestamanda,cn=users,dc=example,dc=com',
-                        'uid=odtestbetty,cn=users,dc=example,dc=com',
-                    ]
-                )
-            )
-
-            # Group with illegal DN value in members
-
-            dn = &quot;cn=odtestgrouptop,cn=groups,dc=example,dc=com&quot;
-            guid = '6C6CD280-E6E3-11DF-9492-0800200C9A66'
-            attrs = {
-                'apple-generateduid': [guid],
-                'uniqueMember': [
-                    'uid=odtestamanda,cn=users,dc=example,dc=com',
-                    'uid=odtestbetty ,cn=users,dc=example,dc=com',
-                    'cn=odtestgroupb+foo,cn=groups,dc=example,dc=com',
-                ],
-                'cn': ['odtestgrouptop']
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_groups
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(
-                record.memberGUIDs(),
-                set(
-                    [
-                        'uid=odtestamanda,cn=users,dc=example,dc=com',
-                        'uid=odtestbetty,cn=users,dc=example,dc=com',
-                    ]
-                )
-            )
-
-            # Resource with delegates, autoSchedule = True, and autoAcceptGroup
-
-            dn = &quot;cn=odtestresource,cn=resources,dc=example,dc=com&quot;
-            guid = 'D3094652-344B-4633-8DB8-09639FA00FB6'
-            attrs = {
-                'apple-generateduid': [guid],
-                'cn': ['odtestresource'],
-                'apple-resource-info': [&quot;&quot;&quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
-&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
-&lt;plist version=&quot;1.0&quot;&gt;
-&lt;dict&gt;
-&lt;key&gt;com.apple.WhitePagesFramework&lt;/key&gt;
-&lt;dict&gt;
- &lt;key&gt;AutoAcceptsInvitation&lt;/key&gt;
-&lt;true/&gt;
-&lt;key&gt;CalendaringDelegate&lt;/key&gt;
-&lt;string&gt;6C6CD280-E6E3-11DF-9492-0800200C9A66&lt;/string&gt;
-&lt;key&gt;ReadOnlyCalendaringDelegate&lt;/key&gt;
-&lt;string&gt;6AA1AE12-592F-4190-A069-547CD83C47C0&lt;/string&gt;
-&lt;key&gt;AutoAcceptGroup&lt;/key&gt;
-&lt;string&gt;77A8EB52-AA2A-42ED-8843-B2BEE863AC70&lt;/string&gt;
-&lt;/dict&gt;
-&lt;/dict&gt;
-&lt;/plist&gt;&quot;&quot;&quot;]
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_resources
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(
-                record.externalProxies(),
-                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66'])
-            )
-            self.assertEquals(
-                record.externalReadOnlyProxies(),
-                set(['6AA1AE12-592F-4190-A069-547CD83C47C0'])
-            )
-            self.assertTrue(record.autoSchedule)
-            self.assertEquals(
-                record.autoAcceptGroup, '77A8EB52-AA2A-42ED-8843-B2BEE863AC70'
-            )
-
-            # Resource with no delegates and autoSchedule = False
-
-            dn = &quot;cn=odtestresource,cn=resources,dc=example,dc=com&quot;
-            guid = 'D3094652-344B-4633-8DB8-09639FA00FB6'
-            attrs = {
-                'apple-generateduid': [guid],
-                'cn': ['odtestresource'],
-                'apple-resource-info': [&quot;&quot;&quot;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
-&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
-&lt;plist version=&quot;1.0&quot;&gt;
-&lt;dict&gt;
-&lt;key&gt;com.apple.WhitePagesFramework&lt;/key&gt;
-&lt;dict&gt;
- &lt;key&gt;AutoAcceptsInvitation&lt;/key&gt;
-&lt;false/&gt;
-&lt;/dict&gt;
-&lt;/dict&gt;
-&lt;/plist&gt;&quot;&quot;&quot;]
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_resources
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(record.externalProxies(), set())
-            self.assertEquals(record.externalReadOnlyProxies(), set())
-            self.assertFalse(record.autoSchedule)
-            self.assertEquals(record.autoAcceptGroup, &quot;&quot;)
-
-            # Now switch off the resourceInfoAttr and switch to individual
-            # attributes...
-            self.service.resourceSchema = {
-                &quot;resourceInfoAttr&quot;: &quot;&quot;,
-                &quot;autoScheduleAttr&quot;: &quot;auto-schedule&quot;,
-                &quot;autoScheduleEnabledValue&quot;: &quot;yes&quot;,
-                &quot;proxyAttr&quot;: &quot;proxy&quot;,
-                &quot;readOnlyProxyAttr&quot;: &quot;read-only-proxy&quot;,
-                &quot;autoAcceptGroupAttr&quot;: &quot;auto-accept-group&quot;,
-            }
-
-            # Resource with delegates and autoSchedule = True
-
-            dn = &quot;cn=odtestresource,cn=resources,dc=example,dc=com&quot;
-            guid = 'D3094652-344B-4633-8DB8-09639FA00FB6'
-            attrs = {
-                'apple-generateduid': [guid],
-                'cn': ['odtestresource'],
-                'auto-schedule': ['yes'],
-                'proxy': ['6C6CD280-E6E3-11DF-9492-0800200C9A66'],
-                'read-only-proxy': ['6AA1AE12-592F-4190-A069-547CD83C47C0'],
-                'auto-accept-group': ['77A8EB52-AA2A-42ED-8843-B2BEE863AC70'],
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_resources
-            )
-            self.assertEquals(record.guid, guid)
-            self.assertEquals(
-                record.externalProxies(),
-                set(['6C6CD280-E6E3-11DF-9492-0800200C9A66'])
-            )
-            self.assertEquals(
-                record.externalReadOnlyProxies(),
-                set(['6AA1AE12-592F-4190-A069-547CD83C47C0'])
-            )
-            self.assertTrue(record.autoSchedule)
-            self.assertEquals(
-                record.autoAcceptGroup,
-                '77A8EB52-AA2A-42ED-8843-B2BEE863AC70'
-            )
-
-            # Record with lowercase guid
-            dn = &quot;uid=odtestamanda,cn=users,dc=example,dc=com&quot;
-            guid = '9dc04a70-e6dd-11df-9492-0800200c9a66'
-            attrs = {
-                'uid': ['odtestamanda'],
-                'apple-generateduid': [guid],
-                'sn': ['Test'],
-                'mail': ['odtestamanda@example.com', 'alternate@example.com'],
-                'givenName': ['Amanda'],
-                'cn': ['Amanda Test']
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_users
-            )
-            self.assertEquals(record.guid, guid.upper())
-
-            # Location with associated Address
-
-            dn = &quot;cn=odtestlocation,cn=locations,dc=example,dc=com&quot;
-            guid = &quot;D3094652-344B-4633-8DB8-09639FA00FB6&quot;
-            attrs = {
-                &quot;apple-generateduid&quot;: [guid],
-                &quot;cn&quot;: [&quot;odtestlocation&quot;],
-                &quot;assocAddr&quot;: [&quot;6C6CD280-E6E3-11DF-9492-0800200C9A66&quot;],
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_locations
-            )
-            self.assertEquals(record.extras, {
-                &quot;associatedAddress&quot;: &quot;6C6CD280-E6E3-11DF-9492-0800200C9A66&quot;
-            })
-
-            # Address with street and geo
-
-            dn = &quot;cn=odtestaddress,cn=buildings,dc=example,dc=com&quot;
-            guid = &quot;6C6CD280-E6E3-11DF-9492-0800200C9A66&quot;
-            attrs = {
-                &quot;apple-generateduid&quot;: [guid],
-                &quot;cn&quot;: [&quot;odtestaddress&quot;],
-                &quot;coordinates&quot;: [&quot;geo:1,2&quot;],
-                &quot;postal&quot;: [&quot;1 Infinite Loop, Cupertino, CA&quot;],
-            }
-            record = self.service._ldapResultToRecord(
-                dn, attrs, self.service.recordType_addresses
-            )
-            self.assertEquals(record.extras, {
-                &quot;geo&quot;: &quot;geo:1,2&quot;,
-                &quot;streetAddress&quot;: &quot;1 Infinite Loop, Cupertino, CA&quot;,
-            })
-
-        def test_listRecords(self):
-            &quot;&quot;&quot;
-            listRecords makes an LDAP query (with fake results in this test)
-            and turns the results into records
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            records = self.service.listRecords(self.service.recordType_users)
-            self.assertEquals(len(records), 4)
-            self.assertEquals(
-                set([r.firstName for r in records]),
-                set([&quot;Amanda&quot;, &quot;Betty&quot;, &quot;Cyrus&quot;, &quot;Wilfredo&quot;])  # Carlene is skipped because no guid in LDAP
-            )
-
-        def test_restrictedPrincipalsUsingDN(self):
-            &quot;&quot;&quot;
-            If restrictToGroup is in place, restrictedPrincipals should return only the principals
-            within that group.  In this case we're testing scenarios in which membership
-            is specified by DN
-            &quot;&quot;&quot;
-            for scenario in (
-                self.nestedUsingSameAttributeUsingDN,
-                self.nestedUsingDifferentAttributeUsingDN,
-            ):
-                self.setupService(scenario)
-
-                self.assertEquals(
-                    set(
-                        [
-                            &quot;cn=left_coast,cn=groups,dc=example,dc=com&quot;,
-                            &quot;cn=right_coast,cn=groups,dc=example,dc=com&quot;,
-                            &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;,
-                            &quot;uid=dreid,cn=users,dc=example,dc=com&quot;,
-                            &quot;uid=lecroy,cn=users,dc=example,dc=com&quot;,
-                            &quot;uid=wsanchez,cn=users,dc=example,dc=com&quot;,
-                        ]
-                    ),
-                    self.service.restrictedPrincipals)
-
-                dn = &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;
-                attrs = {
-                    'uid': ['cdaboo'],
-                    'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                    'sn': ['Daboo'],
-                    'mail': ['daboo@example.com'],
-                    'givenName': ['Cyrus'],
-                    'cn': ['Cyrus Daboo']
-                }
-                self.assertTrue(self.service.isAllowedByRestrictToGroup(dn, attrs))
-
-                dn = &quot;uid=unknown,cn=users,dc=example,dc=com&quot;
-                attrs = {
-                    'uid': ['unknown'],
-                    'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                    'sn': ['unknown'],
-                    'mail': ['unknown@example.com'],
-                    'givenName': ['unknown'],
-                    'cn': ['unknown']
-                }
-                self.assertFalse(self.service.isAllowedByRestrictToGroup(dn, attrs))
-
-
-        def test_restrictedPrincipalsUsingGUID(self):
-            &quot;&quot;&quot;
-            If restrictToGroup is in place, restrictedPrincipals should return only the principals
-            within that group.  In this case we're testing scenarios in which membership
-            is specified by an attribute, not DN
-            &quot;&quot;&quot;
-            for scenario in (
-                self.nestedUsingDifferentAttributeUsingGUID,
-                self.nestedUsingSameAttributeUsingGUID,
-            ):
-                self.setupService(scenario)
-
-                self.assertEquals(
-                    set(
-                        [
-                            &quot;left_coast&quot;,
-                            &quot;right_coast&quot;,
-                            &quot;5A985493-EE2C-4665-94CF-4DFEA3A89500&quot;,
-                            &quot;6423F94A-6B76-4A3A-815B-D52CFD77935D&quot;,
-                        ]
-                    ),
-                    self.service.restrictedPrincipals)
-
-                dn = &quot;uid=cdaboo,cn=users,dc=example,dc=com&quot;
-                attrs = {
-                    'uid': ['cdaboo'],
-                    'apple-generateduid': ['5A985493-EE2C-4665-94CF-4DFEA3A89500'],
-                    'sn': ['Daboo'],
-                    'mail': ['daboo@example.com'],
-                    'givenName': ['Cyrus'],
-                    'cn': ['Cyrus Daboo']
-                }
-                self.assertTrue(self.service.isAllowedByRestrictToGroup(dn, attrs))
-
-                dn = &quot;uid=unknown,cn=users,dc=example,dc=com&quot;
-                attrs = {
-                    'uid': ['unknown'],
-                    'apple-generateduid': ['unknown'],
-                    'sn': ['unknown'],
-                    'mail': ['unknown@example.com'],
-                    'givenName': ['unknown'],
-                    'cn': ['unknown']
-                }
-                self.assertFalse(self.service.isAllowedByRestrictToGroup(dn, attrs))
-
-
-        @inlineCallbacks
-        def test_groupMembershipAliases(self):
-            &quot;&quot;&quot;
-            Exercise a directory environment where group membership does not refer
-            to guids but instead uses LDAP DNs.  This example uses the LDAP attribute
-            &quot;uniqueMember&quot; to specify members of a group.  The value of this attribute
-            is each members' DN.  Even though the proxy database deals strictly in
-            guids, updateCache( ) is smart enough to map between guids and this
-            attribute which is referred to in the code as record.cachedGroupsAlias().
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            # Set up proxydb and preload it from xml
-            calendaruserproxy.ProxyDBService = calendaruserproxy.ProxySqliteDB(&quot;proxies.sqlite&quot;)
-            yield XMLCalendarUserProxyLoader(proxiesFile.path).updateProxyDB()
-
-            # Set up the GroupMembershipCache
-            cache = GroupMembershipCache(&quot;ProxyDB&quot;, expireSeconds=60)
-            self.service.groupMembershipCache = cache
-            updater = GroupMembershipCacheUpdater(
-                calendaruserproxy.ProxyDBService,
-                self.service, 30, 15, 30, cache=cache, useExternalProxies=False
-            )
-
-            self.assertEquals((False, 8, 8), (yield updater.updateCache()))
-
-            users = self.service.recordType_users
-
-            for shortName, groups in [
-                (&quot;cdaboo&quot;, set([&quot;both_coasts&quot;, &quot;recursive1_coasts&quot;, &quot;recursive2_coasts&quot;])),
-                (&quot;wsanchez&quot;, set([&quot;both_coasts&quot;, &quot;left_coast&quot;, &quot;recursive1_coasts&quot;, &quot;recursive2_coasts&quot;])),
-            ]:
-
-                record = self.service.recordWithShortName(users, shortName)
-                self.assertEquals(groups, (yield record.cachedGroups()))
-
-
-        def test_getExternalProxyAssignments(self):
-            &quot;&quot;&quot;
-            Verify getExternalProxyAssignments can extract assignments from the
-            directory, and that guids are normalized.
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-            self.assertEquals(
-                self.service.getExternalProxyAssignments(),
-                [
-                    ('D91B21B9-B856-495A-8E36-0E5AD54EFB3A#calendar-proxy-read',
-                        ['5A985493-EE2C-4665-94CF-4DFEA3A89500']),
-                    ('D91B21B9-B856-495A-8E36-0E5AD54EFB3A#calendar-proxy-write',
-                        ['6423F94A-6B76-4A3A-815B-D52CFD77935D']),
-                    ('753E5A60-AFFD-45E4-BF2C-31DAB459353F#calendar-proxy-write',
-                        ['6423F94A-6B76-4A3A-815B-D52CFD77935D'])
-                ]
-            )
-
-        def test_splitIntoBatches(self):
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-            # Data is perfect multiple of size
-            results = list(splitIntoBatches(set(range(12)), 4))
-            self.assertEquals(
-                results,
-                [set([0, 1, 2, 3]), set([4, 5, 6, 7]), set([8, 9, 10, 11])]
-            )
-
-            # Some left overs
-            results = list(splitIntoBatches(set(range(12)), 5))
-            self.assertEquals(
-                results,
-                [set([0, 1, 2, 3, 4]), set([8, 9, 5, 6, 7]), set([10, 11])]
-            )
-
-            # Empty
-            results = list(splitIntoBatches(set([]), 5))  # empty data
-            self.assertEquals(results, [set([])])
-
-        def test_recordTypeForDN(self):
-            # Ensure dn comparison is case insensitive and ignores extra
-            # whitespace
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            # Base DNs for each recordtype should already be lowercase
-            for dn in self.service.typeDNs.itervalues():
-                dnStr = ldap.dn.dn2str(dn)
-                self.assertEquals(dnStr, dnStr.lower())
-
-            # Match
-            dnStr = &quot;uid=foo,cn=USers ,dc=EXAMple,dc=com&quot;
-            self.assertEquals(self.service.recordTypeForDN(dnStr), &quot;users&quot;)
-            dnStr = &quot;uid=foo,cn=PLaces,dc=EXAMple,dc=com&quot;
-            self.assertEquals(self.service.recordTypeForDN(dnStr), &quot;locations&quot;)
-            dnStr = &quot;uid=foo,cn=Groups  ,dc=EXAMple,dc=com&quot;
-            self.assertEquals(self.service.recordTypeForDN(dnStr), &quot;groups&quot;)
-            dnStr = &quot;uid=foo,cn=Resources  ,dc=EXAMple,dc=com&quot;
-            self.assertEquals(self.service.recordTypeForDN(dnStr), &quot;resources&quot;)
-
-            # No Match
-            dnStr = &quot;uid=foo,cn=US ers ,dc=EXAMple,dc=com&quot;
-            self.assertEquals(self.service.recordTypeForDN(dnStr), None)
-
-        def test_normalizeDN(self):
-            for input, expected in (
-                (&quot;uid=foo,cn=users,dc=example,dc=com&quot;,
-                 &quot;uid=foo,cn=users,dc=example,dc=com&quot;),
-                (&quot;uid=FoO,cn=uSeRs,dc=ExAmPlE,dc=CoM&quot;,
-                 &quot;uid=foo,cn=users,dc=example,dc=com&quot;),
-                (&quot;uid=FoO , cn=uS eRs , dc=ExA mPlE ,   dc=CoM&quot;,
-                 &quot;uid=foo,cn=us ers,dc=exa mple,dc=com&quot;),
-                (&quot;uid=FoO , cn=uS  eRs , dc=ExA    mPlE ,   dc=CoM&quot;,
-                 &quot;uid=foo,cn=us ers,dc=exa mple,dc=com&quot;),
-            ):
-                self.assertEquals(expected, normalizeDNstr(input))
-
-        def test_queryDirectory(self):
-            &quot;&quot;&quot;
-            Verify queryDirectory skips LDAP queries where there has been no
-            LDAP attribute mapping provided for the given index type.
-            &quot;&quot;&quot;
-            self.setupService(self.nestedUsingDifferentAttributeUsingDN)
-
-            self.history = []
-
-            def stubSearchMethod(base, scope, filterstr=&quot;(objectClass=*)&quot;,
-                                 attrlist=None, timeoutSeconds=-1,
-                                 resultLimit=0):
-                self.history.append((base, scope, filterstr))
-
-            recordTypes = [
-                self.service.recordType_users,
-                self.service.recordType_groups,
-                self.service.recordType_locations,
-                self.service.recordType_resources,
-            ]
-            self.service.queryDirectory(
-                recordTypes,
-                self.service.INDEX_TYPE_CUA,
-                &quot;mailto:test@example.com&quot;,
-                queryMethod=stubSearchMethod
-            )
-            self.assertEquals(
-                self.history,
-                [('cn=users,dc=example,dc=com', 2, '(&amp;(!(objectClass=organizationalUnit))(|(mail=test@example.com)(emailAliases=test@example.com)))'), ('cn=groups,dc=example,dc=com', 2, '(&amp;(!(objectClass=organizationalUnit))(|(mail=test@example.com)(emailAliases=test@example.com)))')]
-            )
</del></span></pre></div>
<a id="CalendarServerbranchesuserssagenmove2who4twistedcaldavdirectorytesttest_livedirectorypy"></a>
<div class="delfile"><h4>Deleted: CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_livedirectory.py (13078 => 13079)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_livedirectory.py        2014-04-01 01:41:02 UTC (rev 13078)
+++ CalendarServer/branches/users/sagen/move2who-4/twistedcaldav/directory/test/test_livedirectory.py        2014-04-01 01:41:25 UTC (rev 13079)
</span><span class="lines">@@ -1,209 +0,0 @@
</span><del>-##
-# Copyright (c) 2011-2014 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-from __future__ import print_function
-
-runLDAPTests = False
-runODTests = False
-
-try:
-    import ldap
-    import socket
-
-    testServer = &quot;localhost&quot;
-    base = &quot;,&quot;.join([&quot;dc=%s&quot; % (p,) for p in socket.gethostname().split(&quot;.&quot;)])
-    print(&quot;Using base: %s&quot; % (base,))
-
-    try:
-        cxn = ldap.open(testServer)
-        results = cxn.search_s(base, ldap.SCOPE_SUBTREE, &quot;(uid=odtestamanda)&quot;,
-            [&quot;cn&quot;])
-        if len(results) == 1:
-            runLDAPTests = True
-    except ldap.LDAPError:
-        pass # Don't run live tests
-
-except ImportError:
-    print(&quot;Could not import ldap module (skipping LDAP tests)&quot;)
-
-try:
-    from calendarserver.platform.darwin.od import opendirectory, dsattributes
-
-    directory = opendirectory.odInit(&quot;/Search&quot;)
-
-    results = list(opendirectory.queryRecordsWithAttribute_list(
-        directory,
-        dsattributes.kDS1AttrGeneratedUID,
-        &quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;,
-        dsattributes.eDSExact,
-        False,
-        dsattributes.kDSStdRecordTypeUsers,
-        None,
-        count=0
-    ))
-    recordNames = [x[0] for x in results]
-    if &quot;odtestamanda&quot; in recordNames:
-        runODTests = True
-    else:
-        print(&quot;Test OD records not found (skipping OD tests)&quot;)
-
-except ImportError:
-    print(&quot;Could not import OpenDirectory framework (skipping OD tests)&quot;)
-
-
-if runLDAPTests or runODTests:
-
-    from twistedcaldav.test.util import TestCase
-    from twistedcaldav.directory import augment
-    from twistedcaldav.directory.test.test_xmlfile import augmentsFile
-    from twisted.internet.defer import inlineCallbacks
-
-    class LiveDirectoryTests(object):
-
-        def test_ldapRecordWithShortName(self):
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestamanda&quot;)
-            self.assertTrue(record is not None)
-
-        def test_ldapRecordWithGUID(self):
-            record = self.svc.recordWithGUID(&quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;)
-            self.assertTrue(record is not None)
-
-        @inlineCallbacks
-        def test_ldapRecordsMatchingFields(self):
-            fields = (
-                (&quot;firstName&quot;, &quot;Amanda&quot;, True, &quot;exact&quot;),
-                (&quot;lastName&quot;, &quot;Te&quot;, True, &quot;starts-with&quot;),
-            )
-            records = list(
-                (yield self.svc.recordsMatchingFields(fields, operand=&quot;and&quot;))
-            )
-            self.assertEquals(1, len(records))
-            record = self.svc.recordWithGUID(&quot;9DC04A70-E6DD-11DF-9492-0800200C9A66&quot;)
-            self.assertEquals(records, [record])
-
-        @inlineCallbacks
-        def test_restrictToGroup(self):
-            self.svc.restrictEnabledRecords = True
-            self.svc.restrictToGroup = &quot;odtestgrouptop&quot;
-
-            # Faulting in specific records will return records outside of
-            # the restrictToGroup, but they won't be enabledForCalendaring
-            # and AddressBooks:
-
-            # Amanda is a direct member of that group
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestamanda&quot;)
-            self.assertTrue(record.enabledForCalendaring)
-            self.assertTrue(record.enabledForAddressBooks)
-
-            # Betty is a direct member of that group
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestbetty&quot;)
-            self.assertTrue(record.enabledForCalendaring)
-            self.assertTrue(record.enabledForAddressBooks)
-
-            # Carlene is in a nested group
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestcarlene&quot;)
-            self.assertTrue(record.enabledForCalendaring)
-            self.assertTrue(record.enabledForAddressBooks)
-
-            # Denise is not in the group
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestdenise&quot;)
-            self.assertFalse(record.enabledForCalendaring)
-            self.assertFalse(record.enabledForAddressBooks)
-
-            # Searching for records using principal-property-search will not
-            # yield records outside of the restrictToGroup:
-
-            fields = (
-                (&quot;lastName&quot;, &quot;Test&quot;, True, &quot;exact&quot;),
-            )
-            records = list(
-                (yield self.svc.recordsMatchingFields(fields))
-            )
-            self.assertEquals(3, len(records))
-
-            # These two are directly in the restrictToGroup:
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestamanda&quot;)
-            self.assertTrue(record in records)
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestbetty&quot;)
-            self.assertTrue(record in records)
-            # Carlene is still picked up because she is in a nested group
-            record = self.svc.recordWithShortName(&quot;users&quot;, &quot;odtestcarlene&quot;)
-            self.assertTrue(record in records)
-
-    if runLDAPTests:
-
-        from twistedcaldav.directory.ldapdirectory import LdapDirectoryService
-        print(&quot;Running live LDAP tests against %s&quot; % (testServer,))
-
-        class LiveLDAPDirectoryServiceCase(LiveDirectoryTests, TestCase):
-
-            def setUp(self):
-                params = {
-                    &quot;augmentService&quot;:
-                        augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,)),
-                    &quot;uri&quot;: &quot;ldap://%s&quot; % (testServer,),
-                    &quot;rdnSchema&quot;: {
-                        &quot;base&quot;: base,
-                        &quot;guidAttr&quot;: &quot;apple-generateduid&quot;,
-                        &quot;users&quot;: {
-                            &quot;rdn&quot;: &quot;cn=users&quot;,
-                            &quot;attr&quot;: &quot;uid&quot;, # used only to synthesize email address
-                            &quot;emailSuffix&quot;: None, # used only to synthesize email address
-                            &quot;filter&quot;: None, # additional filter for this type
-                            &quot;loginEnabledAttr&quot; : &quot;&quot;, # attribute controlling login
-                            &quot;loginEnabledValue&quot; : &quot;yes&quot;, # &quot;True&quot; value of above attribute
-                            &quot;mapping&quot; : { # maps internal record names to LDAP
-                                &quot;recordName&quot;: &quot;uid&quot;,
-                                &quot;fullName&quot; : &quot;cn&quot;,
-                                &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
-                                &quot;firstName&quot; : &quot;givenName&quot;,
-                                &quot;lastName&quot; : &quot;sn&quot;,
-                            },
-                        },
-                        &quot;groups&quot;: {
-                            &quot;rdn&quot;: &quot;cn=groups&quot;,
-                            &quot;attr&quot;: &quot;cn&quot;, # used only to synthesize email address
-                            &quot;emailSuffix&quot;: None, # used only to synthesize email address
-                            &quot;filter&quot;: None, # additional filter for this type
-                            &quot;mapping&quot; : { # maps internal record names to LDAP
-                                &quot;recordName&quot;: &quot;cn&quot;,
-                                &quot;fullName&quot; : &quot;cn&quot;,
-                                &quot;emailAddresses&quot; : [&quot;mail&quot;], # multiple LDAP fields supported
-                                &quot;firstName&quot; : &quot;givenName&quot;,
-                                &quot;lastName&quot; : &quot;sn&quot;,
-                            },
-                        },
-                    },
-                    &quot;groupSchema&quot;: {
-                        &quot;membersAttr&quot;: &quot;apple-group-memberguid&quot;, # how members are specified
-                        &quot;nestedGroupsAttr&quot; : &quot;apple-group-nestedgroup&quot;, # how nested groups are specified
-                        &quot;memberIdAttr&quot;: &quot;apple-generateduid&quot;, # which attribute the above refers to
-                    },
-                }
-                self.svc = LdapDirectoryService(params)
-
-    if runODTests:
-
-        from twistedcaldav.directory.appleopendirectory import OpenDirectoryService
-        print(&quot;Running live OD tests&quot;)
-
-        class LiveODDirectoryServiceCase(LiveDirectoryTests, TestCase):
-
-            def setUp(self):
-                params = {
-                    &quot;augmentService&quot;:
-                        augment.AugmentXMLDB(xmlFiles=(augmentsFile.path,)),
-                }
-                self.svc = OpenDirectoryService(params)
</del></span></pre>
</div>
</div>

</body>
</html>