diff --git a/tools/harness-automation/autothreadharness/harness_case.py b/tools/harness-automation/autothreadharness/harness_case.py index a187cde4e..cdba8e6e0 100644 --- a/tools/harness-automation/autothreadharness/harness_case.py +++ b/tools/harness-automation/autothreadharness/harness_case.py @@ -54,6 +54,9 @@ THREAD_CHANNEL_MAX = 26 THREAD_CHANNEL_MIN = 11 """Minimum channel number of thread protocol""" +DEFAULT_TIMEOUT = 2700 +"""Timeout for each test case in seconds""" + class HarnessCase(unittest.TestCase): """This is the case class of all automation test cases. @@ -118,6 +121,8 @@ class HarnessCase(unittest.TestCase): auto_dut = settings.AUTO_DUT """bool: whether use harness auto dut feature""" + timeout = hasattr(settings, 'TIMEOUT') and settings.TIMEOUT or DEFAULT_TIMEOUT + def wait_until(self, what, times=-1): """Wait until `what` return True @@ -412,8 +417,6 @@ class HarnessCase(unittest.TestCase): raise Exception('Golden devices is not enough') device_type_id = settings.GOLDEN_DEVICE_TYPE - if device_type_id == 'OpenThread': - device_type_id = 'ARM' while golden_devices_required: device = browser.find_element_by_id(device_type_id) @@ -445,7 +448,7 @@ class HarnessCase(unittest.TestCase): self._connect_devices() button_next = browser.find_element_by_id('nextBtn') if not self.wait_until(lambda: 'disabled' not in button_next.get_attribute('class'), - times=(30 + 3 * golden_devices_required)): + times=(30 + 4 * self.golden_devices_required)): bad_ones = [] for selected_hw in selected_hw_set: form_inputs = selected_hw.find_elements_by_tag_name('input') @@ -523,12 +526,14 @@ class HarnessCase(unittest.TestCase): checkbox = None self.wait_until(lambda: self._browser.find_elements_by_css_selector('.tree-node .tree-title') and True) elems = self._browser.find_elements_by_css_selector('.tree-node .tree-title') + finder = re.compile(r'.*\b' + case + r'\b') + finder_dotted = re.compile(r'.*\b' + case.replace(' ', r'\.') + r'\b') for elem in elems: action_chains = ActionChains(self._browser) action_chains.move_to_element(elem) action_chains.perform() logger.debug(elem.text) - if elem.text.startswith(case): + if finder.match(elem.text) or finder_dotted.match(elem.text): parent = elem.find_element_by_xpath('..') checkbox = parent.find_element_by_class_name('tree-checkbox') break @@ -590,12 +595,12 @@ class HarnessCase(unittest.TestCase): self._browser.switch_to.window(main_window) timestamp = time.strftime('%Y%m%d%H%M%S') - os.system('move "%%HOMEPATH%%\\Downloads\\NewPdf_*.pdf" %s\\%s-%s.pdf' - % (self.result_dir, self.__class__.__name__, timestamp)) - os.system('move "%%HOMEPATH%%\\Downloads\\ExcelReport*.xlsx" %s\\%s-%s.xlsx' - % (self.result_dir, self.__class__.__name__, timestamp)) - os.system('move "%s\\Captures\\*.pcapng" %s\\%s-%s.pcapng' - % (settings.HARNESS_HOME, self.result_dir, self.__class__.__name__, timestamp)) + os.system('copy "%%HOMEPATH%%\\Downloads\\NewPdf_*.pdf" %s\\' + % self.result_dir) + os.system('copy "%%HOMEPATH%%\\Downloads\\ExcelReport_*.xlsx" %s\\' + % self.result_dir) + os.system('copy "%s\\Captures\\*.pcapng" %s\\' + % (settings.HARNESS_HOME, self.result_dir)) os.system('copy "%s\\Thread_Harness\\temp\\*.*" "%s"' % (settings.HARNESS_HOME, self.result_dir)) @@ -605,7 +610,8 @@ class HarnessCase(unittest.TestCase): logger.debug('waiting for dialog') done = False error = False - while not done: + + while not done and self.timeout: try: dialog = self._browser.find_element_by_id('RemoteConfirm') except: @@ -640,6 +646,8 @@ class HarnessCase(unittest.TestCase): time.sleep(5) done = True + self.timeout -= 1 + # Wait until case really stopped self.wait_until(lambda: self._browser.find_element_by_id('runTest') and True, 30) diff --git a/tools/harness-automation/autothreadharness/open_thread_controller.py b/tools/harness-automation/autothreadharness/open_thread_controller.py index 7828ea3d2..c87be917b 100644 --- a/tools/harness-automation/autothreadharness/open_thread_controller.py +++ b/tools/harness-automation/autothreadharness/open_thread_controller.py @@ -118,7 +118,7 @@ class OpenThreadController(threading.Thread): else: self.handle.write(data) - def _expect(self, expected, times=10): + def _expect(self, expected, times=50): """Find the `expected` line within `times` trials. Args: @@ -126,17 +126,19 @@ class OpenThreadController(threading.Thread): times int: number of trials """ logger.debug('[%s] Expecting [%s]' % (self.port, expected)) - + retry_times = 10 for i in range(0, times): + if not retry_times: + break + line = self._readline() - logger.debug('[%s] Got line [%s]' % (self.port, line)) if line == expected: - logger.debug('[%s] Expected [%s]' % (self.port, expected)) return if not line: - time.sleep(1) + retry_times -= 1 + time.sleep(0.1) raise Exception('failed to find expected string[%s]' % expected) @@ -179,7 +181,7 @@ class OpenThreadController(threading.Thread): self._write(line + '\r\n') # wait for write to complete - time.sleep(0.1) + time.sleep(0.5) def _req(self, req): """Send command and wait for response. @@ -208,7 +210,7 @@ class OpenThreadController(threading.Thread): while True: line = self._readline() - logger.debug(line) + logger.debug('Got line %s', line) if line == 'Done': break diff --git a/tools/harness-automation/cases/commissioner_8_2_1.py b/tools/harness-automation/cases/commissioner_8_2_1.py index 05bfc480d..6dfb9a760 100644 --- a/tools/harness-automation/cases/commissioner_8_2_1.py +++ b/tools/harness-automation/cases/commissioner_8_2_1.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Commissioner_8_2_1(HarnessCase): role = HarnessCase.ROLE_COMMISSIONER - case = '! 8 2 1' + case = '8 2 1' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/cases/commissioner_8_2_2.py b/tools/harness-automation/cases/commissioner_8_2_2.py index d4ff27c35..9c0c90760 100644 --- a/tools/harness-automation/cases/commissioner_8_2_2.py +++ b/tools/harness-automation/cases/commissioner_8_2_2.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Commissioner_8_2_2(HarnessCase): role = HarnessCase.ROLE_COMMISSIONER - case = '! 8 2 2' + case = '8 2 2' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/cases/commissioner_8_2_5.py b/tools/harness-automation/cases/commissioner_8_2_5.py index fbe082c3c..d5977562c 100644 --- a/tools/harness-automation/cases/commissioner_8_2_5.py +++ b/tools/harness-automation/cases/commissioner_8_2_5.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Commissioner_8_2_5(HarnessCase): role = HarnessCase.ROLE_COMMISSIONER - case = '! 8 2 5' + case = '8 2 5' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/cases/commissioner_8_2_6.py b/tools/harness-automation/cases/commissioner_8_2_6.py deleted file mode 100644 index 31bb7128c..000000000 --- a/tools/harness-automation/cases/commissioner_8_2_6.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - - -import unittest - -from autothreadharness.harness_case import HarnessCase - -class Commissioner_8_2_6(HarnessCase): - role = HarnessCase.ROLE_COMMISSIONER - case = '8 2 6' - golden_devices_required = 2 - def on_dialog(self, dialog, title): - pass - -if __name__ == '__main__': - unittest.main() diff --git a/tools/harness-automation/cases/ed_6_1_7.py b/tools/harness-automation/cases/ed_6_1_7.py deleted file mode 100644 index 3fd5111f9..000000000 --- a/tools/harness-automation/cases/ed_6_1_7.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2016, The OpenThread Authors. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the copyright holder nor the -# names of its contributors may be used to endorse or promote products -# derived from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# - - -import unittest - -from autothreadharness.harness_case import HarnessCase - -class ED_6_1_7(HarnessCase): - suite = 32 - case = '6 1 7' - golden_devices_required = 4 - def on_dialog(self, dialog, title): - pass - -if __name__ == '__main__': - unittest.main() diff --git a/tools/harness-automation/cases/med_6_3_2.py b/tools/harness-automation/cases/med_6_3_2.py index caab0ebea..201945b45 100644 --- a/tools/harness-automation/cases/med_6_3_2.py +++ b/tools/harness-automation/cases/med_6_3_2.py @@ -32,7 +32,7 @@ import unittest from autothreadharness.harness_case import HarnessCase -class ED_6_3_2(HarnessCase): +class MED_6_3_2(HarnessCase): role = HarnessCase.ROLE_MED case = '6 3 2' golden_devices_required = 1 diff --git a/tools/harness-automation/cases/router_8_2_1.py b/tools/harness-automation/cases/router_8_2_1.py index 3f75c424e..0552ccd0f 100644 --- a/tools/harness-automation/cases/router_8_2_1.py +++ b/tools/harness-automation/cases/router_8_2_1.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Router_8_2_1(HarnessCase): role = HarnessCase.ROLE_ROUTER - case = '! 8 2 1' + case = '8 2 1' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/cases/router_8_2_2.py b/tools/harness-automation/cases/router_8_2_2.py index ae939ad61..175160b19 100644 --- a/tools/harness-automation/cases/router_8_2_2.py +++ b/tools/harness-automation/cases/router_8_2_2.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Router_8_2_2(HarnessCase): role = HarnessCase.ROLE_ROUTER - case = '! 8 2 2' + case = '8 2 2' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/cases/router_8_2_5.py b/tools/harness-automation/cases/router_8_2_5.py index afa8d32cc..0aeb14360 100644 --- a/tools/harness-automation/cases/router_8_2_5.py +++ b/tools/harness-automation/cases/router_8_2_5.py @@ -34,7 +34,7 @@ from autothreadharness.harness_case import HarnessCase class Router_8_2_5(HarnessCase): role = HarnessCase.ROLE_ROUTER - case = '! 8 2 5' + case = '8 2 5' golden_devices_required = 2 def on_dialog(self, dialog, title): pass diff --git a/tools/harness-automation/requirements.txt b/tools/harness-automation/requirements.txt index 98725daf1..e36117d68 100644 --- a/tools/harness-automation/requirements.txt +++ b/tools/harness-automation/requirements.txt @@ -1,4 +1,2 @@ pyserial -pexpect -pexpect_serial selenium diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py old mode 100644 new mode 100755 index 138b8964b..052cc4110 --- a/tools/harness-thci/OpenThread.py +++ b/tools/harness-thci/OpenThread.py @@ -98,7 +98,7 @@ class OpenThread(IThci): except Exception, e: ModuleHelper.WriteIntoDebugLogger("delete() Error: " + str(e)) - def _expect(self, expected, times=100): + def _expect(self, expected, times=50): """Find the `expected` line within `times` trials. Args: @@ -107,7 +107,11 @@ class OpenThread(IThci): """ print '[%s] Expecting [%s]' % (self.port, expected) + retry_times = 10 for i in range(0, times): + if not retry_times: + break + line = self._readline() print '[%s] Got line [%s]' % (self.port, line) @@ -116,7 +120,8 @@ class OpenThread(IThci): return if not line: - time.sleep(1) + retry_times -= 1 + time.sleep(0.1) raise Exception('failed to find expected string[%s]' % expected) @@ -696,7 +701,6 @@ class OpenThread(IThci): except Exception, e: ModuleHelper.WriteIntoDebugLogger("intialize() Error: " + str(e)) self.deviceConnected = False - sys.exit() def setNetworkName(self, networkName='GRL'): """set Thread Network name