diff --git a/ducktape/mark/__init__.py b/ducktape/mark/__init__.py index f38c58211..d26b5f65b 100644 --- a/ducktape/mark/__init__.py +++ b/ducktape/mark/__init__.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -from ._mark import parametrize, matrix, defaults, ignore, ok_to_fail, parametrized, ignored, oked_to_fail, env, is_env # NOQA +from ._mark import parametrize, matrix, defaults, ignore, ok_to_fail, parametrized, ignored, oked_to_fail, env, is_env, ok_to_fail_fips, oked_to_fail_fips # NOQA diff --git a/ducktape/mark/_mark.py b/ducktape/mark/_mark.py index 634446e53..717564353 100644 --- a/ducktape/mark/_mark.py +++ b/ducktape/mark/_mark.py @@ -125,6 +125,24 @@ def apply(self, seed_context, context_list): return context_list +class OkToFailFIPS(Mark): + """Run the test but categorize status as OPASSFIPS or OFAILFIPS instead of PASS or FAIL.""" + + def __init__(self): + super(OkToFailFIPS, self).__init__() + self.injected_args = None + + @property + def name(self): + return "OK_TO_FAIL_FIPS" + + def apply(self, seed_context, context_list): + assert len(context_list) > 0, "ignore annotation is not being applied to any test cases" + for ctx in context_list: + ctx.ok_to_fail_fips = ctx.ok_to_fail_fips or self.injected_args is None + return context_list + + class Matrix(Mark): """Parametrize with a matrix of arguments. Assume each values in self.injected_args is iterable @@ -242,6 +260,7 @@ def __eq__(self, other): DEFAULTS = Defaults() IGNORE = Ignore() OK_TO_FAIL = OkToFail() +OK_TO_FAIL_FIPS = OkToFailFIPS() ENV = Env() @@ -264,6 +283,11 @@ def oked_to_fail(f): return Mark.marked(f, OK_TO_FAIL) +def oked_to_fail_fips(f): + """Is this function or object decorated with @ok_to_fail_fips?""" + return Mark.marked(f, OK_TO_FAIL_FIPS) + + def is_env(f): return Mark.marked(f, ENV) @@ -459,6 +483,35 @@ def the_test(...): return args[0] +def ok_to_fail_fips(*args, **kwargs): + """ + Test method decorator which signals to the test runner to run test but to set OFAIL_FIPS or OPASS_FIPS. + This mark is only applied if the operating system is actually running in FIPS mode. If not, no mark is made + and test runs as normal + + Example:: + @ok_to_fail_fips + def the_test(...): + ... + """ + def running_fips() -> bool: + fips_file = "/proc/sys/crypto/fips_enabled" + if os.path.exists(fips_file) and os.path.isfile(fips_file): + with open(fips_file, 'r') as f: + contents = f.read().strip() + return contents == '1' + + return False + + if len(args) == 1 and len(kwargs) == 0 and running_fips(): + # this corresponds to the usage of the decorator with no arguments + # @ok_to_fail_fips + # def test_function: + # ... + Mark.mark(args[0], OkToFailFIPS()) + return args[0] + + def env(**kwargs): def environment(f): Mark.mark(f, Env(**kwargs)) diff --git a/ducktape/templates/report/report.css b/ducktape/templates/report/report.css index 8d41cbde2..123c23be5 100644 --- a/ducktape/templates/report/report.css +++ b/ducktape/templates/report/report.css @@ -86,6 +86,14 @@ h1, h2, h3, h4, h5, h6 { background-color: #9cf; } +.ofailfips { + background-color: #ffc +} + +.opassfips { + background-color: #9cf; +} + .testcase { margin-left: 2em; } diff --git a/ducktape/templates/report/report.html b/ducktape/templates/report/report.html index 8009b9e2c..dd8b79e68 100644 --- a/ducktape/templates/report/report.html +++ b/ducktape/templates/report/report.html @@ -14,6 +14,8 @@
+ +