Skip to content

Commit bb5c2cf

Browse files
committed
Duplicate host tests for drivers
1 parent 0a759aa commit bb5c2cf

File tree

6 files changed

+606
-0
lines changed

6 files changed

+606
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""
2+
Copyright (c) 2011-2020, Arm Limited and affiliates
3+
SPDX-License-Identifier: Apache-2.0
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
18+
19+
import uuid
20+
from mbed_host_tests import BaseHostTest
21+
22+
class Device_Echo(BaseHostTest):
23+
24+
def _callback_repeat(self, key, value, _):
25+
self.send_kv(key, value)
26+
27+
def setup(self):
28+
self.register_callback("echo", self._callback_repeat)
29+
self.register_callback("echo_count", self._callback_repeat)
30+
31+
def teardown(self):
32+
pass
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
"""
2+
Copyright (c) 2018-2019 Arm Limited and affiliates.
3+
SPDX-License-Identifier: Apache-2.0
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
import time
18+
from mbed_host_tests import BaseHostTest
19+
20+
DEFAULT_SYNC_DELAY = 4.0
21+
22+
MSG_VALUE_WATCHDOG_PRESENT = 1
23+
MSG_VALUE_DUMMY = '0'
24+
MSG_VALUE_RESET_REASON_GET = 'get'
25+
MSG_VALUE_RESET_REASON_CLEAR = 'clear'
26+
MSG_VALUE_DEVICE_RESET_NVIC = 'nvic'
27+
MSG_VALUE_DEVICE_RESET_WATCHDOG = 'watchdog'
28+
29+
MSG_KEY_DEVICE_READY = 'ready'
30+
MSG_KEY_RESET_REASON_RAW = 'reason_raw'
31+
MSG_KEY_RESET_REASON = 'reason'
32+
MSG_KEY_DEVICE_RESET = 'reset'
33+
MSG_KEY_SYNC = '__sync'
34+
MSG_KEY_RESET_COMPLETE = 'reset_complete'
35+
36+
RESET_REASONS = {
37+
'POWER_ON': '0',
38+
'PIN_RESET': '1',
39+
'BROWN_OUT': '2',
40+
'SOFTWARE': '3',
41+
'WATCHDOG': '4',
42+
'LOCKUP': '5',
43+
'WAKE_LOW_POWER': '6',
44+
'ACCESS_ERROR': '7',
45+
'BOOT_ERROR': '8',
46+
'MULTIPLE': '9',
47+
'PLATFORM': '10',
48+
'UNKNOWN': '11'
49+
}
50+
51+
52+
def raise_if_different(expected, actual, text=''):
53+
"""Raise a RuntimeError if actual is different than expected."""
54+
if expected != actual:
55+
raise RuntimeError('{}Got {!r}, expected {!r}'
56+
.format(text, actual, expected))
57+
58+
59+
class ResetReasonTest(BaseHostTest):
60+
"""Test for the Reset Reason HAL API.
61+
62+
Given a device supporting a Reset Reason API.
63+
When the device is restarted using various methods.
64+
Then the device returns a correct reset reason for every restart.
65+
"""
66+
67+
def __init__(self):
68+
super(ResetReasonTest, self).__init__()
69+
self.device_reasons = None
70+
self.device_has_watchdog = None
71+
self.raw_reset_reasons = set()
72+
self.sync_delay = DEFAULT_SYNC_DELAY
73+
self.test_steps_sequence = self.test_steps()
74+
# Advance the coroutine to it's first yield statement.
75+
self.test_steps_sequence.send(None)
76+
77+
def setup(self):
78+
sync_delay = self.get_config_item('forced_reset_timeout')
79+
self.sync_delay = sync_delay if sync_delay is not None else DEFAULT_SYNC_DELAY
80+
self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready)
81+
self.register_callback(MSG_KEY_RESET_REASON_RAW, self.cb_reset_reason_raw)
82+
self.register_callback(MSG_KEY_RESET_REASON, self.cb_reset_reason)
83+
self.register_callback(MSG_KEY_DEVICE_RESET, self.cb_reset_reason)
84+
self.register_callback(MSG_KEY_RESET_COMPLETE, self.cb_reset_reason)
85+
86+
def cb_device_ready(self, key, value, timestamp):
87+
"""Request a raw value of the reset_reason register.
88+
89+
Additionally, save the device's reset_reason capabilities
90+
and the watchdog status on the first call.
91+
"""
92+
if self.device_reasons is None:
93+
reasons, wdg_status = (int(i, base=16) for i in value.split(','))
94+
self.device_has_watchdog = (wdg_status == MSG_VALUE_WATCHDOG_PRESENT)
95+
self.device_reasons = [k for k, v in RESET_REASONS.items() if (reasons & 1 << int(v))]
96+
self.send_kv(MSG_KEY_RESET_REASON_RAW, MSG_VALUE_RESET_REASON_GET)
97+
98+
def cb_reset_reason_raw(self, key, value, timestamp):
99+
"""Verify that the raw reset_reason register value is unique.
100+
101+
Fail the test suite if the raw reset_reason value is not unique.
102+
Request a platform independent reset_reason otherwise.
103+
"""
104+
if value in self.raw_reset_reasons:
105+
self.log('TEST FAILED: The raw reset reason is not unique. '
106+
'{!r} is already present in {!r}.'
107+
.format(value, self.raw_reset_reasons))
108+
self.notify_complete(False)
109+
else:
110+
self.raw_reset_reasons.add(value)
111+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_GET)
112+
113+
def cb_reset_reason(self, key, value, timestamp):
114+
"""Feed the test_steps coroutine with reset_reason value.
115+
116+
Pass the test suite if the coroutine yields True.
117+
Fail the test suite if the iterator stops or raises a RuntimeError.
118+
"""
119+
try:
120+
if self.test_steps_sequence.send(value):
121+
self.notify_complete(True)
122+
except (StopIteration, RuntimeError) as exc:
123+
self.log('TEST FAILED: {}'.format(exc))
124+
self.notify_complete(False)
125+
126+
def test_steps(self):
127+
"""Generate a sequence of test steps.
128+
129+
This coroutine calls yield to wait for the input from the device
130+
(the reset_reason). If the device gives the wrong response, the
131+
generator raises a RuntimeError exception and fails the test.
132+
"""
133+
# Ignore the first reason.
134+
__ignored_reset_reason = yield
135+
self.raw_reset_reasons.clear()
136+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
137+
__ignored_clear_ack = yield
138+
139+
# Request a NVIC_SystemReset() call.
140+
expected_reason = 'SOFTWARE'
141+
if expected_reason not in self.device_reasons:
142+
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
143+
else:
144+
# Request a NVIC_SystemReset() call.
145+
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC)
146+
__ignored_reset_ack = yield
147+
time.sleep(self.sync_delay)
148+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
149+
reset_reason = yield
150+
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
151+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
152+
__ignored_clear_ack = yield
153+
154+
# Reset the device using DAP.
155+
expected_reason = 'PIN_RESET'
156+
if expected_reason not in self.device_reasons:
157+
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
158+
else:
159+
self.reset()
160+
__ignored_reset_ack = yield # 'reset_complete'
161+
time.sleep(self.sync_delay)
162+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
163+
reset_reason = yield
164+
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
165+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
166+
__ignored_clear_ack = yield
167+
168+
# Start a watchdog timer and wait for it to reset the device.
169+
expected_reason = 'WATCHDOG'
170+
if expected_reason not in self.device_reasons or not self.device_has_watchdog:
171+
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
172+
else:
173+
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG)
174+
__ignored_reset_ack = yield
175+
time.sleep(self.sync_delay)
176+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
177+
reset_reason = yield
178+
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
179+
180+
# The sequence is correct -- test passed.
181+
yield True
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
Copyright (c) 2019 Arm Limited and affiliates.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
"""
18+
19+
from mbed_host_tests import BaseHostTest
20+
21+
22+
MSG_KEY_ECHO_MESSAGE = "echo_message"
23+
24+
25+
class SerialComms(BaseHostTest):
26+
"""Host side test that handles messages sent using serial classes."""
27+
28+
def __init__(self):
29+
"""Initialize an object."""
30+
super(SerialComms, self).__init__()
31+
32+
def setup(self):
33+
"""Register call backs to handle message from the target."""
34+
self.register_callback(MSG_KEY_ECHO_MESSAGE, self.cb_echo_message)
35+
36+
def cb_echo_message(self, key, value, timestamp):
37+
"""Send back the key and value received."""
38+
self.send_kv(key, value)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
Copyright (c) 2018-2019 Arm Limited and affiliates.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
"""
18+
import time
19+
from mbed_host_tests import BaseHostTest
20+
21+
DEFAULT_SYNC_DELAY = 4.0
22+
23+
MSG_VALUE_DUMMY = '0'
24+
MSG_KEY_DEVICE_READY = 'ready'
25+
MSG_KEY_START_CASE = 'start_case'
26+
MSG_KEY_DEVICE_RESET = 'reset_on_case_teardown'
27+
MSG_KEY_SYNC = '__sync'
28+
29+
30+
class SyncOnReset(BaseHostTest):
31+
"""Host side test that handles device reset during case teardown.
32+
33+
Given a device that performs a reset during a test case teardown.
34+
When the device notifies the host about the reset.
35+
Then the host:
36+
* keeps track of the test case index of the current test suite,
37+
* performs a dev-host handshake,
38+
* advances the test suite to next test case.
39+
40+
Note:
41+
Developed for a watchdog test, so that it can be run on devices that
42+
do not support watchdog timeout updates after the initial setup.
43+
As a solution, after testing watchdog with one set of settings, the
44+
device performs a reset and notifies the host with the test case number,
45+
so that the test suite may be advanced once the device boots again.
46+
"""
47+
48+
def __init__(self):
49+
super(SyncOnReset, self).__init__()
50+
self.test_case_num = 0
51+
self.sync_delay = DEFAULT_SYNC_DELAY
52+
53+
def setup(self):
54+
sync_delay = self.get_config_item('forced_reset_timeout')
55+
self.sync_delay = sync_delay if sync_delay is not None else DEFAULT_SYNC_DELAY
56+
self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready)
57+
self.register_callback(MSG_KEY_DEVICE_RESET, self.cb_device_reset)
58+
59+
def cb_device_ready(self, key, value, timestamp):
60+
"""Advance the device test suite to the next test case."""
61+
self.send_kv(MSG_KEY_START_CASE, self.test_case_num)
62+
63+
def cb_device_reset(self, key, value, timestamp):
64+
"""Wait for the device to boot and perform a handshake.
65+
66+
Additionally, keep track of the last test case number.
67+
"""
68+
try:
69+
self.test_case_num = int(value)
70+
except ValueError:
71+
pass
72+
self.test_case_num += 1
73+
time.sleep(self.sync_delay)
74+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)

0 commit comments

Comments
 (0)