"""
libfiu python wrapper
This module is a wrapper for the libfiu, the fault injection C library.
It provides an almost one-to-one mapping of the libfiu functions, although its
primary use is to be able to test C code from within Python.
For fault injection in Python, a native library would be more suitable.
See libfiu's manpage for more detailed documentation.
"""
import fiu_ll as _ll
def fail(name):
"Returns the failure status of the given point of failure."
return _ll.fail(name)
def failinfo():
"""Returns the information associated with the last failure. Use with
care, can be fatal if the point of failure was not enabled via
Python."""
return _ll.failinfo()
class Flags:
"""Contains the valid flag constants.
ONETIME: This point of failure is disabled immediately after failing once.
"""
ONETIME = _ll.FIU_ONETIME
# To be sure failinfo doesn't dissapear from under our feet, we keep a
# name -> failinfo table. See fiu_ll's comments for more details.
_fi_table = {}
def enable(name, failnum=1, failinfo=None, flags=0):
"Enables the given point of failure."
_fi_table[name] = failinfo
r = _ll.enable(name, failnum, failinfo, flags)
if r != 0:
del _fi_table[name]
raise RuntimeError(r)
def enable_random(name, probability, failnum=1, failinfo=None, flags=0):
"Enables the given point of failure, with the given probability."
_fi_table[name] = failinfo
r = _ll.enable_random(name, failnum, failinfo, flags, probability)
if r != 0:
del _fi_table[name]
raise RuntimeError(r)
def enable_external(name, cb, failnum=1, flags=0):
"""Enables the given point of failure, leaving the decision whether to
fail or not to the given external function, which should return 0 if
it is not to fail, or 1 otherwise.
The cb parameter is a Python function that takes three parameters,
name, failnum and flags, with the same values that we receive.
For technical limitations, enable_external() cannot take
failinfo."""
# in this case, use the table to prevent the function from
# dissapearing
_fi_table[name] = cb
r = _ll.enable_external(name, failnum, flags, cb)
if r != 0:
del _fi_table[name]
raise RuntimeError(r)
def enable_stack_by_name(
name, func_name, failnum=1, failinfo=None, flags=0, pos_in_stack=-1
):
"""Enables the given point of failure, but only if 'func_name' is in
the stack.
'func_name' is be the name of the C function to look for.
"""
_fi_table[name] = failinfo
r = _ll.enable_stack_by_name(
name, failnum, failinfo, flags, func_name, pos_in_stack
)
if r != 0:
del _fi_table[name]
raise RuntimeError(r)
def disable(name):
"""Disables the given point of failure, undoing the actions of the
enable*() functions."""
if name in _fi_table:
del _fi_table[name]
r = _ll.disable(name)
if r != 0:
raise RuntimeError(r)
def set_prng_seed(seed):
"""Sets the PRNG seed. Don't use this unless you know what you're
doing."""
return _ll.set_prng_seed(seed)
def rc_fifo(basename):
"""Enables remote control over a named pipe that begins with the given
basename. The final path will be "basename-$PID"."""
r = _ll.rc_fifo(basename)
if r != 0:
raise RuntimeError(r)