From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit changes the way commands report their results. The
NetTestCommandGeneric class no longer defines a set_result function, and
instead set_pass or set_fail functions should be used. These functions
create the result object (a dictionary) that contains relevant fields.
The functions also check the expect property of the command potentially
inverting the result of the command, with a relevant message added.
Previously there was an option to supply a message when calling the
set_pass or set_fail method from a test module. This was removed and
instead these messages should be moved into the res_data object of the
test module.
The main reason for this was to move the checking of expect to the slave
and to also move res_data formatting to the slave.
Both set_ functions accept a parameter that contains result data of the
command. This should be a dictionary that can be serialized into a valid
xml document and a check function for this will be added later.
The supplied res_data is formatted using the function format_res_data
which can be overridden in the subclasses if the user wants to customize
the formatting.
The function _format_cmd_res_header is used to format the first line of
the command summary, which differs by command type. This shouldn't be
overridden when implementing a custom test module.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Common/NetTestCommand.py | 100 ++++++++++++++++++++++++++++++-----
lnst/Common/TestsCommon.py | 26 ++++-----
lnst/Controller/NetTestController.py | 6 ++-
3 files changed, 101 insertions(+), 31 deletions(-)
diff --git a/lnst/Common/NetTestCommand.py b/lnst/Common/NetTestCommand.py
index 1d50c7c..da763f9 100644
--- a/lnst/Common/NetTestCommand.py
+++ b/lnst/Common/NetTestCommand.py
@@ -126,7 +126,9 @@ class NetTestCommand:
else:
logging.debug("Running in background with"
" bg_id \"%s\" pid \"%d\"" %
(self._id, self._pid))
- return {"passed": True}
+ return {"passed": True,
+ "res_header": self._cmd_cls._format_cmd_res_header(),
+ "msg": "Running in background."}
def _run(self):
os.setpgrp()
@@ -184,8 +186,8 @@ class NetTestCommand:
def get_result(self):
if self._killed:
result = {}
- result["type"] = "result"
result["passed"] = True
+ result["msg"] = "Command killed."
else:
result = self._result
@@ -251,9 +253,6 @@ class NetTestCommandGeneric:
def run(self):
pass
- def set_result(self, result):
- self._result = result
-
def get_result(self):
if not self._result:
'''
@@ -263,16 +262,55 @@ class NetTestCommandGeneric:
self.set_pass()
return self._result
- def set_fail(self, err_msg):
- result = {"passed": False, "err_msg": err_msg}
- self.set_result(result)
+ def set_fail(self, res_data=None):
+ res = False
+ msg = ""
+ if "expect" in self._command and self._command["expect"] ==
False:
+ res = True
+ msg = "Command failed, as was specified in the recipe."
+ result = {"passed": res,
+ "res_data": res_data,
+ "msg": msg,
+ "report": self.format_res_data(res_data),
+ "res_header": self._format_cmd_res_header()}
+ self._result = result
return result
- def set_pass(self):
- result = {"passed": True}
- self.set_result(result)
+ def set_pass(self, res_data=None):
+ res = True
+ msg = ""
+ if "expect" in self._command and self._command["expect"] ==
False:
+ res = False
+ msg = "Command expected to fail, but passed!"
+ result = {"passed": res,
+ "res_data": res_data,
+ "msg": msg,
+ "report": self.format_res_data(res_data),
+ "res_header": self._format_cmd_res_header()}
+ self._result = result
return result
+ def format_res_data(self, res_data, level=0):
+ formatted_data = ""
+ if res_data:
+ max_key_len = 0
+ for key in res_data.keys():
+ if len(key) > max_key_len:
+ max_key_len = len(key)
+ for key, value in res_data.iteritems():
+ if type(value) == dict:
+ formatted_data += level*4*" " + str(key) + ":\n"
+ formatted_data += self.format_res_data(value, level+1)
+ else:
+ formatted_data += level*4*" " + str(key) + ":" +
\
+ (max_key_len-len(key))*" " + \
+ "\t" + str(value) + "\n"
+
+ return formatted_data
+
+ def _format_cmd_res_header(self):
+ return "%-14s" % self._command["type"]
+
def set_handle_intr(self):
pass
@@ -305,6 +343,18 @@ class NetTestCommandExec(NetTestCommandGeneric):
else:
self.set_fail("Command failed to execute")
+ def _format_cmd_res_header(self):
+ cmd_type = self._command["type"]
+ cmd_val = self._command["command"]
+
+ if "bg_id" in self._command:
+ bg_id = "bg_id: %s" % self._command["bg_id"]
+ else:
+ bg_id = ""
+
+ cmd = "%-14s%s%s" %(cmd_type, cmd_val, bg_id)
+ return cmd
+
class NetTestCommandConfig(NetTestCommandGeneric):
def _retrive_option(self, option):
cmd_str = "cat %s" % option
@@ -343,15 +393,34 @@ class NetTestCommandConfig(NetTestCommandGeneric):
"current_val": value,
"previous_val": prev_val})
- res = {"passed": True}
- res["res_data"] = res_data
- return res
+ self.set_pass(res_data)
+ return self.get_result()
+
+ def format_res_data(self, res_data, level=0):
+ formatted_data = ""
+ max_name_len = 0
+ for option in res_data["options"]:
+ if len(option["name"]) > max_name_len:
+ max_name_len = len(option["name"])
+ for option in res_data["options"]:
+ vals = "previous: %s current: %s" %
(option["previous_val"],
+ option["current_val"])
+ formatted_data += 4*level*" " + option["name"] + \
+ (max_name_len - len(option["name"]))*"
" + \
+ "\t" + vals + "\n"
+ return formatted_data
class NetTestCommandControl(NetTestCommandGeneric):
def __init__(self, command_context, command):
self._command_context = command_context
NetTestCommandGeneric.__init__(self, command)
+ def _format_cmd_res_header(self):
+ cmd_type = self._command["type"]
+ cmd_val = self._command["proc_id"]
+ cmd = "%-14s id: %s" % (cmd_type, cmd_val)
+ return cmd
+
class NetTestCommandWait(NetTestCommandControl):
def run(self):
bg_id = self._command["proc_id"]
@@ -361,6 +430,7 @@ class NetTestCommandWait(NetTestCommandControl):
if result != None:
bg_cmd.join()
self._command_context.del_cmd(bg_cmd)
+ result["res_header"] = self._format_cmd_res_header()
return result
class NetTestCommandIntr(NetTestCommandControl):
@@ -372,6 +442,7 @@ class NetTestCommandIntr(NetTestCommandControl):
if result != None:
bg_cmd.join()
self._command_context.del_cmd(bg_cmd)
+ result["res_header"] = self._format_cmd_res_header()
return result
class NetTestCommandKill(NetTestCommandControl):
@@ -383,6 +454,7 @@ class NetTestCommandKill(NetTestCommandControl):
if result != None:
bg_cmd.join()
self._command_context.del_cmd(bg_cmd)
+ result["res_header"] = self._format_cmd_res_header()
return result
def get_command_class(command_context, command, resource_table):
diff --git a/lnst/Common/TestsCommon.py b/lnst/Common/TestsCommon.py
index 38c3287..3008e81 100644
--- a/lnst/Common/TestsCommon.py
+++ b/lnst/Common/TestsCommon.py
@@ -84,22 +84,6 @@ class TestGeneric(NetTestCommandGeneric):
continue
break
- def set_fail(self, err_msg, res_data = None):
- self._testLogger.error("FAILED - %s" % err_msg)
- res = {"passed": False, "err_msg": err_msg}
- if res_data:
- res["res_data"] = res_data
- self.set_result(res)
- return res
-
- def set_pass(self, res_data = None):
- self._testLogger.debug("PASSED")
- res = {"passed": True}
- if res_data:
- res["res_data"] = res_data
- self.set_result(res)
- return res
-
def _get_val(self, value, opt_type, default):
if opt_type == "addr":
'''
@@ -154,3 +138,13 @@ class TestGeneric(NetTestCommandGeneric):
This should be used to get mandatory multi options (array of values)
'''
return self.get_multi_opt(name, mandatory=True, opt_type=opt_type)
+
+ def _format_cmd_res_header(self):
+ cmd_val = self._command["module"]
+ cmd_type = self._command["type"]
+ if "bg_id" in self._command:
+ bg_id = " bg_id: %s" % self._command["bg_id"]
+ else:
+ bg_id = ""
+ cmd = "%-14s%s%s" %(cmd_type, cmd_val, bg_id)
+ return cmd
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index 33ead31..a5b2c2f 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -489,7 +489,11 @@ class NetTestController:
if command["type"] == "ctl_wait":
sleep(command["seconds"])
- cmd_res = {"passed" : True}
+ cmd_res = {"passed": True,
+ "res_header": "%-14s%ss" %
("ctl_wait",
+ command["seconds"]),
+ "msg": "",
+ "res_data": None}
return cmd_res
machine_id = command["machine"]
--
1.8.3.1