Merge branch 'PrzemekWirkus-host-test-plugin-improvements'

pull/606/head
0xc0170 2014-10-27 08:09:47 +00:00
commit 7c67a393f1
14 changed files with 831 additions and 233 deletions

View File

@ -22,18 +22,17 @@ except ImportError, e:
print "Error: Can't import 'serial' module: %s"% e
exit(-1)
import os
from sys import stdout
from time import sleep, time
from optparse import OptionParser
import host_tests_plugins
# This is a little tricky. We need to add upper directory to path so
# we can find packages we want from the same level as other files do
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
from workspace_tools.settings import EACOMMANDER_CMD
class Mbed:
@ -158,27 +157,6 @@ class Mbed:
result = None
return result
def safe_sendBreak(self, serial):
""" Wraps serial.sendBreak() to avoid serial::serialposix.py exception on Linux
Traceback (most recent call last):
File "make.py", line 189, in <module>
serial.sendBreak()
File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 511, in sendBreak
termios.tcsendbreak(self.fd, int(duration/0.25))
error: (32, 'Broken pipe')
"""
result = True
try:
serial.sendBreak()
except:
# In linux a termios.error is raised in sendBreak and in setBreak.
# The following setBreak() is needed to release the reset signal on the target mcu.
try:
serial.setBreak(False)
except:
result = False
return result
def touch_file(self, path):
""" Touch file and set timestamp to items
"""
@ -192,56 +170,15 @@ class Mbed:
sleep(1)
def reset(self):
""" Reset function.
Supports:
- 'standard' send break command via Mbed's CDC,
- also handles other reset modes:
- E.g. reset by touching file with specific file name:
reboot.txt - startup from standby state, reboots when in run mode.
shutdown.txt - shutdown from run mode
reset.txt - reset FPGA during run mode
- eACommander for reset of SiLabs Gecko baords.
""" Calls proper reset plugin to do the job.
Please refer to host_test_plugins functionality
"""
if self.options.forced_reset_type:
if self.options.forced_reset_type == 'eACommander':
# For this copy method 'disk' will be 'serialno' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [EACOMMANDER_CMD,
'--serialno', self.disk.rstrip('/\\'),
'--resettype', '2', '--reset',]
try:
self.flush()
ret = call(cmd, shell=True)
if ret:
resutl_msg = "Return code: %d. Command: "% ret + " ".join(cmd)
result = False
except Exception, e:
resutl_msg = e
result = False
elif self.options.forced_reset_type == 'eACommander-usb':
# For this copy method 'disk' will be 'usb address' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [EACOMMANDER_CMD,
'--usb', self.disk.rstrip('/\\'),
'--resettype', '2', '--reset',]
try:
self.flush()
ret = call(cmd, shell=True)
if ret:
resutl_msg = "Return code: %d. Command: "% ret + " ".join(cmd)
result = False
except Exception, e:
resutl_msg = e
result = False
elif self.options.forced_reset_type.endswith('.txt'):
reset_file_path = os.path.join(self.disk, self.options.forced_reset_type.lower())
self.touch_file(reset_file_path)
self.flush()
else:
self.safe_sendBreak(self.serial) # Instead of serial.sendBreak()
self.flush()
# Flush serials to get only input after reset
#self.flush()
self.flush()
if self.options.forced_reset_type:
host_tests_plugins.call_plugin('ResetMethod', self.options.forced_reset_type, disk=self.disk)
else:
host_tests_plugins.call_plugin('ResetMethod', 'default', serial=self.serial)
# Give time to wait for the image loading
reset_tout_s = self.options.forced_reset_timeout if self.options.forced_reset_timeout is not None else self.DEFAULT_RESET_TOUT
self.reset_timeout(reset_tout_s)
@ -275,20 +212,17 @@ class Test(TestResults):
def run(self):
""" Test runner for host test. This function will start executing
test() function and forward test result via serial port to test suite
test and forward test result via serial port to test suite
"""
try:
# We expect here output from test in one of possible statuses
# E.g. self.RESULT_SUCCESS, self.RESULT_FAILURE, self.RESULT_ERROR
result_status = self.test()
self.print_result(result_status)
result = self.test()
self.print_result(self.RESULT_SUCCESS if result else self.RESULT_FAILURE)
except Exception, e:
self.notify(str(e))
print str(e)
self.print_result(self.RESULT_ERROR)
def setup(self):
""" Setup and check if configuration for test is correct.
E.g. if serial port can be opened
""" Setup and check if configuration for test is correct. E.g. if serial port can be opened
"""
result = True
if not self.mbed.serial:
@ -325,19 +259,17 @@ class Simple(DefaultTest):
output from MUT, no supervision over test running in MUT is executed.
Just waiting for result
"""
def test(self):
def run(self):
try:
while True:
c = self.mbed.serial_read(512)
if c is None:
return self.RESULT_IO_SERIAL
self.print_result(self.RESULT_IO_SERIAL)
break
stdout.write(c)
stdout.flush()
except KeyboardInterrupt, _:
self.notify("\r\n[CTRL+C] exit")
# If this function ends we assume user break or exception
# occured and error should be issued to test suite
return self.RESULT_ERROR
if __name__ == '__main__':

View File

@ -0,0 +1,59 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import host_test_registry
# This plugins provide 'flashing' methods to host test scripts
import module_copy_mbed
import module_copy_shell
import module_copy_firefox
import module_copy_silabs
# Plugins used to reset certain platform
import module_reset_mbed
import module_reset_mps2
import module_reset_silabs
# Plugin registry instance
HOST_TEST_PLUGIN_REGISTRY = host_test_registry.HostTestRegistry()
# Static plugin registration
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_copy_mbed.load_plugin())
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_copy_shell.load_plugin())
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_copy_firefox.load_plugin())
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_copy_silabs.load_plugin())
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_reset_mbed.load_plugin())
# Extra supported by default platforms
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_reset_mps2.load_plugin())
HOST_TEST_PLUGIN_REGISTRY.register_plugin(module_reset_silabs.load_plugin())
# TODO: extend plugin loading to files with name module_*.py loaded ad-hoc
###############################################################################
# Functional interface for host test plugin registry
###############################################################################
def call_plugin(type, capability, *args, **kwargs):
""" Interface to call plugin registry functional way
"""
return HOST_TEST_PLUGIN_REGISTRY.call_plugin(type, capability, *args, **kwargs)
def print_plugin_info():
""" Prints plugins' information in user friendly way
"""
print HOST_TEST_PLUGIN_REGISTRY

View File

@ -0,0 +1,86 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from subprocess import call
class HostTestPluginBase:
""" Base class for all plug-ins used with host tests.
"""
###########################################################################
# Interface:
###########################################################################
###########################################################################
# Interface attributes defining plugin name, type etc.
###########################################################################
name = "HostTestPluginBase" # Plugin name, can be plugin class name
type = "BasePlugin" # Plugin type: ResetMethod, Copymethod etc.
capabilities = [] # Capabilities names: what plugin can achieve
# (e.g. reset using some external command line tool)
stable = False # Determine if plugin is stable and can be used
###########################################################################
# Interface methods
###########################################################################
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
return False
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability e.g. may directly just call some command line
program or execute building pythonic function
"""
return False
###########################################################################
# Interface helper methods - overload only if you need to have custom behaviour
###########################################################################
def print_plugin_error(self, text):
""" Function prints error in console and exits always with False
"""
print "Plugin error: %s::%s: %s"% (self.name, self.type, text)
return False
def check_parameters(self, capabilitity, *args, **kwargs):
""" This function should be ran each time we call execute()
to check if none of the required parameters is missing.
"""
missing_parameters = []
for parameter in self.required_parameters:
if parameter not in kwargs:
missing_parameters.append(parameter)
if len(missing_parameters) > 0:
self.print_plugin_error("execute parameter(s) '%s' missing!"% (', '.join(parameter)))
return False
return True
def run_command(self, cmd, shell=True):
""" Runs command from command line.
"""
result = True
try:
ret = call(cmd, shell=shell)
if ret:
self.print_plugin_error("[ret=%d] Command: %s"% (self.name, self.type, ret, ' '.join(cmd)))
except Exception, e:
result = False
self.print_plugin_error("[ret=%d] Command: %s"% (self.name, self.type, ret, " ".join(cmd)))
self.print_plugin_error("%s::%s: " + str(e))
return result

View File

@ -0,0 +1,77 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
class HostTestRegistry:
""" Simple class used to register and store
host test plugins for further usage
"""
# Here we actually store all the plugins
PLUGINS = {} # 'Plugin Name' : Plugin Object
def print_error(self, text):
print "Plugin load failed. Reason: %s"% text
def register_plugin(self, plugin):
""" Registers and stores plugin inside registry for further use.
Method also calls plugin's setup() function to configure plugin if needed.
Note: Different groups of plugins may demand different extra parameter. Plugins
should be at least for one type of plugin configured with the same parameters
because we do not know which of them will actually use particular parameter.
"""
# TODO:
# - check for unique caps for specified type
if plugin.name not in self.PLUGINS:
if plugin.setup(): # Setup plugin can be completed without errors
self.PLUGINS[plugin.name] = plugin
return True
else:
self.print_error("%s setup failed"% plugin.name)
self.print_error("%s already loaded"% plugin.name)
return False
def call_plugin(self, type, capability, *args, **kwargs):
""" Execute plugin functionality respectively to its purpose
"""
for plugin_name in self.PLUGINS:
plugin = self.PLUGINS[plugin_name]
if plugin.type == type and capability in plugin.capabilities:
return plugin.execute(capability, *args, **kwargs)
return False
def load_plugin(self, name):
""" Used to load module from
"""
mod = __import__("module_%s"% name)
return mod
def __str__(self):
""" User friendly printing method to show hooked plugins
"""
from prettytable import PrettyTable
column_names = ['name', 'type', 'capabilities', 'stable']
pt = PrettyTable(column_names)
for column in column_names:
pt.align[column] = 'l'
for plugin_name in sorted(self.PLUGINS.keys()):
name = self.PLUGINS[plugin_name].name
type = self.PLUGINS[plugin_name].type
stable = self.PLUGINS[plugin_name].stable
capabilities = ', '.join(self.PLUGINS[plugin_name].capabilities)
row = [name, type, capabilities, stable]
pt.add_row(row)
return pt.get_string()

View File

@ -0,0 +1,76 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from os.path import join, basename
from host_test_plugins import HostTestPluginBase
class HostTestPluginCopyMethod_Firefox(HostTestPluginBase):
def file_store_firefox(self, file_path, dest_disk):
try:
from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.folderList', 2) # custom location
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.download.dir', dest_disk)
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream')
# Launch browser with profile and get file
browser = webdriver.Firefox(profile)
browser.get(file_path)
browser.close()
except:
return False
return True
# Plugin interface
name = 'HostTestPluginCopyMethod_Firefox'
type = 'CopyMethod'
capabilities = ['firefox']
required_parameters = ['image_path', 'destination_disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
try:
from selenium import webdriver
except ImportError, e:
self.print_plugin_error("Error: firefox copy method requires selenium library. %s"% e)
return False
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
image_path = kwargs['image_path']
destination_disk = kwargs['destination_disk']
# Prepare correct command line parameter values
image_base_name = basename(image_path)
destination_path = join(destination_disk, image_base_name)
if capabilitity == 'firefox':
self.file_store_firefox(image_path, destination_path)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginCopyMethod_Firefox()

View File

@ -0,0 +1,68 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from shutil import copy
from host_test_plugins import HostTestPluginBase
class HostTestPluginCopyMethod_Mbed(HostTestPluginBase):
def generic_mbed_copy(self, image_path, destination_disk):
""" Generic mbed copy method for "mbed enabled" devices.
It uses standard python shuitl function to copy
image_file (target specific binary) to device's disk.
"""
result = True
if not destination_disk.endswith('/') and not destination_disk.endswith('\\'):
destination_disk += '/'
try:
copy(image_path, destination_disk)
except Exception, e:
self.print_plugin_error("shutil.copy(%s, %s) failed: %s"% (image_path, destination_disk, str(e)))
result = False
return result
# Plugin interface
name = 'HostTestPluginCopyMethod_Mbed'
type = 'CopyMethod'
stable = True
capabilities = ['default']
required_parameters = ['image_path', 'destination_disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
if capabilitity == 'default':
image_path = kwargs['image_path']
destination_disk = kwargs['destination_disk']
result = self.generic_mbed_copy(image_path, destination_disk)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginCopyMethod_Mbed()

View File

@ -0,0 +1,107 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from shutil import copy
from os.path import join
from host_test_plugins import HostTestPluginBase
class HostTestPluginCopyMethod_MPS2(HostTestPluginBase):
# MPS2 specific flashing / binary setup funcitons
def mps2_set_board_image_file(self, disk, images_cfg_path, image0file_path, image_name='images.txt'):
""" This function will alter image cfg file.
Main goal of this function is to change number of images to 1, comment all
existing image entries and append at the end of file new entry with test path.
@return True when all steps succeed.
"""
MBED_SDK_TEST_STAMP = 'test suite entry'
image_path = join(disk, images_cfg_path, image_name)
new_file_lines = [] # New configuration file lines (entries)
# Check each line of the image configuration file
try:
with open(image_path, 'r') as file:
for line in file:
if re.search('^TOTALIMAGES', line):
# Check number of total images, should be 1
new_file_lines.append(re.sub('^TOTALIMAGES:[\t ]*[\d]+', 'TOTALIMAGES: 1', line))
elif re.search('; - %s[\n\r]*$'% MBED_SDK_TEST_STAMP, line):
# Look for test suite entries and remove them
pass # Omit all test suite entries
elif re.search('^IMAGE[\d]+FILE', line):
# Check all image entries and mark the ';'
new_file_lines.append(';' + line) # Comment non test suite lines
else:
# Append line to new file
new_file_lines.append(line)
except IOError as e:
return False
# Add new image entry with proper commented stamp
new_file_lines.append('IMAGE0FILE: %s ; - %s\r\n'% (image0file_path, MBED_SDK_TEST_STAMP))
# Write all lines to file
try:
with open(image_path, 'w') as file:
for line in new_file_lines:
file.write(line),
except IOError:
return False
return True
def mps2_select_core(self, disk, mobo_config_name=""):
""" Function selects actual core
"""
# TODO: implement core selection
pass
def mps2_switch_usb_auto_mounting_after_restart(self, disk, usb_config_name=""):
""" Function alters configuration to allow USB MSD to be mounted after restarts
"""
# TODO: implement USB MSD restart detection
pass
# Plugin interface
name = 'HostTestPluginCopyMethod_MPS2'
type = 'CopyMethod'
capabilities = ['mps2']
required_parameters = ['image_path', 'destination_disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
if capabilitity == 'mps2':
# TODO: Implement MPS2 firmware setup here
pass
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginCopyMethod_MPS2()

View File

@ -0,0 +1,58 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from os.path import join, basename
from host_test_plugins import HostTestPluginBase
class HostTestPluginCopyMethod_Shell(HostTestPluginBase):
# Plugin interface
name = 'HostTestPluginCopyMethod_Shell'
type = 'CopyMethod'
stable = True
capabilities = ['cp', 'copy', 'xcopy']
required_parameters = ['image_path', 'destination_disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
image_path = kwargs['image_path']
destination_disk = kwargs['destination_disk']
# Prepare correct command line parameter values
image_base_name = basename(image_path)
destination_path = join(destination_disk, image_base_name)
if capabilitity == 'cp' or capabilitity == 'copy' or capabilitity == 'copy':
copy_method = capabilitity
cmd = [copy_method, image_path, destination_path]
result = self.run_command(cmd)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginCopyMethod_Shell()

View File

@ -0,0 +1,61 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from host_test_plugins import HostTestPluginBase
class HostTestPluginCopyMethod_Silabs(HostTestPluginBase):
# Plugin interface
name = 'HostTestPluginCopyMethod_Silabs'
type = 'CopyMethod'
capabilities = ['eACommander', 'eACommander-usb']
required_parameters = ['image_path', 'destination_disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
self.EACOMMANDER_CMD = 'eACommander.exe'
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
image_path = kwargs['image_path']
destination_disk = kwargs['destination_disk']
if capabilitity == 'eACommander':
cmd = [self.EACOMMANDER_CMD,
'--serialno', destination_disk,
'--flash', image_path,
'--resettype', '2', '--reset']
result = self.run_command(cmd)
elif capabilitity == 'eACommander-usb':
cmd = [self.EACOMMANDER_CMD,
'--usb', destination_disk,
'--flash', image_path]
result = self.run_command(cmd)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginCopyMethod_Silabs()

View File

@ -0,0 +1,72 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from host_test_plugins import HostTestPluginBase
class HostTestPluginResetMethod_Mbed(HostTestPluginBase):
def safe_sendBreak(self, serial):
""" Wraps serial.sendBreak() to avoid serial::serialposix.py exception on Linux
Traceback (most recent call last):
File "make.py", line 189, in <module>
serial.sendBreak()
File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 511, in sendBreak
termios.tcsendbreak(self.fd, int(duration/0.25))
error: (32, 'Broken pipe')
"""
result = True
try:
serial.sendBreak()
except:
# In linux a termios.error is raised in sendBreak and in setBreak.
# The following setBreak() is needed to release the reset signal on the target mcu.
try:
serial.setBreak(False)
except:
result = False
return result
# Plugin interface
name = 'HostTestPluginResetMethod_Mbed'
type = 'ResetMethod'
stable = True
capabilities = ['default']
required_parameters = ['serial']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
if capabilitity == 'default':
serial = kwargs['serial']
result = self.safe_sendBreak(serial)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginResetMethod_Mbed()

View File

@ -0,0 +1,74 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os
from host_test_plugins import HostTestPluginBase
# Note: This plugin is not fully functional, needs improvements
class HostTestPluginResetMethod_MPS2(HostTestPluginBase):
""" Plugin used to reset ARM_MPS2 platform
Supports:
reboot.txt - startup from standby state, reboots when in run mode.
shutdown.txt - shutdown from run mode.
reset.txt - reset FPGA during run mode.
"""
def touch_file(self, path):
""" Touch file and set timestamp to items
"""
with open(path, 'a'):
os.utime(path, None)
# Plugin interface
name = 'HostTestPluginResetMethod_MPS2'
type = 'ResetMethod'
capabilities = ['reboot.txt', 'shutdown.txt', 'reset.txt']
required_parameters = ['disk']
def setup(self, *args, **kwargs):
""" Prepare / configure plugin to work.
This method can receive plugin specific parameters by kwargs and
ignore other parameters which may affect other plugins.
"""
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
if capabilitity == 'reboot.txt':
# TODO: Implement touch file for reboot
pass
elif capabilitity == 'shutdown.txt':
# TODO: Implement touch file for shutdown
pass
elif capabilitity == 'reset.txt':
# TODO: Implement touch file for reset
pass
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginResetMethod_MPS2()

View File

@ -0,0 +1,66 @@
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from host_test_plugins import HostTestPluginBase
class HostTestPluginResetMethod_SiLabs(HostTestPluginBase):
# Plugin interface
name = 'HostTestPluginResetMethod_SiLabs'
type = 'ResetMethod'
stable = True
capabilities = ['eACommander', 'eACommander-usb']
required_parameters = ['disk']
def setup(self, *args, **kwargs):
""" Configure plugin, this function should be called before plugin execute() method is used.
"""
# Note you need to have eACommander.exe on your system path!
self.EACOMMANDER_CMD = 'eACommander.exe'
return True
def execute(self, capabilitity, *args, **kwargs):
""" Executes capability by name.
Each capability may directly just call some command line
program or execute building pythonic function
"""
result = False
if self.check_parameters(capabilitity, *args, **kwargs) is True:
disk = kwargs['disk'].rstrip('/\\')
if capabilitity == 'eACommander':
# For this copy method 'disk' will be 'serialno' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [self.EACOMMANDER_CMD,
'--serialno', disk,
'--resettype', '2', '--reset',]
result = self.run_command(cmd)
elif capabilitity == 'eACommander-usb':
# For this copy method 'disk' will be 'usb address' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [self.EACOMMANDER_CMD,
'--usb', disk,
'--resettype', '2', '--reset',]
result = self.run_command(cmd)
return result
def load_plugin():
""" Returns plugin available in this module
"""
return HostTestPluginResetMethod_SiLabs()

View File

@ -76,9 +76,6 @@ GOANNA_PATH = "c:/Program Files (x86)/RedLizards/Goanna Central 3.2.3/bin"
CPPCHECK_CMD = ["cppcheck", "--enable=all"]
CPPCHECK_MSG_FORMAT = ["--template=[{severity}] {file}@{line}: {id}:{message}"]
# SiliconLabs energyAware Commander 2.84 path
EACOMMANDER_CMD = 'c:/SiliconLabs/SimplicityStudio/v2/commander/eACommander.exe'
BUILD_OPTIONS = []
# mbed.org username

View File

@ -32,10 +32,9 @@ from prettytable import PrettyTable
from time import sleep, time
from Queue import Queue, Empty
from shutil import copy
from os.path import join, exists, basename
from threading import Thread
from subprocess import Popen, PIPE, call
from subprocess import Popen, PIPE
# Imports related to mbed build api
from workspace_tools.tests import TESTS
@ -46,7 +45,6 @@ from workspace_tools.utils import ToolException
from workspace_tools.utils import construct_enum
from workspace_tools.targets import TARGET_MAP
from workspace_tools.test_db import BaseDBAccess
from workspace_tools.settings import EACOMMANDER_CMD
from workspace_tools.build_api import build_project, build_mbed_libs, build_lib
from workspace_tools.build_api import get_target_supported_toolchains
from workspace_tools.libraries import LIBRARIES, LIBRARY_MAP
@ -54,6 +52,9 @@ from workspace_tools.toolchains import TOOLCHAIN_BIN_PATH
from workspace_tools.test_exporters import ReportExporter, ResultExporterType
import workspace_tools.host_tests.host_tests_plugins as host_tests_plugins
class ProcessObserver(Thread):
def __init__(self, proc):
Thread.__init__(self)
@ -591,22 +592,6 @@ class SingleTestRunner(object):
result = self.TEST_LOOPS_DICT[test_id]
return result
def file_store_firefox(self, file_path, dest_disk):
try:
from selenium import webdriver
except ImportError, e:
print "Error: firefox copy method requires selenium library. %s"% e
exit(-1)
profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.folderList', 2) # custom location
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.download.dir', dest_disk)
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/octet-stream')
# Launch browser with profile and get file
browser = webdriver.Firefox(profile)
browser.get(file_path)
browser.close()
def image_copy_method_selector(self, target_name, image_path, disk, copy_method,
images_config=None, image_dest=None, verbose=False):
""" Function copied image file and fiddles with image configuration files in needed.
@ -615,82 +600,20 @@ class SingleTestRunner(object):
"""
image_dest = image_dest if image_dest is not None else ''
_copy_res, _err_msg, _copy_method = self.file_copy_method_selector(image_path, disk, copy_method, image_dest=image_dest, verbose=verbose)
if images_config is not None:
# For different targets additional configuration file has to be changed
# Here we select target and proper function to handle configuration change
if target_name == 'ARM_MPS2':
images_cfg_path = images_config
image0file_path = os.path.join(disk, image_dest, basename(image_path))
mps2_set_board_image_file(disk, images_cfg_path, image0file_path)
return _copy_res, _err_msg, _copy_method
def file_copy_method_selector(self, image_path, disk, copy_method, image_dest='', verbose=False):
""" Copy file depending on method you want to use. Handles exception
and return code from shell copy commands.
"""
result = True
resutl_msg = ""
if copy_method == 'cp' or copy_method == 'copy' or copy_method == 'xcopy':
source_path = image_path.encode('ascii', 'ignore')
image_base_name = basename(image_path).encode('ascii', 'ignore')
destination_path = os.path.join(disk.encode('ascii', 'ignore'), image_dest, image_base_name)
cmd = [copy_method, source_path, destination_path]
try:
ret = call(cmd, shell=True)
if ret:
resutl_msg = "Return code: %d. Command: "% (ret + " ".join(cmd))
result = False
except Exception, e:
resutl_msg = e
result = False
elif copy_method == 'firefox':
try:
source_path = image_path.encode('ascii', 'ignore')
destination_path = os.path.join(disk.encode('ascii', 'ignore'), image_dest)
self.file_store_firefox(source_path, destination_path)
except Exception, e:
resutl_msg = e
result = False
elif copy_method == 'eACommander':
# For this copy method 'disk' will be 'serialno' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [EACOMMANDER_CMD,
'--serialno', disk.rstrip('/\\'),
'--flash', image_path.encode('ascii', 'ignore'),
'--resettype', '2', '--reset']
try:
ret = call(cmd, shell=True)
if ret:
resutl_msg = "Return code: %d. Command: "% ret + " ".join(cmd)
result = False
except Exception, e:
resutl_msg = e
result = False
elif copy_method == 'eACommander-usb':
# For this copy method 'disk' will be 'usb address' for eACommander command line parameters
# Note: Commands are executed in the order they are specified on the command line
cmd = [EACOMMANDER_CMD,
'--usb', disk.rstrip('/\\'),
'--flash', image_path.encode('ascii', 'ignore')]
try:
ret = call(cmd, shell=True)
if ret:
resutl_msg = "Return code: %d. Command: "% ret + " ".join(cmd)
result = False
except Exception, e:
resutl_msg = e
result = False
result = False
resutl_msg = '' # TODO: pass result_msg from plugin to test suite
if copy_method is not None:
# image_path - Where is binary with target's firmware
result = host_tests_plugins.call_plugin('CopyMethod', copy_method, image_path=image_path, destination_disk=disk)
else:
copy_method = "shutils.copy()"
# Default python method
try:
if not disk.endswith('/') and not disk.endswith('\\'):
disk += '/'
copy(image_path, disk)
except Exception, e:
resutl_msg = e
result = False
copy_method = 'default'
result = host_tests_plugins.call_plugin('CopyMethod', copy_method, image_path=image_path, destination_disk=disk)
return result, resutl_msg, copy_method
def delete_file(self, file_path):
@ -1324,64 +1247,6 @@ def singletest_in_cli_mode(single_test):
report_exporter.report_to_file(test_summary_ext, single_test.opts_report_junit_file_name, test_suite_properties=test_suite_properties_ext)
def mps2_set_board_image_file(disk, images_cfg_path, image0file_path, image_name='images.txt'):
""" This function will alter image cfg file.
Main goal of this function is to change number of images to 1, comment all
existing image entries and append at the end of file new entry with test path.
@return True when all steps succeed.
"""
MBED_SDK_TEST_STAMP = 'test suite entry'
image_path = os.path.join(disk, images_cfg_path, image_name)
new_file_lines = [] # New configuration file lines (entries)
# Check each line of the image configuration file
try:
with open(image_path, 'r') as file:
for line in file:
if re.search('^TOTALIMAGES', line):
# Check number of total images, should be 1
new_file_lines.append(re.sub('^TOTALIMAGES:[\t ]*[\d]+', 'TOTALIMAGES: 1', line))
pass
elif re.search('; - %s[\n\r]*$'% MBED_SDK_TEST_STAMP, line):
# Look for test suite entries and remove them
pass # Omit all test suite entries
elif re.search('^IMAGE[\d]+FILE', line):
# Check all image entries and mark the ';'
new_file_lines.append(';' + line) # Comment non test suite lines
else:
# Append line to new file
new_file_lines.append(line)
except IOError as e:
return False
# Add new image entry with proper commented stamp
new_file_lines.append('IMAGE0FILE: %s ; - %s\r\n'% (image0file_path, MBED_SDK_TEST_STAMP))
# Write all lines to file
try:
with open(image_path, 'w') as file:
for line in new_file_lines:
file.write(line),
except IOError:
return False
return True
def mps2_select_core(disk, mobo_config_name=""):
""" Function selects actual core
"""
# TODO: implement core selection
pass
def mps2_switch_usb_auto_mounting_after_restart(disk, usb_config_name=""):
""" Function alters configuration to allow USB MSD to be mounted after restarts
"""
# TODO: implement USB MSD restart detection
pass
class TestLogger():
""" Super-class for logging and printing ongoing events for test suite pass
"""