Mbed Host Tests
base_host_test.py
Go to the documentation of this file.
1"""
2mbed SDK
3Copyright (c) 2011-2016 ARM Limited
4
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16"""
17
18import inspect
19from time import time
20from inspect import isfunction, ismethod
21
22
24 """ Base class for each host-test test cases with standard
25 setup, test and teardown set of functions
26 """
27
28 name = '' # name of the host test (used for local registration)
29 __event_queue = None # To main even loop
30 __dut_event_queue = None # To DUT
31 script_location = None # Path to source file used to load host test
32 __config = {}
33
34 def __notify_prn(self, text):
35 if self.__event_queue:
36 self.__event_queue.put(('__notify_prn', text, time()))
37
38 def __notify_conn_lost(self, text):
39 if self.__event_queue:
40 self.__event_queue.put(('__notify_conn_lost', text, time()))
41
42 def __notify_sync_failed(self, text):
43 if self.__event_queue:
44 self.__event_queue.put(('__notify_sync_failed', text, time()))
45
46 def __notify_dut(self, key, value):
47 """! Send data over serial to DUT """
48 if self.__dut_event_queue:
49 self.__dut_event_queue.put((key, value, time()))
50
51 def notify_complete(self, result=None):
52 """! Notify main even loop that host test finished processing
53 @param result True for success, False failure. If None - no action in main even loop
54 """
55 if self.__event_queue:
56 self.__event_queue.put(('__notify_complete', result, time()))
57
58 def reset_dut(self, value):
59 """
60 Reset device under test
61 :return:
62 """
63 if self.__event_queue:
64 self.__event_queue.put(('__reset_dut', value, time()))
65
66 def reset(self):
67 """
68 Reset the device under test and continue running the host test
69 :return:
70 """
71 if self.__event_queue:
72 self.__event_queue.put(("__reset", "0", time()))
73
74 def notify_conn_lost(self, text):
75 """! Notify main even loop that there was a DUT-host test connection error
76 @param consume If True htrun will process (consume) all remaining events
77 """
78 self.__notify_conn_lost(text)
79
80 def log(self, text):
81 """! Send log message to main event loop """
82 self.__notify_prn(text)
83
84 def send_kv(self, key, value):
85 """! Send Key-Value data to DUT """
86 self.__notify_dut(key, value)
87
88 def setup_communication(self, event_queue, dut_event_queue, config={}):
89 """! Setup queues used for IPC """
90 self.__event_queue = event_queue # To main even loop
91 self.__dut_event_queue = dut_event_queue # To DUT
92 self.__config__config = config
93
94 def get_config_item(self, name):
95 """
96 Return test config
97
98 :param name:
99 :return:
100 """
101 return self.__config__config.get(name, None)
102
103 def setup(self):
104 """! Setup your tests and callbacks """
105 raise NotImplementedError
106
107 def result(self):
108 """! Returns host test result (True, False or None) """
109 raise NotImplementedError
110
111 def teardown(self):
112 """! Blocking always guaranteed test teardown """
113 raise NotImplementedError
114
115
116def event_callback(key):
117 """
118 Decorator for defining a event callback method. Adds a property attribute "event_key" with value as the passed key.
119
120 :param key:
121 :return:
122 """
123 def decorator(func):
124 func.event_key = key
125 return func
126 return decorator
127
128
130
131 def __init__(self):
132 BaseHostTestAbstract.__init__(self)
133 self.__callbacks = {}
135 '__coverage_start',
136 '__testcase_start',
137 '__testcase_finish',
138 '__testcase_summary',
139 '__exit',
140 '__exit_event_queue'
141 ]
142
143 self.__consume_by_default = [
144 '__coverage_start',
145 '__testcase_start',
146 '__testcase_finish',
147 '__testcase_count',
148 '__testcase_name',
149 '__testcase_summary',
150 '__rxd_line',
151 ]
152
155
156 def __callback_default(self, key, value, timestamp):
157 """! Default callback """
158 #self.log("CALLBACK: key=%s, value=%s, timestamp=%f"% (key, value, timestamp))
159 pass
160
161 def __default_end_callback(self, key, value, timestamp):
162 """
163 Default handler for event 'end' that gives test result from target.
164 This callback is not decorated as we don't know then in what order this
165 callback would be registered. We want to let users over write this callback.
166 Hence it should be registered before registering user defined callbacks.
167
168 :param key:
169 :param value:
170 :param timestamp:
171 :return:
172 """
173 self.notify_complete(value == 'success')
174
175 def __assign_default_callbacks(self):
176 """! Assigns default callback handlers """
177 for key in self.__consume_by_default:
178 self.__callbacks[key] = self.__callback_default
179 # Register default handler for event 'end' before assigning user defined callbacks to let users over write it.
180 self.register_callback('end', self.__default_end_callback)
181
182 def __assign_decorated_callbacks(self):
183 """
184 It looks for any callback methods decorated with @event_callback
185
186 Example:
187 Define a method with @event_callback decorator like:
188
189 @event_callback('<event key>')
190 def event_handler(self, key, value, timestamp):
191 do something..
192
193 :return:
194 """
195 for name, method in inspect.getmembers(self, inspect.ismethod):
196 key = getattr(method, 'event_key', None)
197 if key:
198 self.register_callback(key, method)
199
200 def register_callback(self, key, callback, force=False):
201 """! Register callback for a specific event (key: event name)
202 @param key String with name of the event
203 @param callback Callable which will be registstered for event "key"
204 @param force God mode
205 """
206
207 # Non-string keys are not allowed
208 if type(key) is not str:
209 raise TypeError("event non-string keys are not allowed")
210
211 # And finally callback should be callable
212 if not callable(callback):
213 raise TypeError("event callback should be callable")
214
215 # Check if callback has all three required parameters (key, value, timestamp)
216 # When callback is class method should have 4 arguments (self, key, value, timestamp)
217 if ismethod(callback):
218 arg_count = callback.__code__.co_argcount
219 if arg_count != 4:
220 err_msg = "callback 'self.%s('%s', ...)' defined with %d arguments"% (callback.__name__, key, arg_count)
221 err_msg += ", should have 4 arguments: self.%s(self, key, value, timestamp)"% callback.__name__
222 raise TypeError(err_msg)
223
224 # When callback is just a function should have 3 arguments func(key, value, timestamp)
225 if isfunction(callback):
226 arg_count = callback.__code__.co_argcount
227 if arg_count != 3:
228 err_msg = "callback '%s('%s', ...)' defined with %d arguments"% (callback.__name__, key, arg_count)
229 err_msg += ", should have 3 arguments: %s(key, value, timestamp)"% callback.__name__
230 raise TypeError(err_msg)
231
232 if not force:
233 # Event starting with '__' are reserved
234 if key.startswith('__'):
235 raise ValueError("event key starting with '__' are reserved")
236
237 # We predefined few callbacks you can't use
238 if key in self.__restricted_callbacks:
239 raise ValueError("we predefined few callbacks you can't use e.g. '%s'"% key)
240
241 self.__callbacks[key] = callback
242
243 def get_callbacks(self):
244 return self.__callbacks
245
246 def setup(self):
247 pass
248
249 def result(self):
250 pass
251
252 def teardown(self):
253 pass
254
255
256class BaseHostTest(HostTestCallbackBase):
257
258 __BaseHostTest_Called = False
259
261 """ This function will check if BaseHostTest ctor was called
262 Call to BaseHostTest is required in order to force required
263 interfaces implementation.
264 @return Returns True if ctor was called (ok behaviour)
265 """
267
268 def __init__(self):
269 HostTestCallbackBase.__init__(self)
271
send_kv(self, key, value)
Send Key-Value data to DUT.
result(self)
Returns host test result (True, False or None)
notify_complete(self, result=None)
Notify main even loop that host test finished processing.
teardown(self)
Blocking always guaranteed test teardown.
log(self, text)
Send log message to main event loop.
notify_conn_lost(self, text)
Notify main even loop that there was a DUT-host test connection error.
setup_communication(self, event_queue, dut_event_queue, config={})
Setup queues used for IPC.
result(self)
Returns host test result (True, False or None)
teardown(self)
Blocking always guaranteed test teardown.
register_callback(self, key, callback, force=False)
Register callback for a specific event (key: event name)