xref: /openbmc/openbmc-test-automation/lib/gen_robot_valid.py (revision c2127d2e3f4f1e2f87748f84dcca3aaddc4050f3)
1#!/usr/bin/env python3
2
3r"""
4This module provides validation functions like valid_value(), valid_integer(), etc. for robot programs.
5"""
6
7import re
8
9import func_args as fa
10import gen_print as gp
11import gen_valid as gv
12from robot.libraries.BuiltIn import BuiltIn
13
14
15def valid_var_name(var_name):
16    r"""
17    Validate the robot variable name and return its value.
18
19    If the variable is undefined, this function will print an error message and call BuiltIn().fail().
20
21    Description of arguments():
22    var_name                        The name of the robot variable (e.g. "var1").  Do not include "${}" (e.g.
23                                    "${var1}".  Just provide the simple name of the variable.
24    """
25
26    # Note: get_variable_value() seems to have no trouble with local variables.
27    var_value = BuiltIn().get_variable_value("${" + var_name + "}")
28    if var_value is None:
29        var_value = "<undefined>"
30        error_message = gv.valid_value(
31            var_value, invalid_values=[var_value], var_name=var_name
32        )
33        BuiltIn().fail(error_message)
34
35    return var_value
36
37
38def valid_init(var_name, *args, **kwargs):
39    r"""
40    Do initialization for variable validation and return var_name, args and kwargs.
41
42    This function is to be called by all of the various validation functions in this module.
43
44    This function is designed solely for use by other functions in this file.
45
46    Description of argument(s):
47    var_name                        The name of the variable to be validated.
48    args                            The positional arguments to be passed to a validation function.
49    kwargs                          The keyword arguments to be passed to a validation function.
50    """
51
52    var_value = valid_var_name(var_name)
53    # Convert python string object definitions to objects (useful for robot callers).
54    args = fa.args_to_objects(args)
55    kwargs = fa.args_to_objects(kwargs)
56    return var_value, args, kwargs
57
58
59def process_error_message(error_message):
60    r"""
61    Process an error message.
62
63    If error_message is non-blank, fail.  Otherwise, do nothing.
64
65    This function is designed solely for use by other functions in this file.
66
67    Description of argument(s):
68    error_message                   The error message to be processed.
69    """
70
71    if error_message:
72        error_message = gp.sprint_error_report(error_message)
73        BuiltIn().fail(error_message)
74
75
76# The docstring header will be prepended to each validation function's existing docstring.
77docstring_header = r"""
78    Fail if the variable named by var_name is invalid.
79    """
80
81
82def customize_doc_string(doc_string):
83    r"""
84    Customize a gen_valid function docstring and return the result.
85
86    This function is designed solely for use by other functions in this file.
87
88    The caller should pass a docstring from a gen_valid.py validation function.  This docstring will be
89    changed to make a suitable docstring for this module's corresponding validation function.
90
91    For example:
92
93    Let's suppose that gen_valid.py has a function called "valid_value()".  This module could make the
94    following call to essentially copy gen_valid's "valid_value()" function, modify it and then assign it to
95    the local version of the valid_value() function.
96
97    valid.__doc__ = customize_doc_string(gv.valid.__doc__)
98
99    Description of argument(s):
100    doc_string                      The docstring to be customized.
101    """
102
103    doc_string = docstring_header + doc_string
104    doc_string = doc_string.split("\n")
105
106    start_ix = 0
107    # Find the "var_value" line.
108    start_ix = next(
109        (
110            index
111            for index, value in enumerate(doc_string[start_ix:], start_ix)
112            if re.match("[ ]+var_value  ", value)
113        ),
114        None,
115    )
116    # If we don't find the var_value in the string, return as it is.
117    try:
118        # Replace the "var_value" line with our "var_name" line.
119        doc_string[start_ix] = (
120            "    var_name                        "
121            + "The name of the variable to be validated."
122        )
123    except TypeError:
124        pass
125
126    return "\n".join(doc_string)
127
128
129# All of the following functions are robot wrappers for the equivalent functions defined in gen_valid.py.
130# Note that the only difference between any two of these locally defined functions is the function name and
131# the gv.<function name> which they call.  Also, note that the docstring for each is created by modifying the
132# docstring from the supporting gen_valid.py function.
133
134
135def valid_type(var_name, *args, **kwargs):
136    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
137    error_message = gv.valid_type(
138        var_value, *args, var_name=var_name, **kwargs
139    )
140    process_error_message(error_message)
141
142
143def valid_value(var_name, *args, **kwargs):
144    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
145    error_message = gv.valid_value(
146        var_value, *args, var_name=var_name, **kwargs
147    )
148    process_error_message(error_message)
149
150
151def valid_range(var_name, *args, **kwargs):
152    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
153    error_message = gv.valid_range(
154        var_value, *args, var_name=var_name, **kwargs
155    )
156    process_error_message(error_message)
157
158
159def valid_integer(var_name, *args, **kwargs):
160    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
161    error_message = gv.valid_integer(
162        var_value, *args, var_name=var_name, **kwargs
163    )
164    process_error_message(error_message)
165
166
167def valid_float(var_name, *args, **kwargs):
168    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
169    error_message = gv.valid_float(
170        var_value, *args, var_name=var_name, **kwargs
171    )
172    process_error_message(error_message)
173
174
175def valid_date_time(var_name, *args, **kwargs):
176    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
177    error_message = gv.valid_date_time(
178        var_value, *args, var_name=var_name, **kwargs
179    )
180    process_error_message(error_message)
181
182
183def valid_dir_path(var_name, *args, **kwargs):
184    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
185    error_message = gv.valid_dir_path(
186        var_value, *args, var_name=var_name, **kwargs
187    )
188    process_error_message(error_message)
189
190
191def valid_file_path(var_name, *args, **kwargs):
192    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
193    error_message = gv.valid_file_path(
194        var_value, *args, var_name=var_name, **kwargs
195    )
196    process_error_message(error_message)
197
198
199def valid_path(var_name, *args, **kwargs):
200    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
201    error_message = gv.valid_path(
202        var_value, *args, var_name=var_name, **kwargs
203    )
204    process_error_message(error_message)
205
206
207def valid_list(var_name, *args, **kwargs):
208    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
209    error_message = gv.valid_list(
210        var_value, *args, var_name=var_name, **kwargs
211    )
212    process_error_message(error_message)
213
214
215def valid_dict(var_name, *args, **kwargs):
216    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
217    error_message = gv.valid_dict(
218        var_value, *args, var_name=var_name, **kwargs
219    )
220    process_error_message(error_message)
221
222
223def valid_program(var_name, *args, **kwargs):
224    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
225    error_message = gv.valid_program(
226        var_value, *args, var_name=var_name, **kwargs
227    )
228    process_error_message(error_message)
229
230
231def valid_length(var_name, *args, **kwargs):
232    var_value, args, kwargs = valid_init(var_name, *args, **kwargs)
233    error_message = gv.valid_length(
234        var_value, *args, var_name=var_name, **kwargs
235    )
236    process_error_message(error_message)
237
238
239# Modify the validation function docstrings by calling customize_doc_string for each function in the
240# func_names list.
241func_names = [
242    "valid_type",
243    "valid_value",
244    "valid_range",
245    "valid_integer",
246    "valid_dir_path",
247    "valid_file_path",
248    "valid_path",
249    "valid_list",
250    "valid_dict",
251    "valid_program",
252    "valid_length",
253    "valid_float",
254    "valid_date_time",
255]
256
257for func_name in func_names:
258    cmd_buf = (
259        func_name
260        + ".__doc__ = customize_doc_string(gv.raw_doc_strings['"
261        + func_name
262        + "'])"
263    )
264    exec(cmd_buf)
265