Skip to content

Commit 5941d17

Browse files
authored
Merge pull request #11023 from ARMmbed/release-candidate
Release candidate for mbed-os-5.13.1
2 parents 7482462 + 4bf9e23 commit 5941d17

File tree

1,375 files changed

+262094
-95547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,375 files changed

+262094
-95547
lines changed

TESTS/host_tests/pyusb_msd.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,17 @@ def _callback_unmount(self, key, value, timestamp):
127127
else:
128128
self.report_error("unmount")
129129

130+
def _callback_os_type(self, key, value, timestamp):
131+
system_name = platform.system()
132+
if system_name == "Windows":
133+
self.send_kv("os_type", 1)
134+
elif system_name == "Linux":
135+
self.send_kv("os_type", 2)
136+
elif system_name == "Darwin":
137+
self.send_kv("os_type", 3)
138+
130139
def setup(self):
140+
self.register_callback("get_os_type", self._callback_os_type)
131141
self.register_callback("get_serial_number", self._callback_device_ready)
132142
self.register_callback('check_if_mounted', self._callback_check_if_mounted)
133143
self.register_callback('check_if_not_mounted', self._callback_check_if_not_mounted)
@@ -204,25 +214,16 @@ def _disk_path_mac(serial):
204214
@staticmethod
205215
def _unmount_windows(serial):
206216
disk_path = MSDUtils._disk_path_windows(serial)
207-
tmp_file = tempfile.NamedTemporaryFile(suffix='.ps1', delete=False)
208-
try:
209-
# create unmount script
210-
tmp_file.write('$disk_leter=$args[0]\n')
211-
tmp_file.write('$driveEject = New-Object -comObject Shell.Application\n')
212-
tmp_file.write('$driveEject.Namespace(17).ParseName($disk_leter).InvokeVerb("Eject")\n')
213-
# close to allow open by other process
214-
tmp_file.close()
215-
216-
try_count = 10
217-
while try_count:
218-
p = subprocess.Popen(["powershell.exe", tmp_file.name + " " + disk_path], stdout=sys.stdout)
219-
p.communicate()
220-
try_count -= 1
221-
if MSDUtils._disk_path_windows(serial) is None:
222-
return True
223-
time.sleep(1)
224-
finally:
225-
os.remove(tmp_file.name)
217+
cmd_string = r'(New-Object -comObject Shell.Application).Namespace(17).ParseName("{}").InvokeVerb("Eject")'.format(disk_path)
218+
219+
try_count = 10
220+
while try_count:
221+
p = subprocess.Popen(["powershell.exe", cmd_string], stdout=sys.stdout)
222+
p.communicate()
223+
try_count -= 1
224+
if MSDUtils._disk_path_windows(serial) is None:
225+
return True
226+
time.sleep(1)
226227

227228
return False
228229

TESTS/host_tests/reset_reason.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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+
from mbed_host_tests.host_tests_runner.host_test_default import DefaultTestSelector
20+
21+
DEFAULT_SYNC_DELAY = 4.0
22+
23+
MSG_VALUE_WATCHDOG_PRESENT = 'wdg_present'
24+
MSG_VALUE_DUMMY = '0'
25+
MSG_VALUE_RESET_REASON_GET = 'get'
26+
MSG_VALUE_RESET_REASON_CLEAR = 'clear'
27+
MSG_VALUE_DEVICE_RESET_NVIC = 'nvic'
28+
MSG_VALUE_DEVICE_RESET_WATCHDOG = 'watchdog'
29+
30+
MSG_KEY_DEVICE_READY = 'ready'
31+
MSG_KEY_RESET_REASON_RAW = 'reason_raw'
32+
MSG_KEY_RESET_REASON = 'reason'
33+
MSG_KEY_DEVICE_RESET = 'reset'
34+
MSG_KEY_SYNC = '__sync'
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_has_watchdog = None
70+
self.raw_reset_reasons = set()
71+
self.sync_delay = DEFAULT_SYNC_DELAY
72+
self.test_steps_sequence = self.test_steps()
73+
# Advance the coroutine to it's first yield statement.
74+
self.test_steps_sequence.send(None)
75+
76+
def setup(self):
77+
sync_delay = self.get_config_item('forced_reset_timeout')
78+
self.sync_delay = sync_delay if sync_delay is not None else DEFAULT_SYNC_DELAY
79+
self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready)
80+
self.register_callback(MSG_KEY_RESET_REASON_RAW, self.cb_reset_reason_raw)
81+
self.register_callback(MSG_KEY_RESET_REASON, self.cb_reset_reason)
82+
self.register_callback(MSG_KEY_DEVICE_RESET, self.cb_reset_reason)
83+
84+
def cb_device_ready(self, key, value, timestamp):
85+
"""Request a raw value of the reset_reason register.
86+
87+
Additionally, save the device's watchdog status on the first call.
88+
"""
89+
if self.device_has_watchdog is None:
90+
self.device_has_watchdog = (value == MSG_VALUE_WATCHDOG_PRESENT)
91+
self.send_kv(MSG_KEY_RESET_REASON_RAW, MSG_VALUE_RESET_REASON_GET)
92+
93+
def cb_reset_reason_raw(self, key, value, timestamp):
94+
"""Verify that the raw reset_reason register value is unique.
95+
96+
Fail the test suite if the raw reset_reason value is not unique.
97+
Request a platform independent reset_reason otherwise.
98+
"""
99+
if value in self.raw_reset_reasons:
100+
self.log('TEST FAILED: The raw reset reason is not unique. '
101+
'{!r} is already present in {!r}.'
102+
.format(value, self.raw_reset_reasons))
103+
self.notify_complete(False)
104+
else:
105+
self.raw_reset_reasons.add(value)
106+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_GET)
107+
108+
def cb_reset_reason(self, key, value, timestamp):
109+
"""Feed the test_steps coroutine with reset_reason value.
110+
111+
Pass the test suite if the coroutine yields True.
112+
Fail the test suite if the iterator stops or raises a RuntimeError.
113+
"""
114+
try:
115+
if self.test_steps_sequence.send(value):
116+
self.notify_complete(True)
117+
except (StopIteration, RuntimeError) as exc:
118+
self.log('TEST FAILED: {}'.format(exc))
119+
self.notify_complete(False)
120+
121+
def test_steps(self):
122+
"""Generate a sequence of test steps.
123+
124+
This coroutine calls yield to wait for the input from the device
125+
(the reset_reason). If the device gives the wrong response, the
126+
generator raises a RuntimeError exception and fails the test.
127+
"""
128+
# Ignore the first reason.
129+
__ignored_reset_reason = yield
130+
self.raw_reset_reasons.clear()
131+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
132+
__ignored_clear_ack = yield
133+
134+
# Request a NVIC_SystemReset() call.
135+
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC)
136+
__ignored_reset_ack = yield
137+
time.sleep(self.sync_delay)
138+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
139+
reset_reason = yield
140+
raise_if_different(RESET_REASONS['SOFTWARE'], reset_reason, 'Wrong reset reason. ')
141+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
142+
__ignored_clear_ack = yield
143+
144+
# Reset the device using DAP.
145+
self.reset_dut(DefaultTestSelector.RESET_TYPE_SW_RST)
146+
reset_reason = yield
147+
raise_if_different(RESET_REASONS['PIN_RESET'], reset_reason, 'Wrong reset reason. ')
148+
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
149+
__ignored_clear_ack = yield
150+
151+
# Start a watchdog timer and wait for it to reset the device.
152+
if not self.device_has_watchdog:
153+
self.log('DUT does not have a watchdog. Skipping this reset reason.')
154+
else:
155+
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG)
156+
__ignored_reset_ack = yield
157+
time.sleep(self.sync_delay)
158+
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
159+
reset_reason = yield
160+
raise_if_different(RESET_REASONS['WATCHDOG'], reset_reason, 'Wrong reset reason. ')
161+
162+
# The sequence is correct -- test passed.
163+
yield True

TESTS/host_tests/sync_on_reset.py

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)