Providing plug-in support:
Typically, a test program is written to perform certain basic tests on a test
machine. For example, one might write an "obmc_boot" program that performs
various boot tests on the Open BMC machine.
Experience has shown that over time, additional testing needs often arise.
Examples of such additional testing needs might include:
- Data base logging of results
- Performance measurements
- Memory leak analysis
- Hardware verification
- Error log (sels) analysis
- SOL_console
The developer could add additional parms to obmc_boot and likewise add
supporting code in obmc_boot each time a need arises. Users would employ
these new functions as follows:
obmc_boot --perf=1 --mem_leak=1 --db_logging=1 --db_userid=xxxx
However, another option would be to add general-purpose plug-in support to
obmc_boot. This would allow the user to indicate to obmc_boot which plug-in
packages it ought to run. Such plug-in packages could be written in any
langauge whatsoever: Robot, python, bash, perl, C++.
An example call to obmc_boot would then look something like this:
obmc_boot --plug_in_dir_paths="Perf:Mem_leak:DB_logging"
Now all the obmc_boot developer needs to do is call the plug-in processing
module (process_plug_in_packages.py) at various call points which are agreed
upon by the obmc_boot developer and the plug-in developers. Example call
points which can be implemented are:
setup - Called at the start of obmc_boot
pre_boot - Called before each boot test initiated by obmc_boot
post_boot - Called after each boot test initiated by obmc_boot
cleanup - Called at the end of obmc_boot
This allows the choice of options to be passed as data to obmc_boot. The
advantages of this approach are:
- Much less maintenance of the original test program (obmc_boot).
- Since plug-ins are separate from the main test program, users are free to
have plug-ins that suit their environments. One user may wish to log results
to a database that is of no interest to the rest of the world. Such a plug-in
can be written and need never be pushed to gerrit/github.
- One can even write temporary plug-ins designed just to collect data or stop
when a particular defect occurs.
In our current environment, the concept has proven exceedingly useful. We
have over 40 permanent plug-ins and in our temp plug-in directory, we still
have over 80 plug-ins.
Change-Id: Iee0ea950cffaef202d56da4dae7c044b6366a59c
Signed-off-by: Michael Walsh <micwalsh@us.ibm.com>
diff --git a/lib/gen_robot_print.py b/lib/gen_robot_print.py
index 803aa4a..331690b 100755
--- a/lib/gen_robot_print.py
+++ b/lib/gen_robot_print.py
@@ -6,7 +6,9 @@
import sys
import re
+
import gen_print as gp
+
from robot.libraries.BuiltIn import BuiltIn
from robot.api import logger
@@ -20,8 +22,8 @@
# string directly to stdout.
# It can be complicated to follow what's being creaed by the exec statement
-# below. Here is an example of the rprint_time() function that will be created
-# (as of the time of this writing):
+# below. Here is an example of the rprint_time() function that will be
+# created (as of the time of this writing):
# def rprint_time(*args):
# s_func = getattr(gp, "sprint_time")
@@ -31,13 +33,14 @@
# Here are comments describing the lines in the body of the created function.
# Put a reference to the "s" version of this function in s_func.
-# Call the "s" version of this function passing it all of our arguments. Write
-# the result to stdout.
+# Call the "s" version of this function passing it all of our arguments.
+# Write the result to stdout.
robot_prefix = "r"
for func_name in gp.func_names:
- # The print_var function's job is to figure out the name of arg 1 and then
- # call print_varx. This is not currently supported for robot programs.
+ # The print_var function's job is to figure out the name of arg 1 and
+ # then call print_varx. This is not currently supported for robot
+ # programs. Though it IS supported for python modules.
if func_name == "print_error":
output_stream = "STDERR"
else:
@@ -47,7 +50,7 @@
"def " + robot_prefix + func_name + "(*args):",
" s_func = getattr(gp, \"s" + func_name + "\")",
" BuiltIn().log_to_console(s_func(*args),"
- " stream = '" + output_stream + "',"
+ " stream='" + output_stream + "',"
" no_newline=True)"
]
@@ -63,37 +66,39 @@
###############################################################################
-def rprint(buffer=""):
+def rprint(buffer="",
+ stream="STDOUT"):
r"""
rprint stands for "Robot Print". This keyword will print the user's
buffer to the console. This keyword does not write a linefeed. It is the
responsibility of the caller to include a line feed if desired. This
keyword is essentially an alias for "Log to Console <string>
- no_newline=True".
+ <stream>".
Description of arguments:
buffer The value that is to written to stdout.
"""
- BuiltIn().log_to_console(buffer, no_newline=True)
+ BuiltIn().log_to_console(buffer, no_newline=True, stream=stream)
###############################################################################
###############################################################################
-def rprintn(buffer=""):
+def rprintn(buffer="",
+ stream='STDOUT'):
r"""
rprintn stands for "Robot print with linefeed". This keyword will print
the user's buffer to the console along with a linefeed. It is basically
- an abbreviated form of "Log go Console <string>"
+ an abbreviated form of "Log go Console <string> <stream>"
Description of arguments:
buffer The value that is to written to stdout.
"""
- BuiltIn().log_to_console(buffer, no_newline=False)
+ BuiltIn().log_to_console(buffer, no_newline=False, stream=stream)
###############################################################################
@@ -157,6 +162,6 @@
###############################################################################
-# Define an alias. rpvar is just a special case of rpvars where the var_names
-# list contains only one element.
+# Define an alias. rpvar is just a special case of rpvars where the
+# var_names list contains only one element.
rpvar = rpvars