~ubuntu-branches/debian/sid/pyro/sid

« back to all changes in this revision

Viewing changes to tests/PyroTests/servertests.py

  • Committer: Bazaar Package Importer
  • Author(s): Carl Chenet, Carl Chenet, Jakub Wilk
  • Date: 2010-09-14 01:04:28 UTC
  • Revision ID: james.westby@ubuntu.com-20100914010428-02r7p1rzr7jvw94z
Tags: 1:3.9.1-2
[Carl Chenet]
* revert to 3.9.1-1 package because of the development status 
  of the 4.1 package is unsuitable for stable use
  DPMT svn #8557 revision (Closes: #589172) 
* added debian/source
* added debian/source/format
* package is now 3.0 (quilt) source format
* debian/control
  - Bump Standards-Version to 3.9.1

[Jakub Wilk]
* Add ‘XS-Python-Version: >= 2.5’ to prevent bytecompilation with python2.4
  (closes: #589053).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""
2
 
Tests for a running Pyro server, without timeouts.
3
 
 
4
 
Pyro - Python Remote Objects.  Copyright by Irmen de Jong.
5
 
irmen@razorvine.net - http://www.razorvine.net/python/Pyro
6
 
"""
7
 
 
8
 
from __future__ import with_statement
9
 
import unittest
10
 
import Pyro.config
11
 
import Pyro.core
12
 
import Pyro.errors
13
 
import time, os, sys
14
 
from Pyro import threadutil
15
 
 
16
 
class MyThing(object):
17
 
    def __init__(self):
18
 
        self.dictionary={"number":42}
19
 
    def getDict(self):
20
 
        return self.dictionary
21
 
    def multiply(self,x,y):
22
 
        return x*y
23
 
    def ping(self):
24
 
        pass
25
 
    def delay(self, delay):
26
 
        time.sleep(delay)
27
 
        return "slept %d seconds" % delay
28
 
    def delayAndId(self, delay, id):
29
 
        time.sleep(delay)
30
 
        return "slept for "+str(id)
31
 
    def testargs(self,x,*args,**kwargs):
32
 
        return x,args,kwargs
33
 
 
34
 
class DaemonLoopThread(threadutil.Thread):
35
 
    def __init__(self, pyrodaemon):
36
 
        super(DaemonLoopThread,self).__init__()
37
 
        self.setDaemon(True)
38
 
        self.pyrodaemon=pyrodaemon
39
 
        self.running=threadutil.Event()
40
 
        self.running.clear()
41
 
    def run(self):
42
 
        self.running.set()
43
 
        try:
44
 
            self.pyrodaemon.requestLoop()
45
 
        except:
46
 
            print "Swallow exception from terminated daemon"
47
 
        
48
 
class ServerTestsThreadNoTimeout(unittest.TestCase):
49
 
    SERVERTYPE="thread"
50
 
    COMMTIMEOUT=None
51
 
    def setUp(self):
52
 
        Pyro.config.POLLTIMEOUT=0.1
53
 
        Pyro.config.SERVERTYPE=self.SERVERTYPE
54
 
        Pyro.config.COMMTIMEOUT=self.COMMTIMEOUT
55
 
        Pyro.config.THREADPOOL_MINTHREADS=2
56
 
        Pyro.config.THREADPOOL_MAXTHREADS=20
57
 
        self.daemon=Pyro.core.Daemon(port=0)
58
 
        obj=MyThing()
59
 
        uri=self.daemon.register(obj, "something")
60
 
        self.objectUri=uri
61
 
        self.daemonthread=DaemonLoopThread(self.daemon)
62
 
        self.daemonthread.start()
63
 
        self.daemonthread.running.wait()
64
 
    def tearDown(self):
65
 
        time.sleep(0.05)
66
 
        self.daemon.shutdown()
67
 
        self.daemonthread.join()
68
 
        Pyro.config.SERVERTYPE="thread"
69
 
        Pyro.config.COMMTIMEOUT=None
70
 
 
71
 
    def testNoDottedNames(self):
72
 
        Pyro.config.DOTTEDNAMES=False
73
 
        with Pyro.core.Proxy(self.objectUri) as p:
74
 
            self.assertEqual(55,p.multiply(5,11))
75
 
            x=p.getDict()
76
 
            self.assertEqual({"number":42}, x)
77
 
            try:
78
 
                p.dictionary.update({"more":666})     # should fail with DOTTEDNAMES=False (the default)
79
 
                self.fail("expected AttributeError")
80
 
            except AttributeError:
81
 
                pass
82
 
            x=p.getDict()
83
 
            self.assertEqual({"number":42}, x)
84
 
            # also test some argument type things
85
 
            self.assertEqual((1,(),{}), p.testargs(1))
86
 
            self.assertEqual((1,(2,3),{'a':4}), p.testargs(1,2,3,a=4))
87
 
            self.assertEqual((1,(),{'a':2}), p.testargs(1, **{'a':2}))
88
 
            if sys.version_info>=(2,6,5):
89
 
                # python 2.6.5 and later support unicode keyword args
90
 
                result=p.testargs(1, **{unichr(0x20ac):2})
91
 
                key=result[2].keys()[0]
92
 
                self.assertTrue(key==unichr(0x20ac))
93
 
 
94
 
 
95
 
    def testDottedNames(self):
96
 
        try:
97
 
            Pyro.config.DOTTEDNAMES=True
98
 
            with Pyro.core.Proxy(self.objectUri) as p:
99
 
                self.assertEqual(55,p.multiply(5,11))
100
 
                x=p.getDict()
101
 
                self.assertEqual({"number":42}, x)
102
 
                p.dictionary.update({"more":666})    # updating it remotely should work with DOTTEDNAMES=True
103
 
                x=p.getDict()
104
 
                self.assertEqual({"number":42, "more":666}, x)  # eek, it got updated!
105
 
        finally:
106
 
            Pyro.config.DOTTEDNAMES=False
107
 
 
108
 
    def testConnectionStuff(self):
109
 
        p1=Pyro.core.Proxy(self.objectUri)
110
 
        p2=Pyro.core.Proxy(self.objectUri)
111
 
        self.assertTrue(p1._pyroConnection is None)
112
 
        self.assertTrue(p2._pyroConnection is None)
113
 
        p1.ping()
114
 
        p2.ping()
115
 
        x=p1.multiply(11,5)
116
 
        x=p2.multiply(11,5)
117
 
        self.assertTrue(p1._pyroConnection is not None)
118
 
        self.assertTrue(p2._pyroConnection is not None)
119
 
        p1._pyroRelease()
120
 
        p1._pyroRelease()
121
 
        p2._pyroRelease()
122
 
        p2._pyroRelease()
123
 
        self.assertTrue(p1._pyroConnection is None)
124
 
        self.assertTrue(p2._pyroConnection is None)
125
 
        p1._pyroBind()
126
 
        x=p1.multiply(11,5)
127
 
        x=p2.multiply(11,5)
128
 
        self.assertTrue(p1._pyroConnection is not None)
129
 
        self.assertTrue(p2._pyroConnection is not None)
130
 
        self.assertEqual("PYRO",p1._pyroUri.protocol)
131
 
        self.assertEqual("PYRO",p2._pyroUri.protocol)
132
 
        p1._pyroRelease()
133
 
        p2._pyroRelease()
134
 
 
135
 
    def testReconnectAndCompression(self):
136
 
        # try reconnects
137
 
        with Pyro.core.Proxy(self.objectUri) as p:
138
 
            self.assertTrue(p._pyroConnection is None)
139
 
            p._pyroReconnect(tries=100)
140
 
            self.assertTrue(p._pyroConnection is not None)
141
 
        self.assertTrue(p._pyroConnection is None)
142
 
        # test compression:
143
 
        try:
144
 
            with Pyro.core.Proxy(self.objectUri) as p:
145
 
                Pyro.config.COMPRESSION=True
146
 
                self.assertEqual(55, p.multiply(5,11))
147
 
                self.assertEqual("*"*1000, p.multiply("*"*500,2))
148
 
        finally:
149
 
            Pyro.config.COMPRESSION=False
150
 
    
151
 
    def testOneway(self):
152
 
        with Pyro.core.Proxy(self.objectUri) as p:
153
 
            self.assertEquals(55, p.multiply(5,11))
154
 
            p._pyroOneway.add("multiply")
155
 
            self.assertEquals(None, p.multiply(5,11))
156
 
            self.assertEquals(None, p.multiply(5,11))
157
 
            self.assertEquals(None, p.multiply(5,11))
158
 
            p._pyroOneway.remove("multiply")
159
 
            self.assertEquals(55, p.multiply(5,11))
160
 
            self.assertEquals(55, p.multiply(5,11))
161
 
            self.assertEquals(55, p.multiply(5,11))
162
 
            # check nonexisting method behavoir
163
 
            self.assertRaises(AttributeError, p.nonexisting)
164
 
            p._pyroOneway.add("nonexisting")
165
 
            # now it shouldn't fail because of oneway semantics
166
 
            p.nonexisting()
167
 
        # also test on class:
168
 
        class ProxyWithOneway(Pyro.core.Proxy):
169
 
            def __init__(self, arg):
170
 
                super(ProxyWithOneway,self).__init__(arg)
171
 
                self._pyroOneway=["multiply"]   # set is faster but don't care for this test
172
 
        with ProxyWithOneway(self.objectUri) as p:
173
 
            self.assertEquals(None, p.multiply(5,11))
174
 
            p._pyroOneway=[]   # empty set is better but don't care in this test
175
 
            self.assertEquals(55, p.multiply(5,11))
176
 
            
177
 
    def testOnewayDelayed(self):
178
 
        try:
179
 
            with Pyro.core.Proxy(self.objectUri) as p:
180
 
                p.ping()
181
 
                Pyro.config.ONEWAY_THREADED=True   # the default
182
 
                p._pyroOneway.add("delay")
183
 
                now=time.time()
184
 
                p.delay(1)  # oneway so we should continue right away
185
 
                self.assertTrue(time.time()-now < 0.2, "delay should be running as oneway")
186
 
                now=time.time()
187
 
                self.assertEquals(55,p.multiply(5,11), "expected a normal result from a non-oneway call")
188
 
                self.assertTrue(time.time()-now < 0.2, "delay should be running in its own thread")
189
 
                # make oneway calls run in the server thread
190
 
                # we can change the config here and the server will pick it up on the fly
191
 
                Pyro.config.ONEWAY_THREADED=False   
192
 
                now=time.time()
193
 
                p.delay(1)  # oneway so we should continue right away
194
 
                self.assertTrue(time.time()-now < 0.2, "delay should be running as oneway")
195
 
                now=time.time()
196
 
                self.assertEquals(55,p.multiply(5,11), "expected a normal result from a non-oneway call")
197
 
                self.assertFalse(time.time()-now < 0.2, "delay should be running in the server thread")
198
 
        finally:
199
 
            Pyro.config.ONEWAY_THREADED=True   # back to normal
200
 
 
201
 
    def testSerializeConnected(self):
202
 
        # online serialization tests
203
 
        ser=Pyro.util.Serializer()
204
 
        proxy=Pyro.core.Proxy(self.objectUri)
205
 
        proxy._pyroBind()
206
 
        self.assertFalse(proxy._pyroConnection is None)
207
 
        p,_=ser.serialize(proxy)
208
 
        proxy2=ser.deserialize(p)
209
 
        self.assertTrue(proxy2._pyroConnection is None)
210
 
        self.assertFalse(proxy._pyroConnection is None)
211
 
        self.assertEqual(proxy2._pyroUri, proxy._pyroUri)
212
 
        self.assertEqual(proxy2._pyroSerializer, proxy._pyroSerializer)
213
 
        proxy2._pyroBind()
214
 
        self.assertFalse(proxy2._pyroConnection is None)
215
 
        self.assertFalse(proxy2._pyroConnection is proxy._pyroConnection)
216
 
        proxy._pyroRelease()
217
 
        proxy2._pyroRelease()
218
 
        self.assertTrue(proxy._pyroConnection is None)
219
 
        self.assertTrue(proxy2._pyroConnection is None)
220
 
        proxy.ping()
221
 
        proxy2.ping()
222
 
        # try copying a connected proxy
223
 
        import copy
224
 
        proxy3=copy.copy(proxy)
225
 
        self.assertTrue(proxy3._pyroConnection is None)
226
 
        self.assertFalse(proxy._pyroConnection is None)
227
 
        self.assertEqual(proxy3._pyroUri, proxy._pyroUri)
228
 
        self.assertFalse(proxy3._pyroUri is proxy._pyroUri)
229
 
        self.assertEqual(proxy3._pyroSerializer, proxy._pyroSerializer)        
230
 
        proxy._pyroRelease()
231
 
        proxy2._pyroRelease()
232
 
        proxy3._pyroRelease()
233
 
 
234
 
    def testTimeoutCall(self):
235
 
        Pyro.config.COMMTIMEOUT=None
236
 
        with Pyro.core.Proxy(self.objectUri) as p:
237
 
            p.ping()
238
 
            start=time.time()
239
 
            p.delay(0.5)
240
 
            duration=time.time()-start
241
 
            self.assertAlmostEqual(0.5, duration, 1)
242
 
            p._pyroTimeout=0.1
243
 
            start=time.time()
244
 
            self.assertRaises(Pyro.errors.TimeoutError, p.delay, 1)
245
 
            duration=time.time()-start
246
 
            if sys.platform!="cli":
247
 
                self.assertAlmostEqual(0.1, duration, 1)
248
 
            else:
249
 
                # ironpython's time is wonky
250
 
                self.assertTrue(0.0<duration<0.7)
251
 
 
252
 
    def testTimeoutConnect(self):
253
 
        # set up a unresponsive daemon
254
 
        with Pyro.core.Daemon(port=0) as d:
255
 
            time.sleep(0.5)
256
 
            obj=MyThing()
257
 
            uri=d.register(obj)
258
 
            # we're not going to start the daemon's event loop
259
 
            p=Pyro.core.Proxy(uri)
260
 
            p._pyroTimeout=0.2
261
 
            start=time.time()
262
 
            self.assertRaises(Pyro.errors.TimeoutError, p.ping)
263
 
            duration=time.time()-start
264
 
            self.assertTrue(duration<2.0)
265
 
            
266
 
    def testProxySharing(self):
267
 
        class SharedProxyThread(threadutil.Thread):
268
 
            def __init__(self, proxy):
269
 
                super(SharedProxyThread,self).__init__()
270
 
                self.proxy=proxy
271
 
                self.terminate=False
272
 
                self.error=True
273
 
                self.setDaemon(True)
274
 
            def run(self):
275
 
                try:
276
 
                    while not self.terminate:
277
 
                        reply=self.proxy.multiply(5,11)
278
 
                        assert reply==55
279
 
                        time.sleep(0.001)
280
 
                    self.error=False
281
 
                except:
282
 
                    print "Something went wrong in the thread (SharedProxyThread):"
283
 
                    print "".join(Pyro.util.getPyroTraceback())
284
 
        with Pyro.core.Proxy(self.objectUri) as p:
285
 
            threads=[]
286
 
            for i in range(5):
287
 
                t=SharedProxyThread(p)
288
 
                threads.append(t)
289
 
                t.start()
290
 
            time.sleep(1)
291
 
            for t in threads:
292
 
                t.terminate=True
293
 
                t.join()
294
 
            for t in threads:
295
 
                self.assertFalse(t.error, "all threads should report no errors") 
296
 
 
297
 
    def testServerConnections(self):
298
 
        # check if the server allows to grow the number of connections
299
 
        proxies=[Pyro.core.Proxy(self.objectUri) for _ in range(10)]
300
 
        try:
301
 
            for p in proxies:
302
 
                p._pyroTimeout=0.5
303
 
                p._pyroBind()
304
 
            for p in proxies:
305
 
                p.ping()
306
 
        finally:
307
 
            for p in proxies:
308
 
                p._pyroRelease()
309
 
 
310
 
    def testServerParallelism(self):
311
 
        class ClientThread(threadutil.Thread):
312
 
            def __init__(self, uri, name):
313
 
                super(ClientThread,self).__init__()
314
 
                self.setDaemon(True)
315
 
                self.proxy=Pyro.core.Proxy(uri)
316
 
                self.name=name
317
 
                self.error=True
318
 
                self.proxy._pyroTimeout=5.0
319
 
                self.proxy._pyroBind()
320
 
            def run(self):
321
 
                try:
322
 
                    reply=self.proxy.delayAndId(0.5, self.name)
323
 
                    assert reply=="slept for "+self.name
324
 
                    self.error=False
325
 
                finally:
326
 
                    self.proxy._pyroRelease()
327
 
        threads=[]
328
 
        start=time.time()
329
 
        try:
330
 
            for i in range(6):
331
 
                t=ClientThread(self.objectUri,"t%d" % i)
332
 
                threads.append(t)
333
 
        except:
334
 
            # some exception (probably timeout) while creating clients
335
 
            # try to clean up some connections first
336
 
            for t in threads:
337
 
                t.proxy._pyroRelease()
338
 
            raise  # re-raise the exception
339
 
        for t in threads:
340
 
            t.start()
341
 
        for t in threads:
342
 
            t.join()
343
 
            self.assertFalse(t.error, "all threads should report no errors")
344
 
        del threads
345
 
        duration=time.time()-start
346
 
        if Pyro.config.SERVERTYPE=="select":
347
 
            # select based server doesn't execute calls in parallel,
348
 
            # so 6 threads times 0.5 seconds =~ 3 seconds
349
 
            self.assertTrue(2.5<duration<3.5)
350
 
        else:
351
 
            # thread based server does execute calls in parallel,
352
 
            # so 6 threads taking 0.5 seconds =~ 0.5 seconds passed
353
 
            self.assertTrue(0.3<duration<0.7)
354
 
 
355
 
if os.name!="java":
356
 
    class ServerTestsSelectNoTimeout(ServerTestsThreadNoTimeout):
357
 
        SERVERTYPE="select"
358
 
        COMMTIMEOUT=None
359
 
        def testProxySharing(self):
360
 
            pass
361
 
 
362
 
if __name__ == "__main__":
363
 
    #import sys;sys.argv = ['', 'Test.testName']
364
 
    unittest.main()