# Path: osbrain/agent.py
# def run_agent(
#     name='',
#     nsaddr=None,
#     addr=None,
#     base=Agent,
#     serializer=None,
#     transport=None,
#     safe=None,
#     attributes=None,
# ):
#     """
#     Ease the agent creation process.
# 
#     This function will create a new agent, start the process and then run
#     its main loop through a proxy.
# 
#     Parameters
#     ----------
#     name : str, default is ''
#         Agent name or alias.
#     nsaddr : SocketAddress, default is None
#         Name server address.
#     addr : SocketAddress, default is None
#         New agent address, if it is to be fixed.
#     transport : str, AgentAddressTransport, default is None
#         Transport protocol.
#     safe : bool, default is None
#         Use safe calls by default from the Proxy.
#     attributes : dict, default is None
#         A dictionary that defines initial attributes for the agent.
# 
#     Returns
#     -------
#     proxy
#         A proxy to the new agent.
#     """
#     if not nsaddr:
#         nsaddr = os.environ.get('OSBRAIN_NAMESERVER_ADDRESS')
#     agent = AgentProcess(
#         name=name,
#         nsaddr=nsaddr,
#         addr=addr,
#         base=base,
#         serializer=serializer,
#         transport=transport,
#         attributes=attributes,
#     )
#     agent_name = agent.start()
# 
#     proxy = Proxy(agent_name, nsaddr, safe=safe)
#     proxy.run()
#     proxy.wait_for_running()
# 
#     return proxy
# 
# Path: osbrain/address.py
# class AgentAddressSerializer(str):
#     """
#     Agent's address serializer class.
# 
#     Each communication channel will have a serializer.
# 
#     Note that for ``raw`` message passing, everything must be on bytes, and the
#     programmer is the one responsible for converting data to bytes.
# 
#     Parameters
#     ----------
#     serializer_type : str
#         Serializer type (i.e.: 'raw', 'pickle', 'cloudpickle', 'dill', 'json').
#     """
# 
#     SERIALIZER_SIMPLE = ('raw',)
#     SERIALIZER_SEPARATOR = ('pickle', 'cloudpickle', 'dill', 'json')
# 
#     def __new__(cls, value):
#         if value not in cls.SERIALIZER_SIMPLE + cls.SERIALIZER_SEPARATOR:
#             raise ValueError('Invalid serializer type %s!' % value)
#         return super().__new__(cls, value)
# 
#     def __init__(self, value):
#         self.requires_separator = value in self.SERIALIZER_SEPARATOR
# 
# Path: osbrain/helper.py
# def last_received_endswith(agent, tail):
#     """
#     Check if the agent's last received message ends with `tail`.
# 
#     It is supposed to be executed as an agent method (in example: use it as
#     the condition in `wait_agent_condition` or execute it with the method
#     `execute_as_method`).
# 
#     Parameters
#     ----------
#     agent : Proxy
#         A proxy to the agent.
#     tail : str or bytes
#         The expected termination of the last received message.
# 
#     Returns
#     -------
#     bool
#         Whether the last message received ends with `tail`.
#     """
#     if not hasattr(agent, 'received'):
#         return False
#     if not agent.received:
#         return False
#     if not agent.received[-1][-len(tail) :] == tail:
#         return False
#     return True
# 
# Path: osbrain/helper.py
# def wait_agent_condition(agent, condition, *args, timeout=3, **kwargs):
#     """
#     Wait for an agent's condition to be true.
# 
#     The condition is passed as a function which must take, at least, the
#     actual agent as a parameter, and must evaluate to a boolean result.
# 
#     Parameters
#     ----------
#     agent : Proxy
#         A proxy to the agent.
#     condition : Callable
#         A function that evaluates the desired condition.
#     timeout : float, default is 3
#         After this number of seconds the function will return `False`.
# 
#     Returns
#     -------
#     bool
#         Whether the specified condition was True.
#     """
#     return wait_condition(
#         agent.execute_as_method, condition, *args, timeout=timeout, **kwargs
#     )
# 
# Path: osbrain/tests/common.py
# def append_received(agent, message, topic=None):
#     agent.received.append(message)


import pytest
from osbrain import run_agent
from osbrain.address import AgentAddressSerializer
from osbrain.helper import last_received_endswith
from osbrain.helper import wait_agent_condition
from .common import append_received




@pytest.mark.parametrize(
    'serializer', AgentAddressSerializer.SERIALIZER_SEPARATOR
)
def test_pubsub_topics_separator(nsproxy, serializer):
    """
    Simple publisher-subscriber pattern test using serializers that
    require a separation in message composition.

    Different messages sent with different agents subscribed to different
    topics are tested within this method.
    """
    a0 = run_agent('a0')
    a1 = run_agent('a1')
    a2 = run_agent('a2')
    a3 = run_agent('a3')
    a4 = run_agent('a4')
    a5 = run_agent('a5')

    for agent in (a1, a2, a3, a4, a5):
        agent.set_attr(received=[])

    addr = a0.bind('PUB', alias='pub', serializer=serializer)


# Path: osbrain/agent.py
# def run_agent(
#     name='',
#     nsaddr=None,
#     addr=None,
#     base=Agent,
#     serializer=None,
#     transport=None,
#     safe=None,
#     attributes=None,
# ):
#     """
#     Ease the agent creation process.
# 
#     This function will create a new agent, start the process and then run
#     its main loop through a proxy.
# 
#     Parameters
#     ----------
#     name : str, default is ''
#         Agent name or alias.
#     nsaddr : SocketAddress, default is None
#         Name server address.
#     addr : SocketAddress, default is None
#         New agent address, if it is to be fixed.
#     transport : str, AgentAddressTransport, default is None
#         Transport protocol.
#     safe : bool, default is None
#         Use safe calls by default from the Proxy.
#     attributes : dict, default is None
#         A dictionary that defines initial attributes for the agent.
# 
#     Returns
#     -------
#     proxy
#         A proxy to the new agent.
#     """
#     if not nsaddr:
#         nsaddr = os.environ.get('OSBRAIN_NAMESERVER_ADDRESS')
#     agent = AgentProcess(
#         name=name,
#         nsaddr=nsaddr,
#         addr=addr,
#         base=base,
#         serializer=serializer,
#         transport=transport,
#         attributes=attributes,
#     )
#     agent_name = agent.start()
# 
#     proxy = Proxy(agent_name, nsaddr, safe=safe)
#     proxy.run()
#     proxy.wait_for_running()
# 
#     return proxy
# 
# Path: osbrain/address.py
# class AgentAddressSerializer(str):
#     """
#     Agent's address serializer class.
# 
#     Each communication channel will have a serializer.
# 
#     Note that for ``raw`` message passing, everything must be on bytes, and the
#     programmer is the one responsible for converting data to bytes.
# 
#     Parameters
#     ----------
#     serializer_type : str
#         Serializer type (i.e.: 'raw', 'pickle', 'cloudpickle', 'dill', 'json').
#     """
# 
#     SERIALIZER_SIMPLE = ('raw',)
#     SERIALIZER_SEPARATOR = ('pickle', 'cloudpickle', 'dill', 'json')
# 
#     def __new__(cls, value):
#         if value not in cls.SERIALIZER_SIMPLE + cls.SERIALIZER_SEPARATOR:
#             raise ValueError('Invalid serializer type %s!' % value)
#         return super().__new__(cls, value)
# 
#     def __init__(self, value):
#         self.requires_separator = value in self.SERIALIZER_SEPARATOR
# 
# Path: osbrain/helper.py
# def last_received_endswith(agent, tail):
#     """
#     Check if the agent's last received message ends with `tail`.
# 
#     It is supposed to be executed as an agent method (in example: use it as
#     the condition in `wait_agent_condition` or execute it with the method
#     `execute_as_method`).
# 
#     Parameters
#     ----------
#     agent : Proxy
#         A proxy to the agent.
#     tail : str or bytes
#         The expected termination of the last received message.
# 
#     Returns
#     -------
#     bool
#         Whether the last message received ends with `tail`.
#     """
#     if not hasattr(agent, 'received'):
#         return False
#     if not agent.received:
#         return False
#     if not agent.received[-1][-len(tail) :] == tail:
#         return False
#     return True
# 
# Path: osbrain/helper.py
# def wait_agent_condition(agent, condition, *args, timeout=3, **kwargs):
#     """
#     Wait for an agent's condition to be true.
# 
#     The condition is passed as a function which must take, at least, the
#     actual agent as a parameter, and must evaluate to a boolean result.
# 
#     Parameters
#     ----------
#     agent : Proxy
#         A proxy to the agent.
#     condition : Callable
#         A function that evaluates the desired condition.
#     timeout : float, default is 3
#         After this number of seconds the function will return `False`.
# 
#     Returns
#     -------
#     bool
#         Whether the specified condition was True.
#     """
#     return wait_condition(
#         agent.execute_as_method, condition, *args, timeout=timeout, **kwargs
#     )
# 
# Path: osbrain/tests/common.py
# def append_received(agent, message, topic=None):
#     agent.received.append(message)


# Path: osbrain/tests/test_agent_pubsub_topics.py
import pytest
from osbrain import run_agent
from osbrain.address import AgentAddressSerializer
from osbrain.helper import last_received_endswith
from osbrain.helper import wait_agent_condition
from .common import append_received





@pytest.mark.parametrize(
    'serializer', AgentAddressSerializer.SERIALIZER_SEPARATOR
)
def test_pubsub_topics_separator(nsproxy, serializer):
    """
    Simple publisher-subscriber pattern test using serializers that
    require a separation in message composition.

    Different messages sent with different agents subscribed to different
    topics are tested within this method.
    """
    a0 = run_agent('a0')
    a1 = run_agent('a1')
    a2 = run_agent('a2')
    a3 = run_agent('a3')
    a4 = run_agent('a4')
    a5 = run_agent('a5')

    for agent in (a1, a2, a3, a4, a5):
        agent.set_attr(received=[])

    addr = a0.bind('PUB', alias='pub', serializer=serializer)


    a1.connect(addr, handler=append_received)