Skip to content

Commit

Permalink
added resource tracking unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Sep 29, 2017
1 parent 41ec167 commit 85a1a49
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 6 deletions.
10 changes: 6 additions & 4 deletions examples/resourcetracking/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ def clientDisconnect(self, conn):
# this method is called by Pyro itself once the client connection gets closed.
# In this example this override is only used to print out some info.
print("client disconnects:", conn.sock.getpeername())
print(" resources: ", set(conn.tracked_resources))
print(" resources: ", [r.name for r in conn.tracked_resources])


class Resource(object):
# a fictional resource that gets allocated and must be freed again later.
def __init__(self, name):
def __init__(self, name, collection):
self.name = name
self.collection = collection

def close(self):
# Pyro will call this on a tracked resource once the client's connection gets closed!
print("Resource: closing", self.name)
self.collection.discard(self)


@Pyro4.expose
Expand All @@ -30,7 +32,7 @@ def __init__(self):
self.resources = set() # the allocated resources

def allocate(self, name):
resource = Resource(name)
resource = Resource(name, self.resources)
self.resources.add(resource)
Pyro4.current_context.track_resource(resource)

Expand All @@ -42,7 +44,7 @@ def free(self, name):
Pyro4.current_context.untrack_resource(r)

def list(self):
return self.resources
return [r.name for r in self.resources]


with CustomDaemon() as daemon:
Expand Down
19 changes: 19 additions & 0 deletions tests/PyroTests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,25 @@ def testProxySerializedBlobArg(self):
self.assertEqual("blobname", blobinfo)
self.assertEqual([1, 2, 3], blobdata)

def testResourceFreeing(self):
rsvc = ResourceService()
uri = self.daemon.register(rsvc)
with Pyro4.core.Proxy(uri) as p:
p.allocate("r1")
p.allocate("r2")
resources = {r.name: r for r in rsvc.resources}
p.free("r1")
rsc = p.list()
self.assertEqual(["r2"], rsc)
self.assertTrue(resources["r1"].close_called)
self.assertFalse(resources["r2"].close_called)
time.sleep(0.02)
self.assertTrue(resources["r1"].close_called)
self.assertTrue(resources["r2"].close_called)
with Pyro4.core.Proxy(uri) as p:
rsc = p.list()
self.assertEqual([], rsc, "r2 must now be freed due to connection loss earlier")


class ServerTestsThreadNoTimeout(unittest.TestCase):
SERVERTYPE = "thread"
Expand Down
39 changes: 37 additions & 2 deletions tests/PyroTests/testsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import sys
import pickle
import threading
from Pyro4 import errors, core
from Pyro4 import errors, core, expose, behavior, current_context
from Pyro4.configuration import config


__all__ = ["tobytes", "tostring", "unicode", "unichr", "basestring", "StringIO",
"NonserializableError", "MyThingPartlyExposed", "MyThingFullExposed",
"MyThingExposedSub", "MyThingPartlyExposedSub", "ConnectionMock",
"AtomicCounter"]
"AtomicCounter", "ResourceService", "Resource"]


config.reset(False) # reset the config to default
Expand Down Expand Up @@ -257,3 +257,38 @@ def decr(self, amount=1):
@property
def value(self):
return self.__value


class Resource(object):
# a fictional resource that gets allocated and must be freed again later.
def __init__(self, name, collection):
self.name = name
self.collection = collection
self.close_called = False

def close(self):
# Pyro will call this on a tracked resource once the client's connection gets closed!
self.collection.discard(self)
self.close_called = True


@expose
@behavior(instance_mode="single")
class ResourceService(object):
def __init__(self):
self.resources = set() # the allocated resources

def allocate(self, name):
resource = Resource(name, self.resources)
self.resources.add(resource)
current_context.track_resource(resource)

def free(self, name):
resources = {r for r in self.resources if r.name == name}
self.resources -= resources
for r in resources:
r.close()
current_context.untrack_resource(r)

def list(self):
return [r.name for r in self.resources]

0 comments on commit 85a1a49

Please sign in to comment.