Example #1
0
def authUsernamePassword(username, password):
    # Authenticate using simple password

    service = DirectoryService()

    creds = UsernamePassword(username, password)
    try:
        id = yield service.requestAvatarId(creds)
        print("OK via UsernamePassword, avatarID: {id}".format(id=id))
        print("   {name}".format(name=id.fullNames))
    except UnauthorizedLogin:
        print("Via UsernamePassword, could not authenticate")

    print("")

    # Authenticate using Digest

    algorithm = "md5"  # "md5-sess"
    cnonce = "/rrD6TqPA3lHRmg+fw/vyU6oWoQgzK7h9yWrsCmv/lE="
    entity = "00000000000000000000000000000000"
    method = "GET"
    nc = "00000001"
    nonce = "128446648710842461101646794502"
    qop = None
    realm = "host.example.com"
    uri = "http://host.example.com"

    responseHash = calcResponse(
        calcHA1(
            algorithm.lower(), username, realm, password, nonce, cnonce
        ),
        algorithm.lower(), nonce, nc, cnonce, qop, method, uri, entity
    )

    response = (
        'Digest username="******", uri="{uri}", response={hash}'.format(
            username=username, uri=uri, hash=responseHash
        )
    )

    fields = {
        "realm": realm,
        "nonce": nonce,
        "response": response,
        "algorithm": algorithm,
    }

    creds = DigestedCredentials(username, method, realm, fields)

    try:
        id = yield service.requestAvatarId(creds)
        print("OK via DigestedCredentials, avatarID: {id}".format(id=id))
        print("   {name}".format(name=id.fullNames))
    except UnauthorizedLogin:
        print("Via DigestedCredentials, could not authenticate")
Example #2
0
def lookup(shortNames):
    service = DirectoryService()
    print(
        "Service = {service}\n"
        "Session = {service.session}\n"
        "Node = {service.node}\n"
        # "Local node = {service.localNode}\n"
        .format(service=service)
    )
    print("-" * 80)

    for shortName in shortNames:
        print("Looking up short name: {0}".format(shortName))

        record = yield service.recordWithShortName(service.recordType.user, shortName)
        if record:
            print(record.description())

        continue

        matchExpression = MatchExpression(
            service.fieldName.shortNames, shortName,
            matchType=MatchType.equals,
        )

        records = yield service.recordsFromExpression(matchExpression)
        for record in records:
            print(record.description())

        compoundExpression = CompoundExpression(
            [
                MatchExpression(
                    service.fieldName.shortNames, shortName,
                    matchType=MatchType.contains
                ),
                MatchExpression(
                    service.fieldName.emailAddresses, shortName,
                    matchType=MatchType.contains
                ),
            ],
            Operand.OR
        )

        records = yield service.recordsFromExpression(compoundExpression)
        for record in records:
            print(record.description())
Example #3
0
 def setUp(self):
     self.service = DirectoryService()
Example #4
0
    class LiveOpenDirectoryServiceTestCase(unittest.TestCase):
        """
        Live service tests for L{DirectoryService}.
        """

        def setUp(self):
            self.service = DirectoryService()

        def tearDown(self):
            self.service._deletePool()


        def verifyResults(self, records, expected, unexpected):
            shortNames = []
            for record in records:
                for shortName in record.shortNames:
                    shortNames.append(shortName)

            for name in expected:
                self.assertTrue(name in shortNames)
            for name in unexpected:
                self.assertFalse(name in shortNames)


        @onlyIfPopulated
        @inlineCallbacks
        def test_shortNameStartsWith(self):
            records = yield self.service.recordsFromExpression(
                MatchExpression(
                    self.service.fieldName.shortNames, u"odtest",
                    matchType=MatchType.startsWith
                )
            )
            self.verifyResults(
                records,
                chain(LOCAL_SHORTNAMES, NETWORK_SHORTNAMES),
                ["anotherodtestamanda", "anotherodtestalbert"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_uid(self):
            for uid, name in (
                (u"9DC04A71-E6DD-11DF-9492-0800200C9A66", u"odtestbetty"),
                (u"9DC04A75-E6DD-11DF-9492-0800200C9A66", u"odtestbill"),
            ):
                record = yield self.service.recordWithUID(uid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_guid(self):
            for guid, name in (
                (UUID("9DC04A71-E6DD-11DF-9492-0800200C9A66"), u"odtestbetty"),
                (UUID("9DC04A75-E6DD-11DF-9492-0800200C9A66"), u"odtestbill"),
            ):
                record = yield self.service.recordWithGUID(guid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithoutRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(expression)

            # We should get back users and groups since we did not specify a type:
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithExplicitRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(
                expression, recordTypes=[self.service.recordType.user]
            )

            # We should get back users but not groups:
            self.verifyResults(
                records,
                ["odtestbetty", "odtestalbert", "anotherodtestalbert"],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithMultipleExplicitRecordTypes(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(
                expression, recordTypes=[
                    self.service.recordType.user,
                    self.service.recordType.group
                ]
            )

            # We should get back users and groups:
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokens(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens([u"be", u"test"])
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokensWithContextUser(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens(
                [u"be", u"test"],
                context=self.calService.searchContext_user
            )
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                ],
                [
                    "odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb",
                    "odtestgroupbetty", "odtestgroupalbert"
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokensWithContextGroup(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens(
                [u"be", u"test"],
                context=self.calService.searchContext_group
            )
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                [
                    "odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingMultipleFieldsNoRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"be", MatchFlags.caseInsensitive, MatchType.contains),
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=None
            ))
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ],
                [
                    "odtestamanda",
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingSingleFieldNoRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=None
            ))
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestamanda",
                ],
                [
                    "nobody",
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingFieldsWithRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"be", MatchFlags.caseInsensitive, MatchType.contains),
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=self.calService.recordType.user
            ))
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ],
                [
                    "odtestamanda", "odtestgroupalbert", "odtestgroupbetty",
                ]
            )
Example #5
0
 def setUp(self):
     self.service = DirectoryService()
Example #6
0
    class LiveOpenDirectoryServiceTestCase(unittest.TestCase):
        """
        Live service tests for L{DirectoryService}.
        """

        def setUp(self):
            self.service = DirectoryService()


        def verifyResults(self, records, expected, unexpected):
            shortNames = []
            for record in records:
                for shortName in record.shortNames:
                    shortNames.append(shortName)

            for name in expected:
                self.assertTrue(name in shortNames)
            for name in unexpected:
                self.assertFalse(name in shortNames)


        @onlyIfPopulated
        @inlineCallbacks
        def test_shortNameStartsWith(self):
            records = yield self.service.recordsFromExpression(
                MatchExpression(
                    self.service.fieldName.shortNames, u"odtest",
                    matchType=MatchType.startsWith
                )
            )
            self.verifyResults(
                records,
                chain(LOCAL_SHORTNAMES, NETWORK_SHORTNAMES),
                ["anotherodtestamanda", "anotherodtestalbert"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_uid(self):
            for uid, name in (
                (u"9DC04A71-E6DD-11DF-9492-0800200C9A66", u"odtestbetty"),
                (u"9DC04A75-E6DD-11DF-9492-0800200C9A66", u"odtestbill"),
            ):
                record = yield self.service.recordWithUID(uid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_guid(self):
            for guid, name in (
                (UUID("9DC04A71-E6DD-11DF-9492-0800200C9A66"), u"odtestbetty"),
                (UUID("9DC04A75-E6DD-11DF-9492-0800200C9A66"), u"odtestbill"),
            ):
                record = yield self.service.recordWithGUID(guid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithoutRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(expression)

            # We should get back users and groups since we did not specify a type:
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithExplicitRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(
                expression, recordTypes=[self.service.recordType.user]
            )

            # We should get back users but not groups:
            self.verifyResults(
                records,
                ["odtestbetty", "odtestalbert", "anotherodtestalbert"],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithMultipleExplicitRecordTypes(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(
                expression, recordTypes=[
                    self.service.recordType.user,
                    self.service.recordType.group
                ]
            )

            # We should get back users and groups:
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithEmbeddedSingleRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"be",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"be",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"test",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"test",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                        ],
                        Operand.AND
                    ),
                    MatchExpression(
                        self.service.fieldName.recordType, self.service.recordType.user,
                    ),
                ],
                Operand.AND
            )
            try:
                yield self.service.recordsFromExpression(expression)
            except QueryNotSupportedError:
                pass
            else:
                self.fail("This should have raised")


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithEmbeddedMultipleRecordTypes(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"be",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"be",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"test",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"test",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                        ],
                        Operand.AND
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.recordType, self.service.recordType.user,
                            ),
                            MatchExpression(
                                self.service.fieldName.recordType, self.service.recordType.group,
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )

            try:
                yield self.service.recordsFromExpression(expression)
            except QueryNotSupportedError:
                pass
            else:
                self.fail("This should have raised")


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokens(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens([u"be", u"test"])
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokensWithContextUser(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens(
                [u"be", u"test"],
                context=self.calService.searchContext_user
            )
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                ],
                [
                    "odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb",
                    "odtestgroupbetty", "odtestgroupalbert"
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingTokensWithContextGroup(self):
            self.calService = CalOpenDirectoryService()
            records = yield self.calService.recordsMatchingTokens(
                [u"be", u"test"],
                context=self.calService.searchContext_group
            )
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert"
                ],
                [
                    "odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingMultipleFieldsNoRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"be", MatchFlags.caseInsensitive, MatchType.contains),
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=None
            ))
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ],
                [
                    "odtestamanda",
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingSingleFieldNoRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=None
            ))
            self.verifyResults(
                records,
                [
                    "odtestgroupbetty", "odtestgroupalbert",
                    "odtestbetty", "odtestalbert", "anotherodtestalbert",
                    "odtestamanda",
                ],
                [
                    "nobody",
                ]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_recordsMatchingFieldsWithRecordType(self):
            self.calService = CalOpenDirectoryService()
            fields = (
                (u"fullNames", u"be", MatchFlags.caseInsensitive, MatchType.contains),
                (u"fullNames", u"test", MatchFlags.caseInsensitive, MatchType.contains),
            )
            records = (yield self.calService.recordsMatchingFields(
                fields, operand=Operand.AND, recordType=self.calService.recordType.user
            ))
            self.verifyResults(
                records,
                [
                    "odtestbetty", "odtestalbert", "anotherodtestalbert"
                ],
                [
                    "odtestamanda", "odtestgroupalbert", "odtestgroupbetty",
                ]
            )
    class LiveOpenDirectoryServiceTestCase(unittest.TestCase):
        """
        Live service tests for L{DirectoryService}.
        """

        def setUp(self):
            self.service = DirectoryService()


        def verifyResults(self, records, expected, unexpected):
            shortNames = []
            for record in records:
                for shortName in record.shortNames:
                    shortNames.append(shortName)

            for name in expected:
                self.assertTrue(name in shortNames)
            for name in unexpected:
                self.assertFalse(name in shortNames)


        @onlyIfPopulated
        @inlineCallbacks
        def test_shortNameStartsWith(self):
            records = yield self.service.recordsFromExpression(
                MatchExpression(
                    self.service.fieldName.shortNames, u"odtest",
                    matchType=MatchType.startsWith
                )
            )
            self.verifyResults(
                records,
                chain(LOCAL_SHORTNAMES, NETWORK_SHORTNAMES),
                ["anotherodtestamanda", "anotherodtestalbert"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_uid(self):
            for uid, name in (
                (u"9DC04A71-E6DD-11DF-9492-0800200C9A66", u"odtestbetty"),
                (u"9DC04A75-E6DD-11DF-9492-0800200C9A66", u"odtestbill"),
            ):
                record = yield self.service.recordWithUID(uid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_guid(self):
            for guid, name in (
                (UUID("9DC04A71-E6DD-11DF-9492-0800200C9A66"), u"odtestbetty"),
                (UUID("9DC04A75-E6DD-11DF-9492-0800200C9A66"), u"odtestbill"),
            ):
                record = yield self.service.recordWithGUID(guid)
                self.assertTrue(record is not None)
                self.assertEquals(record.shortNames[0], name)


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithoutRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"be",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"be",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.fullNames, u"test",
                                matchType=MatchType.contains
                            ),
                            MatchExpression(
                                self.service.fieldName.emailAddresses, u"test",
                                matchType=MatchType.startsWith
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(expression)

            # We should get back users and groups since we did not specify a type:
            self.verifyResults(
                records,
                ["odtestbetty", "odtestalbert", "anotherodtestalbert", "odtestgroupbetty", "odtestgroupalbert"],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithSingleRecordType(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"be",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"be",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"test",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"test",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                        ],
                        Operand.AND
                    ),
                    MatchExpression(
                        self.service.fieldName.recordType, self.service.recordType.user,
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(expression)

            # We should only get users back, not groups:
            self.verifyResults(
                records,
                ["odtestbetty", "odtestalbert", "anotherodtestalbert"],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb", "odtestgroupbetty", "odtestgroupalbert"]
            )


        @onlyIfPopulated
        @inlineCallbacks
        def test_compoundWithMultipleRecordTypes(self):
            expression = CompoundExpression(
                [
                    CompoundExpression(
                        [
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"be",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"be",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                            CompoundExpression(
                                [
                                    MatchExpression(
                                        self.service.fieldName.fullNames, u"test",
                                        matchType=MatchType.contains
                                    ),
                                    MatchExpression(
                                        self.service.fieldName.emailAddresses, u"test",
                                        matchType=MatchType.startsWith
                                    ),
                                ],
                                Operand.OR
                            ),
                        ],
                        Operand.AND
                    ),
                    CompoundExpression(
                        [
                            MatchExpression(
                                self.service.fieldName.recordType, self.service.recordType.user,
                            ),
                            MatchExpression(
                                self.service.fieldName.recordType, self.service.recordType.group,
                            ),
                        ],
                        Operand.OR
                    ),
                ],
                Operand.AND
            )
            records = yield self.service.recordsFromExpression(expression)

            # We should get users and groups back, since we asked for either type:
            self.verifyResults(
                records,
                ["odtestbetty", "odtestalbert", "anotherodtestalbert", "odtestgroupbetty", "odtestgroupalbert"],
                ["odtestamanda", "odtestbill", "odtestgroupa", "odtestgroupb"]
            )

        test_compoundWithMultipleRecordTypes.skip = "This ends up doing a brute force query!"