add test for message encode/decode
in corner cases, encode_msg and decode_msg_frame fail Change-Id: I28b3ddcdce80c7c5b71afe19b11bb73cd761f595 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/22211 Tested-by: JenkinsCodeReview <bjoern_pedersen@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
parent
2d98fe8812
commit
e623fe8287
@ -17,35 +17,26 @@
|
||||
#
|
||||
# Module authors:
|
||||
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
|
||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||
#
|
||||
# *****************************************************************************
|
||||
|
||||
import json
|
||||
|
||||
EOL = b'\n'
|
||||
SPACE = b' '
|
||||
|
||||
def encode_msg_frame(action, specifier=None, data=None):
|
||||
""" encode a msg_tripel into an msg_frame, ready to be sent
|
||||
""" encode a msg_triple into an msg_frame, ready to be sent
|
||||
|
||||
action (and optional specifier) are str strings,
|
||||
data may be an json-yfied python object"""
|
||||
action = action.encode('utf-8')
|
||||
if specifier is None:
|
||||
if data is None:
|
||||
return b''.join((action, EOL))
|
||||
# error_activate might have no specifier
|
||||
specifier = ''
|
||||
specifier = specifier.encode('utf-8')
|
||||
if data:
|
||||
data = json.dumps(data).encode('utf-8')
|
||||
return b''.join((action, SPACE, specifier, SPACE, data, EOL))
|
||||
return b''.join((action, SPACE, specifier, EOL))
|
||||
msg = (action, specifier or '', '' if data is None else json.dumps(data))
|
||||
return ' '.join(msg).strip().encode('utf-8') + EOL
|
||||
|
||||
|
||||
def get_msg(_bytes):
|
||||
"""try to deframe the next msg in (binary) input
|
||||
always return a tupel (msg, remaining_input)
|
||||
always return a tuple (msg, remaining_input)
|
||||
msg may also be None
|
||||
"""
|
||||
if EOL not in _bytes:
|
||||
@ -54,14 +45,7 @@ def get_msg(_bytes):
|
||||
|
||||
|
||||
def decode_msg(msg):
|
||||
"""decode the (binary) msg into a (str) msg_tripel"""
|
||||
# check for leading/trailing CR and remove it
|
||||
res = msg.split(b' ', 2)
|
||||
action = res[0].decode('utf-8')
|
||||
if len(res) == 1:
|
||||
return action, None, None
|
||||
specifier = res[1].decode('utf-8')
|
||||
if len(res) == 2:
|
||||
return action, specifier, None
|
||||
data = json.loads(res[2].decode('utf-8'))
|
||||
return action, specifier, data
|
||||
"""decode the (binary) msg into a (str) msg_triple"""
|
||||
res = msg.strip().decode('utf-8').split(' ', 2) + ['', '']
|
||||
action, specifier, data = res[0:3]
|
||||
return action, specifier or None, None if data == '' else json.loads(data)
|
||||
|
52
test/test_msg.py
Normal file
52
test/test_msg.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# *****************************************************************************
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Module authors:
|
||||
# Markus Zolliker <markus.zolliker@psi.ch>
|
||||
#
|
||||
# *****************************************************************************
|
||||
"""test message encoding and decoding."""
|
||||
|
||||
import pytest
|
||||
|
||||
from secop.protocol.interface import encode_msg_frame, decode_msg
|
||||
import secop.protocol.messages as m
|
||||
|
||||
# args are: msg tuple, msg bytes
|
||||
MSG = [
|
||||
[(m.DESCRIPTIONREQUEST, None, None), b'describe'],
|
||||
[(m.DESCRIPTIONREPLY, '.', dict(key=0)), b'describing . {"key": 0}'],
|
||||
[(m.ENABLEEVENTSREQUEST, 'module:param', None), b'activate module:param'],
|
||||
[(m.ERRORPREFIX + m.ENABLEEVENTSREQUEST, None, ['ErrClass', 'text', {}]),
|
||||
b'error_activate ["ErrClass", "text", {}]'],
|
||||
[(m.COMMANDREQUEST, 'module:stop', None), b'do module:stop'],
|
||||
[(m.COMMANDREPLY, 'module:cmd', ''), b'done module:cmd ""'],
|
||||
[(m.WRITEREQUEST, 'module', 0), b'change module 0'],
|
||||
[(m.WRITEREPLY, 'm:p', 'with space'), b'changed m:p "with space"'],
|
||||
[(m.EVENTREPLY, 'mod:par', [123, dict(t=12.25)]), b'update mod:par [123, {"t": 12.25}]'],
|
||||
[(m.HEARTBEATREQUEST, '0', None), b'ping 0'],
|
||||
[(m.HEARTBEATREPLY, None, [None, dict(t=11.75)]), b'pong [null, {"t": 11.75}]'],
|
||||
[(m.ERRORPREFIX + m.WRITEREQUEST, 'm:p', ['ErrClass', 'text', dict()]),
|
||||
b'error_change m:p ["ErrClass", "text", {}]'],
|
||||
]
|
||||
@pytest.mark.parametrize('msg, line', MSG)
|
||||
def test_encode(msg, line):
|
||||
assert line + b'\n' == encode_msg_frame(*msg)
|
||||
|
||||
@pytest.mark.parametrize('msg, line', MSG)
|
||||
def test_decode(msg, line):
|
||||
assert decode_msg(line) == msg
|
Loading…
x
Reference in New Issue
Block a user