Skip to content

Commit eb9dbc1

Browse files
tiranencukou
authored andcommitted
Fix error reporting of LDAPObject.set_option()
Fix error reporting of LDAPObject.set_option() The method LDAPObject.set_option() did not signal an exception in case the set option failed. The bug was caused by checking for the wrong error value. The internal C function LDAP_set_option() returns ``1`` for sucess and ``0`` for error, but LDAPObject.set_option() was checking for ``-1``. Add some tests for LDAPObject.set_option() and LDAPObject.get_option(). python-ldap#101 Closes: python-ldap#100 Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent c4bcf1d commit eb9dbc1

File tree

2 files changed

+85
-27
lines changed

2 files changed

+85
-27
lines changed

Modules/LDAPObject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,7 @@ l_ldap_set_option(PyObject* self, PyObject *args)
12731273

12741274
if (!PyArg_ParseTuple(args, "iO:set_option", &option, &value))
12751275
return NULL;
1276-
if (LDAP_set_option((LDAPObject *)self, option, value) == -1)
1276+
if (!LDAP_set_option((LDAPObject *)self, option, value))
12771277
return NULL;
12781278
Py_INCREF(Py_None);
12791279
return Py_None;

Tests/t_ldap_options.py

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from ldap.controls import RequestControlTuples
99
from ldap.controls.pagedresults import SimplePagedResultsControl
1010
from ldap.controls.openldap import SearchNoOpControl
11-
from slapdtest import requires_tls
12-
11+
from ldap.ldapobject import SimpleLDAPObject
12+
from slapdtest import SlapdTestCase, requires_tls
1313

1414
SENTINEL = object()
1515

@@ -26,54 +26,68 @@
2626
]
2727

2828

29-
class TestGlobalOptions(unittest.TestCase):
29+
class BaseTestOptions(object):
30+
"""Common tests for getting/setting options
31+
32+
Used in subclasses below
33+
"""
34+
35+
def get_option(self, option):
36+
raise NotImplementedError()
37+
38+
def set_option(self, option, value):
39+
raise NotImplementedError()
40+
3041
def _check_option(self, option, value, expected=SENTINEL,
3142
nonevalue=None):
32-
old = ldap.get_option(option)
43+
old = self.get_option(option)
3344
try:
34-
ldap.set_option(option, value)
35-
new = ldap.get_option(option)
45+
self.set_option(option, value)
46+
new = self.get_option(option)
3647
if expected is SENTINEL:
3748
self.assertEqual(new, value)
3849
else:
3950
self.assertEqual(new, expected)
4051
finally:
41-
ldap.set_option(option, old if old is not None else nonevalue)
42-
self.assertEqual(ldap.get_option(option), old)
52+
self.set_option(
53+
option,
54+
old if old is not None else nonevalue
55+
)
56+
self.assertEqual(self.get_option(option), old)
4357

4458
def test_invalid(self):
4559
with self.assertRaises(ValueError):
46-
ldap.get_option(-1)
60+
self.get_option(-1)
4761
with self.assertRaises(ValueError):
48-
ldap.set_option(-1, '')
62+
self.set_option(-1, '')
4963

50-
def test_timeout(self):
51-
self._check_option(ldap.OPT_TIMEOUT, 0, nonevalue=-1)
52-
self._check_option(ldap.OPT_TIMEOUT, 10.5, nonevalue=-1)
64+
def _test_timeout(self, option):
65+
self._check_option(option, 10.5, nonevalue=-1)
66+
self._check_option(option, 0, nonevalue=-1)
5367
with self.assertRaises(ValueError):
54-
self._check_option(ldap.OPT_TIMEOUT, -5, nonevalue=-1)
68+
self._check_option(option, -5, nonevalue=-1)
5569
with self.assertRaises(TypeError):
56-
ldap.set_option(ldap.OPT_TIMEOUT, object)
70+
self.set_option(option, object)
71+
72+
def test_timeout(self):
73+
self._test_timeout(ldap.OPT_TIMEOUT)
5774

5875
def test_network_timeout(self):
59-
self._check_option(ldap.OPT_NETWORK_TIMEOUT, 0, nonevalue=-1)
60-
self._check_option(ldap.OPT_NETWORK_TIMEOUT, 10.5, nonevalue=-1)
61-
with self.assertRaises(ValueError):
62-
self._check_option(ldap.OPT_NETWORK_TIMEOUT, -5, nonevalue=-1)
76+
self._test_timeout(ldap.OPT_NETWORK_TIMEOUT)
6377

6478
def _test_controls(self, option):
6579
self._check_option(option, [])
6680
self._check_option(option, TEST_CTRL, TEST_CTRL_EXPECTED)
6781
self._check_option(option, tuple(TEST_CTRL), TEST_CTRL_EXPECTED)
6882
with self.assertRaises(TypeError):
69-
ldap.set_option(option, object)
83+
self.set_option(option, object)
7084

7185
with self.assertRaises(TypeError):
7286
# must contain a tuple
73-
ldap.set_option(option, [list(TEST_CTRL[0])])
87+
self.set_option(option, [list(TEST_CTRL[0])])
7488
with self.assertRaises(TypeError):
7589
# data must be bytes or None
76-
ldap.set_option(
90+
self.set_option(
7791
option,
7892
[TEST_CTRL[0][0], TEST_CTRL[0][1], u'data']
7993
)
@@ -87,20 +101,64 @@ def test_server_controls(self):
87101
def test_uri(self):
88102
self._check_option(ldap.OPT_URI, "ldapi:///path/to/socket")
89103
with self.assertRaises(TypeError):
90-
ldap.set_option(ldap.OPT_URI, object)
104+
self.set_option(ldap.OPT_URI, object)
91105

92106
@requires_tls()
93107
def test_cafile(self):
94108
# None or a distribution or OS-specific path
95-
ldap.get_option(ldap.OPT_X_TLS_CACERTFILE)
109+
self.get_option(ldap.OPT_X_TLS_CACERTFILE)
96110

97111
def test_readonly(self):
98-
value = ldap.get_option(ldap.OPT_API_INFO)
112+
value = self.get_option(ldap.OPT_API_INFO)
99113
self.assertIsInstance(value, dict)
100114
with self.assertRaises(ValueError) as e:
101-
ldap.set_option(ldap.OPT_API_INFO, value)
115+
self.set_option(ldap.OPT_API_INFO, value)
102116
self.assertIn('read-only', str(e.exception))
103117

104118

119+
class TestGlobalOptions(BaseTestOptions, unittest.TestCase):
120+
"""Test setting/getting options globally
121+
"""
122+
123+
def get_option(self, option):
124+
return ldap.get_option(option)
125+
126+
def set_option(self, option, value):
127+
return ldap.set_option(option, value)
128+
129+
130+
class TestLDAPObjectOptions(BaseTestOptions, SlapdTestCase):
131+
"""Test setting/getting connection-specific options
132+
"""
133+
134+
ldap_object_class = SimpleLDAPObject
135+
136+
def setUp(self):
137+
self.conn = self._open_ldap_conn(
138+
who=self.server.root_dn,
139+
cred=self.server.root_pw
140+
)
141+
142+
def tearDown(self):
143+
self.conn.unbind_s()
144+
self.conn = None
145+
146+
def get_option(self, option):
147+
return self.conn.get_option(option)
148+
149+
def set_option(self, option, value):
150+
return self.conn.set_option(option, value)
151+
152+
# test is failing with:
153+
# pyasn1.error.SubstrateUnderrunError: Short octet stream on tag decoding
154+
@unittest.expectedFailure
155+
def test_client_controls(self):
156+
self._test_controls(ldap.OPT_CLIENT_CONTROLS)
157+
158+
@unittest.expectedFailure
159+
def test_server_controls(self):
160+
self._test_controls(ldap.OPT_SERVER_CONTROLS)
161+
162+
105163
if __name__ == '__main__':
106164
unittest.main()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy