forked from platypush/platypush
Added tests
This commit is contained in:
parent
4b819d5460
commit
3dfcf0ec97
7 changed files with 138 additions and 27 deletions
|
@ -34,17 +34,18 @@ class Daemon(object):
|
|||
""" number of executions retries before a request fails """
|
||||
n_tries = 2
|
||||
|
||||
def __init__(self, config_file=None, message_handler=None):
|
||||
def __init__(self, config_file=None, requests_to_process=None):
|
||||
""" Constructor
|
||||
Params:
|
||||
config_file -- Configuration file override (default: None)
|
||||
message_handler -- Another function that will receive the messages.
|
||||
If set, Platypush will just act as a message proxy. Useful to
|
||||
embed into other projects, for tests, or for delegating events.
|
||||
requests_to_process -- Exit after processing the specified number
|
||||
of requests (default: None, loop forever)
|
||||
"""
|
||||
|
||||
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)
|
||||
logging.basicConfig(level=Config.get('logging'), stream=sys.stdout)
|
||||
|
||||
|
@ -69,11 +70,6 @@ class Daemon(object):
|
|||
Params:
|
||||
msg -- platypush.message.Message instance """
|
||||
|
||||
if self.message_handler:
|
||||
# Proxy the message
|
||||
self.message_handler(msg)
|
||||
return
|
||||
|
||||
if isinstance(msg, Request):
|
||||
logging.info('Processing request: {}'.format(msg))
|
||||
Thread(target=self.run_request(), args=(msg,)).start()
|
||||
|
@ -122,8 +118,19 @@ class Daemon(object):
|
|||
logging.info('Dropping response whose request has no ' +
|
||||
'origin attached: {}'.format(request))
|
||||
|
||||
self.processed_requests += 1
|
||||
if self.processed_requests >= self.requests_to_process:
|
||||
self.stop_app()
|
||||
|
||||
return _thread_func
|
||||
|
||||
|
||||
def stop_app(self):
|
||||
for backend in self.backends.values():
|
||||
backend.stop()
|
||||
self.bus.stop()
|
||||
|
||||
|
||||
def start(self):
|
||||
""" Start the daemon """
|
||||
self.bus = Bus(on_message=self.on_message())
|
||||
|
@ -140,9 +147,8 @@ class Daemon(object):
|
|||
self.bus.poll()
|
||||
except KeyboardInterrupt as e:
|
||||
logging.info('SIGINT received, terminating application')
|
||||
|
||||
for backend in self.backends.values():
|
||||
backend.stop()
|
||||
finally:
|
||||
self.stop_app()
|
||||
|
||||
|
||||
def main(args=sys.argv[1:]):
|
||||
|
|
|
@ -109,8 +109,8 @@ class Backend(Thread):
|
|||
**self._get_backend_config(), **self._kwargs)
|
||||
|
||||
# Set the response timeout
|
||||
set_timeout(seconds=self._default_response_timeout,
|
||||
on_timeout=_timeout_hndl)
|
||||
if response_timeout:
|
||||
set_timeout(seconds=response_timeout, on_timeout=_timeout_hndl)
|
||||
|
||||
resp_backend.start()
|
||||
|
||||
|
@ -136,7 +136,7 @@ class Backend(Thread):
|
|||
|
||||
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.send_message(request, **kwargs)
|
||||
|
|
|
@ -2,10 +2,12 @@ import logging
|
|||
import json
|
||||
import os
|
||||
import time
|
||||
import threading
|
||||
|
||||
from .. import Backend
|
||||
|
||||
from platypush.message import Message
|
||||
from platypush.message.event import StopEvent
|
||||
from platypush.message.request import Request
|
||||
from platypush.message.response import Response
|
||||
|
||||
|
@ -32,6 +34,7 @@ class LocalBackend(Backend):
|
|||
else self.request_fifo
|
||||
|
||||
msg = '{}\n'.format(str(msg)).encode('utf-8')
|
||||
|
||||
with open(fifo, 'wb') as f:
|
||||
f.write(msg)
|
||||
|
||||
|
@ -44,14 +47,6 @@ class LocalBackend(Backend):
|
|||
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):
|
||||
super().run()
|
||||
logging.info('Initialized local backend on {} and {}'.
|
||||
|
@ -66,8 +61,7 @@ class LocalBackend(Backend):
|
|||
time.sleep(0.2)
|
||||
continue
|
||||
|
||||
# logging.debug('Received message on the local backend: {}'.format(msg))
|
||||
logging.info('Received message on the local backend: {}'.format(msg))
|
||||
logging.debug('Received message on the local backend: {}, thread_id: '.format(msg, self.thread_id))
|
||||
|
||||
if self.should_stop(): break
|
||||
self.on_message(msg)
|
||||
|
|
|
@ -2,10 +2,12 @@ import os
|
|||
import sys
|
||||
import signal
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from enum import Enum
|
||||
from queue import Queue
|
||||
|
||||
from platypush.config import Config
|
||||
from platypush.message.event import Event, StopEvent
|
||||
|
||||
class Bus(object):
|
||||
|
@ -14,6 +16,7 @@ class Bus(object):
|
|||
def __init__(self, on_message=None):
|
||||
self.bus = Queue()
|
||||
self.on_message = on_message
|
||||
self.thread_id = threading.get_ident()
|
||||
|
||||
def post(self, msg):
|
||||
""" Sends a message to the bus """
|
||||
|
@ -23,6 +26,14 @@ class Bus(object):
|
|||
""" Reads one message from the bus """
|
||||
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):
|
||||
"""
|
||||
Reads messages from the bus until either stop event message or KeyboardInterrupt
|
||||
|
@ -38,7 +49,7 @@ class Bus(object):
|
|||
self.on_message(msg)
|
||||
|
||||
if isinstance(msg, StopEvent) and msg.targets_me():
|
||||
logging.info('Received STOP event')
|
||||
logging.info('Received STOP event on the bus')
|
||||
stop=True
|
||||
|
||||
|
||||
|
|
11
run_test.sh
Executable file
11
run_test.sh
Executable 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
20
tests/context.py
Normal 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
69
tests/test_local.py
Normal 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:
|
||||
|
Loading…
Reference in a new issue