1# -*- coding: utf-8 -*-
2"""
3Automatic tests for module ldap0.dn
4"""
5
6# from Python's standard lib
7import sys
8import unittest
9
10import ldap0.dn
11from ldap0.dn import DNObj
12
13
14class TestDNFunctions(unittest.TestCase):
15    """
16    test functions in ldap0.dn
17    """
18
19    def test_is_dn(self):
20        """
21        test function is_dn()
22        """
23        self.assertEqual(ldap0.dn.is_dn('foobar,dc=example,dc=com'), False)
24        self.assertEqual(ldap0.dn.is_dn('-cn=foobar,dc=example,dc=com'), False)
25        self.assertEqual(ldap0.dn.is_dn(';cn=foobar,dc=example,dc=com'), False)
26        self.assertEqual(ldap0.dn.is_dn(',cn=foobar,dc=example,dc=com'), False)
27        self.assertEqual(ldap0.dn.is_dn('cn=foobar,dc=example,dc=com,'), False)
28        self.assertEqual(ldap0.dn.is_dn('uid=xkcd,cn=foobar,dc=example,dc=com'), True)
29        self.assertEqual(ldap0.dn.is_dn('cn=äöüÄÖÜß'), True)
30        self.assertEqual(ldap0.dn.is_dn('-'), False)
31        self.assertEqual(ldap0.dn.is_dn(''), True)
32
33    def test_escape_str(self):
34        """
35        test function escape_str()
36        """
37        self.assertEqual(ldap0.dn.escape_str(''), '')
38        self.assertEqual(ldap0.dn.escape_str('foobar'), 'foobar')
39        self.assertEqual(ldap0.dn.escape_str('foo,bar'), 'foo\\,bar')
40        self.assertEqual(ldap0.dn.escape_str('foo=bar'), 'foo\\=bar')
41        self.assertEqual(ldap0.dn.escape_str('foo#bar'), 'foo#bar')
42        self.assertEqual(ldap0.dn.escape_str('#foobar'), '\\#foobar')
43        self.assertEqual(ldap0.dn.escape_str('foo bar'), 'foo bar')
44        self.assertEqual(ldap0.dn.escape_str(' foobar'), '\\ foobar')
45        self.assertEqual(ldap0.dn.escape_str('  foobar'), '\\  foobar')
46        self.assertEqual(ldap0.dn.escape_str('foobar  '), 'foobar \\ ')
47        self.assertEqual(ldap0.dn.escape_str(' '), '\\ ')
48        self.assertEqual(ldap0.dn.escape_str('  '), '\\ \\ ')
49
50
51class TestDNObj(unittest.TestCase):
52    """
53    test class ldap0.dn.DNObj
54    """
55
56    def test001_simple(self):
57        self.assertEqual(DNObj.from_str(''), DNObj((())))
58        self.assertEqual(DNObj.from_str('').rdn(), DNObj((())))
59        self.assertEqual(DNObj.from_str('').rdn_attrs(), {})
60        self.assertEqual(len(DNObj.from_str('')), 0)
61        self.assertEqual(len(DNObj.from_str('ou=dept1  ,  dc=example, dc=com')), 3)
62        self.assertEqual(
63            str(DNObj.from_str('ou=dept1  ,  dc=example, dc=com').rdn()),
64            'ou=dept1'
65        )
66        self.assertEqual(
67            DNObj.from_str('ou=dept1  ,  dc=example, dc=com').rdn_attrs(),
68            {'ou': 'dept1'}
69        )
70        self.assertEqual(
71            DNObj.from_str('ou=dept1 + mail=test@example.com ,  dc=example, dc=com').rdn_attrs(),
72            {'mail': 'test@example.com', 'ou': 'dept1'}
73        )
74        self.assertEqual(
75            str(DNObj.from_str('ou=dept1,  dc=example, dc=com').parent()),
76            'dc=example,dc=com'
77        )
78        for dn_str in (
79                '',
80                'dc=example,dc=com',
81                'ou=dept1,dc=example,dc=com',
82                'cn=äöüÄÖÜß',
83                'cn=Michael Ströder,dc=example,dc=com',
84            ):
85            dn_obj = DNObj.from_str(dn_str, flags=0)
86            self.assertEqual(bytes(dn_obj), dn_str.encode('utf-8'))
87            self.assertEqual(dn_obj.__str__(), dn_str)
88
89    def test002_weird_whitespaces(self):
90        self.assertEqual(
91            DNObj.from_str('uid = test42 + uidNumber = 42, dc = example , dc = com'),
92            DNObj((
93                (
94                    ('uid', 'test42'),
95                    ('uidNumber', '42')
96                ),
97                (('dc', 'example'),),
98                (('dc', 'com'),)
99            ))
100        )
101
102    def test003_repr(self):
103        if sys.version_info.major >= 3:
104            correct_repr = "DNObj(((('uid', 'test42'), ('uidNumber', '42')), (('dc', 'example'),), (('dc', 'com'),)))"
105        else:
106            correct_repr = "DNObj(((('uid', 'test42'), ('uidNumber', '42')), (('dc', 'example'),), (('dc', 'com'),)))"
107        self.assertEqual(
108            repr(DNObj((
109                (
110                    ('uid', 'test42'),
111                    ('uidNumber', '42')
112                ),
113                (('dc', 'example'),),
114                (('dc', 'com'),)
115            ))),
116            correct_repr
117        )
118
119    def test004_hashable(self):
120        dn = DNObj((
121            (
122                ('uid', 'test42'),
123                ('uidNumber', '42')
124            ),
125            (('dc', 'example'),),
126            (('dc', 'com'),)
127        ))
128        data = {dn: 'foo'}
129        self.assertEqual(data[dn], 'foo')
130        self.assertEqual(set([dn]), set([dn, dn]))
131
132    def test005_slicing(self):
133        dn = DNObj.from_str('ou=dept1  ,  dc=example, dc=com')
134        self.assertEqual(dn[0], (('ou', 'dept1'),))
135        self.assertEqual(dn[1], (('dc', 'example'),))
136        self.assertEqual(dn[2], (('dc', 'com'),))
137        self.assertEqual(DNObj(dn[:]), dn)
138        with self.assertRaises(IndexError):
139            self.assertEqual(dn[3], ())
140        self.assertEqual(
141            reversed(DNObj.from_str('ou=dept1,dc=example,dc=com')),
142            DNObj.from_str('dc=com,dc=example,ou=dept1')
143        )
144        self.assertEqual(
145            DNObj.from_str('ou=dept1,dc=example,dc=com')[1:],
146            DNObj.from_str('dc=example,dc=com')[:]
147        )
148        self.assertEqual(
149            DNObj.from_str('ou=dept1,dc=example,dc=com')[:2],
150            DNObj.from_str('ou=dept1,dc=example')[:]
151        )
152        self.assertEqual(
153            DNObj.from_str('ou=dept1,dc=example,dc=com').slice(1, None),
154            DNObj.from_str('dc=example,dc=com')
155        )
156        self.assertEqual(
157            DNObj.from_str('ou=dept1,dc=example,dc=com').slice(None, 2),
158            DNObj.from_str('ou=dept1,dc=example')
159        )
160        domain = 'sub3.sub2.sub1.example.com'
161        dns_labels = domain.split('.')
162        dno = DNObj.from_domain(domain)
163        for i, dn_comp in enumerate(dno):
164            self.assertEqual(dn_comp[0][0], 'dc')
165            self.assertEqual(dn_comp[0][1], dns_labels[i])
166            self.assertEqual(dno[i], dn_comp)
167
168    def test006_domain(self):
169        self.assertEqual(
170            str(DNObj.from_domain('example.com')),
171            'dc=example,dc=com'
172        )
173        self.assertEqual(
174            DNObj.from_domain('example.com').domain(),
175            'example.com'
176        )
177        self.assertEqual(
178            DNObj.from_domain(u'ströder.de').domain(),
179            u'ströder.de'.encode('idna').decode('ascii')
180        )
181        self.assertEqual(
182            DNObj.from_str('ou=dept1,  dc=example, dc=com').domain(only_dc=False),
183            'example.com'
184        )
185        with self.assertRaises(ValueError):
186            DNObj.from_str('ou=dept1,dc=example,dc=com').domain(only_dc=True)
187        with self.assertRaises(ValueError):
188            DNObj.from_str('ou=dept1,dc=example,dc=com+dc=net').domain()
189        with self.assertRaises(ValueError):
190            DNObj.from_str('ou=foo+dc=example,dc=com').domain()
191
192
193    def test007_add(self):
194        self.assertEqual(
195            DNObj.from_domain('dept1')+DNObj.from_domain('example.com'),
196            DNObj.from_domain('dept1.example.com'),
197        )
198        self.assertEqual(
199            bytes(DNObj.from_domain('dept1')+DNObj.from_domain('example.com')),
200            b'dc=dept1,dc=example,dc=com',
201        )
202        self.assertEqual(
203            (DNObj.from_domain('dept1')+DNObj.from_domain('example.com')).domain(),
204            'dept1.example.com',
205        )
206
207    def test008_match(self):
208        dn_obj = DNObj.from_domain('example.com')
209        self.assertEqual(
210            dn_obj.match([DNObj.from_domain('example.com')]),
211            DNObj.from_domain('example.com')
212        )
213        self.assertEqual(
214            dn_obj.match([DNObj.from_domain('sub1.example.com')]),
215            DNObj((()))
216        )
217        self.assertEqual(
218            dn_obj.match([
219                DNObj.from_domain('example.com'),
220                DNObj.from_domain('example.net'),
221            ]),
222            DNObj.from_domain('example.com')
223        )
224        self.assertEqual(
225            dn_obj.match([
226                DNObj.from_str('CN=Michael, dc=example, dc=com'),
227                DNObj.from_str('DC=example, DC=com'),
228            ]),
229            DNObj.from_domain('example.com'),
230        )
231        self.assertEqual(
232            DNObj.from_str('cn=Person,dc=foo,dc=example,dc=com').match([
233                DNObj.from_domain('foo.example.com'),
234                DNObj.from_domain('bar.example.com'),
235            ]),
236            DNObj.from_domain('foo.example.com'),
237        )
238        # sub entry match
239        dn_obj = DNObj.from_domain('sub1.example.com')
240        self.assertEqual(
241            dn_obj.match([
242                DNObj.from_domain('sub2.example.com'),
243                DNObj.from_domain('example.com'),
244                DNObj.from_domain('example.net'),
245            ]),
246            DNObj.from_domain('example.com')
247        )
248        self.assertEqual(
249            dn_obj.match([
250                DNObj.from_domain('sub1.example.com'),
251                DNObj.from_domain('example.com'),
252            ]),
253            DNObj.from_domain('sub1.example.com')
254        )
255        # no match
256        dn_obj = DNObj.from_domain('example.net')
257        self.assertEqual(
258            dn_obj.match([
259                DNObj.from_domain('example.com'),
260            ]),
261            DNObj((()))
262        )
263        self.assertEqual(
264            dn_obj.match([
265                DNObj.from_domain('sub2.example.net'),
266                DNObj.from_domain('example.com'),
267            ]),
268            DNObj((()))
269        )
270        # empty
271        self.assertEqual(
272            DNObj((())).match([DNObj((()))]),
273            DNObj((()))
274        )
275
276    def test009_parents(self):
277        self.assertEqual(
278            DNObj.from_domain('example.com').parents(),
279            [DNObj.from_domain('com')]
280        )
281        self.assertEqual(
282            DNObj.from_domain('sub1.example.com').parents(),
283            [
284                DNObj.from_domain('example.com'),
285                DNObj.from_domain('com'),
286            ]
287        )
288
289    def test010_equals(self):
290        self.assertTrue(
291            DNObj.from_str('cn=Michael, dc=example, dc=com')==DNObj.from_str('CN=Michael, DC=example, DC=com')
292        )
293        self.assertFalse(
294            DNObj.from_str('uid=Michael, dc=example, dc=com')==DNObj.from_str('CN=Michael, DC=example, DC=com')
295        )
296        self.assertFalse(
297            DNObj.from_str('cn=Michael, dc=example, dc=com')==DNObj.from_str('CN=Mike, DC=example, DC=com')
298        )
299        self.assertEqual(
300            DNObj.from_str('cn=Foo + mail= foo@example.com + sn = Bar,dc=example,dc=com'),
301            DNObj.from_str('mail=foo@example.com+sn=Bar+cn=Foo,dc=example,dc=com'),
302        )
303        self.assertNotEqual(
304            DNObj.from_str('cn=Foo2 + mail= foo@example.com + sn = Bar,dc=example,dc=com'),
305            DNObj.from_str('mail=foo@example.com+sn=Bar+cn=Foo,dc=example,dc=com'),
306        )
307        self.assertNotEqual(
308            DNObj.from_str('cn=Foo + mail= foo@example.com + sn = Bar,dc=example,dc=com'),
309            DNObj.from_str('mail2=foo@example.com+sn=Bar+cn=Foo,dc=example,dc=com'),
310        )
311
312    def test010_at_sanitizer(self):
313        self.assertNotEqual(
314            str(DNObj.from_str('cn=Michael, dc=example, dc=com')),
315            str(DNObj.from_str('CN=Michael, DC=example, DC=com'))
316        )
317        self.assertEqual(
318            str(DNObj.from_str('cn=Michael, dc=example, dc=com')),
319            str(DNObj.from_str('CN=Michael, DC=example, DC=com', at_sanitizer=str.lower))
320        )
321
322
323if __name__ == '__main__':
324    unittest.main()
325