File: test_naming.py

package info (click to toggle)
pyro4 4.82-2
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 2,528 kB
  • sloc: python: 17,736; makefile: 169; sh: 113; javascript: 62
file content (331 lines) | stat: -rw-r--r-- 14,123 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
"""
Tests for the name server (online/running).

Pyro - Python Remote Objects.  Copyright by Irmen de Jong (irmen@razorvine.net).
"""

import time
import threading
import unittest
import Pyro4.core
import Pyro4.naming
import Pyro4.socketutil
import Pyro4.constants
from Pyro4.errors import CommunicationError, NamingError
from Pyro4.configuration import config


class NSLoopThread(threading.Thread):
    def __init__(self, nameserver):
        super(NSLoopThread, self).__init__()
        self.setDaemon(True)
        self.nameserver = nameserver
        self.running = threading.Event()
        self.running.clear()

    def run(self):
        self.running.set()
        try:
            self.nameserver.requestLoop()
        except CommunicationError:
            pass  # ignore pyro communication errors


@unittest.skip("no network access on buildds")
class BCSetupTests(unittest.TestCase):
    def testBCstart(self):
        myIpAddress = Pyro4.socketutil.getIpAddress("", workaround127=True)
        nsUri, nameserver, bcserver = Pyro4.naming.startNS(host=myIpAddress, port=0, bcport=0, enableBroadcast=False)
        self.assertIsNone(bcserver)
        nameserver.close()
        nsUri, nameserver, bcserver = Pyro4.naming.startNS(host=myIpAddress, port=0, bcport=0, enableBroadcast=True)
        self.assertIsNotNone(bcserver, "expected a BC server to be running. Check DNS setup (hostname must not resolve to loopback address")
        self.assertGreater(bcserver.fileno(), 1)
        self.assertIsNotNone(bcserver.sock)
        nameserver.close()
        bcserver.close()


@unittest.skip("no network access on buildds")
class NameServerTests(unittest.TestCase):
    def setUp(self):
        config.POLLTIMEOUT = 0.1
        myIpAddress = Pyro4.socketutil.getIpAddress("", workaround127=True)
        self.nsUri, self.nameserver, self.bcserver = Pyro4.naming.startNS(host=myIpAddress, port=0, bcport=0)
        self.assertIsNotNone(self.bcserver, "expected a BC server to be running")
        self.bcserver.runInThread()
        self.daemonthread = NSLoopThread(self.nameserver)
        self.daemonthread.start()
        self.daemonthread.running.wait()
        time.sleep(0.05)
        self.old_bcPort = config.NS_BCPORT
        self.old_nsPort = config.NS_PORT
        self.old_nsHost = config.NS_HOST
        config.NS_PORT = self.nsUri.port
        config.NS_HOST = myIpAddress
        config.NS_BCPORT = self.bcserver.getPort()

    def tearDown(self):
        time.sleep(0.01)
        self.nameserver.shutdown()
        self.bcserver.close()
        self.daemonthread.join()
        config.NS_HOST = self.old_nsHost
        config.NS_PORT = self.old_nsPort
        config.NS_BCPORT = self.old_bcPort

    def testLookupUnixsockParsing(self):
        # this must not raise AttributeError, it did before because of a parse bug
        with self.assertRaises(NamingError):
            Pyro4.naming.locateNS("./u:/tmp/pyro4-naming.usock")

    def testLookupAndRegister(self):
        ns = Pyro4.naming.locateNS()  # broadcast lookup
        self.assertIsInstance(ns, Pyro4.core.Proxy)
        ns._pyroRelease()
        ns = Pyro4.naming.locateNS(self.nsUri.host)  # normal lookup
        self.assertIsInstance(ns, Pyro4.core.Proxy)
        uri = ns._pyroUri
        self.assertEqual("PYRO", uri.protocol)
        self.assertEqual(self.nsUri.host, uri.host)
        self.assertEqual(config.NS_PORT, uri.port)
        self.assertIsNone(ns._pyroHmacKey)
        ns._pyroRelease()
        ns = Pyro4.naming.locateNS(self.nsUri.host, config.NS_PORT, hmac_key=None)
        uri = ns._pyroUri
        self.assertEqual("PYRO", uri.protocol)
        self.assertEqual(self.nsUri.host, uri.host)
        self.assertEqual(config.NS_PORT, uri.port)
        self.assertIsNone(ns._pyroHmacKey)
        # check that we cannot register a stupid type
        self.assertRaises(TypeError, ns.register, "unittest.object1", 5555)
        # we can register str or URI, lookup always returns URI
        ns.register("unittest.object2", "PYRO:55555@host.com:4444")
        self.assertEqual(Pyro4.core.URI("PYRO:55555@host.com:4444"), ns.lookup("unittest.object2"))
        ns.register("unittest.object3", Pyro4.core.URI("PYRO:66666@host.com:4444"))
        self.assertEqual(Pyro4.core.URI("PYRO:66666@host.com:4444"), ns.lookup("unittest.object3"))
        ns._pyroRelease()

    def testLookupInvalidHmac(self):
        with self.assertRaises(NamingError):
            Pyro4.naming.locateNS(self.nsUri.host, config.NS_PORT, hmac_key="invalidkey")

    def testDaemonPyroObj(self):
        uri = self.nsUri
        uri.object = Pyro4.constants.DAEMON_NAME
        with Pyro4.core.Proxy(uri) as daemonobj:
            daemonobj.ping()
            daemonobj.registered()
            try:
                daemonobj.shutdown()
                self.fail("should not succeed to call unexposed method on daemon")
            except AttributeError:
                pass

    def testMulti(self):
        uristr = str(self.nsUri)
        p = Pyro4.core.Proxy(uristr)
        p._pyroBind()
        p._pyroRelease()
        uri = Pyro4.naming.resolve(uristr)
        p = Pyro4.core.Proxy(uri)
        p._pyroBind()
        p._pyroRelease()
        uri = Pyro4.naming.resolve(uristr)
        p = Pyro4.core.Proxy(uri)
        p._pyroBind()
        p._pyroRelease()
        uri = Pyro4.naming.resolve(uristr)
        p = Pyro4.core.Proxy(uri)
        p._pyroBind()
        p._pyroRelease()
        uri = Pyro4.naming.resolve(uristr)
        p = Pyro4.core.Proxy(uri)
        p._pyroBind()
        p._pyroRelease()
        uri = Pyro4.naming.resolve(uristr)
        p = Pyro4.core.Proxy(uri)
        p._pyroBind()
        p._pyroRelease()
        daemonUri = "PYRO:" + Pyro4.constants.DAEMON_NAME + "@" + uri.location
        _ = Pyro4.naming.resolve(daemonUri)
        _ = Pyro4.naming.resolve(daemonUri)
        _ = Pyro4.naming.resolve(daemonUri)
        _ = Pyro4.naming.resolve(daemonUri)
        _ = Pyro4.naming.resolve(daemonUri)
        _ = Pyro4.naming.resolve(daemonUri)
        uri = Pyro4.naming.resolve(daemonUri)
        pyronameUri = "PYRONAME:" + Pyro4.constants.NAMESERVER_NAME + "@" + uri.location
        _ = Pyro4.naming.resolve(pyronameUri)
        _ = Pyro4.naming.resolve(pyronameUri)
        _ = Pyro4.naming.resolve(pyronameUri)
        _ = Pyro4.naming.resolve(pyronameUri)
        _ = Pyro4.naming.resolve(pyronameUri)
        _ = Pyro4.naming.resolve(pyronameUri)

    def testResolve(self):
        resolved1 = Pyro4.naming.resolve(Pyro4.core.URI("PYRO:12345@host.com:4444"), hmac_key=None)
        resolved2 = Pyro4.naming.resolve("PYRO:12345@host.com:4444", hmac_key=None)
        self.assertTrue(type(resolved1) is Pyro4.core.URI)
        self.assertEqual(resolved1, resolved2)
        self.assertEqual("PYRO:12345@host.com:4444", str(resolved1))

        ns = Pyro4.naming.locateNS(self.nsUri.host, self.nsUri.port)
        host = "[" + self.nsUri.host + "]" if ":" in self.nsUri.host else self.nsUri.host
        uri = Pyro4.naming.resolve("PYRONAME:" + Pyro4.constants.NAMESERVER_NAME + "@" + host + ":" + str(self.nsUri.port))
        self.assertEqual("PYRO", uri.protocol)
        self.assertEqual(self.nsUri.host, uri.host)
        self.assertEqual(Pyro4.constants.NAMESERVER_NAME, uri.object)
        self.assertEqual(uri, ns._pyroUri)
        ns._pyroRelease()

        # broadcast lookup
        self.assertRaises(NamingError, Pyro4.naming.resolve, "PYRONAME:unknown_object")
        uri = Pyro4.naming.resolve("PYRONAME:" + Pyro4.constants.NAMESERVER_NAME)
        self.assertEqual(Pyro4.core.URI, type(uri))
        self.assertEqual("PYRO", uri.protocol)

        # test some errors
        self.assertRaises(NamingError, Pyro4.naming.resolve, "PYRONAME:unknown_object@" + host)
        self.assertRaises(TypeError, Pyro4.naming.resolve, 999)  # wrong arg type

    def testRefuseDottedNames(self):
        old_metadata = config.METADATA
        config.METADATA = False
        with Pyro4.naming.locateNS(self.nsUri.host, self.nsUri.port) as ns:
            # the name server should never have dotted names enabled
            self.assertRaises(AttributeError, ns.namespace.keys)
            self.assertIsNotNone(ns._pyroConnection)
        self.assertIsNone(ns._pyroConnection)
        config.METADATA = old_metadata

    def testAutoClean(self):
        try:
            config.NS_AUTOCLEAN = 0.0
            config.COMMTIMEOUT = 0.5
            Pyro4.naming.AutoCleaner.max_unreachable_time = 1
            Pyro4.naming.AutoCleaner.loop_delay = 0.5
            Pyro4.naming.AutoCleaner.override_autoclean_min = True
            with Pyro4.naming.NameServerDaemon(port=0) as ns:
                self.assertIsNone(ns.cleaner_thread)
            config.NS_AUTOCLEAN = 0.2
            with Pyro4.naming.NameServerDaemon(port=0) as ns:
                self.assertIsNotNone(ns.cleaner_thread)
                ns.nameserver.register("test", "PYRO:test@localhost:59999")
                self.assertEqual(2, ns.nameserver.count())
                time.sleep(4)
                self.assertEqual(1, ns.nameserver.count(), "registration should be cleaned up")
            self.assertIsNone(ns.cleaner_thread)
        finally:
            Pyro4.naming.AutoCleaner.override_autoclean_min = False
            Pyro4.naming.AutoCleaner.max_unreachable_time = 20
            Pyro4.naming.AutoCleaner.loop_delay = 2
            config.NS_AUTOCLEAN = 0.0
            config.COMMTIMEOUT = 0.0


@unittest.skip("no network access on buildds")
class NameServerTests0000(unittest.TestCase):
    def setUp(self):
        config.POLLTIMEOUT = 0.1
        self.nsUri, self.nameserver, self.bcserver = Pyro4.naming.startNS(host="", port=0, bcport=0)
        host_check = self.nsUri.host
        self.assertEqual("0.0.0.0", host_check, "for hostname \"\" the resulting ip must be 0.0.0.0 (or ipv6 equivalent)")
        self.assertIsNotNone(self.bcserver, "expected a BC server to be running")
        self.bcthread = self.bcserver.runInThread()
        self.old_bcPort = config.NS_BCPORT
        self.old_nsPort = config.NS_PORT
        self.old_nsHost = config.NS_HOST
        config.NS_PORT = self.nsUri.port
        config.NS_HOST = self.nsUri.host
        config.NS_BCPORT = self.bcserver.getPort()

    def tearDown(self):
        time.sleep(0.01)
        self.nameserver.shutdown()
        self.bcserver.close()
        self.bcthread.join()
        config.NS_HOST = self.old_nsHost
        config.NS_PORT = self.old_nsPort
        config.NS_BCPORT = self.old_bcPort

    def testBCLookup0000(self):
        ns = Pyro4.naming.locateNS()  # broadcast lookup
        self.assertIsInstance(ns, Pyro4.core.Proxy)
        self.assertNotEqual("0.0.0.0", ns._pyroUri.host, "returned location must not be 0.0.0.0 when running on 0.0.0.0")
        ns._pyroRelease()


@unittest.skip("no network access on buildds")
class NameServerTestsHmac(unittest.TestCase):
    def setUp(self):
        config.POLLTIMEOUT = 0.1
        myIpAddress = Pyro4.socketutil.getIpAddress("", workaround127=True)
        self.nsUri, self.nameserver, self.bcserver = Pyro4.naming.startNS(host=myIpAddress, port=0, bcport=0, hmac=b"test_key")
        self.assertIsNotNone(self.bcserver, "expected a BC server to be running")
        self.bcserver.runInThread()
        self.daemonthread = NSLoopThread(self.nameserver)
        self.daemonthread.start()
        self.daemonthread.running.wait()
        time.sleep(0.05)
        self.old_bcPort = config.NS_BCPORT
        self.old_nsPort = config.NS_PORT
        self.old_nsHost = config.NS_HOST
        config.NS_PORT = self.nsUri.port
        config.NS_HOST = myIpAddress
        config.NS_BCPORT = self.bcserver.getPort()

    def tearDown(self):
        time.sleep(0.01)
        self.nameserver.shutdown()
        self.bcserver.close()
        self.daemonthread.join()
        config.NS_HOST = self.old_nsHost
        config.NS_PORT = self.old_nsPort
        config.NS_BCPORT = self.old_bcPort

    def testLookupAndRegister(self):
        ns = Pyro4.naming.locateNS()  # broadcast lookup without providing hmac still works
        self.assertIsInstance(ns, Pyro4.core.Proxy)
        self.assertIsNone(ns._pyroHmacKey)   #... but no hmac is set on the proxy
        ns._pyroRelease()
        ns = Pyro4.naming.locateNS(hmac_key=b"test_key")  # broadcast lookup providing hmac
        self.assertIsInstance(ns, Pyro4.core.Proxy)
        self.assertEqual(b"test_key", ns._pyroHmacKey)  # ... sets the hmac on the proxy
        ns._pyroRelease()
        ns = Pyro4.naming.locateNS(self.nsUri.host, config.NS_PORT, hmac_key=b"test_key")
        uri = ns._pyroUri
        self.assertEqual("PYRO", uri.protocol)
        self.assertEqual(self.nsUri.host, uri.host)
        self.assertEqual(config.NS_PORT, uri.port)
        self.assertEqual(b"test_key", ns._pyroHmacKey)
        ns._pyroRelease()

    def testResolve(self):
        uri = Pyro4.naming.resolve("PYRONAME:Pyro.NameServer", hmac_key=b"test_key")
        self.assertEqual("PYRO", uri.protocol)
        self.assertEqual(self.nsUri.host, uri.host)
        self.assertEqual(config.NS_PORT, uri.port)

    def testPyroname(self):
        with Pyro4.core.Proxy("PYRONAME:Pyro.NameServer") as p:
            p._pyroHmacKey = b"test_key"
            p.ping()   # the resolve() that is done should also use the hmac key

    def testResolveWrongHmac(self):
        with self.assertRaises(CommunicationError) as ex:
            Pyro4.naming.resolve("PYRONAME:Pyro.NameServer", hmac_key=b"wrong_key")
        emsg = str(ex.exception)
        self.assertTrue(emsg.startswith("cannot connect to "))
        self.assertTrue(emsg.endswith("message hmac mismatch"))

    def testResolveAsymmetricHmacUsage(self):
        with self.assertRaises(CommunicationError) as ex:
            Pyro4.naming.resolve("PYRONAME:Pyro.NameServer", hmac_key=None)
        emsg = str(ex.exception)
        self.assertTrue(emsg.startswith("cannot connect to "))
        self.assertTrue(emsg.endswith("hmac key config not symmetric"))


if __name__ == "__main__":
    unittest.main()