[pytango] 72/122: Get test context port by decoding the ds IOR

Sandor Bodo-Merle sbodomerle-guest at moszumanska.debian.org
Thu Sep 28 19:18:19 UTC 2017


This is an automated email from the git hooks/post-receive script.

sbodomerle-guest pushed a commit to tag v9.2.1
in repository pytango.

commit cafce2234289496c4e669e06f951b127cad73b00
Author: Vincent Michel <vincent.michel at maxlab.lu.se>
Date:   Mon Oct 17 19:42:01 2016 +0200

    Get test context port by decoding the ds IOR
---
 tango/test_context.py | 122 ++++++++++++++++++++++++++------------------------
 1 file changed, 64 insertions(+), 58 deletions(-)

diff --git a/tango/test_context.py b/tango/test_context.py
index 57e3372..a6aec05 100644
--- a/tango/test_context.py
+++ b/tango/test_context.py
@@ -6,15 +6,11 @@ __all__ = ["DeviceTestContext", "run_device_test_context"]
 
 # Imports
 import os
-import time
-import socket
-import platform
+import six
+import struct
 import tempfile
-import functools
-
-# Concurrency imports
-from threading import Thread
-from multiprocessing import Process
+import threading
+import collections
 
 # CLI imports
 from ast import literal_eval
@@ -23,38 +19,41 @@ from argparse import ArgumentParser
 
 # Local imports
 from .server import run
-from . import DeviceProxy, Database, ConnectionFailed, DevFailed
+from . import DeviceProxy, Database, Util
 
 
 # Helpers
 
-def retry(period, errors, pause=0.001):
-    """Retry decorator."""
-    errors = tuple(errors)
-
-    def dec(func):
-        @functools.wraps(func)
-        def wrapper(*args, **kwargs):
-            stop = time.time() + period
-            first = True
-            while first or time.time() < stop:
-                time.sleep(pause)
-                try:
-                    return func(*args, **kwargs)
-                except errors as exc:
-                    e = exc
-                    first = False
-            raise e
-        return wrapper
-    return dec
-
-
-def get_port():
-    sock = socket.socket()
-    sock.bind(('', 0))
-    res = sock.getsockname()[1]
-    del sock
-    return res
+IOR = collections.namedtuple(
+    'IOR',
+    'first dtype_length dtype nb_profile tag '
+    'length major minor wtf host_length host port body')
+
+
+def ascii_to_bytes(s):
+    convert = lambda x: six.int2byte(int(x, 16))
+    return b''.join(convert(s[i:i+2]) for i in range(0, len(s), 2))
+
+
+def parse_ior(encoded_ior):
+    assert encoded_ior[:4] == 'IOR:'
+    ior = ascii_to_bytes(encoded_ior[4:])
+    dtype_length = struct.unpack_from('II', ior)[-1]
+    form = 'II{:d}sIIIBBHI'.format(dtype_length)
+    host_length = struct.unpack_from(form, ior)[-1]
+    form = 'II{:d}sIIIBBHI{:d}sH0I'.format(dtype_length, host_length)
+    values = struct.unpack_from(form, ior)
+    values += (ior[struct.calcsize(form):],)
+    strip = lambda x: x[:-1] if isinstance(x, bytes) else x
+    return IOR(*map(strip, values))
+
+
+def get_server_host_port():
+    util = Util.instance()
+    ds = util.get_dserver_device()
+    encoded_ior = util.get_dserver_ior(ds)
+    ior = parse_ior(encoded_ior)
+    return ior.host.decode(), ior.port
 
 
 def literal_dict(arg):
@@ -73,14 +72,14 @@ def device(path):
 class DeviceTestContext(object):
     """ Context to run a device without a database."""
 
-    nodb = "#dbase=no"
+    nodb = "dbase=no"
     command = "{0} {1} -ORBendPoint giop:tcp::{2} -file={3}"
-    connect_timeout = 6.0
+    connect_timeout = 1.0
     disconnect_timeout = connect_timeout
 
     def __init__(self, device, device_cls=None, server_name=None,
                  instance_name=None, device_name=None, properties={},
-                 db=None, port=0, debug=3, daemon=False, process=False):
+                 db=None, port=0, debug=3, daemon=False):
         """Inititalize the context to run a given device."""
         # Argument
         tangoclass = device.__name__
@@ -90,17 +89,16 @@ class DeviceTestContext(object):
             instance_name = server_name.lower()
         if not device_name:
             device_name = 'test/nodb/' + server_name.lower()
-        if not port:
-            port = get_port()
         if db is None:
             _, db = tempfile.mkstemp()
         # Attributes
         self.db = db
+        self.host = ''
         self.port = port
         self.device_name = device_name
         self.server_name = "/".join(("dserver", server_name, instance_name))
-        self.host = "{0}:{1}/".format(platform.node(), self.port)
         self.device = self.server = None
+        self.waiter = threading.Event()
         # File
         self.generate_db_file(server_name, instance_name, device_name,
                               tangoclass, properties)
@@ -119,10 +117,15 @@ class DeviceTestContext(object):
             target = device.run_server
             args = (cmd_args,)
         # Thread
-        cls = Process if process else Thread
-        self.thread = cls(target=target, args=args)
+        cls = threading.Thread
+        kwargs = {'post_init_callback': self.post_init}
+        self.thread = cls(target=target, args=args, kwargs=kwargs)
         self.thread.daemon = daemon
 
+    def post_init(self):
+        self.host, self.port = get_server_host_port()
+        self.waiter.set()
+
     def generate_db_file(self, server, instance, device,
                          tangoclass=None, properties={}):
         """Generate a database file corresponding to the given arguments."""
@@ -134,7 +137,7 @@ class DeviceTestContext(object):
             f.write(': "' + device + '"\n')
         # Create database
         db = Database(self.db)
-        # Patched the property dict to avoid a PyTango bug
+        # Patch the property dict to avoid a PyTango bug
         patched = dict((key, value if value != '' else ' ')
                        for key, value in properties.items())
         # Write properties
@@ -143,11 +146,13 @@ class DeviceTestContext(object):
 
     def get_device_access(self):
         """Return the full device name."""
-        return self.host+self.device_name+self.nodb
+        form = 'tango://{0}:{1}/{2}#{3}'
+        return form.format(self.host, self.port, self.device_name, self.nodb)
 
     def get_server_access(self):
         """Return the full server name."""
-        return self.host+self.server_name+self.nodb
+        form = 'tango://{0}:{1}/{2}#{3}'
+        return form.format(self.host, self.port, self.server_name, self.nodb)
 
     def start(self):
         """Run the server."""
@@ -155,26 +160,27 @@ class DeviceTestContext(object):
         self.connect()
         return self
 
-    @retry(connect_timeout, [ConnectionFailed, DevFailed])
     def connect(self):
-        if not self.thread.is_alive():
+        if not self.waiter.wait(self.connect_timeout):
             raise RuntimeError(
-                'The server did not start. Check stdout for more information.')
-        self.device = DeviceProxy(self.get_device_access())
-        self.device.ping()
+                'The server did not start. '
+                'Check stdout/stderr for more information.')
+        # Get server proxy
+        print(self.get_server_access())
         self.server = DeviceProxy(self.get_server_access())
         self.server.ping()
+        # Get device proxy
+        self.device = DeviceProxy(self.get_device_access())
+        self.device.ping()
 
-    def stop(self, timeout=None):
+    def stop(self):
         """Kill the server."""
         if self.server:
             self.server.command_inout('Kill')
-        self.join(timeout)
+        self.join(self.disconnect_timeout)
         os.unlink(self.db)
 
     def join(self, timeout=None):
-        if timeout is None:
-            timeout = self.disconnect_timeout
         self.thread.join(timeout)
 
     def __enter__(self):
@@ -200,10 +206,10 @@ def parse_command_line_args(args=None):
                         type=device, help=msg)
     msg = "The port to use."
     parser.add_argument('--port', metavar='PORT',
-                        type=int, help=msg, default=0)
+                        type=int, help=msg, default=8888)
     msg = "The debug level."
     parser.add_argument('--debug', metavar='DEBUG',
-                        type=int, help=msg, default=0)
+                        type=int, help=msg, default=3)
     msg = "The properties to set as python dict."
     parser.add_argument('--prop', metavar='PROP',
                         type=literal_dict, help=msg, default='{}')

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pytango.git



More information about the debian-science-commits mailing list