osmo-python-tests/osmopy/osmo_interact/ctrl.py

175 lines
5.6 KiB
Python
Executable File

#!/usr/bin/env python3
#
# (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
# All rights reserved.
#
# Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
'''
Run CTRL commands or test transcripts against a given application. Commandline
invocation exposes only direct command piping, the transcript verification code
is exposed as commandline args by osmo_verify_transcript_ctrl.py.
'''
import re
from .common import *
from osmopy.osmo_ipa import Ctrl, IPA
class InteractCtrl(Interact):
next_id = 1
keep_ids = True
re_command = re.compile('^(SET|GET) ([^ ]*) (.*)$')
class CtrlStep(Interact.StepBase):
@staticmethod
def is_next_step(line, interact_instance):
m = InteractCtrl.re_command.match(line)
if not m:
return None
next_step = InteractCtrl.CtrlStep()
set_get = m.group(1)
cmd_id = m.group(2)
var_val = m.group(3)
if not interact_instance.keep_ids:
cmd_id = interact_instance.next_id
interact_instance.next_id += 1
next_step.command = '%s %s %s' % (set_get, cmd_id, var_val)
return next_step
def __init__(self, port, host, verbose=False, update=False, keep_ids=True):
if not update:
keep_ids = True
self.keep_ids = keep_ids
super().__init__(InteractCtrl.CtrlStep, port=port, host=host, verbose=verbose, update=update)
def connect(self):
self.next_id = 1
super().connect()
def send(self, data):
data = Ctrl().add_header(data)
return self.socket.send(data) == len(data)
def receive(self):
responses = []
data = self.socket.recv(4096)
while (len(data)>0):
(response_with_header, data) = IPA().split_combined(data)
response = Ctrl().rem_header(response_with_header)
responses.append(response.decode('utf-8'))
return responses
def command(self, command):
assert self.send(command)
res = self.receive()
split_responses = []
for r in res:
split_responses.extend(r.splitlines())
sys.stdout.flush()
sys.stderr.flush()
return split_responses
def main_interact_ctrl():
'''
Run CTRL commands against a given application by stdin/stdout piping.
Optionally, this can launch and tear down the application with -r.
For example, to start a session that allows typing CTRL commands on stdin:
osmo_interact_ctrl.py -p 4259 \\
-r 'osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /tmp/hlr.db'
Where 4259 is OsmoHLR's CTRL port number, see
https://osmocom.org/projects/cellular-infrastructure/wiki/Port_Numbers
If osmo-hlr is already running, this shortens to just
osmo_interact_ctrl.py -p 4259
See also osmo_verify_transcript_vty.py, which allows verifying and updating
complete CTRL session transcripts, in essence to write CTRL tests from a screen
dump of a CTRL session.
A VTY equivalent is osmo_interact_vty.py.
'''
parser = common_parser(__doc__)
parser_add_run_args(parser)
args = parser.parse_args()
interact = InteractCtrl(args.port, args.host, verbose=False, update=False,
keep_ids=True)
main_run_commands(args.run_app_str, args.output_path, args.cmd_str,
args.cmd_files, interact)
def main_verify_transcript_ctrl():
'''
A CTRL transcript contains CTRL commands and their expected results.
It looks like:
"
SET 1 var val
SET_REPLY 1 var OK
GET 2 var
GET_REPLY 2 var val
"
Optionally, this can launch and tear down the application with -r.
For example, if above transcript example is in file test.ctrl, you can verify
that OsmoHLR still shows this behavior by:
osmo_interact_ctrl.py -p 4259 \\
-r 'osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /tmp/hlr.db' \\
test.ctrl
Where 4259 is OsmoHLR's CTRL port number, see
https://osmocom.org/projects/cellular-infrastructure/wiki/Port_Numbers
If osmo-hlr is already running, this shortens to just
osmo_interact_ctrl.py -p 4259 test.ctrl
If osmo-hlr has changed its behavior, e.g. some reply changed, the transcript
can be automatically updated, which overwrites the file, like:
osmo_interact_ctrl.py -p 4259 -u test.ctrl
See also osmo_interact_ctrl.py, which allows piping CTRL commands to stdin.
A VTY equivalent is osmo_verify_transcript_vty.py.
'''
parser = common_parser(__doc__)
parser_add_verify_args(parser)
parser.add_argument('-i', '--keep-ids', dest='keep_ids', action='store_true',
help='With --update, default is to overwrite the command IDs'
' so that they are consecutive numbers starting from 1.'
' With --keep-ids, do not change these command IDs.')
args = parser.parse_args()
interact = InteractCtrl(args.port, args.host, args.verbose, args.update, args.keep_ids)
main_verify_transcripts(args.run_app_str, args.transcript_files, interact, args.verbose)
# vim: tabstop=4 shiftwidth=4 expandtab nocin ai