mirror of
				https://github.com/avatao-content/baseimage-tutorial-framework
				synced 2025-11-04 01:12:55 +00:00 
			
		
		
		
	Implement robust unit test cases for message queue timing
This commit is contained in:
		@@ -6,6 +6,7 @@ from threading import Thread
 | 
			
		||||
class MessageQueueHandler:
 | 
			
		||||
    keys = ['message.queue']
 | 
			
		||||
    type_id = 'ControlEventHandler'
 | 
			
		||||
    avg_word_len = 5
 | 
			
		||||
 | 
			
		||||
    def __init__(self, wpm):
 | 
			
		||||
        self.connector = None
 | 
			
		||||
@@ -15,11 +16,17 @@ class MessageQueueHandler:
 | 
			
		||||
 | 
			
		||||
    def _dispatch_messages(self):
 | 
			
		||||
        for message in iter(self._queue.get, None):
 | 
			
		||||
            wpm = message['wpm'] if 'wpm' in message else self.wpm
 | 
			
		||||
            cps = 5 * wpm / 60
 | 
			
		||||
            message['typing'] = not self._queue.empty()
 | 
			
		||||
            self.connector.send_message(message)
 | 
			
		||||
            sleep(len(message['message']) / cps)
 | 
			
		||||
            self._sleep(self._get_sleep_time(message))
 | 
			
		||||
 | 
			
		||||
    def _get_sleep_time(self, message):
 | 
			
		||||
        words_per_min = message['wpm'] if 'wpm' in message else self.wpm
 | 
			
		||||
        chars_per_min = self.avg_word_len * words_per_min / 60
 | 
			
		||||
        return len(message['message']) / chars_per_min
 | 
			
		||||
 | 
			
		||||
    def _sleep(self, seconds):  # pylint: disable=no-self-use
 | 
			
		||||
        sleep(seconds)
 | 
			
		||||
 | 
			
		||||
    def handle_event(self, message, _):
 | 
			
		||||
        for unpacked in self._generate_messages_from_queue(message):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
# pylint: disable=redefined-outer-name
 | 
			
		||||
from math import inf
 | 
			
		||||
from time import sleep
 | 
			
		||||
from time import time
 | 
			
		||||
from os import urandom
 | 
			
		||||
from random import randint
 | 
			
		||||
from queue import Queue
 | 
			
		||||
 | 
			
		||||
import pytest
 | 
			
		||||
 | 
			
		||||
@@ -12,56 +12,97 @@ from .message_queue_handler import MessageQueueHandler
 | 
			
		||||
class MockConnector:
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.callback = None
 | 
			
		||||
        self.messages = []
 | 
			
		||||
        self.messages = Queue()
 | 
			
		||||
        self.send_times = Queue()
 | 
			
		||||
 | 
			
		||||
    def raise_event(self, message):
 | 
			
		||||
        self.callback(message, self)
 | 
			
		||||
        sleep(0.01)
 | 
			
		||||
 | 
			
		||||
    def send_message(self, message):
 | 
			
		||||
        self.messages.append(message)
 | 
			
		||||
        self.messages.put(message)
 | 
			
		||||
        self.send_times.put(time())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def handler():
 | 
			
		||||
    connector = MockConnector()
 | 
			
		||||
    handler = MessageQueueHandler(inf)
 | 
			
		||||
    handler.connector = connector
 | 
			
		||||
    connector.callback = handler.handle_event
 | 
			
		||||
    class NoSleepMessageQueueHandler(MessageQueueHandler):
 | 
			
		||||
        sleep_start_times = Queue()
 | 
			
		||||
        sleep_seconds = Queue()
 | 
			
		||||
        sleep_end_times = Queue()
 | 
			
		||||
 | 
			
		||||
        def _sleep(self, seconds):
 | 
			
		||||
            self.sleep_start_times.put(time())
 | 
			
		||||
            self.sleep_seconds.put(seconds)
 | 
			
		||||
            super()._sleep(seconds)
 | 
			
		||||
            self.sleep_end_times.put(time())
 | 
			
		||||
 | 
			
		||||
    handler = NoSleepMessageQueueHandler(100000)
 | 
			
		||||
    handler.connector = MockConnector()
 | 
			
		||||
    handler.connector.callback = handler.handle_event
 | 
			
		||||
 | 
			
		||||
    handler.start()
 | 
			
		||||
    yield handler
 | 
			
		||||
    handler.cleanup()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def queue():
 | 
			
		||||
    yield {
 | 
			
		||||
def get_message_queue(*, size=None):
 | 
			
		||||
    size = randint(5, 10) if not size else size
 | 
			
		||||
    return {
 | 
			
		||||
        'key': 'message.queue',
 | 
			
		||||
        'messages': [
 | 
			
		||||
            {'originator': urandom(4).hex(), 'message': urandom(16).hex()}
 | 
			
		||||
            for _ in range(randint(5, 10))
 | 
			
		||||
            {'originator': urandom(4).hex(), 'message': urandom(randint(10, 20)).hex()}
 | 
			
		||||
            for _ in range(size)
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_message_order(handler, queue):
 | 
			
		||||
def test_order(handler):
 | 
			
		||||
    queue = get_message_queue()
 | 
			
		||||
    handler.connector.raise_event(queue)
 | 
			
		||||
    old_list = queue['messages']
 | 
			
		||||
    new_list = handler.connector.messages
 | 
			
		||||
    length = len(old_list)
 | 
			
		||||
    assert len(new_list) == length
 | 
			
		||||
    for i in range(length):
 | 
			
		||||
        unpacked = new_list[i]
 | 
			
		||||
        assert unpacked['key'] == 'message.send'
 | 
			
		||||
        assert unpacked['originator'] == old_list[i]['originator']
 | 
			
		||||
        assert unpacked['typing'] == (i < length-1)
 | 
			
		||||
    expected_messages = queue['messages']
 | 
			
		||||
 | 
			
		||||
    actual_messages = []
 | 
			
		||||
    for _ in expected_messages:
 | 
			
		||||
        actual_messages.append(handler.connector.messages.get())
 | 
			
		||||
 | 
			
		||||
    assert len(actual_messages) == len(expected_messages)
 | 
			
		||||
    for i in range(len(expected_messages)):  # pylint: disable=consider-using-enumerate
 | 
			
		||||
        message = actual_messages[i]
 | 
			
		||||
        assert message['key'] == 'message.send'
 | 
			
		||||
        assert message['originator'] == expected_messages[i]['originator']
 | 
			
		||||
        assert message['typing'] == (i < len(expected_messages)-1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_wpm(handler, queue):
 | 
			
		||||
    handler.wpm = 10000
 | 
			
		||||
    handler.connector.raise_event(queue)
 | 
			
		||||
    assert len(handler.connector.messages) == 1
 | 
			
		||||
    handler.wpm = 100000000
 | 
			
		||||
    handler.connector.raise_event(queue)
 | 
			
		||||
    sleep(0.25)
 | 
			
		||||
    assert len(handler.connector.messages) == 2*len(queue['messages'])
 | 
			
		||||
def test_timing(handler):
 | 
			
		||||
    q1 = get_message_queue(size=2)
 | 
			
		||||
    q2 = get_message_queue(size=2)
 | 
			
		||||
    handler.connector.raise_event(q1)
 | 
			
		||||
    handler.connector.raise_event(q2)
 | 
			
		||||
 | 
			
		||||
    messages = []
 | 
			
		||||
    send_times = []
 | 
			
		||||
    sleep_start_times = []
 | 
			
		||||
    sleep_seconds = []
 | 
			
		||||
    sleep_end_times = []
 | 
			
		||||
    for _ in range(len(q1['messages']) + len(q2['messages'])):
 | 
			
		||||
        messages.append(handler.connector.messages.get())
 | 
			
		||||
        send_times.append(handler.connector.send_times.get())
 | 
			
		||||
        sleep_start_times.append(handler.sleep_start_times.get())
 | 
			
		||||
        sleep_seconds.append(handler.sleep_seconds.get())
 | 
			
		||||
        sleep_end_times.append(handler.sleep_end_times.get())
 | 
			
		||||
 | 
			
		||||
    # no sleep before first message
 | 
			
		||||
    assert sleep_start_times[0] > send_times[0]
 | 
			
		||||
    assert messages[0]['typing']
 | 
			
		||||
 | 
			
		||||
    # at least 'seconds' sleep before sending next messages
 | 
			
		||||
    assert (send_times[0] + sleep_seconds[0]) < sleep_end_times[0]
 | 
			
		||||
    assert (send_times[0] + sleep_seconds[0]) < send_times[1]
 | 
			
		||||
    assert messages[1]['typing']
 | 
			
		||||
    assert (send_times[1] + sleep_seconds[1]) < sleep_end_times[1]
 | 
			
		||||
    assert (send_times[1] + sleep_seconds[1]) < send_times[2]
 | 
			
		||||
    assert messages[2]['typing']
 | 
			
		||||
 | 
			
		||||
    # at least 'seconds' sleep after last message
 | 
			
		||||
    assert (send_times[2] + sleep_seconds[2]) < sleep_end_times[3]
 | 
			
		||||
    assert not messages[3]['typing']
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user