Files
tryton/trytond/tests/test_bus.py
T
Cédric Krier 774d6eeb5a Do not keeping lock when relaunch listener and join listener in test
We can not recursively call Bus._listen when holding the lock because it
blocks all subscription until the listener stops.
The tearDown of the test should ensure the listener is really stopped before
ending.

issue8039
review52611002
2019-01-30 10:04:11 +01:00

149 lines
4.8 KiB
Python

# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import time
import unittest
from unittest.mock import patch
from trytond import bus, backend
from trytond.bus import _MessageQueue, notify, Bus
from trytond.tests.test_tryton import (
activate_module, with_transaction, DB_NAME)
from trytond.transaction import Transaction
class MessageQueueTestCase(unittest.TestCase):
def setUp(self):
self._timestamp = 0
def _time(self):
_timestamp = self._timestamp
self._timestamp += 1
return _timestamp
def test_get_next(self):
"Testing the basic functionality of get_next"
with patch('time.time', self._time):
mq = _MessageQueue(5)
for x in range(15):
mq.append('channel', {'message_id': x})
channel, content = mq.get_next({'channel'}, 11)
self.assertEqual(content, {'message_id': 12})
def test_get_next_channels(self):
"Testing get_next with multiple channels"
with patch('time.time', self._time):
mq = _MessageQueue(5)
for x in range(15):
mq.append('odd' if x % 2 else 'even', {'message_id': x})
channel, content = mq.get_next({'odd'}, 11)
self.assertEqual(content, {'message_id': 13})
self.assertEqual(channel, 'odd')
def test_get_next_timeout_expired(self):
"Testing get_next when requesting an outdated message"
with patch('time.time', self._time):
mq = _MessageQueue(5)
for x in range(15):
mq.append('channel', {'message_id': x})
channel, content = mq.get_next({'channel'}, 0)
self.assertEqual(content, {'message_id': 10})
def test_get_next_message_id_missing(self):
"Testing get_next when requesting a missing message"
with patch('time.time', self._time):
mq = _MessageQueue(5)
for x in range(15):
mq.append('channel', {'message_id': x})
channel, content = mq.get_next({'channel'}, -5)
self.assertEqual(content, {'message_id': 10})
def test_get_next_message_id_None(self):
"Testing get_next when not specifying a message"
with patch('time.time', self._time):
mq = _MessageQueue(5)
for x in range(15):
mq.append('channel', {'message_id': x})
channel, content = mq.get_next({'channel'})
self.assertEqual(content, {'message_id': 10})
class BusTestCase(unittest.TestCase):
"Test Bus"
@classmethod
def setUpClass(cls):
activate_module('ir')
super().setUpClass()
def setUp(self):
super().setUp()
reset_polling_timeout = bus._long_polling_timeout
bus._long_polling_timeout = 1
self.addCleanup(
setattr, bus, '_long_polling_timeout', reset_polling_timeout)
reset_select_timeout = bus._select_timeout
bus._select_timeout = 1
self.addCleanup(
setattr, bus, '_select_timeout', reset_select_timeout)
def tearDown(self):
if DB_NAME in Bus._queues:
with Bus._queues_lock:
Bus._queues[DB_NAME]['timeout'] = 0
listener = Bus._queues[DB_NAME]['listener']
listener.join()
Bus._messages.clear()
@with_transaction()
def test_notify(self):
"Test notify"
notify("Test", "Message", user=1)
@unittest.skipIf(backend.name() == 'sqlite', 'SQLite has not channel')
def test_subscribe_nothing(self):
"Test subscribe with nothing"
response = Bus.subscribe(DB_NAME, ['user:1'])
self.assertEqual(response, {'message': None, 'channel': None})
@unittest.skipIf(backend.name() == 'sqlite', 'SQLite has not channel')
def test_subscribe_message(self):
"Test subscribe with message"
Bus.subscribe(DB_NAME, ['user:1'])
transaction = Transaction()
with transaction.start(DB_NAME, 1):
notify("Test", "Message", user=1)
transaction.commit()
# Let the listen thread registers the message
time.sleep(1)
response = Bus.subscribe(DB_NAME, ['user:1'])
self.assertTrue(response['message'].pop('message_id'))
self.assertEqual(response, {
'message': {
'type': 'notification',
'title': "Test",
'body': "Message",
'priority': 1,
},
'channel': 'user:1',
})
def suite():
suite_ = unittest.TestSuite()
suite_.addTests(unittest.TestLoader().loadTestsFromTestCase(
MessageQueueTestCase))
suite_.addTests(unittest.TestLoader().loadTestsFromTestCase(
BusTestCase))
return suite_