irq_test: Add IRQ testing tool
Add python scripts for debuggers to test IRQ handling in TF-M.
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
Change-Id: I6c5c0b920e3a0c38b3a0c867c93dd5851c66ff8b
diff --git a/irq_test_tool/irq_test_executor.py b/irq_test_tool/irq_test_executor.py
new file mode 100644
index 0000000..d98096f
--- /dev/null
+++ b/irq_test_tool/irq_test_executor.py
@@ -0,0 +1,180 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+from irq_test_abstract_debugger import Location
+import logging
+import json
+
+def create_locations_from_file(breakpoints_file_name):
+ """Internal function to create Location objects of a breakpoints data file
+ """
+ # Read in the points to break at
+ logging.info("Reading breakpoints file '%s'", breakpoints_file_name)
+ breakpoints_file = open(breakpoints_file_name)
+ breakpoints = json.load(breakpoints_file)
+ logging.debug("breakpoints: %s", str(breakpoints))
+
+ #TODO: go over the breakpoints and try to set them as a sanity check
+
+ locations = {}
+
+ for loc_name in breakpoints['breakpoints']:
+ bkpt = breakpoints['breakpoints'][loc_name]
+ offset = 0
+
+ if 'file' in bkpt:
+ filename = bkpt['file']
+ else:
+ filename = None
+
+ if 'symbol' in bkpt:
+ symbol = bkpt['symbol']
+ if 'offset' in bkpt:
+ offset = bkpt['offset']
+ else:
+ offset = 0
+ else:
+ if 'offset' in bkpt:
+ logging.error("In location %s offset is included without a"
+ " symbol")
+ exit(2)
+ symbol = None
+
+ if 'line' in bkpt:
+ line = bkpt['line']
+ try:
+ int(line)
+ except ValueError:
+ logging.error("In location %s line is not a valid int",
+ loc_name)
+ exit(2)
+ else:
+ line = None
+
+ if symbol:
+ if line or filename:
+ logging.error("In location %s nor filename nor line should"
+ "be present when symbol is present", loc_name)
+ exit(2)
+
+ if (not line and filename) or (line and not filename):
+ logging.error("In location %s line and filename have to be "
+ "present the same time", loc_name)
+ exit(2)
+
+ if (not symbol) and (not filename):
+ logging.error("In location %s no symbol nor code location is "
+ "specified at all", loc_name)
+ exit(2)
+
+ loc = Location(symbol=symbol, offset=offset, filename=filename, line=line)
+
+ locations[loc_name] = loc
+
+ return locations
+
+class TestExecutor(object):
+ """ This class implements the test logic.
+
+ It reads the input files, and executes the steps of the testcase. It receives an
+ AbstractDebugger instance on creation. The test execution is implemented in the
+ execute function.
+ """
+
+ def __init__(self, debugger):
+ self.debugger = debugger
+
+ def execute(self, irqs_filename, breakpoints_filename, testcase_filename):
+ """ Execute a testcase
+
+ Execute the testcase defined in 'testcase_filename', using the IRQs and
+ breakpoints defined in irqs_filename and breakpoints_filename.
+ """
+ # Read in the list of IRQs
+ logging.info("Reading irqs file '%s'", irqs_filename)
+ irqs_file = open(irqs_filename)
+ irqs = json.load(irqs_file)
+ logging.debug("irqs: %s", str(irqs))
+
+ # read in the test sequence
+ logging.info("Reading test sequence file '%s'", testcase_filename)
+ test_file = open(testcase_filename)
+ test = json.load(test_file)
+ logging.debug("testcase: %s", str(test))
+
+ # TODO: crosscheck the tests file against the breakpoints and the irq's
+ # available
+
+ locations = create_locations_from_file(breakpoints_filename)
+
+ self.debugger.clear_breakpoints()
+
+ # execute the test
+ steps = test['steps']
+ for i, step in enumerate(steps):
+
+ logging.info("---- Step %d ----", i)
+
+ continue_execution = False
+
+ if 'wait_for' in step:
+ bp_name = step['wait_for']
+ self.debugger.set_breakpoint(bp_name, locations[bp_name])
+ next_to_break_at = bp_name
+ continue_execution = True
+ elif 'expect' in step:
+ bp_name = step['expect']
+ self.debugger.set_breakpoint(bp_name, locations[bp_name])
+ next_to_break_at = bp_name
+
+ # Find the next wait_for in the test sequence, and set a
+ # breakpoint for that as well. So that it can be detected if an
+ # expected breakpoint is missed.
+
+ wait_for_found = False
+ ii = i+1
+
+ while ii < len(steps) and not wait_for_found:
+ next_step = steps[ii]
+ if 'wait_for' in next_step:
+ next_bp_name = next_step['wait_for']
+ self.debugger.set_breakpoint(next_bp_name,
+ locations[next_bp_name])
+ wait_for_found = True
+ ii += 1
+
+ continue_execution = True
+
+
+ if 'trigger' in step:
+ irqs_dict = irqs['irqs']
+ irq = irqs_dict[step['trigger']]
+ line_nu = irq['line_num']
+ self.debugger.trigger_interrupt(line_nu)
+
+
+ if continue_execution:
+ self.debugger.continue_execution()
+
+ triggered_breakpoint = self.debugger.get_triggered_breakpoint()
+
+ if triggered_breakpoint is None:
+ logging.error("No breakpoint was hit?????")
+ exit(0)
+
+ if triggered_breakpoint != next_to_break_at:
+ logging.error("execution stopped at '%s' instead of '%s'",
+ triggered_breakpoint, next_to_break_at)
+ exit(0)
+ else:
+ logging.error("execution stopped as no breakpoint is set")
+ exit(1)
+
+ self.debugger.clear_breakpoints()
+
+ logging.info("All the steps in the test file are executed successfully"
+ " with the expected result.")