[tests] make ldap source test run its own local (Open)LDAP server stable
authorDavid Douard <david.douard@logilab.fr>
Tue, 25 Jan 2011 09:52:49 +0100
branchstable
changeset 6887 72d7feeb071e
parent 6886 b571d2d32971
child 6888 c02e5ba43366
[tests] make ldap source test run its own local (Open)LDAP server
server/sources/ldapuser.py
server/test/data/ldap_test.ldif
server/test/data/slapd.conf
server/test/unittest_ldapuser.py
--- a/server/sources/ldapuser.py	Tue Jan 25 09:51:47 2011 +0100
+++ b/server/sources/ldapuser.py	Tue Jan 25 09:52:49 2011 +0100
@@ -177,7 +177,7 @@
         self.cnx_dn = source_config.get('data-cnx-dn') or ''
         self.cnx_pwd = source_config.get('data-cnx-password') or ''
         self.user_base_scope = globals()[source_config['user-scope']]
-        self.user_base_dn = source_config['user-base-dn']
+        self.user_base_dn = str(source_config['user-base-dn'])
         self.user_base_scope = globals()[source_config['user-scope']]
         self.user_classes = splitstrip(source_config['user-classes'])
         self.user_login_attr = source_config['user-login-attr']
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/test/data/ldap_test.ldif	Tue Jan 25 09:52:49 2011 +0100
@@ -0,0 +1,55 @@
+dn: dc=cubicweb,dc=test
+structuralObjectClass: organization
+objectClass: dcObject
+objectClass: organization
+o: cubicweb
+dc: cubicweb
+
+dn: ou=People,dc=cubicweb,dc=test
+objectClass: organizationalUnit
+ou: People
+structuralObjectClass: organizationalUnit
+
+dn: uid=syt,ou=People,dc=cubicweb,dc=test
+loginShell: /bin/bash
+objectClass: inetOrgPerson
+objectClass: posixAccount
+objectClass: top
+objectClass: shadowAccount
+structuralObjectClass: inetOrgPerson
+cn: Sylvain Thenault
+sn: Thenault
+shadowMax: 99999
+gidNumber: 1004
+uid: syt
+homeDirectory: /home/syt
+shadowFlag: 134538764
+uidNumber: 1004
+givenName: Sylvain
+telephoneNumber: 106
+displayName: sthenault
+gecos: Sylvain Thenault
+mail: sylvain.thenault@logilab.fr
+mail: syt@logilab.fr
+
+dn: uid=adim,ou=People,dc=cubicweb,dc=test
+loginShell: /bin/bash
+objectClass: inetOrgPerson
+objectClass: posixAccount
+objectClass: top
+objectClass: shadowAccount
+cn: Adrien Di Mascio
+sn: Di Mascio
+shadowMax: 99999
+gidNumber: 1006
+uid: adim
+homeDirectory: /home/adim
+uidNumber: 1006
+structuralObjectClass: inetOrgPerson
+givenName: Adrien
+telephoneNumber: 109
+displayName: adimascio
+gecos: Adrien Di Mascio
+mail: adim@logilab.fr
+mail: adrien.dimascio@logilab.fr
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/test/data/slapd.conf	Tue Jan 25 09:52:49 2011 +0100
@@ -0,0 +1,53 @@
+# This is the main slapd configuration file. See slapd.conf(5) for more
+# info on the configuration options.
+
+#######################################################################
+# Global Directives:
+
+# Features to permit
+#allow bind_v2
+
+# Schema and objectClass definitions
+include         /etc/ldap/schema/core.schema
+include         /etc/ldap/schema/cosine.schema
+include         /etc/ldap/schema/nis.schema
+include         /etc/ldap/schema/inetorgperson.schema
+include         /etc/ldap/schema/openldap.schema
+include         /etc/ldap/schema/misc.schema
+
+# Where the pid file is put. The init.d script
+# will not stop the server if you change this.
+pidfile         ./data/test-slapd.pid
+
+# List of arguments that were passed to the server
+argsfile        ./data/slapd.args
+
+# Read slapd.conf(5) for possible values
+loglevel        sync
+# none
+
+# Where the dynamically loaded modules are stored
+modulepath	/usr/lib/ldap
+moduleload	back_hdb
+moduleload	back_bdb
+moduleload      back_monitor
+
+# The maximum number of entries that is returned for a search operation
+sizelimit 500
+
+# The tool-threads parameter sets the actual amount of cpu's that is used
+# for indexing.
+tool-threads 1
+
+database        bdb
+
+# The base of your directory in database #1
+suffix          "dc=cubicweb,dc=test"
+
+# rootdn directive for specifying a superuser on the database. This is needed
+# for syncrepl.
+#rootdn          "cn=admin,dc=cubicweb,dc=test"
+#rootpw          "cubicwebrocks"
+# Where the database file are physically stored for database #1
+directory       "./data/ldapdb"
+
--- a/server/test/unittest_ldapuser.py	Tue Jan 25 09:51:47 2011 +0100
+++ b/server/test/unittest_ldapuser.py	Tue Jan 25 09:52:49 2011 +0100
@@ -17,7 +17,12 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """cubicweb.server.sources.ldapusers unit and functional tests"""
 
-import socket
+import os
+import shutil
+import time
+from os.path import abspath, join, exists
+import subprocess
+from socket import socket, error as socketerror
 
 from logilab.common.testlib import TestCase, unittest_main, mock_object
 from cubicweb.devtools.testlib import CubicWebTC
@@ -25,30 +30,17 @@
 
 from cubicweb.server.sources.ldapuser import *
 
-if '17.1' in socket.gethostbyname('ldap1'):
-    SYT = 'syt'
-    SYT_EMAIL = 'Sylvain Thenault'
-    ADIM = 'adim'
-    CONFIG = u'''host=ldap1
-user-base-dn=ou=People,dc=logilab,dc=fr
+SYT = 'syt'
+SYT_EMAIL = 'Sylvain Thenault'
+ADIM = 'adim'
+CONFIG = u'''host=%s
+user-base-dn=ou=People,dc=cubicweb,dc=test
 user-scope=ONELEVEL
 user-classes=top,posixAccount
 user-login-attr=uid
 user-default-group=users
 user-attrs-map=gecos:email,uid:login
 '''
-else:
-    SYT = 'sthenault'
-    SYT_EMAIL = 'sylvain.thenault@logilab.fr'
-    ADIM = 'adimascio'
-    CONFIG = u'''host=ldap1
-user-base-dn=ou=People,dc=logilab,dc=net
-user-scope=ONELEVEL
-user-classes=top,OpenLDAPperson
-user-login-attr=uid
-user-default-group=users
-user-attrs-map=mail:email,uid:login
-'''
 
 
 def nopwd_authenticate(self, session, login, password):
@@ -71,15 +63,21 @@
     return self.extid2eid(user['dn'], 'CWUser', session)
 
 def setUpModule(*args):
+    create_slapd_configuration(LDAPUserSourceTC.config)
     global repo
-    LDAPUserSourceTC._init_repo()
-    repo = LDAPUserSourceTC.repo
-    add_ldap_source(LDAPUserSourceTC.cnx)
+    try:
+        LDAPUserSourceTC._init_repo()
+        repo = LDAPUserSourceTC.repo
+        add_ldap_source(LDAPUserSourceTC.cnx)
+    except:
+        terminate_slapd()
+        raise
 
 def tearDownModule(*args):
     global repo
     repo.shutdown()
     del repo
+    terminate_slapd()
 
 def add_ldap_source(cnx):
     cnx.request().create_entity('CWSource', name=u'ldapuser', type=u'ldapuser',
@@ -93,6 +91,55 @@
     # check we get some users from ldap
     assert len(rset) > 1
 
+def create_slapd_configuration(config):
+    global slapd_process, CONFIG
+    basedir = join(config.apphome, "ldapdb")
+    slapdconf = join(config.apphome, "slapd.conf")
+    if not exists(basedir):
+        os.makedirs(basedir)
+        # fill ldap server with some data
+        ldiffile = join(config.apphome, "ldap_test.ldif")
+        print "Initing ldap database"
+        cmdline = "/usr/sbin/slapadd -f %s -l %s -c" % (slapdconf, ldiffile)
+        subprocess.call(cmdline, shell=True)
+
+
+    #ldapuri = 'ldapi://' + join(basedir, "ldapi").replace('/', '%2f')
+    for port in range(9000, 9100):
+        try:
+            socket().bind(('localhost', port))
+        except socketerror, e:
+            if e.errno == 98: # Address already in use
+                pass
+            else:
+                raise
+        else:
+            break
+    else:
+        raise Exception("Can't find a free TCP port on localhost")
+
+    host = 'localhost:%s' % port
+    ldapuri = 'ldap://%s' % host
+    cmdline = ["/usr/sbin/slapd", "-f",  slapdconf,  "-h",  ldapuri, "-d", "0"]
+    print "Starting slapd on", ldapuri
+    slapd_process = subprocess.Popen(cmdline)
+    time.sleep(0.2)
+    if slapd_process.poll() is None:
+        print "slapd started with pid %s" % slapd_process.pid
+    else:
+        raise EnvironmentError('Cannot start slapd with cmdline="%s" (from directory "%s")' %
+                               (" ".join(cmdline), os.getcwd()))
+    CONFIG = CONFIG % host
+
+def terminate_slapd():
+    global slapd_process
+    if slapd_process.returncode is None:
+        print "terminating slapd"
+        slapd_process.terminate()
+        slapd_process.wait()
+        print "DONE"
+
+    del slapd_process
 
 class LDAPUserSourceTC(CubicWebTC):
 
@@ -117,7 +164,8 @@
 
     def test_base(self):
         # check a known one
-        e = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT}).get_entity(0, 0)
+        rset = self.sexecute('CWUser X WHERE X login %(login)s', {'login': SYT})
+        e = rset.get_entity(0, 0)
         self.assertEqual(e.login, SYT)
         e.complete()
         self.assertEqual(e.creation_date, None)