Repository: opensistemas-hub/osbrain
Pull request #119 (2017-05-09 09:13:00)

Little changes
- In the docs `conf.py` file.
- In the `logger_received()` helper function, to accept regular expressions.


Patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
index f50aaa8..d67cb89 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -54,16 +54,16 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'osBrain'
-copyright = u'2016, Open Sistemas de Información Internet S.L.'
+copyright = u'Open Sistemas de Información Internet S.L.'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
-# The short X.Y version.
-version = osbrain.__version__.split('-')[0]
 # The full version, including alpha/beta/rc tags.
 release = osbrain.__version__
+# The short X.Y version.
+version = release.split('-')[0]
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/osbrain/helper.py b/osbrain/helper.py
index 48f49cc..bcc6526 100644
--- a/osbrain/helper.py
+++ b/osbrain/helper.py
@@ -1,11 +1,28 @@
 """
 Helper functions for osbrain (usually for testing purposes).
 """
+import re
 import time
 from uuid import uuid4
 
 
-def logger_received(logger, log_name, message, timeout=1.):
+def regex_count_in_list(regex, strings):
+    """
+    Returns
+    -------
+    int
+        The number of times a regular expression was found in a list of
+        strings.
+    """
+    matches = 0
+    for candidate in strings:
+        if re.findall(regex, candidate, re.DOTALL):
+            matches += 1
+    return matches
+
+
+def logger_received(logger, message, log_name='log_history_info',
+                    position=None, timeout=1.):
     """
     Check if a logger receives a message.
 
@@ -13,27 +30,34 @@ def logger_received(logger, log_name, message, timeout=1.):
     ----------
     logger : Proxy
         Proxy to the logger.
-    log_name : str
+    log_name : str, default is `'log_history_info'`
         The name of the attribue to look for in the logger.
     message : anything
-        Message to look for in the log. Can be a partial match.
+        Message to look for in the log. Can be a partial match. Regular
+        expressions are allowed.
+    position : int, default is None
+        Where to look for the message in the log. If not set, the message
+        will be searched for through all the log.
     timeout : float
         After this number of seconds the function will return `False`.
 
     Returns
     -------
-    bool
-        Whether the logger received the message or not.
+    int
+        The number of times the logger received a message that matched the
+        expression. Can be higher than 1 if `position` is not set.
     """
     t0 = time.time()
     while True:
         time.sleep(0.01)
         log_history = logger.get_attr(log_name)
-        if len(log_history) and message in log_history[-1]:
-            break
+        if position is not None:
+            log_history = [log_history[position]]
+        matches = regex_count_in_list(message, log_history)
+        if matches:
+            return matches
         if timeout and time.time() - t0 > timeout:
-            return False
-    return True
+            return 0
 
 
 def sync_agent_logger(agent, logger):


Test patch:
diff --git a/osbrain/tests/common.py b/osbrain/tests/common.py
index 5fbf2bc..944c658 100644
--- a/osbrain/tests/common.py
+++ b/osbrain/tests/common.py
@@ -1,5 +1,9 @@
 import pytest
+
+from osbrain import run_agent
+from osbrain import run_logger
 from osbrain import run_nameserver
+from osbrain.helper import sync_agent_logger
 
 
 @pytest.fixture(scope='function')
@@ -7,3 +11,14 @@ def nsproxy(request):
     ns = run_nameserver()
     yield ns
     ns.shutdown()
+
+
+@pytest.fixture(scope='function')
+def agent_logger(request):
+    ns = run_nameserver()
+    agent = run_agent('a0')
+    logger = run_logger('logger')
+    agent.set_logger(logger)
+    sync_agent_logger(agent=agent, logger=logger)
+    yield agent, logger
+    ns.shutdown()
diff --git a/osbrain/tests/test_agent.py b/osbrain/tests/test_agent.py
index 1fb2b55..c591122 100644
--- a/osbrain/tests/test_agent.py
+++ b/osbrain/tests/test_agent.py
@@ -442,28 +442,28 @@ def test_log_levels(nsproxy):
     # Log info
     message = str(uuid4())
     agent.log_info(message)
-    assert logger_received(logger, 'log_history_info', message)
+    assert logger_received(logger, message, log_name='log_history_info')
     # Log warning
     message = str(uuid4())
     agent.log_warning(message)
-    assert logger_received(logger, 'log_history_warning', message)
+    assert logger_received(logger, message, log_name='log_history_warning')
     # Log error
     message = str(uuid4())
     agent.log_error(message)
-    assert logger_received(logger, 'log_history_error', message)
+    assert logger_received(logger, message, log_name='log_history_error')
     # Log debug
     message = str(uuid4())
     agent.set_attr(_DEBUG=True)
     agent.log_debug(message)
-    assert logger_received(logger, 'log_history_debug', message)
+    assert logger_received(logger, message, log_name='log_history_debug')
     message = str(uuid4())
     agent.set_attr(_DEBUG=False)
     agent.log_debug(message)
-    assert not logger_received(logger, 'log_history_debug', message)
+    assert not logger_received(logger, message, log_name='log_history_debug')
     message = str(uuid4())
     agent.set_attr(_DEBUG=True)
     agent.log_debug(message)
-    assert logger_received(logger, 'log_history_debug', message)
+    assert logger_received(logger, message, log_name='log_history_debug')
 
 
 def test_running_exception(nsproxy):
@@ -481,7 +481,7 @@ def test_running_exception(nsproxy):
     with pytest.raises(RuntimeError):
         agent.raise_exception()
     message = 'User raised an exception'
-    assert logger_received(logger, 'log_history_error', message)
+    assert logger_received(logger, message, log_name='log_history_error')
     assert not agent.get_attr('running')
 
 
diff --git a/osbrain/tests/test_agent_req_rep.py b/osbrain/tests/test_agent_req_rep.py
index 4cfaa9d..0ff146e 100644
--- a/osbrain/tests/test_agent_req_rep.py
+++ b/osbrain/tests/test_agent_req_rep.py
@@ -88,6 +88,6 @@ def test_multiple_yield(nsproxy):
     # Response is received successfully
     assert response == 'Hello world!'
     # Replier should crash
-    assert logger_received(logger, 'log_history_error',
+    assert logger_received(logger, log_name='log_history_error',
                            message='yielded more than once')
     assert agent_dies(a0, nsproxy)
diff --git a/osbrain/tests/test_helper.py b/osbrain/tests/test_helper.py
index d2d0ec9..eae2a0f 100644
--- a/osbrain/tests/test_helper.py
+++ b/osbrain/tests/test_helper.py
@@ -4,15 +4,14 @@ Test file for functionality implemented in `osbrain/tests/common.py`.
 import pytest
 
 from osbrain import run_agent
-from osbrain import run_logger
 from osbrain import Agent
 from osbrain.helper import logger_received
-from osbrain.helper import sync_agent_logger
 from osbrain.helper import agent_dies
 from osbrain.helper import attribute_match
 from osbrain.helper import wait_agent_attr
 
 from common import nsproxy  # pragma: no flakes
+from common import agent_logger  # pragma: no flakes
 
 
 def test_agent_dies(nsproxy):
@@ -24,29 +23,79 @@ def test_agent_dies(nsproxy):
     assert not agent_dies('a0', nsproxy, timeout=0.5)
 
 
-def test_sync_agent_logger(nsproxy):
+def test_sync_agent_logger(agent_logger):
     """
     After synchronizing and agent and a logger, a message logged should
     always be received by the logger.
     """
-    a0 = run_agent('a0')
-    logger = run_logger('logger')
-    a0.set_logger(logger)
-    sync_agent_logger(agent=a0, logger=logger)
+    a0, logger = agent_logger
     a0.log_info('asdf')
-    assert logger_received(logger, 'log_history_info', message='asdf')
+    assert logger_received(logger, message='asdf')
 
 
-def test_logger_received(nsproxy):
+def test_logger_received(agent_logger):
     """
     The function `logger_received` should return `False` if the message is
     not received after a timeout.
     """
-    a0 = run_agent('a0')
-    logger = run_logger('logger')
-    a0.set_logger(logger)
-    sync_agent_logger(agent=a0, logger=logger)
-    assert not logger_received(logger, 'log_history_error', message='asdf')
+    a0, logger = agent_logger
+    assert not logger_received(logger, 'asdf', log_name='log_history_error')
+
+
+def test_logger_received_position(agent_logger):
+    """
+    The function `logger_received` should accept a parameter to specify the
+    exact position where the regular expression should be matching.
+    """
+    a0, logger = agent_logger
+    a0.log_info('m0')
+    a0.log_info('m1')
+    a0.log_info('m2')
+    # Any position
+    assert logger_received(logger, message='m2')
+    assert logger_received(logger, message='m1')
+    assert logger_received(logger, message='m0')
+    # -1 position
+    assert logger_received(logger, message='m2', position=-1, timeout=0.1)
+    assert not logger_received(logger, message='m1', position=-1, timeout=0.1)
+    assert not logger_received(logger, message='m0', position=-1, timeout=0.1)
+    # -2 position
+    assert not logger_received(logger, message='m2', position=-2, timeout=0.1)
+    assert logger_received(logger, message='m1', position=-2, timeout=0.1)
+    assert not logger_received(logger, message='m0', position=-2, timeout=0.1)
+    # 0 position (important to test vs. None)
+    assert not logger_received(logger, message='m2', position=0, timeout=0.1)
+    assert not logger_received(logger, message='m1', position=0, timeout=0.1)
+    assert not logger_received(logger, message='m0', position=0, timeout=0.1)
+
+
+def test_logger_received_newline(agent_logger):
+    """
+    The `'.'` special character in `logger_received` regular expressions
+    should match newline characters too.
+    """
+    a0, logger = agent_logger
+    a0.log_info('foo\nbar')
+    assert logger_received(logger, message='foo.*bar')
+
+
+def test_logger_received_count(agent_logger):
+    """
+    The function `logger_received` actually returns an integer with the total
+    number of matches.
+    """
+    a0, logger = agent_logger
+    a0.log_info('foo bar')
+    a0.log_info('foo beer')
+    a0.log_info('foo asdf bar')
+    # Make sure logger receives the last message
+    assert logger_received(logger, message='foo asdf bar')
+    # Start counting...
+    assert logger_received(logger, message='foo') == 3
+    assert logger_received(logger, message='foo b') == 2
+    assert logger_received(logger, message='foo beer') == 1
+    assert logger_received(logger, message='bar') == 2
+    assert logger_received(logger, message='foo.*bar') == 2
 
 
 @pytest.mark.parametrize('attribute,length,data,value,match', [