blob: 86ddf8ffc382ece90e3f92f3e3a364fdc735de8f [file] [log] [blame]
Kevin Penga127b452021-02-23 10:02:55 +08001#-------------------------------------------------------------------------------
2# Copyright (c) 2020, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8from irq_test_abstract_debugger import Location
9import logging
10import json
11
12def create_locations_from_file(breakpoints_file_name):
13 """Internal function to create Location objects of a breakpoints data file
14 """
15 # Read in the points to break at
16 logging.info("Reading breakpoints file '%s'", breakpoints_file_name)
17 breakpoints_file = open(breakpoints_file_name)
18 breakpoints = json.load(breakpoints_file)
19 logging.debug("breakpoints: %s", str(breakpoints))
20
21 #TODO: go over the breakpoints and try to set them as a sanity check
22
23 locations = {}
24
25 for loc_name in breakpoints['breakpoints']:
26 bkpt = breakpoints['breakpoints'][loc_name]
27 offset = 0
28
29 if 'file' in bkpt:
30 filename = bkpt['file']
31 else:
32 filename = None
33
34 if 'symbol' in bkpt:
35 symbol = bkpt['symbol']
36 if 'offset' in bkpt:
37 offset = bkpt['offset']
38 else:
39 offset = 0
40 else:
41 if 'offset' in bkpt:
42 logging.error("In location %s offset is included without a"
43 " symbol")
44 exit(2)
45 symbol = None
46
47 if 'line' in bkpt:
48 line = bkpt['line']
49 try:
50 int(line)
51 except ValueError:
52 logging.error("In location %s line is not a valid int",
53 loc_name)
54 exit(2)
55 else:
56 line = None
57
58 if symbol:
59 if line or filename:
60 logging.error("In location %s nor filename nor line should"
61 "be present when symbol is present", loc_name)
62 exit(2)
63
64 if (not line and filename) or (line and not filename):
65 logging.error("In location %s line and filename have to be "
66 "present the same time", loc_name)
67 exit(2)
68
69 if (not symbol) and (not filename):
70 logging.error("In location %s no symbol nor code location is "
71 "specified at all", loc_name)
72 exit(2)
73
74 loc = Location(symbol=symbol, offset=offset, filename=filename, line=line)
75
76 locations[loc_name] = loc
77
78 return locations
79
80class TestExecutor(object):
81 """ This class implements the test logic.
82
83 It reads the input files, and executes the steps of the testcase. It receives an
84 AbstractDebugger instance on creation. The test execution is implemented in the
85 execute function.
86 """
87
88 def __init__(self, debugger):
89 self.debugger = debugger
90
91 def execute(self, irqs_filename, breakpoints_filename, testcase_filename):
92 """ Execute a testcase
93
94 Execute the testcase defined in 'testcase_filename', using the IRQs and
95 breakpoints defined in irqs_filename and breakpoints_filename.
96 """
97 # Read in the list of IRQs
98 logging.info("Reading irqs file '%s'", irqs_filename)
99 irqs_file = open(irqs_filename)
100 irqs = json.load(irqs_file)
101 logging.debug("irqs: %s", str(irqs))
102
103 # read in the test sequence
104 logging.info("Reading test sequence file '%s'", testcase_filename)
105 test_file = open(testcase_filename)
106 test = json.load(test_file)
107 logging.debug("testcase: %s", str(test))
108
109 # TODO: crosscheck the tests file against the breakpoints and the irq's
110 # available
111
112 locations = create_locations_from_file(breakpoints_filename)
113
114 self.debugger.clear_breakpoints()
115
116 # execute the test
117 steps = test['steps']
118 for i, step in enumerate(steps):
119
120 logging.info("---- Step %d ----", i)
121
122 continue_execution = False
123
124 if 'wait_for' in step:
125 bp_name = step['wait_for']
126 self.debugger.set_breakpoint(bp_name, locations[bp_name])
127 next_to_break_at = bp_name
128 continue_execution = True
129 elif 'expect' in step:
130 bp_name = step['expect']
131 self.debugger.set_breakpoint(bp_name, locations[bp_name])
132 next_to_break_at = bp_name
133
134 # Find the next wait_for in the test sequence, and set a
135 # breakpoint for that as well. So that it can be detected if an
136 # expected breakpoint is missed.
137
138 wait_for_found = False
139 ii = i+1
140
141 while ii < len(steps) and not wait_for_found:
142 next_step = steps[ii]
143 if 'wait_for' in next_step:
144 next_bp_name = next_step['wait_for']
145 self.debugger.set_breakpoint(next_bp_name,
146 locations[next_bp_name])
147 wait_for_found = True
148 ii += 1
149
150 continue_execution = True
151
152
153 if 'trigger' in step:
154 irqs_dict = irqs['irqs']
155 irq = irqs_dict[step['trigger']]
156 line_nu = irq['line_num']
157 self.debugger.trigger_interrupt(line_nu)
158
159
160 if continue_execution:
161 self.debugger.continue_execution()
162
163 triggered_breakpoint = self.debugger.get_triggered_breakpoint()
164
165 if triggered_breakpoint is None:
166 logging.error("No breakpoint was hit?????")
167 exit(0)
168
169 if triggered_breakpoint != next_to_break_at:
170 logging.error("execution stopped at '%s' instead of '%s'",
171 triggered_breakpoint, next_to_break_at)
172 exit(0)
173 else:
174 logging.error("execution stopped as no breakpoint is set")
175 exit(1)
176
177 self.debugger.clear_breakpoints()
178
179 logging.info("All the steps in the test file are executed successfully"
180 " with the expected result.")