Added tests

This commit is contained in:
Fabio Manganiello 2017-12-22 02:11:56 +01:00
parent 4b819d5460
commit 3dfcf0ec97
7 changed files with 138 additions and 27 deletions

View file

@ -34,17 +34,18 @@ class Daemon(object):
""" number of executions retries before a request fails """ """ number of executions retries before a request fails """
n_tries = 2 n_tries = 2
def __init__(self, config_file=None, message_handler=None): def __init__(self, config_file=None, requests_to_process=None):
""" Constructor """ Constructor
Params: Params:
config_file -- Configuration file override (default: None) config_file -- Configuration file override (default: None)
message_handler -- Another function that will receive the messages. requests_to_process -- Exit after processing the specified number
If set, Platypush will just act as a message proxy. Useful to of requests (default: None, loop forever)
embed into other projects, for tests, or for delegating events.
""" """
self.config_file = config_file self.config_file = config_file
self.message_handler = message_handler self.requests_to_process = requests_to_process
self.processed_requests = 0
Config.init(self.config_file) Config.init(self.config_file)
logging.basicConfig(level=Config.get('logging'), stream=sys.stdout) logging.basicConfig(level=Config.get('logging'), stream=sys.stdout)
@ -69,11 +70,6 @@ class Daemon(object):
Params: Params:
msg -- platypush.message.Message instance """ msg -- platypush.message.Message instance """
if self.message_handler:
# Proxy the message
self.message_handler(msg)
return
if isinstance(msg, Request): if isinstance(msg, Request):
logging.info('Processing request: {}'.format(msg)) logging.info('Processing request: {}'.format(msg))
Thread(target=self.run_request(), args=(msg,)).start() Thread(target=self.run_request(), args=(msg,)).start()
@ -122,8 +118,19 @@ class Daemon(object):
logging.info('Dropping response whose request has no ' + logging.info('Dropping response whose request has no ' +
'origin attached: {}'.format(request)) 'origin attached: {}'.format(request))
self.processed_requests += 1
if self.processed_requests >= self.requests_to_process:
self.stop_app()
return _thread_func return _thread_func
def stop_app(self):
for backend in self.backends.values():
backend.stop()
self.bus.stop()
def start(self): def start(self):
""" Start the daemon """ """ Start the daemon """
self.bus = Bus(on_message=self.on_message()) self.bus = Bus(on_message=self.on_message())
@ -140,9 +147,8 @@ class Daemon(object):
self.bus.poll() self.bus.poll()
except KeyboardInterrupt as e: except KeyboardInterrupt as e:
logging.info('SIGINT received, terminating application') logging.info('SIGINT received, terminating application')
finally:
for backend in self.backends.values(): self.stop_app()
backend.stop()
def main(args=sys.argv[1:]): def main(args=sys.argv[1:]):

View file

@ -109,8 +109,8 @@ class Backend(Thread):
**self._get_backend_config(), **self._kwargs) **self._get_backend_config(), **self._kwargs)
# Set the response timeout # Set the response timeout
set_timeout(seconds=self._default_response_timeout, if response_timeout:
on_timeout=_timeout_hndl) set_timeout(seconds=response_timeout, on_timeout=_timeout_hndl)
resp_backend.start() resp_backend.start()
@ -136,7 +136,7 @@ class Backend(Thread):
request.origin = self.device_id request.origin = self.device_id
if on_response and response_timeout: if on_response and response_timeout != 0:
self._setup_response_handler(request, on_response, response_timeout) self._setup_response_handler(request, on_response, response_timeout)
self.send_message(request, **kwargs) self.send_message(request, **kwargs)

View file

@ -2,10 +2,12 @@ import logging
import json import json
import os import os
import time import time
import threading
from .. import Backend from .. import Backend
from platypush.message import Message from platypush.message import Message
from platypush.message.event import StopEvent
from platypush.message.request import Request from platypush.message.request import Request
from platypush.message.response import Response from platypush.message.response import Response
@ -32,6 +34,7 @@ class LocalBackend(Backend):
else self.request_fifo else self.request_fifo
msg = '{}\n'.format(str(msg)).encode('utf-8') msg = '{}\n'.format(str(msg)).encode('utf-8')
with open(fifo, 'wb') as f: with open(fifo, 'wb') as f:
f.write(msg) f.write(msg)
@ -44,14 +47,6 @@ class LocalBackend(Backend):
return Message.build(msg) if len(msg) else None return Message.build(msg) if len(msg) else None
def on_stop(self):
try: os.remove(self.request_fifo)
except: pass
try: os.remove(self.response_fifo)
except: pass
def run(self): def run(self):
super().run() super().run()
logging.info('Initialized local backend on {} and {}'. logging.info('Initialized local backend on {} and {}'.
@ -66,8 +61,7 @@ class LocalBackend(Backend):
time.sleep(0.2) time.sleep(0.2)
continue continue
# logging.debug('Received message on the local backend: {}'.format(msg)) logging.debug('Received message on the local backend: {}, thread_id: '.format(msg, self.thread_id))
logging.info('Received message on the local backend: {}'.format(msg))
if self.should_stop(): break if self.should_stop(): break
self.on_message(msg) self.on_message(msg)

View file

@ -2,10 +2,12 @@ import os
import sys import sys
import signal import signal
import logging import logging
import threading
from enum import Enum from enum import Enum
from queue import Queue from queue import Queue
from platypush.config import Config
from platypush.message.event import Event, StopEvent from platypush.message.event import Event, StopEvent
class Bus(object): class Bus(object):
@ -14,6 +16,7 @@ class Bus(object):
def __init__(self, on_message=None): def __init__(self, on_message=None):
self.bus = Queue() self.bus = Queue()
self.on_message = on_message self.on_message = on_message
self.thread_id = threading.get_ident()
def post(self, msg): def post(self, msg):
""" Sends a message to the bus """ """ Sends a message to the bus """
@ -23,6 +26,14 @@ class Bus(object):
""" Reads one message from the bus """ """ Reads one message from the bus """
return self.bus.get() return self.bus.get()
def stop(self):
""" Stops the bus by sending a STOP event """
evt = StopEvent(target=Config.get('device_id'),
origin=Config.get('device_id'),
thread_id=self.thread_id)
self.bus.put(evt)
def poll(self): def poll(self):
""" """
Reads messages from the bus until either stop event message or KeyboardInterrupt Reads messages from the bus until either stop event message or KeyboardInterrupt
@ -38,7 +49,7 @@ class Bus(object):
self.on_message(msg) self.on_message(msg)
if isinstance(msg, StopEvent) and msg.targets_me(): if isinstance(msg, StopEvent) and msg.targets_me():
logging.info('Received STOP event') logging.info('Received STOP event on the bus')
stop=True stop=True

11
run_test.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/bash
PYTHON=python
for testcase in tests/test_*.py
do
$PYTHON -m unittest $testcase
done
# vim:sw=4:ts=4:et:

20
tests/context.py Normal file
View file

@ -0,0 +1,20 @@
import os
import sys
testdir = os.path.dirname(__file__)
sys.path.insert(0, os.path.abspath(os.path.join(testdir, '..')))
config_file = os.path.join(testdir, 'etc', 'config.yaml')
from platypush.config import Config
Config.init(config_file)
import platypush
class TestTimeoutException(RuntimeError):
def __init__(self, msg):
self.msg = msg
# vim:sw=4:ts=4:et:

69
tests/test_local.py Normal file
View file

@ -0,0 +1,69 @@
from .context import platypush, config_file, TestTimeoutException
import os
import sys
import logging
import unittest
import threading
from threading import Thread
from platypush import Daemon
from platypush.config import Config
from platypush.pusher import Pusher
from platypush.utils import set_timeout, clear_timeout
class TestLocal(unittest.TestCase):
timeout = 5
def setUp(self):
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
backends = Config.get_backends()
self.assertTrue('local' in backends)
def test_local_shell_exec_flow(self):
self.start_sender()
self.start_receiver()
def on_response(self):
def _f(response):
logging.info("Received response: {}".format(response))
self.assertEqual(response.output.strip(), 'ping')
# os._exit(0)
return _f
def on_timeout(self, msg):
def _f(): raise TestTimeoutException(msg)
return _f
def start_sender(self):
def _run_sender():
pusher = Pusher(config_file=config_file, backend='local',
on_response=self.on_response())
logging.info('Sending request')
pusher.push(target=Config.get('device_id'), action='shell.exec',
cmd='echo ping', timeout=None)
# Start the sender thread and wait for a response
set_timeout(seconds=self.timeout,
on_timeout=self.on_timeout('Receiver response timed out'))
self.sender = Thread(target=_run_sender)
self.sender.start()
def start_receiver(self):
set_timeout(seconds=self.timeout,
on_timeout=self.on_timeout('Sender request timed out'))
self.receiver = Daemon(config_file=config_file, requests_to_process=1)
self.receiver.start()
if __name__ == '__main__':
unittest.main()
# vim:sw=4:ts=4:et: