diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2007-11-21 11:47:55 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2007-12-21 05:45:51 +0100 |
commit | ea851658411e3ff03a906f7ae6afc7e9319d6f90 (patch) | |
tree | 76cbc3b9417c3668b9f33511272cc79d5b2bb8a3 | |
parent | 5256d93a458d0f653afa788bb8f8d894dd1a25b2 (diff) | |
download | samba-ea851658411e3ff03a906f7ae6afc7e9319d6f90.tar.gz samba-ea851658411e3ff03a906f7ae6afc7e9319d6f90.tar.bz2 samba-ea851658411e3ff03a906f7ae6afc7e9319d6f90.zip |
r26068: Import improved Python bindings for LDB, including tests.
(This used to be commit fc3a8caef749ddac56a4f035dde8b6ceeaa95c48)
-rw-r--r-- | source4/build/smb_build/input.pm | 1 | ||||
-rw-r--r-- | source4/build/smb_build/makefile.pm | 2 | ||||
-rw-r--r-- | source4/configure.ac | 119 | ||||
-rw-r--r-- | source4/lib/ldb/config.mk | 7 | ||||
-rw-r--r-- | source4/lib/ldb/ldb.i (renamed from source4/lib/ldb/swig/ldb.i) | 0 | ||||
-rw-r--r-- | source4/lib/ldb/libldb.m4 | 32 | ||||
-rwxr-xr-x | source4/lib/ldb/setup.py | 2 | ||||
-rw-r--r-- | source4/lib/ldb/swig/Ldb.py | 178 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/api.py | 353 | ||||
-rw-r--r-- | source4/samba4-skip | 1 | ||||
-rw-r--r-- | source4/scripting/swig/config.mk | 1 | ||||
-rwxr-xr-x | source4/selftest/samba4_tests.sh | 6 |
12 files changed, 485 insertions, 217 deletions
diff --git a/source4/build/smb_build/input.pm b/source4/build/smb_build/input.pm index 2d1aaedb13..d0d923bf5e 100644 --- a/source4/build/smb_build/input.pm +++ b/source4/build/smb_build/input.pm @@ -137,6 +137,7 @@ sub check_library($$$) unless(defined($lib->{INSTALLDIR})) { $lib->{INSTALLDIR} = "LIBDIR"; } + add_libreplace($lib); } diff --git a/source4/build/smb_build/makefile.pm b/source4/build/smb_build/makefile.pm index 5d942f48eb..043f13d518 100644 --- a/source4/build/smb_build/makefile.pm +++ b/source4/build/smb_build/makefile.pm @@ -398,7 +398,7 @@ sub SharedLibrary($$) if ($ctx->{TYPE} eq "PYTHON") { push (@{$self->{python_dsos}}, - "$ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}"); + "$ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}"); } push(@{$self->{all_objs}}, "\$($ctx->{TYPE}_$ctx->{NAME}_FULL_OBJ_LIST)"); diff --git a/source4/configure.ac b/source4/configure.ac index 520808051e..bb0dbf47f1 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -79,9 +79,126 @@ m4_include(lib/events/config.m4) dnl m4_include(auth/kerberos/config.m4) +AC_ARG_VAR([PYTHON_VERSION],[The installed Python + version to use, for example '2.3'. This string + will be appended to the Python interpreter + canonical name.]) + +AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) +if test -z "$PYTHON"; then + AC_MSG_ERROR([No python found]) +fi + +AC_SUBST(PYTHON) + +# +# Check for a version of Python >= 2.1.0 +# +AC_MSG_CHECKING([for a version of Python >= '2.1.0']) +ac_supports_python_ver=`$PYTHON -c "import sys, string; \ + ver = string.split(sys.version)[[0]]; \ + print ver >= '2.1.0'"` +if test "$ac_supports_python_ver" != "True"; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([No recent version of python found]) +else + AC_MSG_RESULT([yes]) +fi + +# +# Check if you have distutils, else fail +# +AC_MSG_CHECKING([for the distutils Python package]) +ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` +if test -z "$ac_distutils_result"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([distutils not available]) +fi + +# +# Check for Python include path +# +AC_MSG_CHECKING([for Python include path]) +if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_inc();"` + if test -n "${python_path}"; then + python_path="-I$python_path" + fi + PYTHON_CPPFLAGS=$python_path +fi +AC_MSG_RESULT([$PYTHON_CPPFLAGS]) +AC_SUBST([PYTHON_CPPFLAGS]) + +# +# Check for Python library path +# +AC_MSG_CHECKING([for Python library path]) +if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) + py_version=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print join(get_config_vars('VERSION'))"` + if test "$py_version" == "[None]"; then + if test -n "$PYTHON_VERSION"; then + py_version=$PYTHON_VERSION + else + py_version=`$PYTHON -c "import sys; \ + print sys.version[[:3]]"` + fi + fi + + PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ + from string import join; \ + print '-L' + get_python_lib(0,1), \ + '-lpython';"`$py_version +fi +AC_MSG_RESULT([$PYTHON_LDFLAGS]) +AC_SUBST([PYTHON_LDFLAGS]) + +# +# Check for site packages +# +AC_MSG_CHECKING([for Python site-packages path]) +if test -z "$PYTHON_SITE_PKG"; then + PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ + print distutils.sysconfig.get_python_lib(0,0);"` +fi +AC_MSG_RESULT([$PYTHON_SITE_PKG]) +AC_SUBST([PYTHON_SITE_PKG]) + +# +# libraries which must be linked in when embedding +# +AC_MSG_CHECKING(python extra libraries) +if test -z "$PYTHON_EXTRA_LIBS"; then + PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LOCALMODLIBS'), conf('LIBS')"` +fi +AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) +AC_SUBST(PYTHON_EXTRA_LIBS) + +# +# linking flags needed when embedding +# +AC_MSG_CHECKING(python extra linking flags) +if test -z "$PYTHON_EXTRA_LDFLAGS"; then + PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ + conf = distutils.sysconfig.get_config_var; \ + print conf('LINKFORSHARED')"` +fi +AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) +AC_SUBST(PYTHON_EXTRA_LDFLAGS) + +SMB_EXT_LIB(LIBPYTHON, [$PYTHON_LDFLAGS], [$PYTHON_CPPFLAGS]) +SMB_ENABLE(LIBPYTHON) + m4_include(auth/gensec/config.m4) m4_include(smbd/process_model.m4) -m4_include(scripting/swig/config.m4) m4_include(ntvfs/posix/config.m4) m4_include(ntvfs/unixuid/config.m4) m4_include(lib/socket_wrapper/config.m4) diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk index 6472612837..38f6c371a2 100644 --- a/source4/lib/ldb/config.mk +++ b/source4/lib/ldb/config.mk @@ -194,10 +194,9 @@ PRIVATE_DEPENDENCIES = \ ####################### # Start LIBRARY swig_ldb -[LIBRARY::swig_ldb] -PUBLIC_DEPENDENCIES = LIBLDB DYNCONFIG -LIBRARY_REALNAME = swig/_ldb.$(SHLIBEXT) -OBJ_FILES = swig/ldb_wrap.o +[PYTHON::swig_ldb] +PUBLIC_DEPENDENCIES = LIBLDB LIBPYTHON +SWIG_FILE = ldb.i # End LIBRARY swig_ldb ####################### diff --git a/source4/lib/ldb/swig/ldb.i b/source4/lib/ldb/ldb.i index cdf1d66de1..cdf1d66de1 100644 --- a/source4/lib/ldb/swig/ldb.i +++ b/source4/lib/ldb/ldb.i diff --git a/source4/lib/ldb/libldb.m4 b/source4/lib/ldb/libldb.m4 index fbef076f81..77ebcc5ff4 100644 --- a/source4/lib/ldb/libldb.m4 +++ b/source4/lib/ldb/libldb.m4 @@ -5,35 +5,3 @@ SMB_ENABLE(ldb_sqlite3, NO) if test x"$with_sqlite3_support" = x"yes"; then SMB_ENABLE(ldb_sqlite3, YES) fi - -AC_MSG_CHECKING([for Python]) - -PYTHON= - -AC_ARG_WITH(python, -[ --with-python=PYTHONNAME build Python libraries], -[ case "${withval-python}" in - yes) - PYTHON=python - ;; - no) - PYTHON= - ;; - *) - PYTHON=${withval-python} - ;; - esac ]) - -if test x"$PYTHON" != "x"; then - incdir=`python -c 'import sys; print "%s/include/python%d.%d" % (sys.prefix, sys.version_info[[0]], sys.version_info[[1]])'` - CPPFLAGS="$CPPFLAGS -I $incdir" -fi - -if test x"$PYTHON" != "x"; then - AC_MSG_RESULT([${withval-python}]) -else - AC_MSG_RESULT(no) - SMB_ENABLE(swig_ldb, NO) -fi - -AC_SUBST(PYTHON) diff --git a/source4/lib/ldb/setup.py b/source4/lib/ldb/setup.py index e5fcddf0db..da3623315e 100755 --- a/source4/lib/ldb/setup.py +++ b/source4/lib/ldb/setup.py @@ -3,6 +3,6 @@ from distutils.core import setup from distutils.extension import Extension setup(name='ldb', version='1.0', - ext_modules=[Extension('_ldb', ['swig/ldb.i'], include_dirs=['include'], + ext_modules=[Extension('_ldb', ['ldb.i'], include_dirs=['include'], libraries=['ldb','ldap'])], ) diff --git a/source4/lib/ldb/swig/Ldb.py b/source4/lib/ldb/swig/Ldb.py deleted file mode 100644 index 4be3eec704..0000000000 --- a/source4/lib/ldb/swig/Ldb.py +++ /dev/null @@ -1,178 +0,0 @@ -"""Provide a more Pythonic and object-oriented interface to ldb.""" - -# -# Swig interface to Samba -# -# Copyright (C) Tim Potter 2006 -# -# 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 <http://www.gnu.org/licenses/>. -# - -# -# Interface notes: -# -# - should an empty dn be represented as None, or an empty string? -# -# - should single-valued attributes be a string, or a list with one -# element? -# - -from ldb import * - -# Global initialisation - -result = ldb_global_init() - -if result != 0: - raise LdbError, (result, 'ldb_global_init failed') - -# Ldb exceptions - -class LdbError(Exception): - """An exception raised when a ldb error occurs. - The exception data is a tuple consisting of the ldb number and a - string description of the error.""" - pass - -# Ldb classes - -class LdbMessage: - """A class representing a ldb message as a Python dictionary.""" - - def __init__(self): - self.mem_ctx = talloc_init(None) - self.msg = ldb_msg_new(self.mem_ctx) - - def __del__(self): - if self.mem_ctx is not None: - talloc_free(self.mem_ctx) - self.mem_ctx = None - self.msg = None - - # Make the dn attribute of the object dynamic - - def __getattr__(self, attr): - if attr == 'dn': - return ldb_dn_linearize(None, self.msg.dn) - return self.__dict__[attr] - - def __setattr__(self, attr, value): - if attr == 'dn': - self.msg.dn = ldb_dn_explode(self.msg, value) - if self.msg.dn == None: - err = LDB_ERR_INVALID_DN_SYNTAX - raise LdbError(err, ldb_strerror(err)) - return - self.__dict__[attr] = value - - # Get and set individual elements - - def __getitem__(self, key): - - elt = ldb_msg_find_element(self.msg, key) - - if elt is None: - raise KeyError, "No such attribute '%s'" % key - - return [ldb_val_array_getitem(elt.values, i) - for i in range(elt.num_values)] - - def __setitem__(self, key, value): - ldb_msg_remove_attr(self.msg, key) - if type(value) in (list, tuple): - [ldb_msg_add_value(self.msg, key, v) for v in value] - else: - ldb_msg_add_value(self.msg, key, value) - - # Dictionary interface - # TODO: move to iterator based interface - - def len(self): - return self.msg.num_elements - - def keys(self): - return [ldb_message_element_array_getitem(self.msg.elements, i).name - for i in range(self.msg.num_elements)] - - def values(self): - return [self[k] for k in self.keys()] - - def items(self): - return [(k, self[k]) for k in self.keys()] - - # Misc stuff - - def sanity_check(self): - return ldb_msg_sanity_check(self.msg) - -class Ldb: - """A class representing a binding to a ldb file.""" - - def __init__(self, url, flags = 0): - """Initialise underlying ldb.""" - - self.mem_ctx = talloc_init('mem_ctx for ldb 0x%x' % id(self)) - self.ldb_ctx = ldb_init(self.mem_ctx) - - result = ldb_connect(self.ldb_ctx, url, flags, None) - - if result != LDB_SUCCESS: - raise LdbError, (result, ldb_strerror(result)) - - def __del__(self): - """Called when the object is to be garbage collected.""" - self.close() - - def close(self): - """Close down a ldb.""" - if self.mem_ctx is not None: - talloc_free(self.mem_ctx) - self.mem_ctx = None - self.ldb_ctx = None - - def _ldb_call(self, fn, *args): - """Call a ldb function with args. Raise a LdbError exception - if the function returns a non-zero return value.""" - - result = fn(*args) - - if result != LDB_SUCCESS: - raise LdbError, (result, ldb_strerror(result)) - - def search(self, expression): - """Search a ldb for a given expression.""" - - self._ldb_call(ldb_search, self.ldb_ctx, None, LDB_SCOPE_DEFAULT, - expression, None); - - return [LdbMessage(ldb_message_ptr_array_getitem(result.msgs, ndx)) - for ndx in range(result.count)] - - def delete(self, dn): - """Delete a dn.""" - - _dn = ldb_dn_explode(self.ldb_ctx, dn) - - self._ldb_call(ldb_delete, self.ldb_ctx, _dn) - - def rename(self, olddn, newdn): - """Rename a dn.""" - - _olddn = ldb_dn_explode(self.ldb_ctx, olddn) - _newdn = ldb_dn_explode(self.ldb_ctx, newdn) - - self._ldb_call(ldb_rename, self.ldb_ctx, _olddn, _newdn) - - def add(self, m): - self._ldb_call(ldb_add, self.ldb_ctx, m.msg) diff --git a/source4/lib/ldb/tests/python/api.py b/source4/lib/ldb/tests/python/api.py new file mode 100755 index 0000000000..b140bfc599 --- /dev/null +++ b/source4/lib/ldb/tests/python/api.py @@ -0,0 +1,353 @@ +#!/usr/bin/python +# Simple tests for the ldb python API +# Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org> +import sys +import unittest +sys.path.append("swig") +sys.path.append("build/lib.linux-i686-2.4") + +import ldb + +class NoContextTests(unittest.TestCase): + def test_valid_attr_name(self): + self.assertTrue(ldb.valid_attr_name("foo")) + self.assertFalse(ldb.valid_attr_name("24foo")) + + def test_timestring(self): + self.assertEquals("19700101000000.0Z", ldb.timestring(0)) + self.assertEquals("20071119191012.0Z", ldb.timestring(1195499412)) + + def test_string_to_time(self): + self.assertEquals(0, ldb.string_to_time("19700101000000.0Z")) + self.assertEquals(1195499412, ldb.string_to_time("20071119191012.0Z")) + + +class SimpleLdb(unittest.TestCase): + def test_connect(self): + ldb.Ldb("foo.tdb") + + def test_connect_none(self): + ldb.Ldb() + + def test_connect_later(self): + x = ldb.Ldb() + x.connect("foo.tdb") + + def test_set_create_perms(self): + x = ldb.Ldb() + x.set_create_perms(0600) + + def test_set_modules_dir(self): + x = ldb.Ldb() + x.set_modules_dir("/tmp") + + def test_search(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(len(l.search()), 1) + + def test_search_attrs(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(len(l.search(ldb.Dn(l, ""), ldb.SCOPE_SUBTREE, "(dc=*)", ["dc"])), 0) + + def test_opaque(self): + l = ldb.Ldb("foo.tdb") + l.set_opaque("my_opaque", l) + self.assertTrue(l.get_opaque("my_opaque") is not None) + self.assertEquals(None, l.get_opaque("unknown")) + + def test_search_scope_base(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(len(l.search(ldb.Dn(l, "dc=foo"), + ldb.SCOPE_ONELEVEL)), 0) + + def test_delete(self): + l = ldb.Ldb("foo.tdb") + self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo"))) + + def test_contains(self): + l = ldb.Ldb("foo.tdb") + self.assertFalse(ldb.Dn(l, "dc=foo") in l) + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo") + m["b"] = ["a"] + l.add(m) + try: + self.assertTrue(ldb.Dn(l, "dc=foo") in l) + finally: + l.delete(m.dn) + + def test_get_config_basedn(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(None, l.get_config_basedn()) + + def test_get_root_basedn(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(None, l.get_root_basedn()) + + def test_get_schema_basedn(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(None, l.get_schema_basedn()) + + def test_get_default_basedn(self): + l = ldb.Ldb("foo.tdb") + self.assertEquals(None, l.get_default_basedn()) + + def test_add(self): + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo") + m["bla"] = "bla" + self.assertEquals(len(l.search()), 1) + l.add(m) + try: + self.assertEquals(len(l.search()), 2) + finally: + l.delete(ldb.Dn(l, "dc=foo")) + + def test_add_dict(self): + l = ldb.Ldb("foo.tdb") + m = {"dn": ldb.Dn(l, "dc=foo"), + "bla": "bla"} + self.assertEquals(len(l.search()), 1) + l.add(m) + try: + self.assertEquals(len(l.search()), 2) + finally: + l.delete(ldb.Dn(l, "dc=foo")) + + def test_rename(self): + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=foo") + m["bla"] = "bla" + self.assertEquals(len(l.search()), 1) + l.add(m) + try: + l.rename(ldb.Dn(l, "dc=foo"), ldb.Dn(l, "dc=bar")) + self.assertEquals(len(l.search()), 2) + finally: + l.delete(ldb.Dn(l, "dc=bar")) + + def test_modify_delete(self): + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ["1234"] + l.add(m) + rm = l.search(m.dn)[0] + self.assertEquals(["1234"], list(rm["bla"])) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ldb.MessageElement([], ldb.CHANGETYPE_DELETE, "bla") + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEquals(1, len(rm)) + finally: + l.delete(ldb.Dn(l, "dc=modify")) + + def test_modify_add(self): + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ["1234"] + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ldb.MessageElement(["456"], ldb.CHANGETYPE_ADD, "bla") + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEquals(2, len(rm)) + self.assertEquals(["1234", "456"], list(rm["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=modify")) + + def test_modify_modify(self): + l = ldb.Ldb("foo.tdb") + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ["1234", "456"] + l.add(m) + try: + m = ldb.Message() + m.dn = ldb.Dn(l, "dc=modify") + m["bla"] = ldb.MessageElement(["456"], ldb.CHANGETYPE_MODIFY, "bla") + l.modify(m) + rm = l.search(m.dn)[0] + self.assertEquals(2, len(rm)) + self.assertEquals(["1234"], list(rm["bla"])) + finally: + l.delete(ldb.Dn(l, "dc=modify")) + + def test_transaction_commit(self): + l = ldb.Ldb("foo.tdb") + l.transaction_start() + m = ldb.Message(ldb.Dn(l, "dc=foo")) + m["foo"] = ["bar"] + l.add(m) + l.transaction_commit() + l.delete(m.dn) + + def test_transaction_cancel(self): + l = ldb.Ldb("foo.tdb") + l.transaction_start() + m = ldb.Message(ldb.Dn(l, "dc=foo")) + m["foo"] = ["bar"] + l.add(m) + l.transaction_cancel() + self.assertEquals(0, len(l.search(ldb.Dn(l, "dc=foo")))) + + def test_set_debug(self): + def my_report_fn(level, text): + pass + l = ldb.Ldb("foo.tdb") + l.set_debug(my_report_fn) + + +class DnTests(unittest.TestCase): + def setUp(self): + self.ldb = ldb.Ldb("foo.tdb") + + def test_str(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals(x.__str__(), "dc=foo,bar=bloe") + + def test_get_casefold(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals(x.get_casefold(), "DC=FOO,BAR=bloe") + + def test_validate(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertTrue(x.validate()) + + def test_parent(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals("bar=bloe", x.parent().__str__()) + + def test_compare(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + y = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals(x, y) + z = ldb.Dn(self.ldb, "dc=foo,bar=blie") + self.assertNotEquals(z, y) + + def test_is_valid(self): + x = ldb.Dn(self.ldb, "dc=foo,dc=bloe") + self.assertTrue(x.is_valid()) + x = ldb.Dn(self.ldb, "") + # is_valid()'s return values appears to be a side effect of + # some other ldb functions. yuck. + # self.assertFalse(x.is_valid()) + + def test_is_special(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertFalse(x.is_special()) + x = ldb.Dn(self.ldb, "@FOOBAR") + self.assertTrue(x.is_special()) + + def test_check_special(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertFalse(x.check_special("FOOBAR")) + x = ldb.Dn(self.ldb, "@FOOBAR") + self.assertTrue(x.check_special("@FOOBAR")) + + def test_len(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals(2, len(x)) + x = ldb.Dn(self.ldb, "dc=foo") + self.assertEquals(1, len(x)) + + def test_add_child(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertTrue(x.add_child(ldb.Dn(self.ldb, "bla=bloe"))) + self.assertEquals("bla=bloe,dc=foo,bar=bloe", x.__str__()) + + def test_add_base(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertTrue(x.add_base(ldb.Dn(self.ldb, "bla=bloe"))) + self.assertEquals("dc=foo,bar=bloe,bla=bloe", x.__str__()) + + def test_add(self): + x = ldb.Dn(self.ldb, "dc=foo") + y = ldb.Dn(self.ldb, "bar=bla") + self.assertEquals("dc=foo,bar=bla", str(y + x)) + + def test_parse_ldif(self): + msgs = self.ldb.parse_ldif("dn: foo=bar\n") + msg = msgs.next() + self.assertEquals("foo=bar", str(msg[1].dn)) + self.assertTrue(isinstance(msg[1], ldb.Message)) + + def test_parse_ldif_more(self): + msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar") + msg = msgs.next() + self.assertEquals("foo=bar", str(msg[1].dn)) + msg = msgs.next() + self.assertEquals("bar=bar", str(msg[1].dn)) + + def test_canonical_string(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals("/bloe/foo", x.canonical_str()) + + def test_canonical_ex_string(self): + x = ldb.Dn(self.ldb, "dc=foo,bar=bloe") + self.assertEquals("/bloe\nfoo", x.canonical_ex_str()) + + +class LdbMsgTests(unittest.TestCase): + def setUp(self): + self.msg = ldb.Message() + + def test_init_dn(self): + self.msg = ldb.Message(ldb.Dn(ldb.Ldb(), "dc=foo")) + self.assertEquals("dc=foo", str(self.msg.dn)) + + def test_len(self): + self.assertEquals(0, len(self.msg)) + + def test_notpresent(self): + self.assertRaises(KeyError, lambda: self.msg["foo"]) + + def test_del(self): + del self.msg["foo"] + + def test_add_value(self): + self.assertEquals(0, len(self.msg)) + self.msg["foo"] = ["foo"] + self.assertEquals(1, len(self.msg)) + + def test_add_value_multiple(self): + self.assertEquals(0, len(self.msg)) + self.msg["foo"] = ["foo", "bla"] + self.assertEquals(1, len(self.msg)) + self.assertEquals(["foo", "bla"], list(self.msg["foo"])) + + def test_set_value(self): + self.msg["foo"] = ["fool"] + self.assertEquals(["fool"], list(self.msg["foo"])) + self.msg["foo"] = ["bar"] + self.assertEquals(["bar"], list(self.msg["foo"])) + + def test_keys(self): + self.msg["foo"] = ["bla"] + self.msg["bar"] = ["bla"] + self.assertEquals(["foo", "bar"], self.msg.keys()) + + def test_dn(self): + self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO") + self.assertEquals("@BASEINFO", self.msg.dn.__str__()) + + +class MessageElementTests(unittest.TestCase): + def test_cmp_element(self): + x = ldb.MessageElement(["foo"]) + y = ldb.MessageElement(["foo"]) + z = ldb.MessageElement(["bzr"]) + self.assertEquals(x, y) + self.assertNotEquals(x, z) + + def test_create_iterable(self): + x = ldb.MessageElement(["foo"]) + self.assertEquals(["foo"], list(x)) diff --git a/source4/samba4-skip b/source4/samba4-skip index d88f010511..f85c9c807e 100644 --- a/source4/samba4-skip +++ b/source4/samba4-skip @@ -49,3 +49,4 @@ RPC-FRSAPI # Not provided by Samba 4 ^samba4.NET-API-BECOME-DC.*$ # Fails WINBIND # FIXME: This should not be skipped NSS-TEST # Fails +samba4.ldb.python # Fails to link properly diff --git a/source4/scripting/swig/config.mk b/source4/scripting/swig/config.mk index bf9a481e4e..67c1f841f7 100644 --- a/source4/scripting/swig/config.mk +++ b/source4/scripting/swig/config.mk @@ -1,6 +1,7 @@ ####################### # Start LIBRARY swig_dcerpc [LIBRARY::swig_dcerpc] +ENABLE = NO LIBRARY_REALNAME = _dcerpc.$(SHLIBEXT) PUBLIC_DEPENDENCIES = LIBCLI_SMB NDR_MISC LIBSAMBA-UTIL LIBSAMBA-CONFIG dcerpc_samr RPC_NDR_LSA DYNCONFIG OBJ_FILES = dcerpc_wrap.o diff --git a/source4/selftest/samba4_tests.sh b/source4/selftest/samba4_tests.sh index 3fde4f3c2f..155a8be7a4 100755 --- a/source4/selftest/samba4_tests.sh +++ b/source4/selftest/samba4_tests.sh @@ -290,3 +290,9 @@ if test -f $samba4bindir/nsstest then plantest "NSS-TEST using winbind" member $VALGRIND $samba4bindir/nsstest $samba4bindir/shared/libnss_winbind.so fi + +# if trial is available, run the python tests: +if which trial 2>/dev/null >/dev/null +then + plantest "ldb.python" none PYTHONPATH=bin/python trial lib/ldb/tests/python/api.py +fi |