summaryrefslogtreecommitdiffstats
path: root/source4/dsdb/tests/python/deletetest.py
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/tests/python/deletetest.py')
-rwxr-xr-xsource4/dsdb/tests/python/deletetest.py565
1 files changed, 565 insertions, 0 deletions
diff --git a/source4/dsdb/tests/python/deletetest.py b/source4/dsdb/tests/python/deletetest.py
new file mode 100755
index 0000000..7375f26
--- /dev/null
+++ b/source4/dsdb/tests/python/deletetest.py
@@ -0,0 +1,565 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import optparse
+import sys
+import os
+
+sys.path.insert(0, "bin/python")
+import samba
+
+from samba.tests.subunitrun import SubunitOptions, TestProgram
+
+import samba.getopt as options
+
+from samba.auth import system_session
+from ldb import SCOPE_BASE, LdbError, Message, MessageElement, Dn, FLAG_MOD_ADD, FLAG_MOD_DELETE, FLAG_MOD_REPLACE
+from ldb import ERR_NO_SUCH_OBJECT, ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_ENTRY_ALREADY_EXISTS, ERR_ATTRIBUTE_OR_VALUE_EXISTS
+from ldb import ERR_UNWILLING_TO_PERFORM, ERR_OPERATIONS_ERROR
+from samba.samdb import SamDB
+from samba.tests import delete_force
+from samba import dsdb
+from samba.common import get_string
+
+parser = optparse.OptionParser("deletetest.py [options] <host|file>")
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+parser.add_option_group(options.VersionOptions(parser))
+# use command line creds if available
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+subunitopts = SubunitOptions(parser)
+parser.add_option_group(subunitopts)
+opts, args = parser.parse_args()
+
+if len(args) < 1:
+ parser.print_usage()
+ sys.exit(1)
+
+host = args[0]
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+
+class BaseDeleteTests(samba.tests.TestCase):
+
+ def GUID_string(self, guid):
+ return get_string(self.ldb.schema_format_value("objectGUID", guid))
+
+ def setUp(self):
+ super(BaseDeleteTests, self).setUp()
+ self.ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp)
+
+ self.base_dn = self.ldb.domain_dn()
+ self.configuration_dn = self.ldb.get_config_basedn().get_linearized()
+
+ def search_guid(self, guid):
+ print("SEARCH by GUID %s" % self.GUID_string(guid))
+
+ res = self.ldb.search(base="<GUID=%s>" % self.GUID_string(guid),
+ scope=SCOPE_BASE,
+ controls=["show_deleted:1"],
+ attrs=["*", "parentGUID"])
+ self.assertEqual(len(res), 1)
+ return res[0]
+
+ def search_dn(self, dn):
+ print("SEARCH by DN %s" % dn)
+
+ res = self.ldb.search(expression="(objectClass=*)",
+ base=dn,
+ scope=SCOPE_BASE,
+ controls=["show_deleted:1"],
+ attrs=["*", "parentGUID"])
+ self.assertEqual(len(res), 1)
+ return res[0]
+
+
+class BasicDeleteTests(BaseDeleteTests):
+
+ def setUp(self):
+ super(BasicDeleteTests, self).setUp()
+
+ def del_attr_values(self, delObj):
+ print("Checking attributes for %s" % delObj["dn"])
+
+ self.assertEqual(str(delObj["isDeleted"][0]), "TRUE")
+ self.assertTrue(not("objectCategory" in delObj))
+ self.assertTrue(not("sAMAccountType" in delObj))
+
+ def preserved_attributes_list(self, liveObj, delObj):
+ print("Checking for preserved attributes list")
+
+ preserved_list = ["nTSecurityDescriptor", "attributeID", "attributeSyntax", "dNReferenceUpdate", "dNSHostName",
+ "flatName", "governsID", "groupType", "instanceType", "lDAPDisplayName", "legacyExchangeDN",
+ "isDeleted", "isRecycled", "lastKnownParent", "msDS-LastKnownRDN", "mS-DS-CreatorSID",
+ "mSMQOwnerID", "nCName", "objectClass", "distinguishedName", "objectGUID", "objectSid",
+ "oMSyntax", "proxiedObjectName", "name", "replPropertyMetaData", "sAMAccountName",
+ "securityIdentifier", "sIDHistory", "subClassOf", "systemFlags", "trustPartner", "trustDirection",
+ "trustType", "trustAttributes", "userAccountControl", "uSNChanged", "uSNCreated", "whenCreated"]
+
+ for a in liveObj:
+ if a in preserved_list:
+ self.assertTrue(a in delObj)
+
+ def check_rdn(self, liveObj, delObj, rdnName):
+ print("Checking for correct rDN")
+ rdn = liveObj[rdnName][0]
+ rdn2 = delObj[rdnName][0]
+ name2 = delObj["name"][0]
+ dn_rdn = delObj.dn.get_rdn_value()
+ guid = liveObj["objectGUID"][0]
+ self.assertEqual(str(rdn2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid))))
+ self.assertEqual(str(name2), ("%s\nDEL:%s" % (rdn, self.GUID_string(guid))))
+ self.assertEqual(str(name2), dn_rdn)
+
+ def delete_deleted(self, ldb, dn):
+ print("Testing the deletion of the already deleted dn %s" % dn)
+
+ try:
+ ldb.delete(dn)
+ self.fail()
+ except LdbError as e:
+ (num, _) = e.args
+ self.assertEqual(num, ERR_NO_SUCH_OBJECT)
+
+ def test_delete_protection(self):
+ """Delete protection tests"""
+
+ print(self.base_dn)
+
+ delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
+ delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
+ delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
+ self.ldb.add({
+ "dn": "cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container"})
+ self.ldb.add({
+ "dn": "cn=entry1,cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container"})
+ self.ldb.add({
+ "dn": "cn=entry2,cn=ldaptestcontainer," + self.base_dn,
+ "objectclass": "container"})
+
+ try:
+ self.ldb.delete("cn=ldaptestcontainer," + self.base_dn)
+ self.fail()
+ except LdbError as e1:
+ (num, _) = e1.args
+ self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
+
+ self.ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:1"])
+
+ try:
+ res = self.ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE, attrs=[])
+ self.fail()
+ except LdbError as e2:
+ (num, _) = e2.args
+ self.assertEqual(num, ERR_NO_SUCH_OBJECT)
+ try:
+ res = self.ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE, attrs=[])
+ self.fail()
+ except LdbError as e3:
+ (num, _) = e3.args
+ self.assertEqual(num, ERR_NO_SUCH_OBJECT)
+ try:
+ res = self.ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn,
+ scope=SCOPE_BASE, attrs=[])
+ self.fail()
+ except LdbError as e4:
+ (num, _) = e4.args
+ self.assertEqual(num, ERR_NO_SUCH_OBJECT)
+
+ delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
+ delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
+ delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
+
+ # Performs some protected object delete testing
+
+ res = self.ldb.search(base="", expression="", scope=SCOPE_BASE,
+ attrs=["dsServiceName", "dNSHostName"])
+ self.assertEqual(len(res), 1)
+
+ # Delete failing since DC's nTDSDSA object is protected
+ try:
+ self.ldb.delete(res[0]["dsServiceName"][0])
+ self.fail()
+ except LdbError as e5:
+ (num, _) = e5.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+
+ res = self.ldb.search(self.base_dn, attrs=["rIDSetReferences"],
+ expression="(&(objectClass=computer)(dNSHostName=" + str(res[0]["dNSHostName"][0]) + "))")
+ self.assertEqual(len(res), 1)
+
+ # Deletes failing since DC's rIDSet object is protected
+ try:
+ self.ldb.delete(res[0]["rIDSetReferences"][0])
+ self.fail()
+ except LdbError as e6:
+ (num, _) = e6.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+ try:
+ self.ldb.delete(res[0]["rIDSetReferences"][0], ["tree_delete:1"])
+ self.fail()
+ except LdbError as e7:
+ (num, _) = e7.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+
+ # Deletes failing since three main crossRef objects are protected
+
+ try:
+ self.ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn)
+ self.fail()
+ except LdbError as e8:
+ (num, _) = e8.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+ try:
+ self.ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn, ["tree_delete:1"])
+ self.fail()
+ except LdbError as e9:
+ (num, _) = e9.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+
+ try:
+ self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn)
+ self.fail()
+ except LdbError as e10:
+ (num, _) = e10.args
+ self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
+ try:
+ self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn, ["tree_delete:1"])
+ self.fail()
+ except LdbError as e11:
+ (num, _) = e11.args
+ self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
+
+ res = self.ldb.search("cn=Partitions," + self.configuration_dn, attrs=[],
+ expression="(nCName=%s)" % self.base_dn)
+ self.assertEqual(len(res), 1)
+
+ try:
+ self.ldb.delete(res[0].dn)
+ self.fail()
+ except LdbError as e12:
+ (num, _) = e12.args
+ self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
+ try:
+ self.ldb.delete(res[0].dn, ["tree_delete:1"])
+ self.fail()
+ except LdbError as e13:
+ (num, _) = e13.args
+ self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
+
+ # Delete failing since "SYSTEM_FLAG_DISALLOW_DELETE"
+ try:
+ self.ldb.delete("CN=Users," + self.base_dn)
+ self.fail()
+ except LdbError as e14:
+ (num, _) = e14.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+
+ # Tree-delete failing since "isCriticalSystemObject"
+ try:
+ self.ldb.delete("CN=Computers," + self.base_dn, ["tree_delete:1"])
+ self.fail()
+ except LdbError as e15:
+ (num, _) = e15.args
+ self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
+
+
+class BasicTreeDeleteTests(BasicDeleteTests):
+
+ def setUp(self):
+ super(BasicTreeDeleteTests, self).setUp()
+
+ # user current time in ms to make unique objects
+ import time
+ marker = str(int(round(time.time() * 1000)))
+ usr1_name = "u_" + marker
+ usr2_name = "u2_" + marker
+ grp_name = "g1_" + marker
+ site_name = "s1_" + marker
+
+ self.usr1 = "cn=%s,cn=users,%s" % (usr1_name, self.base_dn)
+ self.usr2 = "cn=%s,cn=users,%s" % (usr2_name, self.base_dn)
+ self.grp1 = "cn=%s,cn=users,%s" % (grp_name, self.base_dn)
+ self.sit1 = "cn=%s,cn=sites,%s" % (site_name, self.configuration_dn)
+ self.ss1 = "cn=NTDS Site Settings,cn=%s,cn=sites,%s" % (site_name, self.configuration_dn)
+ self.srv1 = "cn=Servers,cn=%s,cn=sites,%s" % (site_name, self.configuration_dn)
+ self.srv2 = "cn=TESTSRV,cn=Servers,cn=%s,cn=sites,%s" % (site_name, self.configuration_dn)
+
+ delete_force(self.ldb, self.usr1)
+ delete_force(self.ldb, self.usr2)
+ delete_force(self.ldb, self.grp1)
+ delete_force(self.ldb, self.ss1)
+ delete_force(self.ldb, self.srv2)
+ delete_force(self.ldb, self.srv1)
+ delete_force(self.ldb, self.sit1)
+
+ self.ldb.add({
+ "dn": self.usr1,
+ "objectclass": "user",
+ "description": "test user description",
+ "samaccountname": usr1_name})
+
+ self.ldb.add({
+ "dn": self.usr2,
+ "objectclass": "user",
+ "description": "test user 2 description",
+ "samaccountname": usr2_name})
+
+ self.ldb.add({
+ "dn": self.grp1,
+ "objectclass": "group",
+ "description": "test group",
+ "samaccountname": grp_name,
+ "member": [self.usr1, self.usr2],
+ "isDeleted": "FALSE"})
+
+ self.ldb.add({
+ "dn": self.sit1,
+ "objectclass": "site"})
+
+ self.ldb.add({
+ "dn": self.ss1,
+ "objectclass": ["applicationSiteSettings", "nTDSSiteSettings"]})
+
+ self.ldb.add({
+ "dn": self.srv1,
+ "objectclass": "serversContainer"})
+
+ self.ldb.add({
+ "dn": self.srv2,
+ "objectClass": "server"})
+
+ self.objLive1 = self.search_dn(self.usr1)
+ self.guid1 = self.objLive1["objectGUID"][0]
+
+ self.objLive2 = self.search_dn(self.usr2)
+ self.guid2 = self.objLive2["objectGUID"][0]
+
+ self.objLive3 = self.search_dn(self.grp1)
+ self.guid3 = self.objLive3["objectGUID"][0]
+
+ self.objLive4 = self.search_dn(self.sit1)
+ self.guid4 = self.objLive4["objectGUID"][0]
+
+ self.objLive5 = self.search_dn(self.ss1)
+ self.guid5 = self.objLive5["objectGUID"][0]
+
+ self.objLive6 = self.search_dn(self.srv1)
+ self.guid6 = self.objLive6["objectGUID"][0]
+
+ self.objLive7 = self.search_dn(self.srv2)
+ self.guid7 = self.objLive7["objectGUID"][0]
+
+ self.deleted_objects_config_dn \
+ = self.ldb.get_wellknown_dn(self.ldb.get_config_basedn(),
+ dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER)
+ deleted_objects_config_obj \
+ = self.search_dn(self.deleted_objects_config_dn)
+
+ self.deleted_objects_config_guid \
+ = deleted_objects_config_obj["objectGUID"][0]
+
+ self.deleted_objects_domain_dn \
+ = self.ldb.get_wellknown_dn(self.ldb.get_default_basedn(),
+ dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER)
+ deleted_objects_domain_obj \
+ = self.search_dn(self.deleted_objects_domain_dn)
+
+ self.deleted_objects_domain_guid \
+ = deleted_objects_domain_obj["objectGUID"][0]
+
+ self.deleted_objects_domain_dn \
+ = self.ldb.get_wellknown_dn(self.ldb.get_default_basedn(),
+ dsdb.DS_GUID_DELETED_OBJECTS_CONTAINER)
+ sites_obj = self.search_dn("cn=sites,%s"
+ % self.ldb.get_config_basedn())
+ self.sites_dn = sites_obj.dn
+ self.sites_guid \
+ = sites_obj["objectGUID"][0]
+
+ def test_all(self):
+ """Basic delete tests"""
+
+ self.ldb.delete(self.usr1)
+ self.ldb.delete(self.usr2)
+ self.ldb.delete(self.grp1)
+ self.ldb.delete(self.srv1, ["tree_delete:1"])
+ self.ldb.delete(self.sit1, ["tree_delete:1"])
+
+ self.check_all()
+
+ def test_tree_delete(self):
+ """Basic delete tests,
+ but use just one tree delete for the config records
+ """
+
+ self.ldb.delete(self.usr1)
+ self.ldb.delete(self.usr2)
+ self.ldb.delete(self.grp1)
+ self.ldb.delete(self.sit1, ["tree_delete:1"])
+
+ self.check_all()
+
+ def check_all(self):
+ objDeleted1 = self.search_guid(self.guid1)
+ objDeleted2 = self.search_guid(self.guid2)
+ objDeleted3 = self.search_guid(self.guid3)
+ objDeleted4 = self.search_guid(self.guid4)
+ objDeleted5 = self.search_guid(self.guid5)
+ objDeleted6 = self.search_guid(self.guid6)
+ objDeleted7 = self.search_guid(self.guid7)
+
+ self.del_attr_values(objDeleted1)
+ self.del_attr_values(objDeleted2)
+ self.del_attr_values(objDeleted3)
+ self.del_attr_values(objDeleted4)
+ self.del_attr_values(objDeleted5)
+ self.del_attr_values(objDeleted6)
+ self.del_attr_values(objDeleted7)
+
+ self.preserved_attributes_list(self.objLive1, objDeleted1)
+ self.preserved_attributes_list(self.objLive2, objDeleted2)
+ self.preserved_attributes_list(self.objLive3, objDeleted3)
+ self.preserved_attributes_list(self.objLive4, objDeleted4)
+ self.preserved_attributes_list(self.objLive5, objDeleted5)
+ self.preserved_attributes_list(self.objLive6, objDeleted6)
+ self.preserved_attributes_list(self.objLive7, objDeleted7)
+
+ self.check_rdn(self.objLive1, objDeleted1, "cn")
+ self.check_rdn(self.objLive2, objDeleted2, "cn")
+ self.check_rdn(self.objLive3, objDeleted3, "cn")
+ self.check_rdn(self.objLive4, objDeleted4, "cn")
+ self.check_rdn(self.objLive5, objDeleted5, "cn")
+ self.check_rdn(self.objLive6, objDeleted6, "cn")
+ self.check_rdn(self.objLive7, objDeleted7, "cn")
+
+ self.delete_deleted(self.ldb, self.usr1)
+ self.delete_deleted(self.ldb, self.usr2)
+ self.delete_deleted(self.ldb, self.grp1)
+ self.delete_deleted(self.ldb, self.sit1)
+ self.delete_deleted(self.ldb, self.ss1)
+ self.delete_deleted(self.ldb, self.srv1)
+ self.delete_deleted(self.ldb, self.srv2)
+
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted1.dn))
+ self.assertEqual(objDeleted1.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted1["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted2.dn))
+ self.assertEqual(objDeleted2.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted2["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted3.dn))
+ self.assertEqual(objDeleted3.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted3["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted4.dn))
+ self.assertEqual(objDeleted4.dn.parent(),
+ self.sites_dn)
+ self.assertEqual(objDeleted4["parentGUID"][0],
+ self.sites_guid)
+
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted5.dn))
+ self.assertEqual(objDeleted5.dn.parent(),
+ self.deleted_objects_config_dn)
+ self.assertEqual(objDeleted5["parentGUID"][0],
+ self.deleted_objects_config_guid)
+
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted6.dn))
+ self.assertEqual(objDeleted6.dn.parent(),
+ objDeleted4.dn)
+ self.assertEqual(objDeleted6["parentGUID"][0],
+ objDeleted4["objectGUID"][0])
+
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted7.dn))
+ self.assertEqual(objDeleted7.dn.parent(),
+ objDeleted6.dn)
+ self.assertEqual(objDeleted7["parentGUID"][0],
+ objDeleted6["objectGUID"][0])
+
+ objDeleted1 = self.search_guid(self.guid1)
+ objDeleted2 = self.search_guid(self.guid2)
+ objDeleted3 = self.search_guid(self.guid3)
+ objDeleted4 = self.search_guid(self.guid4)
+ objDeleted5 = self.search_guid(self.guid5)
+ objDeleted6 = self.search_guid(self.guid6)
+ objDeleted7 = self.search_guid(self.guid7)
+
+ self.del_attr_values(objDeleted1)
+ self.del_attr_values(objDeleted2)
+ self.del_attr_values(objDeleted3)
+ self.del_attr_values(objDeleted4)
+ self.del_attr_values(objDeleted5)
+ self.del_attr_values(objDeleted6)
+ self.del_attr_values(objDeleted7)
+
+ self.preserved_attributes_list(self.objLive1, objDeleted1)
+ self.preserved_attributes_list(self.objLive2, objDeleted2)
+ self.preserved_attributes_list(self.objLive3, objDeleted3)
+ self.preserved_attributes_list(self.objLive4, objDeleted4)
+ self.preserved_attributes_list(self.objLive5, objDeleted5)
+ self.preserved_attributes_list(self.objLive6, objDeleted6)
+ self.preserved_attributes_list(self.objLive7, objDeleted7)
+
+ self.check_rdn(self.objLive1, objDeleted1, "cn")
+ self.check_rdn(self.objLive2, objDeleted2, "cn")
+ self.check_rdn(self.objLive3, objDeleted3, "cn")
+ self.check_rdn(self.objLive4, objDeleted4, "cn")
+ self.check_rdn(self.objLive5, objDeleted5, "cn")
+ self.check_rdn(self.objLive6, objDeleted6, "cn")
+ self.check_rdn(self.objLive7, objDeleted7, "cn")
+
+ self.delete_deleted(self.ldb, self.usr1)
+ self.delete_deleted(self.ldb, self.usr2)
+ self.delete_deleted(self.ldb, self.grp1)
+ self.delete_deleted(self.ldb, self.sit1)
+ self.delete_deleted(self.ldb, self.ss1)
+ self.delete_deleted(self.ldb, self.srv1)
+ self.delete_deleted(self.ldb, self.srv2)
+
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted1.dn))
+ self.assertEqual(objDeleted1.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted1["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted2.dn))
+ self.assertEqual(objDeleted2.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted2["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted3.dn))
+ self.assertEqual(objDeleted3.dn.parent(),
+ self.deleted_objects_domain_dn)
+ self.assertEqual(objDeleted3["parentGUID"][0],
+ self.deleted_objects_domain_guid)
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted4.dn))
+ self.assertTrue("CN=Deleted Objects" in str(objDeleted5.dn))
+ self.assertEqual(objDeleted5.dn.parent(),
+ self.deleted_objects_config_dn)
+ self.assertEqual(objDeleted5["parentGUID"][0],
+ self.deleted_objects_config_guid)
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted6.dn))
+ self.assertFalse("CN=Deleted Objects" in str(objDeleted7.dn))
+
+
+if "://" not in host:
+ if os.path.isfile(host):
+ host = "tdb://%s" % host
+ else:
+ host = "ldap://%s" % host
+
+TestProgram(module=__name__, opts=subunitopts)