From 4c8bd317d039c7dc05effffe09088f8b2e6699fb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 06:56:09 -0700 Subject: [PATCH 01/36] Remove unused imports. Change-Id: I8915f62206edb53ffc2d89434e46d9e71db8bb9a Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit f0fa5636e30063a75f2942013fc1579afa3525c2) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- auth/credentials/tests/bind.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/auth/credentials/tests/bind.py b/auth/credentials/tests/bind.py index aa4b17a..ceb3e8f 100755 --- a/auth/credentials/tests/bind.py +++ b/auth/credentials/tests/bind.py @@ -17,18 +17,12 @@ samba.ensure_external_module("subunit", "subunit/python") import samba.getopt as options -from ldb import ( - SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_NO_SUCH_OBJECT) -from samba.dcerpc import security +from ldb import SCOPE_BASE, SCOPE_SUBTREE -from samba.auth import system_session from samba import gensec -from samba.samdb import SamDB -from samba.credentials import Credentials import samba.tests, unittest from samba.tests import delete_force from subunit.run import SubunitTestRunner -from samba.tests import TestCase, TestSkipped parser = optparse.OptionParser("ldap [options] ") sambaopts = options.SambaOptions(parser) -- 2.1.4 From d2e58cf70b76b99a236eadc9a82973df22324d6c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 12 Oct 2014 21:11:22 -0700 Subject: [PATCH 02/36] urgent_replication: Use subunit reporting, remove allow_empty_output. Change-Id: I6d479b218eff6c4292fbb99e4760bbd62ce1f380 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 23ac8d130c1f476fda5d984531266a6c210c2982) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- python/samba/tests/__init__.py | 7 +- source4/dsdb/tests/python/urgent_replication.py | 116 +++++++++--------------- source4/selftest/tests.py | 2 +- 3 files changed, 50 insertions(+), 75 deletions(-) diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py index 2df30a6..8d3b4dd 100644 --- a/python/samba/tests/__init__.py +++ b/python/samba/tests/__init__.py @@ -166,8 +166,9 @@ class BlackboxTestCase(TestCase): raise BlackboxProcessError(retcode, line, p.stdout.read(), p.stderr.read()) return p.stdout.read() + def connect_samdb(samdb_url, lp=None, session_info=None, credentials=None, - flags=0, ldb_options=None, ldap_only=False): + flags=0, ldb_options=None, ldap_only=False, global_schema=True): """Create SamDB instance and connects to samdb_url database. :param samdb_url: Url for database to connect to. @@ -176,6 +177,7 @@ def connect_samdb(samdb_url, lp=None, session_info=None, credentials=None, :param credentials: Optional credentials, defaults to anonymous. :param flags: Optional LDB flags :param ldap_only: If set, only remote LDAP connection will be created. + :param global_schema: Whether to use global schema. Added value for tests is that we have a shorthand function to make proper URL for ldb.connect() while using default @@ -207,7 +209,8 @@ def connect_samdb(samdb_url, lp=None, session_info=None, credentials=None, session_info=session_info, credentials=credentials, flags=flags, - options=ldb_options) + options=ldb_options, + global_schema=global_schema) def connect_samdb_ex(samdb_url, lp=None, session_info=None, credentials=None, diff --git a/source4/dsdb/tests/python/urgent_replication.py b/source4/dsdb/tests/python/urgent_replication.py index 2a07a58..8083ce4 100755 --- a/source4/dsdb/tests/python/urgent_replication.py +++ b/source4/dsdb/tests/python/urgent_replication.py @@ -3,29 +3,26 @@ import optparse import sys -import os - sys.path.insert(0, "bin/python") import samba samba.ensure_external_module("testtools", "testtools") samba.ensure_external_module("subunit", "subunit/python") -import samba.getopt as options - -from samba.auth import system_session from ldb import (LdbError, ERR_NO_SUCH_OBJECT, Message, MessageElement, Dn, FLAG_MOD_REPLACE) -from samba.samdb import SamDB import samba.tests import samba.dsdb as dsdb +import samba.getopt as options from subunit.run import SubunitTestRunner + import unittest parser = optparse.OptionParser("urgent_replication.py [options] ") 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) @@ -37,8 +34,6 @@ if len(args) < 1: host = args[0] -lp = sambaopts.get_loadparm() -creds = credopts.get_credentials(lp) class UrgentReplicationTests(samba.tests.TestCase): @@ -50,30 +45,29 @@ class UrgentReplicationTests(samba.tests.TestCase): def setUp(self): super(UrgentReplicationTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() + self.ldb = samba.tests.connect_samdb(host, global_schema=False) + self.base_dn = self.ldb.domain_dn() print "baseDN: %s\n" % self.base_dn def test_nonurgent_object(self): - """Test if the urgent replication is not activated - when handling a non urgent object""" + """Test if the urgent replication is not activated when handling a non urgent object.""" self.ldb.add({ "dn": "cn=nonurgenttest,cn=users," + self.base_dn, "objectclass":"user", "samaccountname":"nonurgenttest", "description":"nonurgenttest description"}) - # urgent replication should not be enabled when creating + # urgent replication should not be enabled when creating res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should not be enabled when modifying m = Message() - m.dn = Dn(ldb, "cn=nonurgenttest,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=nonurgenttest,cn=users," + self.base_dn) m["description"] = MessageElement("new description", FLAG_MOD_REPLACE, "description") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) @@ -82,12 +76,11 @@ class UrgentReplicationTests(samba.tests.TestCase): res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) - def test_nTDSDSA_object(self): - '''Test if the urgent replication is activated - when handling a nTDSDSA object''' + """Test if the urgent replication is activated when handling a nTDSDSA object.""" self.ldb.add({ - "dn": "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,%s" % self.ldb.get_config_basedn(), + "dn": "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,%s" % + self.ldb.get_config_basedn(), "objectclass":"server", "cn":"test server", "name":"test server", @@ -107,10 +100,10 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should NOT be enabled when modifying m = Message() - m.dn = Dn(ldb, "cn=NTDS Settings test,cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn) + m.dn = Dn(self.ldb, "cn=NTDS Settings test,cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn) m["options"] = MessageElement("0", FLAG_MOD_REPLACE, "options") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) @@ -121,15 +114,13 @@ systemFlags: 33554432""", ["relax:0"]) self.delete_force(self.ldb, "cn=test server,cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration," + self.base_dn) - def test_crossRef_object(self): - '''Test if the urgent replication is activated - when handling a crossRef object''' + """Test if the urgent replication is activated when handling a crossRef object.""" self.ldb.add({ "dn": "CN=test crossRef,CN=Partitions,CN=Configuration,"+ self.base_dn, "objectClass": "crossRef", "cn": "test crossRef", - "dnsRoot": lp.get("realm").lower(), + "dnsRoot": self.get_loadparm().get("realm").lower(), "instanceType": "4", "nCName": self.base_dn, "showInAdvancedViewOnly": "TRUE", @@ -142,10 +133,10 @@ systemFlags: 33554432""", ["relax:0"]) # urgent replication should NOT be enabled when modifying m = Message() - m.dn = Dn(ldb, "cn=test crossRef,CN=Partitions,CN=Configuration," + self.base_dn) + m.dn = Dn(self.ldb, "cn=test crossRef,CN=Partitions,CN=Configuration," + self.base_dn) m["systemFlags"] = MessageElement("0", FLAG_MOD_REPLACE, "systemFlags") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) @@ -155,11 +146,8 @@ systemFlags: 33554432""", ["relax:0"]) res = self.ldb.load_partition_usn("cn=Configuration," + self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) - - def test_attributeSchema_object(self): - '''Test if the urgent replication is activated - when handling an attributeSchema object''' + """Test if the urgent replication is activated when handling an attributeSchema object""" try: self.ldb.add_ldif( @@ -186,19 +174,17 @@ name: test attributeSchema""") except LdbError: print "Not testing urgent replication when creating attributeSchema object ...\n" - # urgent replication should be enabled when modifying + # urgent replication should be enabled when modifying m = Message() - m.dn = Dn(ldb, "CN=test attributeSchema,CN=Schema,CN=Configuration," + self.base_dn) + m.dn = Dn(self.ldb, "CN=test attributeSchema,CN=Schema,CN=Configuration," + self.base_dn) m["lDAPDisplayName"] = MessageElement("updated test attributeSchema", FLAG_MOD_REPLACE, "lDAPDisplayName") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) - def test_classSchema_object(self): - '''Test if the urgent replication is activated - when handling a classSchema object''' + """Test if the urgent replication is activated when handling a classSchema object.""" try: self.ldb.add_ldif( """dn: CN=test classSchema,CN=Schema,CN=Configuration,%s""" % self.base_dn + """ @@ -231,17 +217,15 @@ defaultHidingValue: TRUE""") # urgent replication should be enabled when modifying m = Message() - m.dn = Dn(ldb, "CN=test classSchema,CN=Schema,CN=Configuration," + self.base_dn) + m.dn = Dn(self.ldb, "CN=test classSchema,CN=Schema,CN=Configuration," + self.base_dn) m["lDAPDisplayName"] = MessageElement("updated test classSchema", FLAG_MOD_REPLACE, "lDAPDisplayName") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn("cn=Schema,cn=Configuration," + self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) - def test_secret_object(self): - '''Test if the urgent replication is activated - when handling a secret object''' + """Test if the urgent replication is activated when handling a secret object.""" self.ldb.add({ "dn": "cn=test secret,cn=System," + self.base_dn, @@ -256,22 +240,20 @@ defaultHidingValue: TRUE""") # urgent replication should be enabled when modifying m = Message() - m.dn = Dn(ldb, "cn=test secret,cn=System," + self.base_dn) + m.dn = Dn(self.ldb, "cn=test secret,cn=System," + self.base_dn) m["currentValue"] = MessageElement("yyyyyyyy", FLAG_MOD_REPLACE, "currentValue") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) - # urgent replication should NOT be enabled when deleting + # urgent replication should NOT be enabled when deleting self.delete_force(self.ldb, "cn=test secret,cn=System," + self.base_dn) res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) - def test_rIDManager_object(self): - '''Test if the urgent replication is activated - when handling a rIDManager object''' + """Test if the urgent replication is activated when handling a rIDManager object.""" self.ldb.add_ldif( """dn: CN=RID Manager test,CN=System,%s""" % self.base_dn + """ objectClass: rIDManager @@ -289,10 +271,10 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) # urgent replication should be enabled when modifying m = Message() - m.dn = Dn(ldb, "CN=RID Manager test,CN=System," + self.base_dn) + m.dn = Dn(self.ldb, "CN=RID Manager test,CN=System," + self.base_dn) m["systemFlags"] = MessageElement("0", FLAG_MOD_REPLACE, "systemFlags") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) @@ -301,10 +283,8 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) - def test_urgent_attributes(self): - '''Test if the urgent replication is activated - when handling urgent attributes of an object''' + """Test if the urgent replication is activated when handling urgent attributes of an object.""" self.ldb.add({ "dn": "cn=user UrgAttr test,cn=users," + self.base_dn, @@ -319,40 +299,40 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) - # urgent replication should be enabled when modifying userAccountControl + # urgent replication should be enabled when modifying userAccountControl m = Message() - m.dn = Dn(ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) m["userAccountControl"] = MessageElement(str(dsdb.UF_NORMAL_ACCOUNT+dsdb.UF_SMARTCARD_REQUIRED), FLAG_MOD_REPLACE, "userAccountControl") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying lockoutTime m = Message() - m.dn = Dn(ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) m["lockoutTime"] = MessageElement("1", FLAG_MOD_REPLACE, "lockoutTime") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should be enabled when modifying pwdLastSet m = Message() - m.dn = Dn(ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) m["pwdLastSet"] = MessageElement("1", FLAG_MOD_REPLACE, "pwdLastSet") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertEquals(res["uSNHighest"], res["uSNUrgent"]) # urgent replication should NOT be enabled when modifying a not-urgent # attribute m = Message() - m.dn = Dn(ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=user UrgAttr test,cn=users," + self.base_dn) m["description"] = MessageElement("updated urgent attributes test description", FLAG_MOD_REPLACE, "description") - ldb.modify(m) + self.ldb.modify(m) res = self.ldb.load_partition_usn(self.base_dn) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) @@ -362,18 +342,10 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) -if not "://" in host: - if os.path.isfile(host): - host = "tdb://%s" % host - else: - host = "ldap://%s" % host - - -ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp, - global_schema=False) - runner = SubunitTestRunner() rc = 0 +# if not runner.run(unittest.makeSuite(UrgentReplicationTests)).wasSuccessful(): rc = 1 + sys.exit(rc) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 8d03b40..4db09c1 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -469,7 +469,7 @@ planoldpythontestsuite("dc", "dsdb_schema_info", extra_path=[os.path.join(samba4srcdir, 'dsdb/tests/python')], name="samba4.schemaInfo.python(dc)", extra_args=['-U"$DOMAIN/$DC_USERNAME%$DC_PASSWORD"']) -plantestsuite("samba4.urgent_replication.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/urgent_replication.py"), '$PREFIX_ABS/dc/private/sam.ldb'], allow_empty_output=True) +plantestsuite("samba4.urgent_replication.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/urgent_replication.py"), '$PREFIX_ABS/dc/private/sam.ldb']) plantestsuite("samba4.ldap.dirsync.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) plantestsuite("samba4.ldap.sites.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: -- 2.1.4 From b1d166c4d21259565af3c31310732613902ff28d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 12 Oct 2014 21:17:05 -0700 Subject: [PATCH 03/36] samba3dump: Add subunit-enabled test for samba3dump. Change-Id: Ie9682c715fc91d923dcd1951236f8b36fa519327 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 77b72d4c8e02e6bba9ef8c90287455a784afe9d8) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/selftest/test_samba3dump.sh | 14 ++++++++++++++ source4/selftest/tests.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100755 source4/selftest/test_samba3dump.sh diff --git a/source4/selftest/test_samba3dump.sh b/source4/selftest/test_samba3dump.sh new file mode 100755 index 0000000..4db142b --- /dev/null +++ b/source4/selftest/test_samba3dump.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Verify that samba3dump completes. + +. lib/subunit/shell/share/subunit.sh + +subunit_start_test samba3dump + +SRCDIR=`dirname $0`/../.. + +if $SRCDIR/source4/scripting/bin/samba3dump $SRCDIR/testdata/samba3; then + subunit_pass_test samba3dump +else + echo | subunit_fail_test samba3dump +fi diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 4db09c1..83a4c3f 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -489,7 +489,7 @@ planpythontestsuite("plugin_s4_dc:local", "samba.tests.posixacl") plantestsuite("samba4.deletetest.python(dc)", "dc", ['PYTHONPATH="$PYTHONPATH:%s/lib/subunit/python:%s/lib/testtools"' % (srcdir(), srcdir()), python, os.path.join(samba4srcdir, "dsdb/tests/python/deletetest.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) -plantestsuite("samba4.blackbox.samba3dump", "none", [python, os.path.join(samba4srcdir, "scripting/bin/samba3dump"), os.path.join(samba4srcdir, "../testdata/samba3")], allow_empty_output=True) +plantestsuite("samba4.blackbox.samba3dump", "none", ['PYTHONPATH="$PYTHONPATH:%s/lib/subunit/python:%s/lib/testtools"' % (srcdir(), srcdir()), os.path.join(samba4srcdir, "selftest/test_samba3dump.sh")]) plantestsuite("samba4.blackbox.upgrade", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_s3upgrade.sh"), '$PREFIX/provision']) plantestsuite("samba4.blackbox.provision.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_provision.sh"), '$PREFIX/provision']) plantestsuite("samba4.blackbox.upgradeprovision.current", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_upgradeprovision.sh"), '$PREFIX/provision']) -- 2.1.4 From 9735e07444b808700f7d3b1cbe5280b98c5208da Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 12 Oct 2014 21:18:08 -0700 Subject: [PATCH 04/36] filter-subunit: Drop support for allow_empty_output hack. Change-Id: If4f336ef770202dcf69484b9bccc6c0c80bd5f9b Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Tue Oct 14 09:06:05 CEST 2014 on sn-devel-104 (cherry picked from commit 0c2c75a2d7afdb3e08aa29f6b996d953dcc3b5a1) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/selftesthelpers.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 40e38aa..d1b3e13 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -90,7 +90,7 @@ def valgrindify(cmdline): return valgrind + " " + cmdline -def plantestsuite(name, env, cmdline, allow_empty_output=False): +def plantestsuite(name, env, cmdline): """Plan a test suite. :param name: Testsuite name @@ -102,17 +102,13 @@ def plantestsuite(name, env, cmdline, allow_empty_output=False): print env if isinstance(cmdline, list): cmdline = " ".join(cmdline) - filter_subunit_args = [] - if not allow_empty_output: - filter_subunit_args.append("--fail-on-empty") + filter_subunit_args = ["--fail-on-empty"] if "$LISTOPT" in cmdline: filter_subunit_args.append("$LISTOPT") print "%s 2>&1 | %s/selftest/filter-subunit %s --prefix=\"%s.\" --suffix=\"(%s)\"" % (cmdline, srcdir(), " ".join(filter_subunit_args), name, env) - if allow_empty_output: - print >>sys.stderr, "WARNING: allowing empty subunit output from %s" % name def add_prefix(prefix, env, support_list=False): -- 2.1.4 From ea7650dcf8d7c41157ea070d4add8e2c44768819 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:27:30 -0700 Subject: [PATCH 05/36] dirsync test: Create and run a single testsuite, should easy migration to regulary Python unit tests. Change-Id: I6fbffd6453f8af966938943f2895bd6d93f8fb59 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 7f0969d79a45c7ae4c62a319889680bf3117b71c) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/dirsync.py | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index f36a3c0..14810d3 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -77,12 +77,12 @@ class DirsyncBaseTests(samba.tests.TestCase): def setUp(self): super(DirsyncBaseTests, self).setUp() - self.ldb_admin = ldb - self.base_dn = ldb.domain_dn() - self.domain_sid = security.dom_sid(ldb.get_domain_sid()) + self.ldb_admin = SamDB(ldapshost, credentials=creds, session_info=system_session(lp), lp=lp) + self.base_dn = self.ldb_admin.domain_dn() + self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid()) self.user_pass = "samba123@AAA" self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized() - self.sd_utils = sd_utils.SDUtils(ldb) + self.sd_utils = sd_utils.SDUtils(self.ldb_admin) #used for anonymous login print "baseDN: %s" % self.base_dn @@ -142,7 +142,6 @@ class SimpleDirsyncTests(DirsyncBaseTests): #def test_dirsync_errors(self): - def test_dirsync_supported(self): """Test the basic of the dirsync is supported""" self.ldb_dirsync = self.get_ldb_connection(self.dirsync_user, self.user_pass) @@ -222,9 +221,6 @@ class SimpleDirsyncTests(DirsyncBaseTests): print l self.assertTrue(str(l).find("LDAP_UNWILLING_TO_PERFORM") != -1) - - - def test_dirsync_attributes(self): """Check behavior with some attributes """ res = self.ldb_admin.search(self.base_dn, @@ -590,7 +586,9 @@ class SimpleDirsyncTests(DirsyncBaseTests): expression="(&(objectClass=organizationalUnit)(!(isDeleted=*)))", controls=controls) + class ExtendedDirsyncTests(SimpleDirsyncTests): + def test_dirsync_linkedattributes(self): flag_incr_linked = 2147483648 self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) @@ -698,14 +696,13 @@ class ExtendedDirsyncTests(SimpleDirsyncTests): self.assertEqual(str(res[0].dn), "") -ldb = SamDB(ldapshost, credentials=creds, session_info=system_session(lp), lp=lp) - runner = SubunitTestRunner() -rc = 0 -# -if not runner.run(unittest.makeSuite(SimpleDirsyncTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(ExtendedDirsyncTests)).wasSuccessful(): +suite = unittest.TestSuite() +suite.addTests(unittest.makeSuite(SimpleDirsyncTests)) +suite.addTests(unittest.makeSuite(ExtendedDirsyncTests)) +if not runner.run(suite).wasSuccessful(): rc = 1 +else: + rc = 0 sys.exit(rc) -- 2.1.4 From cf443df245a6329e9152d7f1f227d74158b35318 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:09:12 -0700 Subject: [PATCH 06/36] speedtest: Create and run a single testsuite, should easy migration to regulary Python unit tests. Change-Id: Ib31eb26b8f6094a51cd4985b9ae98d018ae95c2d Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 5757c5071e3cf5f207bc9772beffe5c2a7eb22f3) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/scripting/devel/speedtest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source4/scripting/devel/speedtest.py b/source4/scripting/devel/speedtest.py index fed2705..84d3760 100755 --- a/source4/scripting/devel/speedtest.py +++ b/source4/scripting/devel/speedtest.py @@ -35,10 +35,8 @@ samba.ensure_external_module("subunit", "subunit/python") import samba.getopt as options -from ldb import ( - SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_NO_SUCH_OBJECT, - ERR_UNWILLING_TO_PERFORM, ERR_INSUFFICIENT_ACCESS_RIGHTS) -from samba.ndr import ndr_pack, ndr_unpack +from ldb import SCOPE_BASE, SCOPE_SUBTREE +from samba.ndr import ndr_unpack from samba.dcerpc import security from samba.auth import system_session @@ -233,9 +231,11 @@ ldb_options = ["modules:paged_searches"] ldb = SamDB(host, credentials=creds, session_info=system_session(), lp=lp, options=ldb_options) runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(SpeedTestAddDel)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclSearchSpeedTest)).wasSuccessful(): +suite = unittest.TestSuite() +suite.addTests(unittest.makeSuite(SpeedTestAddDel)) +suite.addTests(unittest.makeSuite(AclSearchSpeedTest)) +if not runner.run(suite).wasSuccessful(): rc = 1 +else: + rc = 0 sys.exit(rc) -- 2.1.4 From 85fba1194e485b4e0044b8cfc52d8dc42eb36cc7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:07:02 -0700 Subject: [PATCH 07/36] dsdb.tests.ldap: Create and run a single testsuite, should easy migration to regulary Python unit tests. Change-Id: I07216ff1063e127b541bf4e5d6349d5a75cec678 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit d8177912be179dc4342118827ce439048df43ef9) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/ldap.py | 189 +++++++++++++++----------------------- 1 file changed, 73 insertions(+), 116 deletions(-) diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py index c0bb18c..cfb21d2 100755 --- a/source4/dsdb/tests/python/ldap.py +++ b/source4/dsdb/tests/python/ldap.py @@ -71,8 +71,6 @@ class BasicTests(samba.tests.TestCase): self.schema_dn = ldb.get_schema_basedn().get_linearized() self.domain_sid = security.dom_sid(ldb.get_domain_sid()) - print "baseDN: %s\n" % self.base_dn - delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn) delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn) @@ -100,8 +98,6 @@ class BasicTests(samba.tests.TestCase): def test_objectclasses(self): """Test objectClass behaviour""" - print "Test objectClass behaviour""" - # Invalid objectclass specified try: self.ldb.add({ @@ -453,8 +449,6 @@ class BasicTests(samba.tests.TestCase): def test_system_only(self): """Test systemOnly objects""" - print "Test systemOnly objects""" - try: self.ldb.add({ "dn": "cn=ldaptestobject," + self.base_dn, @@ -540,8 +534,6 @@ class BasicTests(samba.tests.TestCase): def test_invalid_parent(self): """Test adding an object with invalid parent""" - print "Test adding an object with invalid parent""" - try: self.ldb.add({ "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123," @@ -566,8 +558,6 @@ class BasicTests(samba.tests.TestCase): def test_invalid_attribute(self): """Test invalid attributes on schema/objectclasses""" - print "Test invalid attributes on schema/objectclasses""" - # attributes not in schema test # add operation @@ -668,8 +658,6 @@ class BasicTests(samba.tests.TestCase): def test_single_valued_attributes(self): """Test single-valued attributes""" - print "Test single-valued attributes" - try: self.ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -713,8 +701,6 @@ class BasicTests(samba.tests.TestCase): def test_attribute_ranges(self): """Test attribute ranges""" - print "Test attribute ranges" - # Too short (min. 1) try: ldb.add({ @@ -768,8 +754,6 @@ class BasicTests(samba.tests.TestCase): def test_empty_messages(self): """Test empty messages""" - print "Test empty messages" - m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -789,8 +773,6 @@ class BasicTests(samba.tests.TestCase): def test_empty_attributes(self): """Test empty attributes""" - print "Test empty attributes" - m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) m["objectClass"] = MessageElement("group", FLAG_MOD_ADD, "objectClass") @@ -834,8 +816,6 @@ class BasicTests(samba.tests.TestCase): def test_instanceType(self): """Tests the 'instanceType' attribute""" - print "Tests the 'instanceType' attribute" - # The instance type is single-valued try: self.ldb.add({ @@ -914,8 +894,6 @@ class BasicTests(samba.tests.TestCase): def test_distinguished_name(self): """Tests the 'distinguishedName' attribute""" - print "Tests the 'distinguishedName' attribute" - # The "dn" shortcut isn't supported m = Message() m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn) @@ -994,8 +972,6 @@ class BasicTests(samba.tests.TestCase): def test_rdn_name(self): """Tests the RDN""" - print "Tests the RDN" - # Search # empty RDN @@ -1189,8 +1165,6 @@ objectClass: container def test_rename(self): """Tests the rename operation""" - print "Tests the rename operations" - try: # cannot rename to be a child of itself ldb.rename(self.base_dn, "dc=test," + self.base_dn) @@ -1300,8 +1274,6 @@ objectClass: container def test_rename_twice(self): """Tests the rename operation twice - this corresponds to a past bug""" - print "Tests the rename twice operation" - self.ldb.add({ "dn": "cn=ldaptestuser5,cn=users," + self.base_dn, "objectclass": "user" }) @@ -1313,17 +1285,13 @@ objectClass: container "objectclass": "user" }) ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn) res = ldb.search(expression="cn=ldaptestuser5") - print "Found %u records" % len(res) self.assertEquals(len(res), 1, "Wrong number of hits for cn=ldaptestuser5") res = ldb.search(expression="(&(cn=ldaptestuser5)(objectclass=user))") - print "Found %u records" % len(res) self.assertEquals(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))") delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn) def test_objectGUID(self): """Test objectGUID behaviour""" - print "Testing objectGUID behaviour\n" - # The objectGUID cannot directly be set try: self.ldb.add_ldif(""" @@ -1355,8 +1323,6 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d def test_parentGUID(self): """Test parentGUID behaviour""" - print "Testing parentGUID behaviour\n" - self.ldb.add({ "dn": "cn=parentguidtest,cn=users," + self.base_dn, "objectclass":"user", @@ -1410,7 +1376,7 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d self.assertTrue(len(res1[0]["samaccountname"]) == 1) self.assertEquals(res1[0]["samaccountname"][0], "parentguidtest"); - print "Testing parentGUID behaviour on rename\n" + # Testing parentGUID behaviour on rename\ self.ldb.add({ "dn": "cn=testotherusers," + self.base_dn, @@ -1429,7 +1395,6 @@ objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d def test_usnChanged(self): """Test usnChanged behaviour""" - print "Testing usnChanged behaviour\n" self.ldb.add({ "dn": "cn=ldaptestcontainer," + self.base_dn, @@ -1584,7 +1549,6 @@ delete: description def test_groupType_int32(self): """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)""" - print "Testing groupType (int32) behaviour\n" res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, attrs=["groupType"], expression="groupType=2147483653"); @@ -1600,7 +1564,6 @@ delete: description def test_linked_attributes(self): """This tests the linked attribute behaviour""" - print "Testing linked attribute behaviour\n" ldb.add({ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn, @@ -1689,7 +1652,6 @@ delete: description def test_wkguid(self): """Test Well known GUID behaviours (including DN+Binary)""" - print "Test Well known GUID behaviours (including DN+Binary)" res = self.ldb.search(base=("" % self.base_dn), scope=SCOPE_BASE, attrs=[]) self.assertEquals(len(res), 1) @@ -1706,7 +1668,6 @@ delete: description def test_subschemasubentry(self): """Test subSchemaSubEntry appears when requested, but not when not requested""" - print "Test subSchemaSubEntry" res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"]) self.assertEquals(len(res), 1) @@ -1719,7 +1680,7 @@ delete: description def test_all(self): """Basic tests""" - print "Testing user add" + # Testing user add ldb.add({ "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn, @@ -1768,7 +1729,7 @@ delete: description "cn": "LDAPtestCOMPUTER3" }) - print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))"; + # Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user)) res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))"); self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res)) @@ -1789,7 +1750,7 @@ delete: description delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn) - print "Testing attribute or value exists behaviour" + # Testing attribute or value exists behaviour try: ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ @@ -1821,7 +1782,7 @@ servicePrincipalName: host/ldaptest2computer except LdbError, (num, msg): self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS) - print "Testing ranged results" + # Testing ranged results ldb.modify_ldif(""" dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """ changetype: modify @@ -1867,12 +1828,10 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-*"]) self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - #print len(res[0]["servicePrincipalName;range=0-*"]) self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"]) self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - # print res[0]["servicePrincipalName;range=0-19"].length self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20) @@ -1897,8 +1856,6 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"]) self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19) - # print res[0]["servicePrincipalName;range=11-*"][18] - # print pos_11 # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11) res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"]) @@ -1908,8 +1865,6 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"]) self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)") - # print res[0]["servicePrincipalName"][18] - # print pos_11 self.assertEquals(len(res[0]["servicePrincipalName"]), 30) # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11) @@ -1921,7 +1876,7 @@ servicePrincipalName: host/ldaptest2computer29 "givenname": "testy", "sn": "ldap user2"}) - print "Testing Ambigious Name Resolution" + # Testing Ambigious Name Resolution # Testing ldb.search for (&(anr=ldap testy)(objectClass=user)) res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))") self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res)) @@ -2003,17 +1958,17 @@ servicePrincipalName: host/ldaptest2computer29 # res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))") # self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))") - print "Testing Renames" + # Testing Renames attrs = ["objectGUID", "objectSid"] - print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user)) res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") # Check rename works with extended/alternate DN forms ldb.rename("" , "cn=ldaptestUSER3,cn=users," + self.base_dn) - print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user)) res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))") @@ -2041,11 +1996,11 @@ servicePrincipalName: host/ldaptest2computer29 res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))") - print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") - should not work" + # Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") - should not work res = ldb.search(expression="(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") self.assertEquals(len(res), 0, "Could find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") - print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")" + # Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") self.assertEquals(len(res), 1, "Could not find (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")") self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn)) @@ -2097,7 +2052,7 @@ servicePrincipalName: host/ldaptest2computer29 ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn) - print "Testing subtree renames" + # Testing subtree renames ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn, "objectClass": "container"}) @@ -2124,14 +2079,14 @@ member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ """) - print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn + # Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn) - print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))") - print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn + # Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn try: res = ldb.search("cn=ldaptestcontainer," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", @@ -2140,7 +2095,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ except LdbError, (num, _): self.assertEquals(num, ERR_NO_SUCH_OBJECT) - print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn + # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn try: res = ldb.search("cn=ldaptestcontainer," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL) @@ -2148,7 +2103,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ except LdbError, (num, _): self.assertEquals(num, ERR_NO_SUCH_OBJECT) - print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container" + # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container" res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE) self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn) @@ -2157,55 +2112,55 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ time.sleep(4) - print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes" + # Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes" res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE) self.assertEquals(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not consistant with subtree renames?") - print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn + # Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn try: ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) - print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn + # Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn try: ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn) self.fail() except LdbError, (num, _): self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER)) - print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn + # Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn try: ldb.delete("cn=ldaptestcontainer2," + self.base_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) - print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + # Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE) self.assertEquals(len(res), 1) res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE) self.assertEquals(len(res), 0) - print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn + # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL) self.assertEquals(len(res), 1) - print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn + # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE) self.assertEquals(len(res), 1) - print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn) + # Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn) ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)) - print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn + # Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn ldb.delete("cn=ldaptestcontainer2," + self.base_dn) ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"}) ldb.add({"dn": "cn=ldaptestutf8user2 èùéìòà,cn=users," + self.base_dn, "objectClass": "user"}) - print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") @@ -2221,26 +2176,26 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) self.assertEquals(len(res[0]["memberOf"]), 1) - print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn() + # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn() res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()) self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()) self.assertEquals(res[0].dn, res2[0].dn) - print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))" + # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))" res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))") self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3)) self.assertEquals(res[0].dn, res3[0].dn) if gc_ldb is not None: - print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog" + # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog" res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))") self.assertEquals(len(res3gc), 1) self.assertEquals(res[0].dn, res3gc[0].dn) - print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control" + # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control" if gc_ldb is not None: res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"]) @@ -2250,7 +2205,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ ldb.delete(res[0].dn) - print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))") @@ -2267,45 +2222,45 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) self.assertEquals(len(res[0]["memberOf"]), 1) - print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn() + # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn() res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()) self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()) self.assertEquals(res[0].dn, res2[0].dn) if gc_ldb is not None: - print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) in Global Catalog" % gc_ldb.get_schema_basedn() + # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) in Global Catalog" % gc_ldb.get_schema_basedn() res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % gc_ldb.get_schema_basedn()) self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) In Global Catalog" % gc_ldb.get_schema_basedn()) self.assertEquals(res[0].dn, res2gc[0].dn) - print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))" + # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))" res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))") self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))") self.assertEquals(res[0].dn, res3[0].dn) if gc_ldb is not None: - print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog" + # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog" res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))") self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog") self.assertEquals(res[0].dn, res3gc[0].dn) - print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))" + # Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))" res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))") self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))") self.assertEquals(res[0].dn, res4[0].dn) - print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))" + # Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))" res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))") self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))") self.assertEquals(res[0].dn, res5[0].dn) - print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))" + # Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))" res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))") self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))") @@ -2313,7 +2268,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ ldb.delete("") - print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))") @@ -2330,7 +2285,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ ldb.delete("") attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"] - print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))" res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") @@ -2350,7 +2305,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ ldaptestuser2_guid = res_user[0]["objectGUID"][0] attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"] - print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))" + # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") @@ -2380,7 +2335,7 @@ member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """ self.assertTrue((";;CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP) - print "Quicktest for linked attributes" + # Quicktest for linked attributes" ldb.modify_ldif(""" dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """ changetype: modify @@ -2443,14 +2398,14 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ time.sleep(4) attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"] - print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete" + # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete") self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn)) self.assertTrue("member" not in res[0]) - print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))") res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))") @@ -2466,11 +2421,11 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ # delete "ldaptestutf8user" ldb.delete(res[0].dn) - print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))") - print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))" + # Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))" res = ldb.search(expression="(&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))") self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))") @@ -2479,37 +2434,37 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn)) - print "Testing that we can't get at the configuration DN from the main search base" + # Testing that we can't get at the configuration DN from the main search base" res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertEquals(len(res), 0) - print "Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control" + # Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control" res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"]) self.assertTrue(len(res) > 0) if gc_ldb is not None: - print "Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0" + # Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0" res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"]) self.assertTrue(len(res) > 0) - print "Testing that we do find configuration elements in the global catlog" + # Testing that we do find configuration elements in the global catlog" res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing that we do find configuration elements and user elements at the same time" + # Testing that we do find configuration elements and user elements at the same time" res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing that we do find configuration elements in the global catlog, with the configuration basedn" + # Testing that we do find configuration elements in the global catlog, with the configuration basedn" res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing that we can get at the configuration DN on the main LDAP port" + # Testing that we can get at the configuration DN on the main LDAP port" res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing objectCategory canonacolisation" + # Testing objectCategory canonacolisation" res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA") self.assertTrue(len(res) != 0) @@ -2518,7 +2473,7 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn) self.assertTrue(len(res) != 0) - print "Testing objectClass attribute order on "+ self.base_dn + # Testing objectClass attribute order on "+ self.base_dn res = ldb.search(expression="objectClass=domain", base=self.base_dn, scope=SCOPE_BASE, attrs=["objectClass"]) self.assertEquals(len(res), 1) @@ -2527,31 +2482,31 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ # check enumeration - print "Testing ldb.search for objectCategory=person" + # Testing ldb.search for objectCategory=person" res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing ldb.search for objectCategory=person with domain scope control" + # Testing ldb.search for objectCategory=person with domain scope control" res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"]) self.assertTrue(len(res) > 0) - print "Testing ldb.search for objectCategory=user" + # Testing ldb.search for objectCategory=user" res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing ldb.search for objectCategory=user with domain scope control" + # Testing ldb.search for objectCategory=user with domain scope control" res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"]) self.assertTrue(len(res) > 0) - print "Testing ldb.search for objectCategory=group" + # Testing ldb.search for objectCategory=group" res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"]) self.assertTrue(len(res) > 0) - print "Testing ldb.search for objectCategory=group with domain scope control" + # Testing ldb.search for objectCategory=group with domain scope control" res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"]) self.assertTrue(len(res) > 0) - print "Testing creating a user with the posixAccount objectClass" + # Testing creating a user with the posixAccount objectClass" self.ldb.add_ldif("""dn: cn=posixuser,CN=Users,%s objectClass: top objectClass: person @@ -2568,13 +2523,13 @@ loginShell: /bin/bash gecos: Posix User;;; description: A POSIX user"""% (self.base_dn)) - print "Testing removing the posixAccount objectClass from an existing user" + # Testing removing the posixAccount objectClass from an existing user" self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s changetype: modify delete: objectClass objectClass: posixAccount"""% (self.base_dn)) - print "Testing adding the posixAccount objectClass to an existing user" + # Testing adding the posixAccount objectClass to an existing user" self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s changetype: modify add: objectClass @@ -2837,7 +2792,7 @@ nTSecurityDescriptor:: """ + desc_base64 def test_dsheuristics(self): """Tests the 'dSHeuristics' attribute""" - print "Tests the 'dSHeuristics' attribute" + # Tests the 'dSHeuristics' attribute" # Get the current value to restore it later dsheuristics = self.ldb.get_dsheuristics() @@ -2880,7 +2835,7 @@ nTSecurityDescriptor:: """ + desc_base64 def test_operational(self): """Tests operational attributes""" - print "Tests operational attributes" + # Tests operational attributes" res = self.ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["createTimeStamp", "modifyTimeStamp", @@ -3060,9 +3015,11 @@ else: gc_ldb = None runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful(): +suite = unittest.TestSuite() +suite.addTests(unittest.makeSuite(BaseDnTests)) +suite.addTests(unittest.makeSuite(BasicTests)) +if not runner.run(suite).wasSuccessful(): rc = 1 +else: + rc = 0 sys.exit(rc) -- 2.1.4 From d9220de77afdafcc7be44e4bc249a0bef38ce2bd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:06:52 -0700 Subject: [PATCH 08/36] dsdb.tests.acl: Create and run a single testsuite, should easy migration to regulary Python unit tests. Change-Id: I89072d3af1d90e87a47c197d28943f47cedc5deb Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 1800bc567d56d0c193410a83692185ebbbce7f43) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/acl.py | 77 ++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index a8c3b12..7ef9ad9 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -67,12 +67,12 @@ class AclTests(samba.tests.TestCase): def setUp(self): super(AclTests, self).setUp() - self.ldb_admin = ldb - self.base_dn = ldb.domain_dn() - self.domain_sid = security.dom_sid(ldb.get_domain_sid()) + self.ldb_admin = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) + self.base_dn = self.ldb_admin.domain_dn() + self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid()) self.user_pass = "samba123@" self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized() - self.sd_utils = sd_utils.SDUtils(ldb) + self.sd_utils = sd_utils.SDUtils(self.ldb_admin) #used for anonymous login self.creds_tmp = Credentials() self.creds_tmp.set_username("") @@ -620,6 +620,19 @@ class AclSearchTests(AclTests): def setUp(self): super(AclSearchTests, self).setUp() + # Get the old "dSHeuristics" if it was set + dsheuristics = self.ldb_admin.get_dsheuristics() + # Reset the "dSHeuristics" as they were before + self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics) + # Set the "dSHeuristics" to activate the correct "userPassword" behaviour + self.ldb_admin.set_dsheuristics("000000001") + # Get the old "minPwdAge" + minPwdAge = self.ldb_admin.get_minPwdAge() + # Reset the "minPwdAge" as it was before + self.addCleanup(self.ldb_admin.set_minPwdAge, minPwdAge) + # Set it temporarely to "0" + self.ldb_admin.set_minPwdAge("0") + self.u1 = "search_u1" self.u2 = "search_u2" self.u3 = "search_u3" @@ -1281,6 +1294,20 @@ class AclCARTests(AclTests): def setUp(self): super(AclCARTests, self).setUp() + + # Get the old "dSHeuristics" if it was set + dsheuristics = self.ldb_admin.get_dsheuristics() + # Reset the "dSHeuristics" as they were before + self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics) + # Set the "dSHeuristics" to activate the correct "userPassword" behaviour + self.ldb_admin.set_dsheuristics("000000001") + # Get the old "minPwdAge" + minPwdAge = self.ldb_admin.get_minPwdAge() + # Reset the "minPwdAge" as it was before + self.addCleanup(self.ldb_admin.set_minPwdAge, minPwdAge) + # Set it temporarely to "0" + self.ldb_admin.set_minPwdAge("0") + self.user_with_wp = "acl_car_user1" self.user_with_pc = "acl_car_user2" self.ldb_admin.newuser(self.user_with_wp, self.user_pass) @@ -1876,35 +1903,17 @@ class AclSPNTests(AclTests): ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(AclAddTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclModifyTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclDeleteTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclRenameTests)).wasSuccessful(): - rc = 1 - -# Get the old "dSHeuristics" if it was set -dsheuristics = ldb.get_dsheuristics() -# Set the "dSHeuristics" to activate the correct "userPassword" behaviour -ldb.set_dsheuristics("000000001") -# Get the old "minPwdAge" -minPwdAge = ldb.get_minPwdAge() -# Set it temporarely to "0" -ldb.set_minPwdAge("0") -if not runner.run(unittest.makeSuite(AclCARTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclSearchTests)).wasSuccessful(): - rc = 1 -# Reset the "dSHeuristics" as they were before -ldb.set_dsheuristics(dsheuristics) -# Reset the "minPwdAge" as it was before -ldb.set_minPwdAge(minPwdAge) - -if not runner.run(unittest.makeSuite(AclExtendedTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(AclSPNTests)).wasSuccessful(): +suite = unittest.TestSuite() +suite.addTests(unittest.makeSuite(AclAddTests)) +suite.addTests(unittest.makeSuite(AclModifyTests)) +suite.addTests(unittest.makeSuite(AclDeleteTests)) +suite.addTests(unittest.makeSuite(AclRenameTests)) +suite.addTests(unittest.makeSuite(AclCARTests)) +suite.addTests(unittest.makeSuite(AclSearchTests)) +suite.addTests(unittest.makeSuite(AclExtendedTests)) +suite.addTests(unittest.makeSuite(AclSPNTests)) +if not runner.run(suite).wasSuccessful(): rc = 1 +else: + rc = 0 sys.exit(rc) -- 2.1.4 From f755d71e80052f47486a1631a67f98949368be29 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 15:57:35 -0700 Subject: [PATCH 09/36] Fix subunit test suite name. Only run it when testscenarios is installed, as it depends on that. Change-Id: I1e1284024cf94f909e585a55b8a15e33273f167b Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit fb08cd5310c2c806e49597da4c3a310b058645ae) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/tests.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/selftest/tests.py b/selftest/tests.py index 88a08c9..fb49e1d 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -37,7 +37,12 @@ if have_man_pages_support: planpythontestsuite("none", "samba.tests.docs") planpythontestsuite("none", "selftest.tests.test_suite", extra_path=[srcdir()]) -planpythontestsuite("none", "subunit") +try: + import testscenarios +except ImportError: + skiptestsuite("subunit", "testscenarios not available") +else: + planpythontestsuite("none", "subunit.tests.test_suite") planpythontestsuite("none", "samba.tests.blackbox.ndrdump") planpythontestsuite("none", "api", name="ldb.python", extra_path=['lib/ldb/tests/python']) planpythontestsuite("none", "samba.tests.credentials") -- 2.1.4 From e158a390fa74d3c3a7e4b7701cea187f8eb31785 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 10:17:23 -0700 Subject: [PATCH 10/36] Support using system ldbmodify. Fixes this test when bin/ldbmodify isn't built because we're using the system ldbmodify. Change-Id: I2ff0d9808245353006c6be4989976a3edad8f98e Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 49445541e750328fc9b766593eddc61a65f97ccb) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- nsswitch/tests/test_rfc2307_mapping.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nsswitch/tests/test_rfc2307_mapping.sh b/nsswitch/tests/test_rfc2307_mapping.sh index f1e3ea9..4fd93a4 100755 --- a/nsswitch/tests/test_rfc2307_mapping.sh +++ b/nsswitch/tests/test_rfc2307_mapping.sh @@ -19,7 +19,12 @@ failed=0 samba4bindir="$BINDIR" wbinfo="$VALGRIND $samba4bindir/wbinfo" samba_tool="$VALGRIND $samba4bindir/samba-tool" -ldbmodify="$samba4bindir/ldbmodify" +if [ -f "$samba4bindir/ldbmodify" ]; then + ldbmodify="$samba4bindir/ldbmodify" +else + # Using system ldbmodify + ldbmodify="ldbmodify" +fi . `dirname $0`/../../testprogs/blackbox/subunit.sh -- 2.1.4 From cdd2f7fb24c617ad9ebe6ee4edf8ba28f0c439eb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Oct 2014 11:31:38 -0700 Subject: [PATCH 11/36] filter-subunit: Consistently use spaces rather than tabs. Change-Id: I760399cb4bf0aa9753f5f1e842919b386e1caca9 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett Autobuild-User(master): Jelmer Vernooij Autobuild-Date(master): Wed Nov 19 20:50:29 CET 2014 on sn-devel-104 (cherry picked from commit 71a9e5da2be8feae2f7cbb248b7c091f435d964e) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/filter-subunit | 72 ++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/selftest/filter-subunit b/selftest/filter-subunit index 2ed1430..5b74343 100755 --- a/selftest/filter-subunit +++ b/selftest/filter-subunit @@ -29,73 +29,73 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/testtools")) import subunithelper parser = optparse.OptionParser("filter-subunit [options] < instream > outstream") -parser.add_option("--expected-failures", type="string", - help="File containing list of regexes matching tests to consider known " - "failures") +parser.add_option("--expected-failures", type="string", + help="File containing list of regexes matching tests to consider known " + "failures") parser.add_option("--flapping", type="string", - help="File containing list of flapping tests, of which to ignore results.") + help="File containing list of flapping tests, of which to ignore results.") parser.add_option("--strip-passed-output", action="store_true", help="Whether to strip output from tests that passed") parser.add_option("--fail-immediately", action="store_true", help="Whether to stop on the first error", default=False) parser.add_option("--prefix", type="string", - help="Add prefix to all test names") + help="Add prefix to all test names") parser.add_option("--suffix", type="string", - help="Add suffix to all test names") + help="Add suffix to all test names") parser.add_option("--fail-on-empty", default=False, - action="store_true", help="Fail if there was no subunit output") + action="store_true", help="Fail if there was no subunit output") parser.add_option("--list", default=False, - action="store_true", help="Operate in list mode") + action="store_true", help="Operate in list mode") opts, args = parser.parse_args() if opts.list: - prefix = opts.prefix - suffix = opts.suffix - if not prefix: - prefix = "" - if not suffix: - suffix = "" - for l in sys.stdin: - sys.stdout.write("%s%s%s\n" % (prefix, l.rstrip(), suffix)) - sys.exit(0) + prefix = opts.prefix + suffix = opts.suffix + if not prefix: + prefix = "" + if not suffix: + suffix = "" + for l in sys.stdin: + sys.stdout.write("%s%s%s\n" % (prefix, l.rstrip(), suffix)) + sys.exit(0) if opts.expected_failures: - expected_failures = subunithelper.read_test_regexes(opts.expected_failures) + expected_failures = subunithelper.read_test_regexes(opts.expected_failures) else: - expected_failures = {} + expected_failures = {} if opts.flapping: - flapping = subunithelper.read_test_regexes(opts.flapping) + flapping = subunithelper.read_test_regexes(opts.flapping) else: - flapping = {} + flapping = {} statistics = { - 'TESTS_UNEXPECTED_OK': 0, - 'TESTS_EXPECTED_OK': 0, - 'TESTS_UNEXPECTED_FAIL': 0, - 'TESTS_EXPECTED_FAIL': 0, - 'TESTS_ERROR': 0, - 'TESTS_SKIP': 0, + 'TESTS_UNEXPECTED_OK': 0, + 'TESTS_EXPECTED_OK': 0, + 'TESTS_UNEXPECTED_FAIL': 0, + 'TESTS_EXPECTED_FAIL': 0, + 'TESTS_ERROR': 0, + 'TESTS_SKIP': 0, } def handle_sigint(sig, stack): - sys.exit(0) + sys.exit(0) signal.signal(signal.SIGINT, handle_sigint) out = subunithelper.SubunitOps(sys.stdout) msg_ops = subunithelper.FilterOps(out, opts.prefix, opts.suffix, expected_failures, - opts.strip_passed_output, - fail_immediately=opts.fail_immediately, - flapping=flapping) + opts.strip_passed_output, + fail_immediately=opts.fail_immediately, + flapping=flapping) try: - ret = subunithelper.parse_results(msg_ops, statistics, sys.stdin) + ret = subunithelper.parse_results(msg_ops, statistics, sys.stdin) except subunithelper.ImmediateFail: - sys.stdout.flush() - sys.exit(1) + sys.stdout.flush() + sys.exit(1) if opts.fail_on_empty and not msg_ops.seen_output: - sys.exit(1) + sys.exit(1) else: - sys.exit(ret) + sys.exit(ret) -- 2.1.4 From 3c539d9061f87cc7cbd4535106d181a05b921c5f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 25 Oct 2014 11:09:10 -0700 Subject: [PATCH 12/36] Add bundled copy of 'extras' python module used by newer versions of testtools/subunit. Change-Id: I5ad9222ccb4228a4b16d54a578276d4b9d4e6c4d Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit a92877f955baf0ed8420f77898bd4405bd319c67) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- lib/extras/.gitignore | 35 +++++++ lib/extras/.testr.conf | 4 + lib/extras/LICENSE | 26 +++++ lib/extras/MANIFEST.in | 6 ++ lib/extras/Makefile | 30 ++++++ lib/extras/NEWS | 27 +++++ lib/extras/README.rst | 57 ++++++++++ lib/extras/extras/__init__.py | 103 ++++++++++++++++++ lib/extras/extras/tests/__init__.py | 17 +++ lib/extras/extras/tests/test_extras.py | 186 +++++++++++++++++++++++++++++++++ lib/extras/setup.cfg | 4 + lib/extras/setup.py | 48 +++++++++ lib/update-external.sh | 5 + lib/wscript_build | 4 +- 14 files changed, 551 insertions(+), 1 deletion(-) create mode 100644 lib/extras/.gitignore create mode 100644 lib/extras/.testr.conf create mode 100644 lib/extras/LICENSE create mode 100644 lib/extras/MANIFEST.in create mode 100644 lib/extras/Makefile create mode 100644 lib/extras/NEWS create mode 100644 lib/extras/README.rst create mode 100644 lib/extras/extras/__init__.py create mode 100644 lib/extras/extras/tests/__init__.py create mode 100644 lib/extras/extras/tests/test_extras.py create mode 100644 lib/extras/setup.cfg create mode 100755 lib/extras/setup.py diff --git a/lib/extras/.gitignore b/lib/extras/.gitignore new file mode 100644 index 0000000..cfc114c --- /dev/null +++ b/lib/extras/.gitignore @@ -0,0 +1,35 @@ +*.py[co] + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +MANIFEST + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +# editors +*.swp +*~ + +# Testrepository +.testrepository diff --git a/lib/extras/.testr.conf b/lib/extras/.testr.conf new file mode 100644 index 0000000..8a65628 --- /dev/null +++ b/lib/extras/.testr.conf @@ -0,0 +1,4 @@ +[DEFAULT] +test_command=${PYTHON:-python} -m subunit.run discover . $LISTOPT $IDOPTION +test_id_option=--load-list $IDFILE +test_list_option=--list diff --git a/lib/extras/LICENSE b/lib/extras/LICENSE new file mode 100644 index 0000000..4dfca45 --- /dev/null +++ b/lib/extras/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2010-2012 the extras authors. + +The extras authors are: + * Jonathan Lange + * Martin Pool + * Robert Collins + +and are collectively referred to as "extras developers". + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/extras/MANIFEST.in b/lib/extras/MANIFEST.in new file mode 100644 index 0000000..da2696e --- /dev/null +++ b/lib/extras/MANIFEST.in @@ -0,0 +1,6 @@ +include LICENSE +include Makefile +include MANIFEST.in +include NEWS +include README.rst +include .gitignore diff --git a/lib/extras/Makefile b/lib/extras/Makefile new file mode 100644 index 0000000..270e8d1 --- /dev/null +++ b/lib/extras/Makefile @@ -0,0 +1,30 @@ +# See README.rst for copyright and licensing details. + +PYTHON=python +SOURCES=$(shell find extras -name "*.py") + +check: + PYTHONPATH=$(PWD) $(PYTHON) -m testtools.run extras.tests.test_suite + +TAGS: ${SOURCES} + ctags -e -R extras/ + +tags: ${SOURCES} + ctags -R extras/ + +clean: + rm -f TAGS tags + find extras -name "*.pyc" -exec rm '{}' \; + +### Documentation ### + +apidocs: + # pydoctor emits deprecation warnings under Ubuntu 10.10 LTS + PYTHONWARNINGS='ignore::DeprecationWarning' \ + pydoctor --make-html --add-package extras \ + --docformat=restructuredtext --project-name=extras \ + --project-url=https://launchpad.net/extras + + +.PHONY: apidocs +.PHONY: check clean diff --git a/lib/extras/NEWS b/lib/extras/NEWS new file mode 100644 index 0000000..60713b8 --- /dev/null +++ b/lib/extras/NEWS @@ -0,0 +1,27 @@ +extras NEWS ++++++++++++ + +Changes and improvements to extras_, grouped by release. + +NEXT +~~~~ + +0.0.3 +~~~~~ + +* Extras setup.py would break on older testtools releases, which could break + installs of newer testtools due to extras then failing to install. + (Robert Collins) + +0.0.2 +~~~~~ + +* Fix Makefile to not have cruft leftover from testtools. + +0.0.1 +~~~~~ + +* Initial extraction from testtools. + + +.. _extras: http://pypi.python.org/pypi/extras diff --git a/lib/extras/README.rst b/lib/extras/README.rst new file mode 100644 index 0000000..7d3f10b --- /dev/null +++ b/lib/extras/README.rst @@ -0,0 +1,57 @@ +====== +extras +====== + +extras is a set of extensions to the Python standard library, originally +written to make the code within testtools cleaner, but now split out for +general use outside of a testing context. + + +Documentation +------------- + +pydoc extras is your friend. extras currently contains the following functions: + +* try_import + +* try_imports + +* safe_hasattr + +Which do what their name suggests. + + +Licensing +--------- + +This project is distributed under the MIT license and copyright is owned by +the extras authors. See LICENSE for details. + + +Required Dependencies +--------------------- + + * Python 2.6+ or 3.0+ + + +Bug reports and patches +----------------------- + +Please report bugs using github issues at . +Patches can also be submitted via github. You can mail the authors directly +via the mailing list testtools-dev@lists.launchpad.net. (Note that Launchpad +discards email from unknown addresses - be sure to sign up for a Launchpad +account before mailing the list, or your mail will be silently discarded). + + +History +------- + +extras used to be testtools.helpers, and was factored out when folk wanted to +use it separately. + + +Thanks +------ + + * Martin Pool diff --git a/lib/extras/extras/__init__.py b/lib/extras/extras/__init__.py new file mode 100644 index 0000000..5f16625 --- /dev/null +++ b/lib/extras/extras/__init__.py @@ -0,0 +1,103 @@ +# Copyright (c) 2010-2012 extras developers. See LICENSE for details. + +"""Extensions to the Python standard library.""" + +import sys + +__all__ = [ + 'safe_hasattr', + 'try_import', + 'try_imports', + ] + +# same format as sys.version_info: "A tuple containing the five components of +# the version number: major, minor, micro, releaselevel, and serial. All +# values except releaselevel are integers; the release level is 'alpha', +# 'beta', 'candidate', or 'final'. The version_info value corresponding to the +# Python version 2.0 is (2, 0, 0, 'final', 0)." Additionally we use a +# releaselevel of 'dev' for unreleased under-development code. +# +# If the releaselevel is 'alpha' then the major/minor/micro components are not +# established at this point, and setup.py will use a version of next-$(revno). +# If the releaselevel is 'final', then the tarball will be major.minor.micro. +# Otherwise it is major.minor.micro~$(revno). + +__version__ = (0, 0, 3, 'final', 0) + + +def try_import(name, alternative=None, error_callback=None): + """Attempt to import ``name``. If it fails, return ``alternative``. + + When supporting multiple versions of Python or optional dependencies, it + is useful to be able to try to import a module. + + :param name: The name of the object to import, e.g. ``os.path`` or + ``os.path.join``. + :param alternative: The value to return if no module can be imported. + Defaults to None. + :param error_callback: If non-None, a callable that is passed the ImportError + when the module cannot be loaded. + """ + module_segments = name.split('.') + last_error = None + while module_segments: + module_name = '.'.join(module_segments) + try: + module = __import__(module_name) + except ImportError: + last_error = sys.exc_info()[1] + module_segments.pop() + continue + else: + break + else: + if last_error is not None and error_callback is not None: + error_callback(last_error) + return alternative + nonexistent = object() + for segment in name.split('.')[1:]: + module = getattr(module, segment, nonexistent) + if module is nonexistent: + if last_error is not None and error_callback is not None: + error_callback(last_error) + return alternative + return module + + +_RAISE_EXCEPTION = object() +def try_imports(module_names, alternative=_RAISE_EXCEPTION, error_callback=None): + """Attempt to import modules. + + Tries to import the first module in ``module_names``. If it can be + imported, we return it. If not, we go on to the second module and try + that. The process continues until we run out of modules to try. If none + of the modules can be imported, either raise an exception or return the + provided ``alternative`` value. + + :param module_names: A sequence of module names to try to import. + :param alternative: The value to return if no module can be imported. + If unspecified, we raise an ImportError. + :param error_callback: If None, called with the ImportError for *each* + module that fails to load. + :raises ImportError: If none of the modules can be imported and no + alternative value was specified. + """ + module_names = list(module_names) + for module_name in module_names: + module = try_import(module_name, error_callback=error_callback) + if module: + return module + if alternative is _RAISE_EXCEPTION: + raise ImportError( + "Could not import any of: %s" % ', '.join(module_names)) + return alternative + + +def safe_hasattr(obj, attr, _marker=object()): + """Does 'obj' have an attribute 'attr'? + + Use this rather than built-in hasattr, as the built-in swallows exceptions + in some versions of Python and behaves unpredictably with respect to + properties. + """ + return getattr(obj, attr, _marker) is not _marker diff --git a/lib/extras/extras/tests/__init__.py b/lib/extras/extras/tests/__init__.py new file mode 100644 index 0000000..e0d7d4a --- /dev/null +++ b/lib/extras/extras/tests/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2010-2012 extras developers. See LICENSE for details. + +"""Tests for extras.""" + +from unittest import TestSuite, TestLoader + + +def test_suite(): + from extras.tests import ( + test_extras, + ) + modules = [ + test_extras, + ] + loader = TestLoader() + suites = map(loader.loadTestsFromModule, modules) + return TestSuite(suites) diff --git a/lib/extras/extras/tests/test_extras.py b/lib/extras/extras/tests/test_extras.py new file mode 100644 index 0000000..33dc87c --- /dev/null +++ b/lib/extras/extras/tests/test_extras.py @@ -0,0 +1,186 @@ +# Copyright (c) 2010-2012 extras developers. See LICENSE for details. + +from testtools import TestCase +from testtools.matchers import ( + Equals, + Is, + Not, + ) + +from extras import ( + safe_hasattr, + try_import, + try_imports, + ) + +def check_error_callback(test, function, arg, expected_error_count, + expect_result): + """General test template for error_callback argument. + + :param test: Test case instance. + :param function: Either try_import or try_imports. + :param arg: Name or names to import. + :param expected_error_count: Expected number of calls to the callback. + :param expect_result: Boolean for whether a module should + ultimately be returned or not. + """ + cb_calls = [] + def cb(e): + test.assertIsInstance(e, ImportError) + cb_calls.append(e) + try: + result = function(arg, error_callback=cb) + except ImportError: + test.assertFalse(expect_result) + else: + if expect_result: + test.assertThat(result, Not(Is(None))) + else: + test.assertThat(result, Is(None)) + test.assertEquals(len(cb_calls), expected_error_count) + + +class TestSafeHasattr(TestCase): + + def test_attribute_not_there(self): + class Foo(object): + pass + self.assertEqual(False, safe_hasattr(Foo(), 'anything')) + + def test_attribute_there(self): + class Foo(object): + pass + foo = Foo() + foo.attribute = None + self.assertEqual(True, safe_hasattr(foo, 'attribute')) + + def test_property_there(self): + class Foo(object): + @property + def attribute(self): + return None + foo = Foo() + self.assertEqual(True, safe_hasattr(foo, 'attribute')) + + def test_property_raises(self): + class Foo(object): + @property + def attribute(self): + 1/0 + foo = Foo() + self.assertRaises(ZeroDivisionError, safe_hasattr, foo, 'attribute') + + +class TestTryImport(TestCase): + + def test_doesnt_exist(self): + # try_import('thing', foo) returns foo if 'thing' doesn't exist. + marker = object() + result = try_import('doesntexist', marker) + self.assertThat(result, Is(marker)) + + def test_None_is_default_alternative(self): + # try_import('thing') returns None if 'thing' doesn't exist. + result = try_import('doesntexist') + self.assertThat(result, Is(None)) + + def test_existing_module(self): + # try_import('thing', foo) imports 'thing' and returns it if it's a + # module that exists. + result = try_import('os', object()) + import os + self.assertThat(result, Is(os)) + + def test_existing_submodule(self): + # try_import('thing.another', foo) imports 'thing' and returns it if + # it's a module that exists. + result = try_import('os.path', object()) + import os + self.assertThat(result, Is(os.path)) + + def test_nonexistent_submodule(self): + # try_import('thing.another', foo) imports 'thing' and returns foo if + # 'another' doesn't exist. + marker = object() + result = try_import('os.doesntexist', marker) + self.assertThat(result, Is(marker)) + + def test_object_from_module(self): + # try_import('thing.object') imports 'thing' and returns + # 'thing.object' if 'thing' is a module and 'object' is not. + result = try_import('os.path.join') + import os + self.assertThat(result, Is(os.path.join)) + + def test_error_callback(self): + # the error callback is called on failures. + check_error_callback(self, try_import, 'doesntexist', 1, False) + + def test_error_callback_missing_module_member(self): + # the error callback is called on failures to find an object + # inside an existing module. + check_error_callback(self, try_import, 'os.nonexistent', 1, False) + + def test_error_callback_not_on_success(self): + # the error callback is not called on success. + check_error_callback(self, try_import, 'os.path', 0, True) + + +class TestTryImports(TestCase): + + def test_doesnt_exist(self): + # try_imports('thing', foo) returns foo if 'thing' doesn't exist. + marker = object() + result = try_imports(['doesntexist'], marker) + self.assertThat(result, Is(marker)) + + def test_fallback(self): + result = try_imports(['doesntexist', 'os']) + import os + self.assertThat(result, Is(os)) + + def test_None_is_default_alternative(self): + # try_imports('thing') returns None if 'thing' doesn't exist. + e = self.assertRaises( + ImportError, try_imports, ['doesntexist', 'noreally']) + self.assertThat( + str(e), + Equals("Could not import any of: doesntexist, noreally")) + + def test_existing_module(self): + # try_imports('thing', foo) imports 'thing' and returns it if it's a + # module that exists. + result = try_imports(['os'], object()) + import os + self.assertThat(result, Is(os)) + + def test_existing_submodule(self): + # try_imports('thing.another', foo) imports 'thing' and returns it if + # it's a module that exists. + result = try_imports(['os.path'], object()) + import os + self.assertThat(result, Is(os.path)) + + def test_nonexistent_submodule(self): + # try_imports('thing.another', foo) imports 'thing' and returns foo if + # 'another' doesn't exist. + marker = object() + result = try_imports(['os.doesntexist'], marker) + self.assertThat(result, Is(marker)) + + def test_fallback_submodule(self): + result = try_imports(['os.doesntexist', 'os.path']) + import os + self.assertThat(result, Is(os.path)) + + def test_error_callback(self): + # One error for every class that doesn't exist. + check_error_callback(self, try_imports, + ['os.doesntexist', 'os.notthiseither'], + 2, False) + check_error_callback(self, try_imports, + ['os.doesntexist', 'os.notthiseither', 'os'], + 2, True) + check_error_callback(self, try_imports, + ['os.path'], + 0, True) diff --git a/lib/extras/setup.cfg b/lib/extras/setup.cfg new file mode 100644 index 0000000..c319dc7 --- /dev/null +++ b/lib/extras/setup.cfg @@ -0,0 +1,4 @@ +[test] +test_module = extras.tests +buffer=1 +catch=1 diff --git a/lib/extras/setup.py b/lib/extras/setup.py new file mode 100755 index 0000000..56612d0 --- /dev/null +++ b/lib/extras/setup.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +"""Distutils installer for extras.""" + +from setuptools import setup +import os.path + +import extras +testtools_cmd = extras.try_import('testtools.TestCommand') + + +def get_version(): + """Return the version of extras that we are building.""" + version = '.'.join( + str(component) for component in extras.__version__[0:3]) + return version + + +def get_long_description(): + readme_path = os.path.join( + os.path.dirname(__file__), 'README.rst') + return open(readme_path).read() + + +cmdclass = {} + +if testtools_cmd is not None: + cmdclass['test'] = testtools_cmd + + +setup(name='extras', + author='Testing cabal', + author_email='testtools-dev@lists.launchpad.net', + url='https://github.com/testing-cabal/extras', + description=('Useful extra bits for Python - things that shold be ' + 'in the standard library'), + long_description=get_long_description(), + version=get_version(), + classifiers=[ + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + ], + packages=[ + 'extras', + 'extras.tests', + ], + cmdclass=cmdclass) diff --git a/lib/update-external.sh b/lib/update-external.sh index ea563ba..d8abcfb 100755 --- a/lib/update-external.sh +++ b/lib/update-external.sh @@ -25,4 +25,9 @@ git clone git://github.com/jcrocholl/pep8 "$WORKDIR/pep8" rm -rf "$WORKDIR/pep8/.git" rsync -avz --delete "$WORKDIR/pep8/" "$TARGETDIR/pep8/" +echo "Updating extra..." +git clone git://github.com/testing-cabal/extras "$WORKDIR/extras" +rm -rf "$WORKDIR/extras/.git" +rsync -avz --delete "$WORKDIR/extras/" "$LIBDIR/extras/" + rm -rf "$WORKDIR" diff --git a/lib/wscript_build b/lib/wscript_build index 97c3cfa..c6ca778 100644 --- a/lib/wscript_build +++ b/lib/wscript_build @@ -6,7 +6,9 @@ import os, Options external_libs = { "dns.resolver": "dnspython/dns", "subunit": "subunit/python/subunit", - "testtools": "testtools/testtools"} + "testtools": "testtools/testtools", + "extras": "extras/extras", + } list = [] -- 2.1.4 From 14eccdf4bffa986b57751ada97deabdccdd933de Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:51:46 -0700 Subject: [PATCH 13/36] Add convenience class for old-style Samba subunit python tests. Change-Id: I84a97cc71cfa99c14e0c93ec19ff9eea6149bb5a Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 8d8d800a0f8ea3e822ee4d3693058b24307ba4e2) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- python/samba/tests/subunitrun.py | 59 ++++++++++++++++++++++++++++++++++++ source4/dsdb/tests/python/dirsync.py | 23 ++++++-------- 2 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 python/samba/tests/subunitrun.py diff --git a/python/samba/tests/subunitrun.py b/python/samba/tests/subunitrun.py new file mode 100644 index 0000000..78632f3 --- /dev/null +++ b/python/samba/tests/subunitrun.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +# Simple subunit testrunner for python + +# NOTE: DO NOT USE THIS MODULE FOR NEW CODE. +# +# Instead, use the standard subunit runner - e.g. "python -m subunit.run +# YOURMODULE". +# +# This wrapper will be removed once all tests can be run +# without it. At the moment there are various tests which still +# get e.g. credentials passed via command-line options to this +# script. + +# Copyright (C) Jelmer Vernooij 2007-2014 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys + +# make sure the script dies immediately when hitting control-C, +# rather than raising KeyboardInterrupt. As we do all database +# operations using transactions, this is safe. +import signal +signal.signal(signal.SIGINT, signal.SIG_DFL) + +# Find right directory when running from source tree +sys.path.insert(0, "bin/python") + +import samba +samba.ensure_external_module("mimeparse", "mimeparse") +samba.ensure_external_module("extras", "extras") +samba.ensure_external_module("testtools", "testtools") +samba.ensure_external_module("subunit", "subunit/python") +import subunit.run + +try: + from subunit.run import TestProgram +except ImportError: + from unittest import TestProgram + + +class TestProgram(TestProgram): + + def __init__(self, module=None, argv=None): + super(TestProgram, self).__init__(module=module, argv=argv, + testRunner=subunit.run.SubunitTestRunner()) diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 14810d3..2de7736 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -22,8 +22,7 @@ import optparse import sys sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") +from samba.tests.subunitrun import TestProgram import samba.getopt as options import base64 @@ -40,8 +39,6 @@ from samba.samdb import SamDB from samba.credentials import Credentials, DONT_USE_KERBEROS import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest parser = optparse.OptionParser("dirsync.py [options] ") sambaopts = options.SambaOptions(parser) @@ -57,7 +54,7 @@ if len(args) < 1: parser.print_usage() sys.exit(1) -host = args[0] +host = args.pop() if not "://" in host: ldaphost = "ldap://%s" % host ldapshost = "ldaps://%s" % host @@ -696,13 +693,13 @@ class ExtendedDirsyncTests(SimpleDirsyncTests): self.assertEqual(str(res[0].dn), "") -runner = SubunitTestRunner() -suite = unittest.TestSuite() -suite.addTests(unittest.makeSuite(SimpleDirsyncTests)) -suite.addTests(unittest.makeSuite(ExtendedDirsyncTests)) -if not runner.run(suite).wasSuccessful(): - rc = 1 +if getattr(opts, "listtests", False): + args.insert(0, "--list") else: - rc = 0 + lp = sambaopts.get_loadparm() + samba.tests.cmdline_credentials = credopts.get_credentials(lp) +if getattr(opts, 'load_list', None): + args.insert(0, "--load-list=%s" % opts.load_list) -sys.exit(rc) + +TestProgram(module=__name__, argv=[sys.argv[0]] + args) -- 2.1.4 From 0f13ce05102a51321b83b2fbc089e9591dbee005 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 20:57:09 -0700 Subject: [PATCH 14/36] subunitrun: Use new samba.tests.subunitrun module. Change-Id: Ie32f16d72c80c831adfd9a8d32735fa348962123 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit ed4c07b34b5571c021684e3df6bf5fc63cde69c5) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/scripting/bin/subunitrun | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/source4/scripting/bin/subunitrun b/source4/scripting/bin/subunitrun index 918195e..c85fc97 100755 --- a/source4/scripting/bin/subunitrun +++ b/source4/scripting/bin/subunitrun @@ -39,9 +39,8 @@ sys.path.insert(0, "bin/python") import optparse import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") -from subunit.run import SubunitTestRunner +from samba.tests.subunitrun import TestProgram + import samba.getopt as options import samba.tests @@ -74,14 +73,6 @@ credopts = options.CredentialsOptions(parser) sambaopts = options.SambaOptions(parser) parser.add_option_group(credopts) parser.add_option_group(sambaopts) -try: - from subunit.run import TestProgram -except ImportError: - from unittest import TestProgram -else: - parser.add_option('-l', '--list', dest='listtests', default=False, - help='List tests rather than running them.', - action="store_true") opts, args = parser.parse_args() @@ -91,5 +82,4 @@ else: lp = sambaopts.get_loadparm() samba.tests.cmdline_credentials = credopts.get_credentials(lp) -runner = SubunitTestRunner() -program = TestProgram(module=None, argv=[sys.argv[0]] + args, testRunner=runner) +TestProgram(module=None, argv=[sys.argv[0]] + args) -- 2.1.4 From 90be8489ef2cf59d75f7ebaea5f0bc451b2c5581 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 21:08:49 -0700 Subject: [PATCH 15/36] Move option parsing to samba.tests.subunitrun. Change-Id: I2939c1b6ebb9739530efa9bc4667668cff7a7aeb Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 24035a6b3ed5ffdb1e75ebd375c3f7c2129742ff) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- python/samba/tests/subunitrun.py | 27 +++++++++++++++++++-------- source4/dsdb/tests/python/dirsync.py | 2 +- source4/scripting/bin/subunitrun | 4 +++- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/python/samba/tests/subunitrun.py b/python/samba/tests/subunitrun.py index 78632f3..abb9881 100644 --- a/python/samba/tests/subunitrun.py +++ b/python/samba/tests/subunitrun.py @@ -28,18 +28,15 @@ # along with this program. If not, see . # -import sys - # make sure the script dies immediately when hitting control-C, # rather than raising KeyboardInterrupt. As we do all database # operations using transactions, this is safe. import signal signal.signal(signal.SIGINT, signal.SIG_DFL) -# Find right directory when running from source tree -sys.path.insert(0, "bin/python") - +import optparse import samba +import sys samba.ensure_external_module("mimeparse", "mimeparse") samba.ensure_external_module("extras", "extras") samba.ensure_external_module("testtools", "testtools") @@ -47,13 +44,27 @@ samba.ensure_external_module("subunit", "subunit/python") import subunit.run try: - from subunit.run import TestProgram + from subunit.run import TestProgram as BaseTestProgram except ImportError: - from unittest import TestProgram + from unittest import TestProgram as BaseTestProgram + + +class SubunitOptions(optparse.OptionGroup): + """Command line options for subunit test runners.""" + + def __init__(self, parser): + optparse.OptionGroup.__init__(self, parser, "Subunit Options") + self.add_option('-l', '--list', dest='listtests', default=False, + help='List tests rather than running them.', + action="store_true") + self.add_option('--load-list', dest='load_list', default=None, + help='Specify a filename containing the test ids to use.') -class TestProgram(TestProgram): +class TestProgram(BaseTestProgram): def __init__(self, module=None, argv=None): + if argv is None: + argv = [sys.argv[0]] super(TestProgram, self).__init__(module=module, argv=argv, testRunner=subunit.run.SubunitTestRunner()) diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 2de7736..a480518 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -702,4 +702,4 @@ if getattr(opts, 'load_list', None): args.insert(0, "--load-list=%s" % opts.load_list) -TestProgram(module=__name__, argv=[sys.argv[0]] + args) +TestProgram(module=__name__) diff --git a/source4/scripting/bin/subunitrun b/source4/scripting/bin/subunitrun index c85fc97..48b507a 100755 --- a/source4/scripting/bin/subunitrun +++ b/source4/scripting/bin/subunitrun @@ -39,7 +39,7 @@ sys.path.insert(0, "bin/python") import optparse import samba -from samba.tests.subunitrun import TestProgram +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options import samba.tests @@ -71,8 +71,10 @@ parser = optparse.OptionParser(usage=usage, description=description) parser.format_description = format_description credopts = options.CredentialsOptions(parser) sambaopts = options.SambaOptions(parser) +subunitopts = SubunitOptions(parser) parser.add_option_group(credopts) parser.add_option_group(sambaopts) +parser.add_option_group(subunitopts) opts, args = parser.parse_args() -- 2.1.4 From cf36f45d6cfc82a0d3233d488440a3919a654a20 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 21:17:39 -0700 Subject: [PATCH 16/36] Move option handling into samba.tests.subunitrun. Change-Id: I65a73b74854af636413f4f284147f3bcf28b6f82 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit ee281c61d01b5fb167571b8ace5e739758100db6) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- python/samba/tests/subunitrun.py | 11 ++++++++--- source4/dsdb/tests/python/dirsync.py | 14 ++++++-------- source4/scripting/bin/subunitrun | 14 ++++++-------- source4/selftest/tests.py | 2 +- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/python/samba/tests/subunitrun.py b/python/samba/tests/subunitrun.py index abb9881..d454676 100644 --- a/python/samba/tests/subunitrun.py +++ b/python/samba/tests/subunitrun.py @@ -63,8 +63,13 @@ class SubunitOptions(optparse.OptionGroup): class TestProgram(BaseTestProgram): - def __init__(self, module=None, argv=None): - if argv is None: - argv = [sys.argv[0]] + def __init__(self, module=None, args=None, opts=None): + if args is None: + args = [] + if getattr(opts, "listtests", False): + args.insert(0, "--list") + if getattr(opts, 'load_list', None): + args.insert(0, "--load-list=%s" % opts.load_list) + argv = [sys.argv[0]] + args super(TestProgram, self).__init__(module=module, argv=argv, testRunner=subunit.run.SubunitTestRunner()) diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index a480518..e6c5bba 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -2,7 +2,7 @@ # # Unit tests for dirsync control # Copyright (C) Matthieu Patou 2011 -# +# Copyright (C) Jelmer Vernooij 2014 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ import optparse import sys sys.path.insert(0, "bin/python") import samba -from samba.tests.subunitrun import TestProgram +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options import base64 @@ -48,6 +48,8 @@ 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: @@ -693,13 +695,9 @@ class ExtendedDirsyncTests(SimpleDirsyncTests): self.assertEqual(str(res[0].dn), "") -if getattr(opts, "listtests", False): - args.insert(0, "--list") -else: +if not getattr(opts, "listtests", False): lp = sambaopts.get_loadparm() samba.tests.cmdline_credentials = credopts.get_credentials(lp) -if getattr(opts, 'load_list', None): - args.insert(0, "--load-list=%s" % opts.load_list) -TestProgram(module=__name__) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/scripting/bin/subunitrun b/source4/scripting/bin/subunitrun index 48b507a..99d5319 100755 --- a/source4/scripting/bin/subunitrun +++ b/source4/scripting/bin/subunitrun @@ -10,18 +10,18 @@ # get e.g. credentials passed via command-line options to this # script. -# Copyright (C) Jelmer Vernooij 2007-2011 -# +# Copyright (C) Jelmer Vernooij 2007-2014 +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . # @@ -78,10 +78,8 @@ parser.add_option_group(subunitopts) opts, args = parser.parse_args() -if getattr(opts, "listtests", False): - args.insert(0, "--list") -else: +if not getattr(opts, "listtests", False): lp = sambaopts.get_loadparm() samba.tests.cmdline_credentials = credopts.get_credentials(lp) -TestProgram(module=None, argv=[sys.argv[0]] + args) +TestProgram(module=None, args=args, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 83a4c3f..b57ac7d 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -470,7 +470,7 @@ planoldpythontestsuite("dc", "dsdb_schema_info", name="samba4.schemaInfo.python(dc)", extra_args=['-U"$DOMAIN/$DC_USERNAME%$DC_PASSWORD"']) plantestsuite("samba4.urgent_replication.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/urgent_replication.py"), '$PREFIX_ABS/dc/private/sam.ldb']) -plantestsuite("samba4.ldap.dirsync.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) +plantestsuite_loadlist("samba4.ldap.dirsync.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.sites.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: plantestsuite("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) -- 2.1.4 From 4603226ab5bd0c90784b4a3e5523bfb8b76cef97 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 08:23:36 -0800 Subject: [PATCH 17/36] sec_descriptor test: Simplify, use samba.tests.subunitrun module. Change-Id: I4ffda49cf3e209eaa28fc83f6fd9ded47f0ad7ee Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 21280da0d6a4e3c547de8f486fe6ae84eea3f135) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- python/samba/tests/subunitrun.py | 0 source4/dsdb/tests/python/sec_descriptor.py | 32 ++++++++++++----------------- source4/selftest/tests.py | 2 +- 3 files changed, 14 insertions(+), 20 deletions(-) mode change 100644 => 100755 python/samba/tests/subunitrun.py diff --git a/python/samba/tests/subunitrun.py b/python/samba/tests/subunitrun.py old mode 100644 new mode 100755 diff --git a/source4/dsdb/tests/python/sec_descriptor.py b/source4/dsdb/tests/python/sec_descriptor.py index 10d3718..39b5d4e 100755 --- a/source4/dsdb/tests/python/sec_descriptor.py +++ b/source4/dsdb/tests/python/sec_descriptor.py @@ -142,12 +142,13 @@ showInAdvancedViewOnly: TRUE def setUp(self): super(DescriptorTests, self).setUp() - self.ldb_admin = ldb - self.base_dn = ldb.domain_dn() + self.ldb_admin = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp, + options=ldb_options) + self.base_dn = self.ldb_admin.domain_dn() self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized() self.schema_dn = self.ldb_admin.get_schema_basedn().get_linearized() self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid()) - self.sd_utils = sd_utils.SDUtils(ldb) + self.sd_utils = sd_utils.SDUtils(self.ldb_admin) print "baseDN: %s" % self.base_dn ################################################################################################ @@ -2173,22 +2174,15 @@ if not "://" in host: if host.lower().startswith("ldap://"): ldb_options = ["modules:paged_searches"] -ldb = SamDB(host, - credentials=creds, - session_info=system_session(lp), - lp=lp, - options=ldb_options) - runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(OwnerGroupDescriptorTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(DaclDescriptorTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(SdFlagsDescriptorTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(RightsAttributesTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(SdAutoInheritTests)).wasSuccessful(): +suite = unittest.TestSuite() +suite.addTests(unittest.makeSuite(OwnerGroupDescriptorTests)) +suite.addTests(unittest.makeSuite(DaclDescriptorTests)) +suite.addTests(unittest.makeSuite(SdFlagsDescriptorTests)) +suite.addTests(unittest.makeSuite(RightsAttributesTests)) +suite.addTests(unittest.makeSuite(SdAutoInheritTests)) +if not runner.run(suite).wasSuccessful(): rc = 1 +else: + rc = 0 sys.exit(rc) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index b57ac7d..9915e42 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -473,7 +473,7 @@ plantestsuite("samba4.urgent_replication.python(dc)", "dc:local", [python, os.pa plantestsuite_loadlist("samba4.ldap.dirsync.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.sites.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: - plantestsuite("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) + plantestsuite_loadlist("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.possibleInferiors.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/samdb/ldb_modules/tests/possibleinferiors.py"), "ldap://$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) plantestsuite("samba4.ldap.secdesc.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/sec_descriptor.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) plantestsuite("samba4.ldap.acl.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/acl.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) -- 2.1.4 From 0dd55f16eac32c4c52fd6c3435a578478bb91411 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 08:30:23 -0800 Subject: [PATCH 18/36] credentials test: Use samba.tests.subunitrun. Change-Id: I8970c66de9535cb8d48b17d88b2759b7d1e39cb8 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 8d933a84c96859cbb782d5ac693f9badf2531947) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- auth/credentials/tests/bind.py | 34 ++++++++++++++-------------------- source4/selftest/tests.py | 2 +- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/auth/credentials/tests/bind.py b/auth/credentials/tests/bind.py index ceb3e8f..91e493d 100755 --- a/auth/credentials/tests/bind.py +++ b/auth/credentials/tests/bind.py @@ -5,24 +5,20 @@ import optparse import sys import base64 -import re -import os import copy import time sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options from ldb import SCOPE_BASE, SCOPE_SUBTREE from samba import gensec -import samba.tests, unittest +import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner parser = optparse.OptionParser("ldap [options] ") sambaopts = options.SambaOptions(parser) @@ -31,6 +27,8 @@ parser.add_option_group(sambaopts) # 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: @@ -53,8 +51,11 @@ class BindTests(samba.tests.TestCase): def setUp(self): super(BindTests, self).setUp() # fetch rootDSEs + + self.ldb = samba.tests.connect_samdb(host, credentials=creds, lp=lp, ldap_only=True) + if self.info_dc is None: - res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) + res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) self.assertEquals(len(res), 1) BindTests.info_dc = res[0] # cache some of RootDSE props @@ -70,8 +71,8 @@ class BindTests(samba.tests.TestCase): def test_computer_account_bind(self): # create a computer acocount for the test - delete_force(ldb, self.computer_dn) - ldb.add_ldif(""" + delete_force(self.ldb, self.computer_dn) + self.ldb.add_ldif(""" dn: """ + self.computer_dn + """ cn: CENTOS53 displayName: CENTOS53$ @@ -89,7 +90,7 @@ dNSHostName: centos53.alabala.test operatingSystemVersion: 5.2 (3790) operatingSystem: Windows Server 2003 """) - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: """ + self.computer_dn + """ changetype: modify replace: unicodePwd @@ -106,8 +107,8 @@ unicodePwd:: """ + base64.b64encode("\"P@ssw0rd\"".encode('utf-16-le')) + """ def test_user_account_bind(self): # create user - ldb.newuser(username=self.username, password=self.password) - ldb_res = ldb.search(base=self.domain_dn, + self.ldb.newuser(username=self.username, password=self.password) + ldb_res = self.ldb.search(base=self.domain_dn, scope=SCOPE_SUBTREE, expression="(samAccountName=%s)" % self.username) self.assertEquals(len(ldb_res), 1) @@ -138,11 +139,4 @@ unicodePwd:: """ + base64.b64encode("\"P@ssw0rd\"".encode('utf-16-le')) + """ res = ldb_user3.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"]) -ldb = samba.tests.connect_samdb(host, credentials=creds, lp=lp, ldap_only=True) - -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(BindTests)).wasSuccessful(): - rc = 1 - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 9915e42..0a1c433 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -497,7 +497,7 @@ plantestsuite("samba4.blackbox.setpassword.py", "none", ["PYTHON=%s" % python, o plantestsuite("samba4.blackbox.newuser.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_newuser.sh"), '$PREFIX/provision']) plantestsuite("samba4.blackbox.group.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_group.sh"), '$PREFIX/provision']) plantestsuite("samba4.blackbox.spn.py(dc:local)", "dc:local", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_spn.sh"), '$PREFIX/dc']) -plantestsuite("samba4.ldap.bind(dc)", "dc", [python, os.path.join(srcdir(), "auth/credentials/tests/bind.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"']) +plantestsuite_loadlist("samba4.ldap.bind(dc)", "dc", [python, os.path.join(srcdir(), "auth/credentials/tests/bind.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '$LOADLIST', '$LISTOPT']) # This makes sure we test the rid allocation code t = "rpc.samr.large-dc" -- 2.1.4 From b1a1e29ae6af3c121f379b744b8098ae76808725 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 08:32:24 -0800 Subject: [PATCH 19/36] speedtest: Use samba.tests.subunitrun. Change-Id: Id842c3f74aec24faeab68e975ff4d9e9a0dc337b Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit d6545fe27b35e63781f9f87fe9262bb933ffa9be) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/scripting/devel/speedtest.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/source4/scripting/devel/speedtest.py b/source4/scripting/devel/speedtest.py index 84d3760..581966b 100755 --- a/source4/scripting/devel/speedtest.py +++ b/source4/scripting/devel/speedtest.py @@ -30,8 +30,7 @@ from decimal import Decimal sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options @@ -45,18 +44,17 @@ from samba.samdb import SamDB from samba.credentials import Credentials import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest parser = optparse.OptionParser("speedtest.py [options] ") 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: @@ -230,12 +228,4 @@ if not "://" in host: ldb_options = ["modules:paged_searches"] ldb = SamDB(host, credentials=creds, session_info=system_session(), lp=lp, options=ldb_options) -runner = SubunitTestRunner() -suite = unittest.TestSuite() -suite.addTests(unittest.makeSuite(SpeedTestAddDel)) -suite.addTests(unittest.makeSuite(AclSearchSpeedTest)) -if not runner.run(suite).wasSuccessful(): - rc = 1 -else: - rc = 0 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) -- 2.1.4 From ae34dd78f765476af58a1bb99d0a5b759f5acb56 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 08:37:08 -0800 Subject: [PATCH 20/36] sites: Use samba.tests.subunitrun. Change-Id: Ic06e1a0f7174683b6b817a5412b8635145329c00 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 330597507c796db55a48b084c7542f03ee4a93ee) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/sites.py | 17 ++++++----------- source4/selftest/tests.py | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/source4/dsdb/tests/python/sites.py b/source4/dsdb/tests/python/sites.py index 8b984b2..402d676 100755 --- a/source4/dsdb/tests/python/sites.py +++ b/source4/dsdb/tests/python/sites.py @@ -22,8 +22,8 @@ import optparse import sys sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options from samba import sites @@ -31,8 +31,6 @@ from samba.auth import system_session from samba.samdb import SamDB import samba.tests from samba.dcerpc import security -from subunit.run import SubunitTestRunner -import unittest parser = optparse.OptionParser("dirsync.py [options] ") sambaopts = options.SambaOptions(parser) @@ -42,6 +40,9 @@ 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: @@ -116,10 +117,4 @@ class SimpleSitesTests(SitesBaseTests): ldb = SamDB(ldapshost, credentials=creds, session_info=system_session(lp), lp=lp) -runner = SubunitTestRunner() -rc = 0 - -if not runner.run(unittest.makeSuite(SimpleSitesTests)).wasSuccessful(): - rc = 1 - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 0a1c433..a6f115e 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -469,9 +469,9 @@ planoldpythontestsuite("dc", "dsdb_schema_info", extra_path=[os.path.join(samba4srcdir, 'dsdb/tests/python')], name="samba4.schemaInfo.python(dc)", extra_args=['-U"$DOMAIN/$DC_USERNAME%$DC_PASSWORD"']) -plantestsuite("samba4.urgent_replication.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/urgent_replication.py"), '$PREFIX_ABS/dc/private/sam.ldb']) +plantestsuite_loadlist("samba4.urgent_replication.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/urgent_replication.py"), '$PREFIX_ABS/dc/private/sam.ldb', '$LOADLIST', '$LISTOPT']) plantestsuite_loadlist("samba4.ldap.dirsync.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/dirsync.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) -plantestsuite("samba4.ldap.sites.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) +plantestsuite_loadlist("samba4.ldap.sites.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sites.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: plantestsuite_loadlist("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.possibleInferiors.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/samdb/ldb_modules/tests/possibleinferiors.py"), "ldap://$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) -- 2.1.4 From 60b90952735b5f43e0488aa4145e7346b26b2ffd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 6 Mar 2015 14:41:50 +1300 Subject: [PATCH 21/36] token_group: Use samba.tests.subunitrun. Change-Id: Id7c247451532eded1f44ef9b1aa1808dd18098c6 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (backport similar to commit fc0b8aac9d5f1f77aa9a412fa5da2cc6b1a984ae) Signed-off-by: Andrew Bartlett BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/token_group.py | 24 ++++++++++-------------- source4/selftest/tests.py | 4 ++-- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/source4/dsdb/tests/python/token_group.py b/source4/dsdb/tests/python/token_group.py index cba6480..e55cd1c 100755 --- a/source4/dsdb/tests/python/token_group.py +++ b/source4/dsdb/tests/python/token_group.py @@ -8,8 +8,8 @@ import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options @@ -22,8 +22,6 @@ from samba import gensec from samba.credentials import Credentials, DONT_USE_KERBEROS from samba.dsdb import GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP -from subunit.run import SubunitTestRunner -import unittest import samba.tests from samba.tests import delete_force @@ -37,6 +35,8 @@ 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: @@ -117,7 +117,7 @@ class StaticTokenTest(samba.tests.TestCase): print("token sids don't match") print("difference : %s" % sidset1.difference(sidset2)) self.fail(msg="calculated groups don't match against user DN tokenGroups") - + def test_pac_groups(self): settings = {} settings["lp_ctx"] = lp @@ -142,8 +142,8 @@ class StaticTokenTest(samba.tests.TestCase): client_finished = False server_finished = False server_to_client = "" - - """Run the actual call loop""" + + # Run the actual call loop. while client_finished == False and server_finished == False: if not client_finished: print "running client gensec_update" @@ -495,10 +495,6 @@ if not "://" in url: else: url = "ldap://%s" % url -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(StaticTokenTest)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(DynamicTokenTest)).wasSuccessful(): - rc = 1 -sys.exit(rc) +samdb = SamDB(url, credentials=creds, session_info=system_session(lp), lp=lp) + +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index a6f115e..000e617 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -462,8 +462,8 @@ planpythontestsuite("dc:local", "samba.tests.dcerpc.rpcecho") planoldpythontestsuite("dc:local", "samba.tests.dcerpc.registry", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("dc", "samba.tests.dcerpc.dnsserver", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("plugin_s4_dc", "samba.tests.dcerpc.dnsserver", extra_args=['-U"$USERNAME%$PASSWORD"']) -plantestsuite("samba4.ldap.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) -plantestsuite("samba4.tokengroups.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) +plantestsuite_loadlist("samba4.ldap.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) +plantestsuite_loadlist("samba4.tokengroups.python(dc)", "dc:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/token_group.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.sam.python(dc)", "dc", [python, os.path.join(samba4srcdir, "dsdb/tests/python/sam.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) planoldpythontestsuite("dc", "dsdb_schema_info", extra_path=[os.path.join(samba4srcdir, 'dsdb/tests/python')], -- 2.1.4 From a30e6855b2031223b1f8eee97446702aca0feb4e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 08:57:37 -0800 Subject: [PATCH 22/36] sec_descriptor: Use samba.tests.subunitrun. Change-Id: I5caba3e27ad21cc5381883a823e0ec5e2966a264 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 0c82bdda0fddab4aa6bdbbbe13b6f888ed1c2c67) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/sec_descriptor.py | 22 ++++++---------------- source4/selftest/tests.py | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/source4/dsdb/tests/python/sec_descriptor.py b/source4/dsdb/tests/python/sec_descriptor.py index 39b5d4e..321d128 100755 --- a/source4/dsdb/tests/python/sec_descriptor.py +++ b/source4/dsdb/tests/python/sec_descriptor.py @@ -10,8 +10,8 @@ import random sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options @@ -29,10 +29,8 @@ from samba.auth import system_session from samba.dsdb import DS_DOMAIN_FUNCTION_2008 from samba.dcerpc.security import ( SECINFO_OWNER, SECINFO_GROUP, SECINFO_DACL, SECINFO_SACL) -from subunit.run import SubunitTestRunner import samba.tests from samba.tests import delete_force -import unittest parser = optparse.OptionParser("sec_descriptor.py [options] ") sambaopts = options.SambaOptions(parser) @@ -42,6 +40,9 @@ 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: @@ -2174,15 +2175,4 @@ if not "://" in host: if host.lower().startswith("ldap://"): ldb_options = ["modules:paged_searches"] -runner = SubunitTestRunner() -suite = unittest.TestSuite() -suite.addTests(unittest.makeSuite(OwnerGroupDescriptorTests)) -suite.addTests(unittest.makeSuite(DaclDescriptorTests)) -suite.addTests(unittest.makeSuite(SdFlagsDescriptorTests)) -suite.addTests(unittest.makeSuite(RightsAttributesTests)) -suite.addTests(unittest.makeSuite(SdAutoInheritTests)) -if not runner.run(suite).wasSuccessful(): - rc = 1 -else: - rc = 0 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 000e617..7adfbaa 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -475,7 +475,7 @@ plantestsuite_loadlist("samba4.ldap.sites.python(dc)", "dc", [python, os.path.jo for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: plantestsuite_loadlist("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.possibleInferiors.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/samdb/ldb_modules/tests/possibleinferiors.py"), "ldap://$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) - plantestsuite("samba4.ldap.secdesc.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/sec_descriptor.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) + plantestsuite_loadlist("samba4.ldap.secdesc.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/sec_descriptor.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.acl.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/acl.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) if env != "fl2000dc": # This test makes excessive use of the "userPassword" attribute which -- 2.1.4 From be0df4579e606e148bf0f6cb66c2ee6427999113 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:13:06 -0800 Subject: [PATCH 23/36] passwords: Use samba.tests.subunitrun. Change-Id: Ib806f63ef412fec264445eefd82146e5140b0bac Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit eae1efca41f4714afedff74afe330aad970f44ab) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/passwords.py | 232 ++++++++++++++++----------------- source4/selftest/tests.py | 2 +- 2 files changed, 114 insertions(+), 120 deletions(-) diff --git a/source4/dsdb/tests/python/passwords.py b/source4/dsdb/tests/python/passwords.py index 0db5e8c..fb3eee5 100755 --- a/source4/dsdb/tests/python/passwords.py +++ b/source4/dsdb/tests/python/passwords.py @@ -16,8 +16,8 @@ import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options @@ -34,8 +34,6 @@ from samba import gensec from samba.samdb import SamDB import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest parser = optparse.OptionParser("passwords.py [options] ") sambaopts = options.SambaOptions(parser) @@ -44,6 +42,9 @@ 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: @@ -66,8 +67,32 @@ class PasswordTests(samba.tests.TestCase): def setUp(self): super(PasswordTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() + self.ldb = SamDB(url=host, session_info=system_session(lp), credentials=creds, lp=lp) + + # Gets back the basedn + base_dn = self.ldb.domain_dn() + + # Gets back the configuration basedn + configuration_dn = self.ldb.get_config_basedn().get_linearized() + + # Get the old "dSHeuristics" if it was set + dsheuristics = self.ldb.get_dsheuristics() + + # Set the "dSHeuristics" to activate the correct "userPassword" behaviour + self.ldb.set_dsheuristics("000000001") + + # Reset the "dSHeuristics" as they were before + self.addCleanup(self.ldb.set_dsheuristics, dsheuristics) + + # Get the old "minPwdAge" + minPwdAge = self.ldb.get_minPwdAge() + + # Set it temporarely to "0" + self.ldb.set_minPwdAge("0") + self.base_dn = self.ldb.domain_dn() + + # Reset the "minPwdAge" as it was before + self.addCleanup(self.ldb.set_minPwdAge, minPwdAge) # (Re)adds the test user "testuser" with no password atm delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn) @@ -136,21 +161,21 @@ add: userPassword self.ldb2 = SamDB(url=host, credentials=creds2, lp=lp) def test_unicodePwd_hash_set(self): - print "Performs a password hash set operation on 'unicodePwd' which should be prevented" + """Performs a password hash set operation on 'unicodePwd' which should be prevented""" # Notice: Direct hash password sets should never work m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["unicodePwd"] = MessageElement("XXXXXXXXXXXXXXXX", FLAG_MOD_REPLACE, "unicodePwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) def test_unicodePwd_hash_change(self): - print "Performs a password hash change operation on 'unicodePwd' which should be prevented" + """Performs a password hash change operation on 'unicodePwd' which should be prevented""" # Notice: Direct hash password changes should never work # Hash password changes should never work @@ -168,16 +193,16 @@ unicodePwd: YYYYYYYYYYYYYYYY self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) def test_unicodePwd_clear_set(self): - print "Performs a password cleartext set operation on 'unicodePwd'" + """Performs a password cleartext set operation on 'unicodePwd'""" m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["unicodePwd"] = MessageElement("\"thatsAcomplPASS2\"".encode('utf-16-le'), FLAG_MOD_REPLACE, "unicodePwd") - ldb.modify(m) + self.ldb.modify(m) def test_unicodePwd_clear_change(self): - print "Performs a password cleartext change operation on 'unicodePwd'" + """Performs a password cleartext change operation on 'unicodePwd'""" self.ldb2.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ @@ -219,21 +244,21 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) self.assertTrue('0000052D' in msg) def test_dBCSPwd_hash_set(self): - print "Performs a password hash set operation on 'dBCSPwd' which should be prevented" + """Performs a password hash set operation on 'dBCSPwd' which should be prevented""" # Notice: Direct hash password sets should never work m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["dBCSPwd"] = MessageElement("XXXXXXXXXXXXXXXX", FLAG_MOD_REPLACE, "dBCSPwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) def test_dBCSPwd_hash_change(self): - print "Performs a password hash change operation on 'dBCSPwd' which should be prevented" + """Performs a password hash change operation on 'dBCSPwd' which should be prevented""" # Notice: Direct hash password changes should never work try: @@ -250,18 +275,18 @@ dBCSPwd: YYYYYYYYYYYYYYYY self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) def test_userPassword_clear_set(self): - print "Performs a password cleartext set operation on 'userPassword'" + """Performs a password cleartext set operation on 'userPassword'""" # Notice: This works only against Windows if "dSHeuristics" has been set # properly m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement("thatsAcomplPASS2", FLAG_MOD_REPLACE, "userPassword") - ldb.modify(m) + self.ldb.modify(m) def test_userPassword_clear_change(self): - print "Performs a password cleartext change operation on 'userPassword'" + """Performs a password cleartext change operation on 'userPassword'""" # Notice: This works only against Windows if "dSHeuristics" has been set # properly @@ -305,15 +330,15 @@ userPassword: thatsAcomplPASS2 self.assertTrue('0000052D' in msg) def test_clearTextPassword_clear_set(self): - print "Performs a password cleartext set operation on 'clearTextPassword'" + """Performs a password cleartext set operation on 'clearTextPassword'""" # Notice: This never works against Windows - only supported by us try: m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["clearTextPassword"] = MessageElement("thatsAcomplPASS2".encode('utf-16-le'), FLAG_MOD_REPLACE, "clearTextPassword") - ldb.modify(m) + self.ldb.modify(m) # this passes against s4 except LdbError, (num, msg): # "NO_SUCH_ATTRIBUTE" is returned by Windows -> ignore it @@ -321,7 +346,7 @@ userPassword: thatsAcomplPASS2 raise LdbError(num, msg) def test_clearTextPassword_clear_change(self): - print "Performs a password cleartext change operation on 'clearTextPassword'" + """Performs a password cleartext change operation on 'clearTextPassword'""" # Notice: This never works against Windows - only supported by us try: @@ -374,10 +399,10 @@ clearTextPassword:: """ + base64.b64encode("thatsAcomplPASS2".encode('utf-16-le' self.assertTrue('0000052D' in msg) def test_failures(self): - print "Performs some failure testing" + """Performs some failure testing""" try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -399,7 +424,7 @@ userPassword: thatsAcomplPASS1 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -419,7 +444,7 @@ delete: userPassword self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify add: userPassword @@ -441,7 +466,7 @@ userPassword: thatsAcomplPASS1 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -469,7 +494,7 @@ userPassword: thatsAcomplPASS2 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -497,7 +522,7 @@ userPassword: thatsAcomplPASS2 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -527,7 +552,7 @@ userPassword: thatsAcomplPASS2 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -557,7 +582,7 @@ userPassword: thatsAcomplPASS2 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS) try: - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify delete: userPassword @@ -623,7 +648,7 @@ userPassword: thatsAcomplPASS4 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE) # Several password changes at once are allowed - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify replace: userPassword @@ -632,7 +657,7 @@ userPassword: thatsAcomplPASS2 """) # Several password changes at once are allowed - ldb.modify_ldif(""" + self.ldb.modify_ldif(""" dn: cn=testuser,cn=users,""" + self.base_dn + """ changetype: modify replace: userPassword @@ -701,111 +726,111 @@ userPassword: thatsAcomplPASS4 delete_force(self.ldb, "cn=testuser2,cn=users," + self.base_dn) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["unicodePwd"] = MessageElement([], FLAG_MOD_ADD, "unicodePwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["dBCSPwd"] = MessageElement([], FLAG_MOD_ADD, "dBCSPwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement([], FLAG_MOD_ADD, "userPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["clearTextPassword"] = MessageElement([], FLAG_MOD_ADD, "clearTextPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or num == ERR_NO_SUCH_ATTRIBUTE) # for Windows m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["unicodePwd"] = MessageElement([], FLAG_MOD_REPLACE, "unicodePwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["dBCSPwd"] = MessageElement([], FLAG_MOD_REPLACE, "dBCSPwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement([], FLAG_MOD_REPLACE, "userPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["clearTextPassword"] = MessageElement([], FLAG_MOD_REPLACE, "clearTextPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertTrue(num == ERR_UNWILLING_TO_PERFORM or num == ERR_NO_SUCH_ATTRIBUTE) # for Windows m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["unicodePwd"] = MessageElement([], FLAG_MOD_DELETE, "unicodePwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["dBCSPwd"] = MessageElement([], FLAG_MOD_DELETE, "dBCSPwd") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement([], FLAG_MOD_DELETE, "userPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["clearTextPassword"] = MessageElement([], FLAG_MOD_DELETE, "clearTextPassword") try: - ldb.modify(m) + self.ldb.modify(m) self.fail() except LdbError, (num, _): self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or @@ -815,96 +840,96 @@ userPassword: thatsAcomplPASS4 print "Performs testing about the standard 'userPassword' behaviour" # Delete the "dSHeuristics" - ldb.set_dsheuristics(None) + self.ldb.set_dsheuristics(None) time.sleep(1) # This switching time is strictly needed! m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement("myPassword", FLAG_MOD_ADD, "userPassword") - ldb.modify(m) + self.ldb.modify(m) - res = ldb.search("cn=testuser,cn=users," + self.base_dn, + res = self.ldb.search("cn=testuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) self.assertEquals(res[0]["userPassword"][0], "myPassword") m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement("myPassword2", FLAG_MOD_REPLACE, "userPassword") - ldb.modify(m) + self.ldb.modify(m) - res = ldb.search("cn=testuser,cn=users," + self.base_dn, + res = self.ldb.search("cn=testuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) self.assertEquals(res[0]["userPassword"][0], "myPassword2") m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement([], FLAG_MOD_DELETE, "userPassword") - ldb.modify(m) + self.ldb.modify(m) - res = ldb.search("cn=testuser,cn=users," + self.base_dn, + res = self.ldb.search("cn=testuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertFalse("userPassword" in res[0]) # Set the test "dSHeuristics" to deactivate "userPassword" pwd changes - ldb.set_dsheuristics("000000000") + self.ldb.set_dsheuristics("000000000") m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement("myPassword3", FLAG_MOD_REPLACE, "userPassword") - ldb.modify(m) + self.ldb.modify(m) - res = ldb.search("cn=testuser,cn=users," + self.base_dn, + res = self.ldb.search("cn=testuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) self.assertEquals(res[0]["userPassword"][0], "myPassword3") # Set the test "dSHeuristics" to deactivate "userPassword" pwd changes - ldb.set_dsheuristics("000000002") + self.ldb.set_dsheuristics("000000002") m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userPassword"] = MessageElement("myPassword4", FLAG_MOD_REPLACE, "userPassword") - ldb.modify(m) + self.ldb.modify(m) - res = ldb.search("cn=testuser,cn=users," + self.base_dn, + res = self.ldb.search("cn=testuser,cn=users," + self.base_dn, scope=SCOPE_BASE, attrs=["userPassword"]) self.assertTrue(len(res) == 1) self.assertTrue("userPassword" in res[0]) self.assertEquals(res[0]["userPassword"][0], "myPassword4") # Reset the test "dSHeuristics" (reactivate "userPassword" pwd changes) - ldb.set_dsheuristics("000000001") + self.ldb.set_dsheuristics("000000001") def test_zero_length(self): # Get the old "minPwdLength" - minPwdLength = ldb.get_minPwdLength() + minPwdLength = self.ldb.get_minPwdLength() # Set it temporarely to "0" - ldb.set_minPwdLength("0") + self.ldb.set_minPwdLength("0") # Get the old "pwdProperties" - pwdProperties = ldb.get_pwdProperties() + pwdProperties = self.ldb.get_pwdProperties() # Set them temporarely to "0" (to deactivate eventually the complexity) - ldb.set_pwdProperties("0") + self.ldb.set_pwdProperties("0") - ldb.setpassword("(sAMAccountName=testuser)", "") + self.ldb.setpassword("(sAMAccountName=testuser)", "") # Reset the "pwdProperties" as they were before - ldb.set_pwdProperties(pwdProperties) + self.ldb.set_pwdProperties(pwdProperties) # Reset the "minPwdLength" as it was before - ldb.set_minPwdLength(minPwdLength) + self.ldb.set_minPwdLength(minPwdLength) def tearDown(self): super(PasswordTests, self).tearDown() @@ -919,35 +944,4 @@ if not "://" in host: else: host = "ldap://%s" % host -ldb = SamDB(url=host, session_info=system_session(lp), credentials=creds, lp=lp) - -# Gets back the basedn -base_dn = ldb.domain_dn() - -# Gets back the configuration basedn -configuration_dn = ldb.get_config_basedn().get_linearized() - -# Get the old "dSHeuristics" if it was set -dsheuristics = ldb.get_dsheuristics() - -# Set the "dSHeuristics" to activate the correct "userPassword" behaviour -ldb.set_dsheuristics("000000001") - -# Get the old "minPwdAge" -minPwdAge = ldb.get_minPwdAge() - -# Set it temporarely to "0" -ldb.set_minPwdAge("0") - -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(PasswordTests)).wasSuccessful(): - rc = 1 - -# Reset the "dSHeuristics" as they were before -ldb.set_dsheuristics(dsheuristics) - -# Reset the "minPwdAge" as it was before -ldb.set_minPwdAge(minPwdAge) - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 7adfbaa..8d8b5be 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -481,7 +481,7 @@ for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: # This test makes excessive use of the "userPassword" attribute which # isn't available on DCs with Windows 2000 domain function level - # therefore skip it in that configuration - plantestsuite("samba4.ldap.passwords.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/passwords.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) + plantestsuite_loadlist("samba4.ldap.passwords.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/passwords.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN", '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.password_lockout.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/password_lockout.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN", "--realm=$REALM"]) planpythontestsuite("dc:local", "samba.tests.upgradeprovisionneeddc") -- 2.1.4 From c090d28b3bb47574334adff6ddf283fb33ed8712 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:30:50 -0800 Subject: [PATCH 24/36] password lockout: Use samba.tests.subunitrun. Change-Id: I848099d22acd4a0ce7d589de48eb72e2d180ceae Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 3961bd68cad510c3ac06270036b54b065d0c3566) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/password_lockout.py | 189 ++++++++++++-------------- source4/selftest/tests.py | 2 +- 2 files changed, 91 insertions(+), 100 deletions(-) diff --git a/source4/dsdb/tests/python/password_lockout.py b/source4/dsdb/tests/python/password_lockout.py index 89e5d69..133b40b 100755 --- a/source4/dsdb/tests/python/password_lockout.py +++ b/source4/dsdb/tests/python/password_lockout.py @@ -11,31 +11,25 @@ import optparse import sys import base64 import time -import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options from samba.auth import system_session from samba.credentials import Credentials, DONT_USE_KERBEROS, MUST_USE_KERBEROS from ldb import SCOPE_BASE, LdbError -from ldb import ERR_ATTRIBUTE_OR_VALUE_EXISTS -from ldb import ERR_UNWILLING_TO_PERFORM, ERR_INSUFFICIENT_ACCESS_RIGHTS -from ldb import ERR_NO_SUCH_ATTRIBUTE from ldb import ERR_CONSTRAINT_VIOLATION from ldb import ERR_INVALID_CREDENTIALS from ldb import Message, MessageElement, Dn -from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE +from ldb import FLAG_MOD_REPLACE from samba import gensec, dsdb from samba.samdb import SamDB import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest from samba.dcerpc import security, samr from samba.ndr import ndr_unpack @@ -46,6 +40,8 @@ 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: @@ -182,7 +178,7 @@ userAccountControl: %d # 10 micro second time.sleep(0.01) - res = ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) self.assertTrue(len(res) == 1) self._check_attribute(res, "badPwdCount", badPwdCount) self._check_attribute(res, "badPasswordTime", badPasswordTime) @@ -229,7 +225,7 @@ userAccountControl: %d # check LDAP again and make sure the samr.QueryUserInfo # doesn't have any impact. - res2 = ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res2 = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) self.assertEquals(res[0], res2[0]) # in order to prevent some time resolution problems we sleep for @@ -239,8 +235,84 @@ userAccountControl: %d def setUp(self): super(PasswordTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() + + self.ldb = SamDB(url=host_url, session_info=system_session(lp), credentials=creds, lp=lp) + + # Gets back the basedn + base_dn = self.ldb.domain_dn() + + # Gets back the configuration basedn + configuration_dn = self.ldb.get_config_basedn().get_linearized() + + # Get the old "dSHeuristics" if it was set + dsheuristics = self.ldb.get_dsheuristics() + + # Reset the "dSHeuristics" as they were before + self.addCleanup(self.ldb.set_dsheuristics, dsheuristics) + + res = self.ldb.search(base_dn, + scope=SCOPE_BASE, attrs=["lockoutDuration", "lockOutObservationWindow", "lockoutThreshold"]) + + if "lockoutDuration" in res[0]: + lockoutDuration = res[0]["lockoutDuration"][0] + else: + lockoutDuration = 0 + + if "lockoutObservationWindow" in res[0]: + lockoutObservationWindow = res[0]["lockoutObservationWindow"][0] + else: + lockoutObservationWindow = 0 + + if "lockoutThreshold" in res[0]: + lockoutThreshold = res[0]["lockoutThreshold"][0] + else: + lockoutTreshold = 0 + + self.addCleanup(self.ldb.modify_ldif, """ +dn: """ + base_dn + """ +changetype: modify +replace: lockoutDuration +lockoutDuration: """ + str(lockoutDuration) + """ +replace: lockoutObservationWindow +lockoutObservationWindow: """ + str(lockoutObservationWindow) + """ +replace: lockoutThreshold +lockoutThreshold: """ + str(lockoutThreshold) + """ +""") + + m = Message() + m.dn = Dn(self.ldb, base_dn) + + self.account_lockout_duration = 10 + account_lockout_duration_ticks = -int(self.account_lockout_duration * (1e7)) + + m["lockoutDuration"] = MessageElement(str(account_lockout_duration_ticks), + FLAG_MOD_REPLACE, "lockoutDuration") + + account_lockout_threshold = 3 + m["lockoutThreshold"] = MessageElement(str(account_lockout_threshold), + FLAG_MOD_REPLACE, "lockoutThreshold") + + self.lockout_observation_window = 5 + lockout_observation_window_ticks = -int(self.lockout_observation_window * (1e7)) + + m["lockOutObservationWindow"] = MessageElement(str(lockout_observation_window_ticks), + FLAG_MOD_REPLACE, "lockOutObservationWindow") + + self.ldb.modify(m) + + # Set the "dSHeuristics" to activate the correct "userPassword" behaviour + self.ldb.set_dsheuristics("000000001") + + # Get the old "minPwdAge" + minPwdAge = self.ldb.get_minPwdAge() + + # Reset the "minPwdAge" as it was before + self.addCleanup(self.ldb.set_minPwdAge, minPwdAge) + + # Set it temporarely to "0" + self.ldb.set_minPwdAge("0") + + self.base_dn = self.ldb.domain_dn() self.domain_sid = security.dom_sid(self.ldb.get_domain_sid()) self.samr = samr.samr("ncacn_ip_tcp:%s[sign]" % host, lp, creds) @@ -670,7 +742,7 @@ userPassword: thatsAcomplPASS2x msDSUserAccountControlComputed=dsdb.UF_LOCKOUT) m = Message() - m.dn = Dn(ldb, "cn=testuser,cn=users," + self.base_dn) + m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn) m["userAccountControl"] = MessageElement( str(dsdb.UF_LOCKOUT), FLAG_MOD_REPLACE, "userAccountControl") @@ -1106,7 +1178,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) badPasswordTime = int(res[0]["badPasswordTime"][0]) lockoutTime = int(res[0]["lockoutTime"][0]) - time.sleep(account_lockout_duration + 1) + time.sleep(self.account_lockout_duration + 1) res = self._check_account("cn=testuser,cn=users," + self.base_dn, badPwdCount=3, effective_bad_password_count=0, @@ -1289,7 +1361,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) dsdb.UF_NORMAL_ACCOUNT, msDSUserAccountControlComputed=dsdb.UF_LOCKOUT) - time.sleep(account_lockout_duration + 1) + time.sleep(self.account_lockout_duration + 1) res = self._check_account("cn=testuser,cn=users," + self.base_dn, badPwdCount=3, effective_bad_password_count=0, @@ -1345,7 +1417,7 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) msDSUserAccountControlComputed=0) badPasswordTime = int(res[0]["badPasswordTime"][0]) - time.sleep(lockout_observation_window + 1) + time.sleep(self.lockout_observation_window + 1) res = self._check_account("cn=testuser,cn=users," + self.base_dn, badPwdCount=2, effective_bad_password_count=0, @@ -1400,85 +1472,4 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) host_url = "ldap://%s" % host -ldb = SamDB(url=host_url, session_info=system_session(lp), credentials=creds, lp=lp) - -# Gets back the basedn -base_dn = ldb.domain_dn() - -# Gets back the configuration basedn -configuration_dn = ldb.get_config_basedn().get_linearized() - -# Get the old "dSHeuristics" if it was set -dsheuristics = ldb.get_dsheuristics() - -res = ldb.search(base_dn, - scope=SCOPE_BASE, attrs=["lockoutDuration", "lockOutObservationWindow", "lockoutThreshold"]) - -if "lockoutDuration" in res[0]: - lockoutDuration = res[0]["lockoutDuration"][0] -else: - lockoutDuration = 0 - -if "lockoutObservationWindow" in res[0]: - lockoutObservationWindow = res[0]["lockoutObservationWindow"][0] -else: - lockoutObservationWindow = 0 - -if "lockoutThreshold" in res[0]: - lockoutThreshold = res[0]["lockoutThreshold"][0] -else: - lockoutTreshold = 0 - -m = Message() -m.dn = Dn(ldb, base_dn) - -account_lockout_duration = 10 -account_lockout_duration_ticks = -int(account_lockout_duration * (1e7)) - -m["lockoutDuration"] = MessageElement(str(account_lockout_duration_ticks), - FLAG_MOD_REPLACE, "lockoutDuration") - -account_lockout_threshold = 3 -m["lockoutThreshold"] = MessageElement(str(account_lockout_threshold), - FLAG_MOD_REPLACE, "lockoutThreshold") - -lockout_observation_window = 5 -lockout_observation_window_ticks = -int(lockout_observation_window * (1e7)) - -m["lockOutObservationWindow"] = MessageElement(str(lockout_observation_window_ticks), - FLAG_MOD_REPLACE, "lockOutObservationWindow") - -ldb.modify(m) - -# Set the "dSHeuristics" to activate the correct "userPassword" behaviour -ldb.set_dsheuristics("000000001") - -# Get the old "minPwdAge" -minPwdAge = ldb.get_minPwdAge() - -# Set it temporarely to "0" -ldb.set_minPwdAge("0") - -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(PasswordTests)).wasSuccessful(): - rc = 1 - -# Reset the "dSHeuristics" as they were before -ldb.set_dsheuristics(dsheuristics) - -# Reset the "minPwdAge" as it was before -ldb.set_minPwdAge(minPwdAge) - -ldb.modify_ldif(""" -dn: """ + base_dn + """ -changetype: modify -replace: lockoutDuration -lockoutDuration: """ + str(lockoutDuration) + """ -replace: lockoutObservationWindow -lockoutObservationWindow: """ + str(lockoutObservationWindow) + """ -replace: lockoutThreshold -lockoutThreshold: """ + str(lockoutThreshold) + """ -""") - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 8d8b5be..3374cf1 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -482,7 +482,7 @@ for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: # isn't available on DCs with Windows 2000 domain function level - # therefore skip it in that configuration plantestsuite_loadlist("samba4.ldap.passwords.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/passwords.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN", '$LOADLIST', '$LISTOPT']) - plantestsuite("samba4.ldap.password_lockout.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/password_lockout.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN", "--realm=$REALM"]) + plantestsuite_loadlist("samba4.ldap.password_lockout.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/password_lockout.py"), "$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN", "--realm=$REALM", '$LOADLIST', '$LISTOPT']) planpythontestsuite("dc:local", "samba.tests.upgradeprovisionneeddc") planpythontestsuite("plugin_s4_dc:local", "samba.tests.posixacl") -- 2.1.4 From a95e23c05ec600ee293a1ec8467c868fe439632d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:32:58 -0800 Subject: [PATCH 25/36] ldap_syntaxes: Use samba.tests.subunitrun. Change-Id: Ib62b747876b4408fdc8ff44e9b4c63578e1a6408 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 6fb26c0e29d74c793f8714b057e0ed0e5ee0cc37) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/ldap_syntaxes.py | 40 ++++++++++++------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/source4/dsdb/tests/python/ldap_syntaxes.py b/source4/dsdb/tests/python/ldap_syntaxes.py index ad89cb1..711678b 100755 --- a/source4/dsdb/tests/python/ldap_syntaxes.py +++ b/source4/dsdb/tests/python/ldap_syntaxes.py @@ -10,8 +10,8 @@ import uuid sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options @@ -21,9 +21,6 @@ from ldb import ERR_CONSTRAINT_VIOLATION from ldb import ERR_INVALID_ATTRIBUTE_SYNTAX from ldb import ERR_ENTRY_ALREADY_EXISTS -from subunit.run import SubunitTestRunner -import unittest - import samba.tests parser = optparse.OptionParser("ldap [options] ") @@ -33,6 +30,8 @@ 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: @@ -48,9 +47,10 @@ class SyntaxTests(samba.tests.TestCase): def setUp(self): super(SyntaxTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() - self.schema_dn = ldb.get_schema_basedn().get_linearized() + self.ldb = samba.tests.connect_samdb(host, credentials=creds, + session_info=system_session(lp), lp=lp) + self.base_dn = self.ldb.domain_dn() + self.schema_dn = self.ldb.get_schema_basedn().get_linearized() self._setup_dn_string_test() self._setup_dn_binary_test() @@ -192,26 +192,26 @@ name: """ + object_name + """ return ldif def test_dn_string(self): - # add obeject with correct value + # add object with correct value object_name1 = "obj-DN-String1" + time.strftime("%s", time.gmtime()) ldif = self._get_object_ldif(object_name1, self.dn_string_class_name, self.dn_string_class_ldap_display_name, self.dn_string_attribute, ": S:5:ABCDE:" + self.base_dn) self.ldb.add_ldif(ldif) # search by specifying the DN part only - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=%s)" % (self.dn_string_attribute, self.base_dn)) self.assertEquals(len(res), 0) # search by specifying the string part only - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=S:5:ABCDE)" % self.dn_string_attribute) self.assertEquals(len(res), 0) # search by DN+Stirng - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=S:5:ABCDE:%s)" % (self.dn_string_attribute, self.base_dn)) self.assertEquals(len(res), 1) @@ -283,7 +283,6 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) - pass def test_dn_binary(self): # add obeject with correct value @@ -293,19 +292,19 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) # search by specifyingthe DN part - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=%s)" % (self.dn_binary_attribute, self.base_dn)) self.assertEquals(len(res), 0) # search by specifying the binary part - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=B:4:1234)" % self.dn_binary_attribute) self.assertEquals(len(res), 0) # search by DN+Binary - res = ldb.search(base=self.base_dn, + res = self.ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE, expression="(%s=B:4:1234:%s)" % (self.dn_binary_attribute, self.base_dn)) self.assertEquals(len(res), 1) @@ -369,12 +368,5 @@ name: """ + object_name + """ self.ldb.add_ldif(ldif) except LdbError, (num, _): self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) - pass - -ldb = samba.tests.connect_samdb(host, credentials=creds, session_info=system_session(lp), lp=lp) -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(SyntaxTests)).wasSuccessful(): - rc = 1 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) -- 2.1.4 From ca4959e0f85eedaf80f61da3ba0f1d2c891bc78f Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:39:17 -0800 Subject: [PATCH 26/36] deletetest: use samba.tests.subunitrun. Change-Id: I13565c7c14ea186709ce1de9038ef840c5b766b8 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit cfb5e9bbf2bde885c50097ab0a2914c674e65860) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/deletetest.py | 112 +++++++++++++++----------------- source4/selftest/tests.py | 4 +- 2 files changed, 54 insertions(+), 62 deletions(-) diff --git a/source4/dsdb/tests/python/deletetest.py b/source4/dsdb/tests/python/deletetest.py index ce972ab..370f56c 100755 --- a/source4/dsdb/tests/python/deletetest.py +++ b/source4/dsdb/tests/python/deletetest.py @@ -7,8 +7,8 @@ import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options @@ -19,9 +19,6 @@ from ldb import ERR_UNWILLING_TO_PERFORM from samba.samdb import SamDB from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest - parser = optparse.OptionParser("deletetest.py [options] ") sambaopts = options.SambaOptions(parser) parser.add_option_group(sambaopts) @@ -29,6 +26,8 @@ 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: @@ -42,20 +41,20 @@ creds = credopts.get_credentials(lp) class BasicDeleteTests(samba.tests.TestCase): - def GUID_string(self, guid): return self.ldb.schema_format_value("objectGUID", guid) def setUp(self): super(BasicDeleteTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() - self.configuration_dn = ldb.get_config_basedn().get_linearized() + 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 = ldb.search(base="" % self.GUID_string(guid), + res = self.ldb.search(base="" % self.GUID_string(guid), scope=SCOPE_BASE, controls=["show_deleted:1"]) self.assertEquals(len(res), 1) return res[0] @@ -63,7 +62,7 @@ class BasicDeleteTests(samba.tests.TestCase): def search_dn(self,dn): print "SEARCH by DN %s" % dn - res = ldb.search(expression="(objectClass=*)", + res = self.ldb.search(expression="(objectClass=*)", base=dn, scope=SCOPE_BASE, controls=["show_deleted:1"]) @@ -119,38 +118,38 @@ class BasicDeleteTests(samba.tests.TestCase): delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn) delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn) - ldb.add({ + self.ldb.add({ "dn": "cn=ldaptestcontainer," + self.base_dn, "objectclass": "container"}) - ldb.add({ + self.ldb.add({ "dn": "cn=entry1,cn=ldaptestcontainer," + self.base_dn, "objectclass": "container"}) - ldb.add({ + self.ldb.add({ "dn": "cn=entry2,cn=ldaptestcontainer," + self.base_dn, "objectclass": "container"}) try: - ldb.delete("cn=ldaptestcontainer," + self.base_dn) + self.ldb.delete("cn=ldaptestcontainer," + self.base_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) - ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:1"]) + self.ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:1"]) try: - res = ldb.search("cn=ldaptestcontainer," + self.base_dn, + res = self.ldb.search("cn=ldaptestcontainer," + self.base_dn, scope=SCOPE_BASE, attrs=[]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NO_SUCH_OBJECT) try: - res = ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn, + res = self.ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn, scope=SCOPE_BASE, attrs=[]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NO_SUCH_OBJECT) try: - res = ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn, + res = self.ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn, scope=SCOPE_BASE, attrs=[]) self.fail() except LdbError, (num, _): @@ -162,29 +161,29 @@ class BasicDeleteTests(samba.tests.TestCase): # Performs some protected object delete testing - res = ldb.search(base="", expression="", scope=SCOPE_BASE, + res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["dsServiceName", "dNSHostName"]) self.assertEquals(len(res), 1) # Delete failing since DC's nTDSDSA object is protected try: - ldb.delete(res[0]["dsServiceName"][0]) + self.ldb.delete(res[0]["dsServiceName"][0]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) - res = ldb.search(self.base_dn, attrs=["rIDSetReferences"], + res = self.ldb.search(self.base_dn, attrs=["rIDSetReferences"], expression="(&(objectClass=computer)(dNSHostName=" + res[0]["dNSHostName"][0] + "))") self.assertEquals(len(res), 1) # Deletes failing since DC's rIDSet object is protected try: - ldb.delete(res[0]["rIDSetReferences"][0]) + self.ldb.delete(res[0]["rIDSetReferences"][0]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) try: - ldb.delete(res[0]["rIDSetReferences"][0], ["tree_delete:1"]) + self.ldb.delete(res[0]["rIDSetReferences"][0], ["tree_delete:1"]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) @@ -192,52 +191,52 @@ class BasicDeleteTests(samba.tests.TestCase): # Deletes failing since three main crossRef objects are protected try: - ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn) + self.ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) try: - ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) + self.ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) try: - ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn) + self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) try: - ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) + self.ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn, ["tree_delete:1"]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) - res = ldb.search("cn=Partitions," + self.configuration_dn, attrs=[], + res = self.ldb.search("cn=Partitions," + self.configuration_dn, attrs=[], expression="(nCName=%s)" % self.base_dn) self.assertEquals(len(res), 1) try: - ldb.delete(res[0].dn) + self.ldb.delete(res[0].dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) try: - ldb.delete(res[0].dn, ["tree_delete:1"]) + self.ldb.delete(res[0].dn, ["tree_delete:1"]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF) # Delete failing since "SYSTEM_FLAG_DISALLOW_DELETE" try: - ldb.delete("CN=Users," + self.base_dn) + self.ldb.delete("CN=Users," + self.base_dn) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) # Tree-delete failing since "isCriticalSystemObject" try: - ldb.delete("CN=Computers," + self.base_dn, ["tree_delete:1"]) + self.ldb.delete("CN=Computers," + self.base_dn, ["tree_delete:1"]) self.fail() except LdbError, (num, _): self.assertEquals(num, ERR_UNWILLING_TO_PERFORM) @@ -263,19 +262,19 @@ class BasicDeleteTests(samba.tests.TestCase): delete_force(self.ldb, srv1) delete_force(self.ldb, sit1) - ldb.add({ + self.ldb.add({ "dn": usr1, "objectclass": "user", "description": "test user description", "samaccountname": "testuser"}) - ldb.add({ + self.ldb.add({ "dn": usr2, "objectclass": "user", "description": "test user 2 description", "samaccountname": "testuser2"}) - ldb.add({ + self.ldb.add({ "dn": grp1, "objectclass": "group", "description": "test group", @@ -283,19 +282,19 @@ class BasicDeleteTests(samba.tests.TestCase): "member": [ usr1, usr2 ], "isDeleted": "FALSE" }) - ldb.add({ + self.ldb.add({ "dn": sit1, "objectclass": "site" }) - ldb.add({ + self.ldb.add({ "dn": ss1, "objectclass": ["applicationSiteSettings", "nTDSSiteSettings"] }) - ldb.add({ + self.ldb.add({ "dn": srv1, "objectclass": "serversContainer" }) - ldb.add({ + self.ldb.add({ "dn": srv2, "objectClass": "server" }) @@ -320,11 +319,11 @@ class BasicDeleteTests(samba.tests.TestCase): objLive7 = self.search_dn(srv2) guid7=objLive7["objectGUID"][0] - ldb.delete(usr1) - ldb.delete(usr2) - ldb.delete(grp1) - ldb.delete(srv1, ["tree_delete:1"]) - ldb.delete(sit1, ["tree_delete:1"]) + self.ldb.delete(usr1) + self.ldb.delete(usr2) + self.ldb.delete(grp1) + self.ldb.delete(srv1, ["tree_delete:1"]) + self.ldb.delete(sit1, ["tree_delete:1"]) objDeleted1 = self.search_guid(guid1) objDeleted2 = self.search_guid(guid2) @@ -358,13 +357,13 @@ class BasicDeleteTests(samba.tests.TestCase): self.check_rdn(objLive6, objDeleted6, "cn") self.check_rdn(objLive7, objDeleted7, "cn") - self.delete_deleted(ldb, usr1) - self.delete_deleted(ldb, usr2) - self.delete_deleted(ldb, grp1) - self.delete_deleted(ldb, sit1) - self.delete_deleted(ldb, ss1) - self.delete_deleted(ldb, srv1) - self.delete_deleted(ldb, srv2) + self.delete_deleted(self.ldb, usr1) + self.delete_deleted(self.ldb, usr2) + self.delete_deleted(self.ldb, grp1) + self.delete_deleted(self.ldb, sit1) + self.delete_deleted(self.ldb, ss1) + self.delete_deleted(self.ldb, srv1) + self.delete_deleted(self.ldb, srv2) self.assertTrue("CN=Deleted Objects" in str(objDeleted1.dn)) self.assertTrue("CN=Deleted Objects" in str(objDeleted2.dn)) @@ -380,11 +379,4 @@ if not "://" in host: else: host = "ldap://%s" % host -ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp) - -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(BasicDeleteTests)).wasSuccessful(): - rc = 1 - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 3374cf1..6a29e01 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -486,9 +486,9 @@ for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: planpythontestsuite("dc:local", "samba.tests.upgradeprovisionneeddc") planpythontestsuite("plugin_s4_dc:local", "samba.tests.posixacl") -plantestsuite("samba4.deletetest.python(dc)", "dc", ['PYTHONPATH="$PYTHONPATH:%s/lib/subunit/python:%s/lib/testtools"' % (srcdir(), srcdir()), +plantestsuite_loadlist("samba4.deletetest.python(dc)", "dc", ['PYTHONPATH="$PYTHONPATH:%s/lib/subunit/python:%s/lib/testtools"' % (srcdir(), srcdir()), python, os.path.join(samba4srcdir, "dsdb/tests/python/deletetest.py"), - '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) + '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.blackbox.samba3dump", "none", ['PYTHONPATH="$PYTHONPATH:%s/lib/subunit/python:%s/lib/testtools"' % (srcdir(), srcdir()), os.path.join(samba4srcdir, "selftest/test_samba3dump.sh")]) plantestsuite("samba4.blackbox.upgrade", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_s3upgrade.sh"), '$PREFIX/provision']) plantestsuite("samba4.blackbox.provision.py", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_provision.sh"), '$PREFIX/provision']) -- 2.1.4 From 2f9c6fbc38db98b41fdca33c5d7baa3a0bacf141 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:44:05 -0800 Subject: [PATCH 27/36] ldap: Use samba.tests.subunitrun. Change-Id: I872654afb31a5eda8c88aac716f9ce79816e5f05 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit d857e7b1a7a2cc1f7f4f9f2ffd5a11f8c627ae39) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/acl.py | 25 ++++++------------------- source4/selftest/tests.py | 2 +- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py index 7ef9ad9..4acc123 100755 --- a/source4/dsdb/tests/python/acl.py +++ b/source4/dsdb/tests/python/acl.py @@ -8,8 +8,8 @@ import base64 import re sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") + +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options from samba.join import dc_join @@ -29,8 +29,6 @@ from samba.samdb import SamDB from samba.credentials import Credentials, DONT_USE_KERBEROS import samba.tests from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest import samba.dsdb parser = optparse.OptionParser("acl.py [options] ") @@ -41,6 +39,9 @@ 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: @@ -1902,18 +1903,4 @@ class AclSPNTests(AclTests): ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp) -runner = SubunitTestRunner() -suite = unittest.TestSuite() -suite.addTests(unittest.makeSuite(AclAddTests)) -suite.addTests(unittest.makeSuite(AclModifyTests)) -suite.addTests(unittest.makeSuite(AclDeleteTests)) -suite.addTests(unittest.makeSuite(AclRenameTests)) -suite.addTests(unittest.makeSuite(AclCARTests)) -suite.addTests(unittest.makeSuite(AclSearchTests)) -suite.addTests(unittest.makeSuite(AclExtendedTests)) -suite.addTests(unittest.makeSuite(AclSPNTests)) -if not runner.run(suite).wasSuccessful(): - rc = 1 -else: - rc = 0 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 6a29e01..6645f65 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -476,7 +476,7 @@ for env in ["dc", "fl2000dc", "fl2003dc", "fl2008r2dc"]: plantestsuite_loadlist("samba4.ldap_schema.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/ldap_schema.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite("samba4.ldap.possibleInferiors.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/samdb/ldb_modules/tests/possibleinferiors.py"), "ldap://$SERVER", '-U"$USERNAME%$PASSWORD"', "-W$DOMAIN"]) plantestsuite_loadlist("samba4.ldap.secdesc.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/sec_descriptor.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) - plantestsuite("samba4.ldap.acl.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/acl.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) + plantestsuite_loadlist("samba4.ldap.acl.python(%s)" % env, env, [python, os.path.join(samba4srcdir, "dsdb/tests/python/acl.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) if env != "fl2000dc": # This test makes excessive use of the "userPassword" attribute which # isn't available on DCs with Windows 2000 domain function level - -- 2.1.4 From 52c0370cc706d9892d109ed401011dbe6f7005cd Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 07:09:00 -0700 Subject: [PATCH 28/36] Include mimeparse, which is used by subunit/testtools. Change-Id: I984c82acc0bc82a165e8ea17d8948c465c786905 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett Autobuild-User(master): Jelmer Vernooij Autobuild-Date(master): Sat Nov 22 04:44:11 CET 2014 on sn-devel-104 (cherry picked from commit 2c67d55614668583dc6290c6db86d5229fb654ea) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- lib/mimeparse/__init__.py | 0 lib/mimeparse/mimeparse.py | 167 ++++++++++++++++ lib/mimeparse/mimeparse_test.py | 68 +++++++ lib/mimeparse/setup.py | 50 +++++ lib/testtools/NEWS | 410 ++++++++++++++++++++++++++++++++++++++++ lib/update-external.sh | 10 + lib/wscript_build | 1 + selftest/filter-subunit | 2 + selftest/format-subunit | 2 + selftest/selftesthelpers.py | 10 +- 10 files changed, 717 insertions(+), 3 deletions(-) create mode 100644 lib/mimeparse/__init__.py create mode 100644 lib/mimeparse/mimeparse.py create mode 100644 lib/mimeparse/mimeparse_test.py create mode 100644 lib/mimeparse/setup.py diff --git a/lib/mimeparse/__init__.py b/lib/mimeparse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/mimeparse/mimeparse.py b/lib/mimeparse/mimeparse.py new file mode 100644 index 0000000..7fb4e43 --- /dev/null +++ b/lib/mimeparse/mimeparse.py @@ -0,0 +1,167 @@ +"""MIME-Type Parser + +This module provides basic functions for handling mime-types. It can handle +matching mime-types against a list of media-ranges. See section 14.1 of the +HTTP specification [RFC 2616] for a complete explanation. + + http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + +Contents: + - parse_mime_type(): Parses a mime-type into its component parts. + - parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q' + quality parameter. + - quality(): Determines the quality ('q') of a mime-type when + compared against a list of media-ranges. + - quality_parsed(): Just like quality() except the second parameter must be + pre-parsed. + - best_match(): Choose the mime-type with the highest quality ('q') + from a list of candidates. +""" + +__version__ = '0.1.3' +__author__ = 'Joe Gregorio' +__email__ = 'joe@bitworking.org' +__license__ = 'MIT License' +__credits__ = '' + + +def parse_mime_type(mime_type): + """Parses a mime-type into its component parts. + + Carves up a mime-type and returns a tuple of the (type, subtype, params) + where 'params' is a dictionary of all the parameters for the media range. + For example, the media range 'application/xhtml;q=0.5' would get parsed + into: + + ('application', 'xhtml', {'q', '0.5'}) + """ + parts = mime_type.split(';') + params = dict([tuple([s.strip() for s in param.split('=', 1)])\ + for param in parts[1:] + ]) + full_type = parts[0].strip() + # Java URLConnection class sends an Accept header that includes a + # single '*'. Turn it into a legal wildcard. + if full_type == '*': + full_type = '*/*' + (type, subtype) = full_type.split('/') + + return (type.strip(), subtype.strip(), params) + + +def parse_media_range(range): + """Parse a media-range into its component parts. + + Carves up a media range and returns a tuple of the (type, subtype, + params) where 'params' is a dictionary of all the parameters for the media + range. For example, the media range 'application/*;q=0.5' would get parsed + into: + + ('application', '*', {'q', '0.5'}) + + In addition this function also guarantees that there is a value for 'q' + in the params dictionary, filling it in with a proper default if + necessary. + """ + (type, subtype, params) = parse_mime_type(range) + if 'q' not in params or not params['q'] or \ + not float(params['q']) or float(params['q']) > 1\ + or float(params['q']) < 0: + params['q'] = '1' + + return (type, subtype, params) + + +def fitness_and_quality_parsed(mime_type, parsed_ranges): + """Find the best match for a mime-type amongst parsed media-ranges. + + Find the best match for a given mime-type against a list of media_ranges + that have already been parsed by parse_media_range(). Returns a tuple of + the fitness value and the value of the 'q' quality parameter of the best + match, or (-1, 0) if no match was found. Just as for quality_parsed(), + 'parsed_ranges' must be a list of parsed media ranges. + """ + best_fitness = -1 + best_fit_q = 0 + (target_type, target_subtype, target_params) =\ + parse_media_range(mime_type) + for (type, subtype, params) in parsed_ranges: + type_match = (type == target_type or\ + type == '*' or\ + target_type == '*') + subtype_match = (subtype == target_subtype or\ + subtype == '*' or\ + target_subtype == '*') + if type_match and subtype_match: + param_matches = sum([1 for (key, value) in \ + target_params.items() if key != 'q' and \ + key in params and value == params[key]], 0) + fitness = (type == target_type) and 100 or 0 + fitness += (subtype == target_subtype) and 10 or 0 + fitness += param_matches + if fitness > best_fitness: + best_fitness = fitness + best_fit_q = params['q'] + + return best_fitness, float(best_fit_q) + + +def quality_parsed(mime_type, parsed_ranges): + """Find the best match for a mime-type amongst parsed media-ranges. + + Find the best match for a given mime-type against a list of media_ranges + that have already been parsed by parse_media_range(). Returns the 'q' + quality parameter of the best match, 0 if no match was found. This function + bahaves the same as quality() except that 'parsed_ranges' must be a list of + parsed media ranges. """ + + return fitness_and_quality_parsed(mime_type, parsed_ranges)[1] + + +def quality(mime_type, ranges): + """Return the quality ('q') of a mime-type against a list of media-ranges. + + Returns the quality 'q' of a mime-type when compared against the + media-ranges in ranges. For example: + + >>> quality('text/html','text/*;q=0.3, text/html;q=0.7, + text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5') + 0.7 + + """ + parsed_ranges = [parse_media_range(r) for r in ranges.split(',')] + + return quality_parsed(mime_type, parsed_ranges) + + +def best_match(supported, header): + """Return mime-type with the highest quality ('q') from list of candidates. + + Takes a list of supported mime-types and finds the best match for all the + media-ranges listed in header. The value of header must be a string that + conforms to the format of the HTTP Accept: header. The value of 'supported' + is a list of mime-types. The list of supported mime-types should be sorted + in order of increasing desirability, in case of a situation where there is + a tie. + + >>> best_match(['application/xbel+xml', 'text/xml'], + 'text/*;q=0.5,*/*; q=0.1') + 'text/xml' + """ + split_header = _filter_blank(header.split(',')) + parsed_header = [parse_media_range(r) for r in split_header] + weighted_matches = [] + pos = 0 + for mime_type in supported: + weighted_matches.append((fitness_and_quality_parsed(mime_type, + parsed_header), pos, mime_type)) + pos += 1 + weighted_matches.sort() + + return weighted_matches[-1][0][1] and weighted_matches[-1][2] or '' + + +def _filter_blank(i): + for s in i: + if s.strip(): + yield s diff --git a/lib/mimeparse/mimeparse_test.py b/lib/mimeparse/mimeparse_test.py new file mode 100644 index 0000000..969cbf3 --- /dev/null +++ b/lib/mimeparse/mimeparse_test.py @@ -0,0 +1,68 @@ +""" +Python tests for Mime-Type Parser. + +This module loads a json file and converts the tests specified therein to a set +of PyUnitTestCases. Then it uses PyUnit to run them and report their status. +""" +__version__ = "0.1" +__author__ = 'Ade Oshineye' +__email__ = "ade@oshineye.com" +__credits__ = "" + +import mimeparse +import unittest +from functools import partial +# Conditional import to support Python 2.5 +try: + import json +except ImportError: + import simplejson as json + +def test_parse_media_range(args, expected): + expected = tuple(expected) + result = mimeparse.parse_media_range(args) + message = "Expected: '%s' but got %s" % (expected, result) + assert expected == result, message + +def test_quality(args, expected): + result = mimeparse.quality(args[0], args[1]) + message = "Expected: '%s' but got %s" % (expected, result) + assert expected == result, message + +def test_best_match(args, expected): + result = mimeparse.best_match(args[0], args[1]) + message = "Expected: '%s' but got %s" % (expected, result) + assert expected == result, message + +def test_parse_mime_type(args, expected): + expected = tuple(expected) + result = mimeparse.parse_mime_type(args) + message = "Expected: '%s' but got %s" % (expected, result) + assert expected == result, message + +def add_tests(suite, json_object, func_name, test_func): + test_data = json_object[func_name] + for test_datum in test_data: + args, expected = test_datum[0], test_datum[1] + desc = "%s(%s) with expected result: %s" % (func_name, str(args), str(expected)) + if len(test_datum) == 3: + desc = test_datum[2] + " : " + desc + func = partial(test_func, *(args, expected)) + func.__name__ = test_func.__name__ + testcase = unittest.FunctionTestCase(func, description=desc) + suite.addTest(testcase) + +def run_tests(): + json_object = json.load(open("testdata.json")) + + suite = unittest.TestSuite() + add_tests(suite, json_object, "parse_media_range", test_parse_media_range) + add_tests(suite, json_object, "quality", test_quality) + add_tests(suite, json_object, "best_match", test_best_match) + add_tests(suite, json_object, "parse_mime_type", test_parse_mime_type) + + test_runner = unittest.TextTestRunner(verbosity=1) + test_runner.run(suite) + +if __name__ == "__main__": + run_tests() diff --git a/lib/mimeparse/setup.py b/lib/mimeparse/setup.py new file mode 100644 index 0000000..de3e81b --- /dev/null +++ b/lib/mimeparse/setup.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +#old way +from distutils.core import setup + +#new way +#from setuptools import setup, find_packages + +setup(name='mimeparse', + version='0.1.4', + description='A module provides basic functions for parsing mime-type names and matching them against a list of media-ranges.', + long_description=""" +This module provides basic functions for handling mime-types. It can handle +matching mime-types against a list of media-ranges. See section 14.1 of +the HTTP specification [RFC 2616] for a complete explanation. + + http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + +Contents: + - parse_mime_type(): Parses a mime-type into its component parts. + - parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q' quality parameter. + - quality(): Determines the quality ('q') of a mime-type when compared against a list of media-ranges. + - quality_parsed(): Just like quality() except the second parameter must be pre-parsed. + - best_match(): Choose the mime-type with the highest quality ('q') from a list of candidates. + """, + classifiers=[ + # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.5', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.1', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + ], + keywords='mime-type', + author='Joe Gregorio', + author_email='joe@bitworking.org', + maintainer='Joe Gregorio', + maintainer_email='joe@bitworking.org', + url='http://code.google.com/p/mimeparse/', + license='MIT', + py_modules=['mimeparse'] + ) diff --git a/lib/testtools/NEWS b/lib/testtools/NEWS index 6f3cb8c..ac88fc1 100644 --- a/lib/testtools/NEWS +++ b/lib/testtools/NEWS @@ -6,6 +6,416 @@ Changes and improvements to testtools_, grouped by release. NEXT ~~~~ +Changes +------- + +* Fixed unit tests which were failing under pypy due to a change in the way + pypy formats tracebacks. (Thomi Richards) + +* Make `testtools.content.text_content` error if anything other than text + is given as content. (Thomi Richards) + +* We now publish wheels of testtools. (Robert Collins, #issue84) + +1.1.0 +~~~~~ + +Improvements +------------ + +* Exceptions in a ``fixture.getDetails`` method will no longer mask errors + raised from the same fixture's ``setUp`` method. + (Robert Collins, #1368440) + +1.0.0 +~~~~~ + +Long overdue, we've adopted a backwards compatibility statement and recognized +that we have plenty of users depending on our behaviour - calling our version +1.0.0 is a recognition of that. + +Improvements +------------ + +* Fix a long-standing bug where tearDown and cleanUps would not be called if the + test run was interrupted. This should fix leaking external resources from + interrupted tests. + (Robert Collins, #1364188) + +* Fix a long-standing bug where calling sys.exit(0) from within a test would + cause the test suite to exit with 0, without reporting a failure of that + test. We still allow the test suite to be exited (since catching higher order + exceptions requires exceptional circumstances) but we now call a last-resort + handler on the TestCase, resulting in an error being reported for the test. + (Robert Collins, #1364188) + +* Fix an issue where tests skipped with the ``skip``* family of decorators would + still have their ``setUp`` and ``tearDown`` functions called. + (Thomi Richards, #https://github.com/testing-cabal/testtools/issues/86) + +* We have adopted a formal backwards compatibility statement (see hacking.rst) + (Robert Collins) + +0.9.39 +~~~~~~ + +Brown paper bag release - 0.9.38 was broken for some users, +_jython_aware_splitext was not defined entirely compatibly. +(Robert Collins, #https://github.com/testing-cabal/testtools/issues/100) + +0.9.38 +~~~~~~ + +Bug fixes for test importing. + +Improvements +------------ + +* Discovery import error detection wasn't implemented for python 2.6 (the + 'discover' module). (Robert Collins) + +* Discovery now executes load_tests (if present) in __init__ in all packages. + (Robert Collins, http://bugs.python.org/issue16662) + +0.9.37 +~~~~~~ + +Minor improvements to correctness. + +Changes +------- + +* ``stdout`` is now correctly honoured on ``run.TestProgram`` - before the + runner objects would be created with no stdout parameter. If construction + fails, the previous parameter list is attempted, permitting compatibility + with Runner classes that don't accept stdout as a parameter. + (Robert Collins) + +* The ``ExtendedToStreamDecorator`` now handles content objects with one less + packet - the last packet of the source content is sent with EOF set rather + than an empty packet with EOF set being sent after the last packet of the + source content. (Robert Collins) + +0.9.36 +~~~~~~ + +Welcome to our long overdue 0.9.36 release, which improves compatibility with +Python3.4, adds assert_that, a function for using matchers without TestCase +objects, and finally will error if you try to use setUp or tearDown twice - +since that invariably leads to bad things of one sort or another happening. + +Changes +------- + +* Error if ``setUp`` or ``tearDown`` are called twice. + (Robert Collins, #882884) + +* Make testtools compatible with the ``unittest.expectedFailure`` decorator in + Python 3.4. (Thomi Richards) + + +Improvements +------------ + +* Introduce the assert_that function, which allows matchers to be used + independent of testtools.TestCase. (Daniel Watkins, #1243834) + + +0.9.35 +~~~~~~ + +Changes +------- + +* Removed a number of code paths where Python 2.4 and Python 2.5 were + explicitly handled. (Daniel Watkins) + +Improvements +------------ + +* Added the ``testtools.TestCase.expectThat`` method, which implements + delayed assertions. (Thomi Richards) + +* Docs are now built as part of the Travis-CI build, reducing the chance of + Read The Docs being broken accidentally. (Daniel Watkins, #1158773) + +0.9.34 +~~~~~~ + +Improvements +------------ + +* Added ability for ``testtools.TestCase`` instances to force a test to + fail, even if no assertions failed. (Thomi Richards) + +* Added ``testtools.content.StacktraceContent``, a content object that + automatically creates a ``StackLinesContent`` object containing the current + stack trace. (Thomi Richards) + +* ``AnyMatch`` is now exported properly in ``testtools.matchers``. + (Robert Collins, Rob Kennedy, github #44) + +* In Python 3.3, if there are duplicate test ids, tests.sort() will + fail and raise TypeError. Detect the duplicate test ids firstly in + sorted_tests() to ensure that all test ids are unique. + (Kui Shi, #1243922) + +* ``json_content`` is now in the ``__all__`` attribute for + ``testtools.content``. (Robert Collins) + +* Network tests now bind to 127.0.0.1 to avoid (even temporary) network + visible ports. (Benedikt Morbach, github #46) + +* Test listing now explicitly indicates by printing 'Failed to import' and + exiting (2) when an import has failed rather than only signalling through the + test name. (Robert Collins, #1245672) + +* ``test_compat.TestDetectEncoding.test_bom`` now works on Python 3.3 - the + corner case with euc_jp is no longer permitted in Python 3.3 so we can + skip it. (Martin [gz], #1251962) + +0.9.33 +~~~~~~ + +Improvements +------------ + +* Added ``addDetailuniqueName`` method to ``testtools.TestCase`` class. + (Thomi Richards) + +* Removed some unused code from ``testtools.content.TracebackContent``. + (Thomi Richards) + +* Added ``testtools.StackLinesContent``: a content object for displaying + pre-processed stack lines. (Thomi Richards) + +* ``StreamSummary`` was calculating testsRun incorrectly: ``exists`` status + tests were counted as run tests, but they are not. + (Robert Collins, #1203728) + +0.9.32 +~~~~~~ + +Regular maintenance release. Special thanks to new contributor, Xiao Hanyu! + +Changes +------- + + * ``testttols.compat._format_exc_info`` has been refactored into several + smaller functions. (Thomi Richards) + +Improvements +------------ + +* Stacktrace filtering no longer hides unittest frames that are surrounded by + user frames. We will reenable this when we figure out a better algorithm for + retaining meaning. (Robert Collins, #1188420) + +* The compatibility code for skipped tests with unittest2 was broken. + (Robert Collins, #1190951) + +* Various documentation improvements (Clint Byrum, Xiao Hanyu). + +0.9.31 +~~~~~~ + +Improvements +------------ + +* ``ExpectedException`` now accepts a msg parameter for describing an error, + much the same as assertEquals etc. (Robert Collins) + +0.9.30 +~~~~~~ + +A new sort of TestResult, the StreamResult has been added, as a prototype for +a revised standard library test result API. Expect this API to change. +Although we will try to preserve compatibility for early adopters, it is +experimental and we might need to break it if it turns out to be unsuitable. + +Improvements +------------ +* ``assertRaises`` works properly for exception classes that have custom + metaclasses + +* ``ConcurrentTestSuite`` was silently eating exceptions that propagate from + the test.run(result) method call. Ignoring them is fine in a normal test + runner, but when they happen in a different thread, the thread that called + suite.run() is not in the stack anymore, and the exceptions are lost. We now + create a synthetic test recording any such exception. + (Robert Collins, #1130429) + +* Fixed SyntaxError raised in ``_compat2x.py`` when installing via Python 3. + (Will Bond, #941958) + +* New class ``StreamResult`` which defines the API for the new result type. + (Robert Collins) + +* New support class ``ConcurrentStreamTestSuite`` for convenient construction + and utilisation of ``StreamToQueue`` objects. (Robert Collins) + +* New support class ``CopyStreamResult`` which forwards events onto multiple + ``StreamResult`` objects (each of which receives all the events). + (Robert Collins) + +* New support class ``StreamSummary`` which summarises a ``StreamResult`` + stream compatibly with ``TestResult`` code. (Robert Collins) + +* New support class ``StreamTagger`` which adds or removes tags from + ``StreamResult`` events. (RobertCollins) + +* New support class ``StreamToDict`` which converts a ``StreamResult`` to a + series of dicts describing a test. Useful for writing trivial stream + analysers. (Robert Collins) + +* New support class ``TestControl`` which permits cancelling an in-progress + run. (Robert Collins) + +* New support class ``StreamFailFast`` which calls a ``TestControl`` instance + to abort the test run when a failure is detected. (Robert Collins) + +* New support class ``ExtendedToStreamDecorator`` which translates both regular + unittest TestResult API calls and the ExtendedTestResult API which testtools + has supported into the StreamResult API. ExtendedToStreamDecorator also + forwards calls made in the StreamResult API, permitting it to be used + anywhere a StreamResult is used. Key TestResult query methods like + wasSuccessful and shouldStop are synchronised with the StreamResult API + calls, but the detailed statistics like the list of errors are not - a + separate consumer will be created to support that. + (Robert Collins) + +* New support class ``StreamToExtendedDecorator`` which translates + ``StreamResult`` API calls into ``ExtendedTestResult`` (or any older + ``TestResult``) calls. This permits using un-migrated result objects with + new runners / tests. (Robert Collins) + +* New support class ``StreamToQueue`` for sending messages to one + ``StreamResult`` from multiple threads. (Robert Collins) + +* New support class ``TimestampingStreamResult`` which adds a timestamp to + events with no timestamp. (Robert Collins) + +* New ``TestCase`` decorator ``DecorateTestCaseResult`` that adapts the + ``TestResult`` or ``StreamResult`` a case will be run with, for ensuring that + a particular result object is used even if the runner running the test doesn't + know to use it. (Robert Collins) + +* New test support class ``testtools.testresult.doubles.StreamResult``, which + captures all the StreamResult events. (Robert Collins) + +* ``PlaceHolder`` can now hold tags, and applies them before, and removes them + after, the test. (Robert Collins) + +* ``PlaceHolder`` can now hold timestamps, and applies them before the test and + then before the outcome. (Robert Collins) + +* ``StreamResultRouter`` added. This is useful for demultiplexing - e.g. for + partitioning analysis of events or sending feedback encapsulated in + StreamResult events back to their source. (Robert Collins) + +* ``testtools.run.TestProgram`` now supports the ``TestRunner`` taking over + responsibility for formatting the output of ``--list-tests``. + (Robert Collins) + +* The error message for setUp and tearDown upcall errors was broken on Python + 3.4. (Monty Taylor, Robert Collins, #1140688) + +* The repr of object() on pypy includes the object id, which was breaking a + test that accidentally depended on the CPython repr for object(). + (Jonathan Lange) + +0.9.29 +~~~~~~ + +A simple bug fix, and better error messages when you don't up-call. + +Changes +------- + +* ``testtools.content_type.ContentType`` incorrectly used ',' rather than ';' + to separate parameters. (Robert Collins) + +Improvements +------------ + +* ``testtools.compat.unicode_output_stream`` was wrapping a stream encoder + around ``io.StringIO`` and ``io.TextIOWrapper`` objects, which was incorrect. + (Robert Collins) + +* Report the name of the source file for setUp and tearDown upcall errors. + (Monty Taylor) + +0.9.28 +~~~~~~ + +Testtools has moved VCS - https://github.com/testing-cabal/testtools/ is +the new home. Bug tracking is still on Launchpad, and releases are on Pypi. + +We made this change to take advantage of the richer ecosystem of tools around +Git, and to lower the barrier for new contributors. + +Improvements +------------ + +* New ``testtools.testcase.attr`` and ``testtools.testcase.WithAttributes`` + helpers allow marking up test case methods with simple labels. This permits + filtering tests with more granularity than organising them into modules and + test classes. (Robert Collins) + +0.9.27 +~~~~~~ + +Improvements +------------ + +* New matcher ``HasLength`` for matching the length of a collection. + (Robert Collins) + +* New matcher ``MatchesPredicateWithParams`` make it still easier to create + ad hoc matchers. (Robert Collins) + +* We have a simpler release process in future - see doc/hacking.rst. + (Robert Collins) + +0.9.26 +~~~~~~ + +Brown paper bag fix: failed to document the need for setup to be able to use +extras. Compounded by pip not supporting setup_requires. + +Changes +------- + +* setup.py now can generate egg_info even if extras is not available. + Also lists extras in setup_requires for easy_install. + (Robert Collins, #1102464) + +0.9.25 +~~~~~~ + +Changes +------- + +* ``python -m testtools.run --load-list`` will now preserve any custom suites + (such as ``testtools.FixtureSuite`` or ``testresources.OptimisingTestSuite``) + rather than flattening them. + (Robert Collins, #827175) + +* Testtools now depends on extras, a small library split out from it to contain + generally useful non-testing facilities. Since extras has been around for a + couple of testtools releases now, we're making this into a hard dependency of + testtools. (Robert Collins) + +* Testtools now uses setuptools rather than distutils so that we can document + the extras dependency. (Robert Collins) + +Improvements +------------ + +* Testtools will no longer override test code registered details called + 'traceback' when reporting caught exceptions from test code. + (Robert Collins, #812793) + 0.9.24 ~~~~~~ diff --git a/lib/update-external.sh b/lib/update-external.sh index d8abcfb..d272f74 100755 --- a/lib/update-external.sh +++ b/lib/update-external.sh @@ -30,4 +30,14 @@ git clone git://github.com/testing-cabal/extras "$WORKDIR/extras" rm -rf "$WORKDIR/extras/.git" rsync -avz --delete "$WORKDIR/extras/" "$LIBDIR/extras/" +echo "Updating extra..." +git clone git://github.com/testing-cabal/extras "$WORKDIR/extras" +rm -rf "$WORKDIR/extras/.git" +rsync -avz --delete "$WORKDIR/extras/" "$LIBDIR/extras/" + +echo "Updating mimeparse..." +svn co http://mimeparse.googlecode.com/svn/trunk/ "$WORKDIR/mimeparse" +rm -rf "$WORKDIR/mimeparse/.svn" +rsync -avz --delete "$WORKDIR/mimeparse/" "$LIBDIR/mimeparse/" + rm -rf "$WORKDIR" diff --git a/lib/wscript_build b/lib/wscript_build index c6ca778..766af49 100644 --- a/lib/wscript_build +++ b/lib/wscript_build @@ -8,6 +8,7 @@ external_libs = { "subunit": "subunit/python/subunit", "testtools": "testtools/testtools", "extras": "extras/extras", + "mimeparse": "mimeparse/mimeparse", } list = [] diff --git a/selftest/filter-subunit b/selftest/filter-subunit index 5b74343..2ce9584 100755 --- a/selftest/filter-subunit +++ b/selftest/filter-subunit @@ -25,6 +25,8 @@ import signal sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/subunit/python")) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/testtools")) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/mimeparse")) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/extras")) import subunithelper diff --git a/selftest/format-subunit b/selftest/format-subunit index b927e95..5da56be 100755 --- a/selftest/format-subunit +++ b/selftest/format-subunit @@ -11,6 +11,8 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/subunit/python")) sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/testtools")) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/mimeparse")) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../lib/extras")) import subunithelper diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index d1b3e13..352595e 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -69,7 +69,8 @@ else: python = os.getenv("PYTHON", "python") # Set a default value, overridden if we find a working one on the system -tap2subunit = "PYTHONPATH=%s/lib/subunit/python:%s/lib/testtools %s %s/lib/subunit/filters/tap2subunit" % (srcdir(), srcdir(), python, srcdir()) +tap2subunit = "PYTHONPATH=%s/lib/subunit/python:%s/lib/testtools:%s/lib/extras:%s/lib/mimeparse %s %s/lib/subunit/filters/tap2subunit" % (srcdir(), srcdir(), srcdir(), srcdir(), python, srcdir()) +subunit2to1 = "PYTHONPATH=%s/lib/subunit/python:%s/lib/testtools:%s/lib/extras:%s/lib/mimeparse %s %s/lib/subunit/filters/subunit-2to1" % (srcdir(), srcdir(), srcdir(), srcdir(), python, srcdir()) sub = subprocess.Popen("tap2subunit", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) @@ -173,8 +174,11 @@ def planpythontestsuite(env, module, name=None, extra_path=[]): name = module pypath = list(extra_path) if not has_system_subunit_run: - pypath.extend(["%s/lib/subunit/python" % srcdir(), - "%s/lib/testtools" % srcdir()]) + pypath.extend([ + "%s/lib/subunit/python" % srcdir(), + "%s/lib/testtools" % srcdir(), + "%s/lib/extras" % srcdir(), + "%s/lib/mimeparse" % srcdir()]) args = [python, "-m", "subunit.run", "$LISTOPT", module] if pypath: args.insert(0, "PYTHONPATH=%s" % ":".join(["$PYTHONPATH"] + pypath)) -- 2.1.4 From 55afe31d03334985b44a56460516f960de75a561 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 21:22:59 -0700 Subject: [PATCH 29/36] Use samba.tests.subunitrun in urgent replication test. Change-Id: I3e7a32876d557ac376326ab75e851298e874d584 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 98b5380af65ea1ec760d00187355384de0757b04) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/urgent_replication.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/source4/dsdb/tests/python/urgent_replication.py b/source4/dsdb/tests/python/urgent_replication.py index 8083ce4..19176c1 100755 --- a/source4/dsdb/tests/python/urgent_replication.py +++ b/source4/dsdb/tests/python/urgent_replication.py @@ -5,8 +5,7 @@ import optparse import sys sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") +from samba.tests.subunitrun import TestProgram, SubunitOptions from ldb import (LdbError, ERR_NO_SUCH_OBJECT, Message, MessageElement, Dn, FLAG_MOD_REPLACE) @@ -14,10 +13,6 @@ import samba.tests import samba.dsdb as dsdb import samba.getopt as options -from subunit.run import SubunitTestRunner - -import unittest - parser = optparse.OptionParser("urgent_replication.py [options] ") sambaopts = options.SambaOptions(parser) parser.add_option_group(sambaopts) @@ -26,6 +21,8 @@ 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: @@ -342,10 +339,4 @@ rIDAvailablePool: 133001-1073741823""", ["relax:0"]) self.assertNotEquals(res["uSNHighest"], res["uSNUrgent"]) -runner = SubunitTestRunner() -rc = 0 -# -if not runner.run(unittest.makeSuite(UrgentReplicationTests)).wasSuccessful(): - rc = 1 - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) -- 2.1.4 From a0fb491edc481fd8006b87706851d10992753151 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 21:31:18 -0700 Subject: [PATCH 30/36] Use samba.tests.subunitrun in dsdb ldap and ldap_schema tests. Change-Id: I51ddc55720a23013a2c6ae20e3225f027348083c Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 4f75f17ba7c9b80cf3aa0ce2db57e1754464403a) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/ldap.py | 34 +++++++++++--------- source4/dsdb/tests/python/ldap_schema.py | 55 ++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/source4/dsdb/tests/python/ldap.py b/source4/dsdb/tests/python/ldap.py index cfb21d2..dc12fea 100755 --- a/source4/dsdb/tests/python/ldap.py +++ b/source4/dsdb/tests/python/ldap.py @@ -2,6 +2,21 @@ # -*- coding: utf-8 -*- # This is a port of the original in testprogs/ejs/ldap.js +# Copyright (C) Jelmer Vernooij 2008-2011 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import optparse import sys import time @@ -10,9 +25,7 @@ import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") - +from samba.tests.subunitrun import SubunitOptions, TestProgram import samba.getopt as options from samba.auth import system_session @@ -35,9 +48,6 @@ from samba.dsdb import (UF_NORMAL_ACCOUNT, SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE, SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE) -from subunit.run import SubunitTestRunner -import unittest - from samba.ndr import ndr_pack, ndr_unpack from samba.dcerpc import security, lsa from samba.tests import delete_force @@ -49,6 +59,8 @@ 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: @@ -3014,12 +3026,4 @@ if not "tdb://" in host: else: gc_ldb = None -runner = SubunitTestRunner() -suite = unittest.TestSuite() -suite.addTests(unittest.makeSuite(BaseDnTests)) -suite.addTests(unittest.makeSuite(BasicTests)) -if not runner.run(suite).wasSuccessful(): - rc = 1 -else: - rc = 0 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) diff --git a/source4/dsdb/tests/python/ldap_schema.py b/source4/dsdb/tests/python/ldap_schema.py index fb0ef9c..1de6519 100755 --- a/source4/dsdb/tests/python/ldap_schema.py +++ b/source4/dsdb/tests/python/ldap_schema.py @@ -2,6 +2,23 @@ # -*- coding: utf-8 -*- # This is a port of the original in testprogs/ejs/ldap.js +# Copyright (C) Jelmer Vernooij 2008-2011 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + + import optparse import sys import time @@ -10,8 +27,7 @@ import os sys.path.insert(0, "bin/python") import samba -samba.ensure_external_module("testtools", "testtools") -samba.ensure_external_module("subunit", "subunit/python") +from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options @@ -26,9 +42,6 @@ from samba.samdb import SamDB from samba.dsdb import DS_DOMAIN_FUNCTION_2003 from samba.tests import delete_force -from subunit.run import SubunitTestRunner -import unittest - parser = optparse.OptionParser("ldap_schema.py [options] ") sambaopts = options.SambaOptions(parser) parser.add_option_group(sambaopts) @@ -36,6 +49,8 @@ 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: @@ -52,9 +67,10 @@ class SchemaTests(samba.tests.TestCase): def setUp(self): super(SchemaTests, self).setUp() - self.ldb = ldb - self.base_dn = ldb.domain_dn() - self.schema_dn = ldb.get_schema_basedn().get_linearized() + self.ldb = SamDB(host, credentials=creds, + session_info=system_session(lp), lp=lp, options=ldb_options) + self.base_dn = self.ldb.domain_dn() + self.schema_dn = self.ldb.get_schema_basedn().get_linearized() def test_generated_schema(self): """Testing we can read the generated schema via LDAP""" @@ -264,8 +280,9 @@ class SchemaTests_msDS_IntId(samba.tests.TestCase): def setUp(self): super(SchemaTests_msDS_IntId, self).setUp() - self.ldb = ldb - res = ldb.search(base="", expression="", scope=SCOPE_BASE, + self.ldb = SamDB(host, credentials=creds, + session_info=system_session(lp), lp=lp, options=ldb_options) + res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext", "defaultNamingContext", "forestFunctionality"]) self.assertEquals(len(res), 1) @@ -540,8 +557,9 @@ class SchemaTests_msDS_isRODC(samba.tests.TestCase): def setUp(self): super(SchemaTests_msDS_isRODC, self).setUp() - self.ldb = ldb - res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["defaultNamingContext"]) + self.ldb = SamDB(host, credentials=creds, + session_info=system_session(lp), lp=lp, options=ldb_options) + res = self.ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["defaultNamingContext"]) self.assertEquals(len(res), 1) self.base_dn = res[0]["defaultNamingContext"][0] @@ -585,15 +603,4 @@ if host.startswith("ldap://"): # user 'paged_search' module when connecting remotely ldb_options = ["modules:paged_searches"] -ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp, options=ldb_options) - -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(SchemaTests_msDS_IntId)).wasSuccessful(): - rc = 1 -if not runner.run(unittest.makeSuite(SchemaTests_msDS_isRODC)).wasSuccessful(): - rc = 1 - -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) -- 2.1.4 From 73687b38c1047b02a479df0d6aa18bc9686835d7 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 2 Nov 2014 09:00:09 -0800 Subject: [PATCH 31/36] sam: Use samba.tests.subunitrun. Change-Id: Ic2ac4b335cf805ddbd442a065c4eaf6ef2b210d9 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 869a9f7a3a01810c1c1e3287b82034f67457b0b5) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- source4/dsdb/tests/python/sam.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py index 804905b..31b5a39 100755 --- a/source4/dsdb/tests/python/sam.py +++ b/source4/dsdb/tests/python/sam.py @@ -8,6 +8,7 @@ import os sys.path.insert(0, "bin/python") import samba +from samba.tests.subunitrun import SubunitOptions, TestProgram samba.ensure_external_module("testtools", "testtools") samba.ensure_external_module("subunit", "subunit/python") @@ -39,9 +40,6 @@ from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE, from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_ADMINS, DOMAIN_RID_DOMAIN_MEMBERS, DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS) -from subunit.run import SubunitTestRunner -import unittest - from samba.dcerpc import security from samba.tests import delete_force @@ -52,6 +50,8 @@ 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: @@ -2885,8 +2885,4 @@ if not "://" in host: ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp) -runner = SubunitTestRunner() -rc = 0 -if not runner.run(unittest.makeSuite(SamTests)).wasSuccessful(): - rc = 1 -sys.exit(rc) +TestProgram(module=__name__, opts=subunitopts) -- 2.1.4 From 001dab5419ecd3f7b0f1d158efda19b32a0148ca Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 26 Oct 2014 20:17:20 -0700 Subject: [PATCH 32/36] selftest: Drop support for TESTSUITE-IDLIST, and remove its last user. Change-Id: Ic616676bb770fa4769195d73c4309915646caae0 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit f6e3cd7f03a15595a2fa65c22a56c60d7d3f8bff) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/selftest.pl | 11 ++++------- selftest/selftesthelpers.py | 17 ++--------------- selftest/testlist.py | 3 +-- selftest/tests/test_testlist.py | 4 ++-- 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/selftest/selftest.pl b/selftest/selftest.pl index f35b063..8e865ec 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -566,9 +566,8 @@ sub read_testlist($) open(IN, $filename) or die("Unable to open $filename: $!"); while () { - if (/-- TEST(-LOADLIST|-IDLIST|) --\n/) { + if (/-- TEST(-LOADLIST|) --\n/) { my $supports_loadlist = (defined($1) and $1 eq "-LOADLIST"); - my $supports_idlist = (defined($1) and $1 eq "-IDLIST"); my $name = ; $name =~ s/\n//g; my $env = ; @@ -576,7 +575,7 @@ sub read_testlist($) my $cmdline = ; $cmdline =~ s/\n//g; if (should_run_test($name) == 1) { - push (@ret, [$name, $env, $cmdline, $supports_loadlist, $supports_idlist]); + push (@ret, [$name, $env, $cmdline, $supports_loadlist]); } } else { print; @@ -821,7 +820,6 @@ sub setup_env($$) } } - return undef unless defined($testenv_vars); $running_envs{$envname} = $testenv_vars; @@ -990,9 +988,8 @@ $envvarstr print $fh substr($test, length($name)+1) . "\n"; } $cmd =~ s/\$LOADLIST/--load-list=$listid_file/g; - } elsif ($$_[4]) { - $cmd =~ s/\s+[^\s]+\s*$//; - $cmd .= " " . join(' ', @{$individual_tests->{$name}}); + } else { + warn("Unable to run individual tests in $name, it does not support --loadlist."); } } diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 352595e..9abd2c5 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -134,19 +134,6 @@ def plantestsuite_loadlist(name, env, cmdline): print "%s $LOADLIST 2>&1 | %s" % (cmdline, add_prefix(name, env, support_list)) -def plantestsuite_idlist(name, env, cmdline): - print "-- TEST-IDLIST --" - if env == "none": - fullname = name - else: - fullname = "%s(%s)" % (name, env) - print fullname - print env - if isinstance(cmdline, list): - cmdline = " ".join(cmdline) - print cmdline - - def skiptestsuite(name, reason): """Indicate that a testsuite was skipped. @@ -179,10 +166,10 @@ def planpythontestsuite(env, module, name=None, extra_path=[]): "%s/lib/testtools" % srcdir(), "%s/lib/extras" % srcdir(), "%s/lib/mimeparse" % srcdir()]) - args = [python, "-m", "subunit.run", "$LISTOPT", module] + args = [python, "-m", "subunit.run", "$LISTOPT", "$LOADLIST", module] if pypath: args.insert(0, "PYTHONPATH=%s" % ":".join(["$PYTHONPATH"] + pypath)) - plantestsuite_idlist(name, env, args) + plantestsuite_loadlist(name, env, args) def get_env_torture_options(): diff --git a/selftest/testlist.py b/selftest/testlist.py index 5102f42..50ea31b 100644 --- a/selftest/testlist.py +++ b/selftest/testlist.py @@ -79,11 +79,10 @@ def read_testlist(inf, outf): return if l.startswith("-- TEST") and l.endswith(" --\n"): supports_loadlist = l.startswith("-- TEST-LOADLIST") - supports_idlist = l.startswith("-- TEST-IDLIST") name = inf.readline().rstrip("\n") env = inf.readline().rstrip("\n") cmdline = inf.readline().rstrip("\n") - yield (name, env, cmdline, supports_loadlist, supports_idlist) + yield (name, env, cmdline, supports_loadlist) else: outf.write(l) diff --git a/selftest/tests/test_testlist.py b/selftest/tests/test_testlist.py index 4474d0a..7846eb1 100644 --- a/selftest/tests/test_testlist.py +++ b/selftest/tests/test_testlist.py @@ -67,14 +67,14 @@ class ReadTestlistTests(TestCase): def test_read_list(self): inf = StringIO("-- TEST --\nfoo\nbar\nbla\n") outf = StringIO() - self.assertEquals([('foo', 'bar', 'bla', False, False)], + self.assertEquals([('foo', 'bar', 'bla', False)], list(read_testlist(inf, outf))) self.assertEquals("", outf.getvalue()) def test_read_list_passes_through(self): inf = StringIO("MORENOISE\n-- TEST --\nfoo\nbar\nbla\nNOISE\n") outf = StringIO() - self.assertEquals([('foo', 'bar', 'bla', False, False)], + self.assertEquals([('foo', 'bar', 'bla', False)], list(read_testlist(inf, outf))) self.assertEquals("MORENOISE\nNOISE\n", outf.getvalue()) -- 2.1.4 From b0ef6ba72314211c8c9b9d5aa8801e2a6b290ef3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 14:40:30 -0700 Subject: [PATCH 33/36] Re-use add_prefix function. Change-Id: I6e91bc9fc6714c147427e920ca0e3e22cb9a076b Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit afe94aa53549ec66cb48959260753a4fa424e481) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/selftesthelpers.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 9abd2c5..358dfea 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -103,13 +103,7 @@ def plantestsuite(name, env, cmdline): print env if isinstance(cmdline, list): cmdline = " ".join(cmdline) - filter_subunit_args = ["--fail-on-empty"] - if "$LISTOPT" in cmdline: - filter_subunit_args.append("$LISTOPT") - print "%s 2>&1 | %s/selftest/filter-subunit %s --prefix=\"%s.\" --suffix=\"(%s)\"" % (cmdline, - srcdir(), - " ".join(filter_subunit_args), - name, env) + print "%s 2>&1 | " + add_prefix(name, env, "$LISTOPT" in cmdline) def add_prefix(prefix, env, support_list=False): -- 2.1.4 From 795a1cb0de3ad94419dc41cf1e5d320d22e11089 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 16:06:09 -0700 Subject: [PATCH 34/36] selftest/tests.py: Remove testsuite samba.tests.samdb which does not have any tests. Change-Id: I8edcf73aa4a9b61c6e5c7cfb592a4692d4030a29 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit c3855dae71e557b824ad2679acd8bb5ad85936e2) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/selftest/tests.py b/selftest/tests.py index fb49e1d..20258be 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -59,7 +59,6 @@ planpythontestsuite("none", "samba.tests.samba3") planpythontestsuite("none", "samba.tests.strings") planpythontestsuite("none", "samba.tests.netcmd") planpythontestsuite("none", "samba.tests.dcerpc.rpc_talloc") -planpythontestsuite("none", "samba.tests.samdb") planpythontestsuite("none", "samba.tests.hostconfig") planpythontestsuite("none", "samba.tests.messaging") planpythontestsuite("none", "samba.tests.samba3sam") -- 2.1.4 From 389fb3905e0b58ec33c3514ee5cea04b8e16e1c5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 15:13:18 -0700 Subject: [PATCH 35/36] selftest: Add separate command line for listing tests, allowing us of subunit-filter (which doesn't support subunit v2). Change-Id: Icb877214a422c63fd38ef92425c7b4fe7ee19ad5 Signed-Off-By: Jelmer Vernooij Reviewed-by: Andrew Bartlett (cherry picked from commit 0f408599f83f5d8e68f0fb0f765143aa6620651e) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/selftest.pl | 20 ++++++++++++-------- selftest/selftesthelpers.py | 19 +++++++++++++++---- selftest/testlist.py | 6 +++++- selftest/tests/test_testlist.py | 6 +++--- source4/scripting/bin/subunitrun | 2 ++ source4/selftest/tests.py | 2 +- 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/selftest/selftest.pl b/selftest/selftest.pl index 8e865ec..96687ea 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -572,10 +572,15 @@ sub read_testlist($) $name =~ s/\n//g; my $env = ; $env =~ s/\n//g; + my $loadlist; + if ($supports_loadlist) { + $loadlist = ; + $loadlist =~ s/\n//g; + } my $cmdline = ; $cmdline =~ s/\n//g; if (should_run_test($name) == 1) { - push (@ret, [$name, $env, $cmdline, $supports_loadlist]); + push (@ret, [$name, $env, $cmdline, $loadlist]); } } else { print; @@ -935,23 +940,22 @@ $envvarstr teardown_env($testenv_name); } elsif ($opt_list) { foreach (@todo) { - my $cmd = $$_[2]; my $name = $$_[0]; my $envname = $$_[1]; + my $cmd = $$_[2]; + my $listcmd = $$_[3]; - unless($cmd =~ /\$LISTOPT/) { + unless (defined($listcmd)) { warn("Unable to list tests in $name"); next; } - $cmd =~ s/\$LISTOPT/--list/g; - - system($cmd); + system($listcmd); if ($? == -1) { - die("Unable to run $cmd: $!"); + die("Unable to run $listcmd: $!"); } elsif ($? & 127) { - die(sprintf("%s died with signal %d, %s coredump\n", $cmd, ($? & 127), ($? & 128) ? 'with' : 'without')); + die(sprintf("%s died with signal %d, %s coredump\n", $listcmd, ($? & 127), ($? & 128) ? 'with' : 'without')); } my $exitcode = $? >> 8; diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index 358dfea..dc655c1 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -83,6 +83,12 @@ if sub.returncode == 0: if sub.returncode == 0: tap2subunit = "tap2subunit" +def to_subunit1(subunit_version): + if subunit_version == 1: + return "" + return " | " + subunit2to1 + + def valgrindify(cmdline): """Run a command under valgrind, if $VALGRIND was set.""" valgrind = os.getenv("VALGRIND") @@ -91,7 +97,7 @@ def valgrindify(cmdline): return valgrind + " " + cmdline -def plantestsuite(name, env, cmdline): +def plantestsuite(name, env, cmdline, subunit_version=1): """Plan a test suite. :param name: Testsuite name @@ -103,7 +109,9 @@ def plantestsuite(name, env, cmdline): print env if isinstance(cmdline, list): cmdline = " ".join(cmdline) - print "%s 2>&1 | " + add_prefix(name, env, "$LISTOPT" in cmdline) + if "$LISTOPT" in cmdline: + raise AssertionError("test %s supports --list, but not --load-list" % name) + print cmdline + " 2>&1 " + to_subunit1(subunit_version) + " | " + add_prefix(name, env) def add_prefix(prefix, env, support_list=False): @@ -114,7 +122,7 @@ def add_prefix(prefix, env, support_list=False): return "%s/selftest/filter-subunit %s--fail-on-empty --prefix=\"%s.\" --suffix=\"(%s)\"" % (srcdir(), listopt, prefix, env) -def plantestsuite_loadlist(name, env, cmdline): +def plantestsuite_loadlist(name, env, cmdline, subunit_version=1): print "-- TEST-LOADLIST --" if env == "none": fullname = name @@ -125,7 +133,10 @@ def plantestsuite_loadlist(name, env, cmdline): if isinstance(cmdline, list): cmdline = " ".join(cmdline) support_list = ("$LISTOPT" in cmdline) - print "%s $LOADLIST 2>&1 | %s" % (cmdline, add_prefix(name, env, support_list)) + if not "$LISTOPT" in cmdline: + raise AssertionError("test %s supports --load-list, but not --list" % name) + print ("%s | %s" % (cmdline, add_prefix(name, env, support_list))).replace("$LISTOPT", "--list") + print cmdline + " $LOADLIST 2>&1 " + to_subunit1(subunit_version) + "| " + add_prefix(name, env, support_list) def skiptestsuite(name, reason): diff --git a/selftest/testlist.py b/selftest/testlist.py index 50ea31b..34c7a5d 100644 --- a/selftest/testlist.py +++ b/selftest/testlist.py @@ -81,8 +81,12 @@ def read_testlist(inf, outf): supports_loadlist = l.startswith("-- TEST-LOADLIST") name = inf.readline().rstrip("\n") env = inf.readline().rstrip("\n") + if supports_loadlist: + loadlist = inf.readline().rstrip("\n") + else: + loadlist = None cmdline = inf.readline().rstrip("\n") - yield (name, env, cmdline, supports_loadlist) + yield (name, env, cmdline, loadlist) else: outf.write(l) diff --git a/selftest/tests/test_testlist.py b/selftest/tests/test_testlist.py index 7846eb1..7007d6d 100644 --- a/selftest/tests/test_testlist.py +++ b/selftest/tests/test_testlist.py @@ -67,14 +67,14 @@ class ReadTestlistTests(TestCase): def test_read_list(self): inf = StringIO("-- TEST --\nfoo\nbar\nbla\n") outf = StringIO() - self.assertEquals([('foo', 'bar', 'bla', False)], + self.assertEquals([('foo', 'bar', 'bla', None)], list(read_testlist(inf, outf))) self.assertEquals("", outf.getvalue()) def test_read_list_passes_through(self): inf = StringIO("MORENOISE\n-- TEST --\nfoo\nbar\nbla\nNOISE\n") outf = StringIO() - self.assertEquals([('foo', 'bar', 'bla', False)], + self.assertEquals([('foo', 'bar', 'bla', None)], list(read_testlist(inf, outf))) self.assertEquals("MORENOISE\nNOISE\n", outf.getvalue()) @@ -143,6 +143,6 @@ class ReadTestListFileTests(TestCase): f.close() outf = StringIO() self.assertEquals( - [('data', 'env', 'cmd', False, False)], + [('data', 'env', 'cmd', None)], list(read_testlist_file(p, outf))) self.assertEquals("noise\n", outf.getvalue()) diff --git a/source4/scripting/bin/subunitrun b/source4/scripting/bin/subunitrun index 99d5319..8d43f25 100755 --- a/source4/scripting/bin/subunitrun +++ b/source4/scripting/bin/subunitrun @@ -81,5 +81,7 @@ opts, args = parser.parse_args() if not getattr(opts, "listtests", False): lp = sambaopts.get_loadparm() samba.tests.cmdline_credentials = credopts.get_credentials(lp) +if getattr(opts, 'load_list', None): + args.insert(0, "--load-list=%s" % opts.load_list) TestProgram(module=None, args=args, opts=subunitopts) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 6645f65..496c2b9 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -436,7 +436,7 @@ def planoldpythontestsuite(env, module, name=None, extra_path=[], environ={}, ex args += extra_args if name is None: name = module - plantestsuite(name, env, args) + plantestsuite_loadlist(name, env, args) planoldpythontestsuite("dc:local", "samba.tests.gensec", extra_args=['-U"$USERNAME%$PASSWORD"']) planoldpythontestsuite("none", "simple", extra_path=["%s/lib/tdb/python/tests" % srcdir()], name="tdb.python") -- 2.1.4 From cf52220bc0010af54d17a67ad97360ed22e3f6e3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 1 Nov 2014 16:36:54 -0700 Subject: [PATCH 36/36] Be consistent about what functions add $LISTOPT and $LOADLIST to the command-line. Change-Id: Ife86624b53a99d48ce9f00d146b14f798c9bdb24 Signed-off-by: Jelmer Vernooij Reviewed-by: Andrew Bartlett Autobuild-User(master): Jelmer Vernooij Autobuild-Date(master): Sun Nov 30 16:43:52 CET 2014 on sn-devel-104 (cherry picked from commit 02e063bd5be06925489f735c51225b65ff961d6b) BUG: https://bugzilla.samba.org/show_bug.cgi?id=11137 --- selftest/selftesthelpers.py | 10 ++++++---- source4/selftest/tests.py | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/selftest/selftesthelpers.py b/selftest/selftesthelpers.py index dc655c1..0ec2137 100644 --- a/selftest/selftesthelpers.py +++ b/selftest/selftesthelpers.py @@ -134,9 +134,11 @@ def plantestsuite_loadlist(name, env, cmdline, subunit_version=1): cmdline = " ".join(cmdline) support_list = ("$LISTOPT" in cmdline) if not "$LISTOPT" in cmdline: - raise AssertionError("test %s supports --load-list, but not --list" % name) - print ("%s | %s" % (cmdline, add_prefix(name, env, support_list))).replace("$LISTOPT", "--list") - print cmdline + " $LOADLIST 2>&1 " + to_subunit1(subunit_version) + "| " + add_prefix(name, env, support_list) + raise AssertionError("loadlist test %s does not support not --list" % name) + if not "$LOADLIST" in cmdline: + raise AssertionError("loadlist test %s does not support --load-list" % name) + print ("%s | %s" % (cmdline.replace("$LOADLIST", ""), add_prefix(name, env, support_list))).replace("$LISTOPT", "--list") + print cmdline.replace("$LISTOPT", "") + " 2>&1 " + to_subunit1(subunit_version) + " | " + add_prefix(name, env, False) def skiptestsuite(name, reason): @@ -208,7 +210,7 @@ def plansmbtorture4testsuite(name, env, options, target, modname=None): if isinstance(options, list): options = " ".join(options) options = " ".join(smbtorture4_options + ["--target=%s" % target]) + " " + options - cmdline = "%s $LISTOPT %s %s" % (valgrindify(smbtorture4), options, name) + cmdline = "%s $LISTOPT $LOADLIST %s %s" % (valgrindify(smbtorture4), options, name) plantestsuite_loadlist(modname, env, cmdline) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 496c2b9..7c4f888 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -313,7 +313,7 @@ plantestsuite("samba4.blackbox.gentest(dc)", "dc", [os.path.join(samba4srcdir, " plantestsuite("samba4.blackbox.rfc2307_mapping(dc:local)", "dc:local", [os.path.join(samba4srcdir, "../nsswitch/tests/test_rfc2307_mapping.sh"), '$DOMAIN', '$USERNAME', '$PASSWORD', "$SERVER", "$UID_RFC2307TEST", "$GID_RFC2307TEST", configuration]) plantestsuite("samba4.blackbox.chgdcpass", "chgdcpass", [os.path.join(bbdir, "test_chgdcpass.sh"), '$SERVER', "CHGDCPASS\$", '$REALM', '$DOMAIN', '$PREFIX', "aes256-cts-hmac-sha1-96", '$SELFTEST_PREFIX/chgdcpass', smbclient4]) plantestsuite("samba4.blackbox.samba_upgradedns(chgdcpass:local)", "chgdcpass:local", [os.path.join(bbdir, "test_samba_upgradedns.sh"), '$SERVER', '$REALM', '$PREFIX', '$SELFTEST_PREFIX/chgdcpass']) -plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) +plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "dc", [valgrindify(smbtorture4), "$LISTOPT", "$LOADLIST", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) # Tests using the "Simple" NTVFS backend for t in ["base.rw1"]: @@ -432,7 +432,7 @@ def planoldpythontestsuite(env, module, name=None, extra_path=[], environ={}, ex if py_path: environ["PYTHONPATH"] = ":".join(["$PYTHONPATH"] + py_path) args = ["%s=%s" % item for item in environ.iteritems()] - args += [subunitrun, "$LISTOPT", module] + args += [subunitrun, "$LISTOPT", "$LOADLIST", module] args += extra_args if name is None: name = module -- 2.1.4