mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'host-test-plugin-improvements' of github.com:PrzemekWirkus/mbed into PrzemekWirkus-host-test-plugin-improvements
Conflicts: workspace_tools/host_tests/host_test.pypull/606/head
commit
7abbd9c5a8
|
@ -22,18 +22,17 @@ except ImportError, e:
|
||||||
print "Error: Can't import 'serial' module: %s"% e
|
print "Error: Can't import 'serial' module: %s"% e
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from sys import stdout
|
from sys import stdout
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
import host_tests_plugins
|
||||||
|
|
||||||
# This is a little tricky. We need to add upper directory to path so
|
# 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
|
# we can find packages we want from the same level as other files do
|
||||||
import sys
|
import sys
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
|
||||||
from workspace_tools.settings import EACOMMANDER_CMD
|
|
||||||
|
|
||||||
|
|
||||||
class Mbed:
|
class Mbed:
|
||||||
|
@ -158,27 +157,6 @@ class Mbed:
|
||||||
result = None
|
result = None
|
||||||
return result
|
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):
|
def touch_file(self, path):
|
||||||
""" Touch file and set timestamp to items
|
""" Touch file and set timestamp to items
|
||||||
"""
|
"""
|
||||||
|
@ -192,56 +170,15 @@ class Mbed:
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
""" Reset function.
|
""" Calls proper reset plugin to do the job.
|
||||||
Supports:
|
Please refer to host_test_plugins functionality
|
||||||
- '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.
|
|
||||||
"""
|
"""
|
||||||
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
|
# 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
|
# 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
|
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)
|
self.reset_timeout(reset_tout_s)
|
||||||
|
@ -275,20 +212,17 @@ class Test(TestResults):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
""" Test runner for host test. This function will start executing
|
""" 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:
|
try:
|
||||||
# We expect here output from test in one of possible statuses
|
result = self.test()
|
||||||
# E.g. self.RESULT_SUCCESS, self.RESULT_FAILURE, self.RESULT_ERROR
|
self.print_result(self.RESULT_SUCCESS if result else self.RESULT_FAILURE)
|
||||||
result_status = self.test()
|
|
||||||
self.print_result(result_status)
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.notify(str(e))
|
print str(e)
|
||||||
self.print_result(self.RESULT_ERROR)
|
self.print_result(self.RESULT_ERROR)
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
""" Setup and check if configuration for test is correct.
|
""" Setup and check if configuration for test is correct. E.g. if serial port can be opened
|
||||||
E.g. if serial port can be opened
|
|
||||||
"""
|
"""
|
||||||
result = True
|
result = True
|
||||||
if not self.mbed.serial:
|
if not self.mbed.serial:
|
||||||
|
@ -325,19 +259,17 @@ class Simple(DefaultTest):
|
||||||
output from MUT, no supervision over test running in MUT is executed.
|
output from MUT, no supervision over test running in MUT is executed.
|
||||||
Just waiting for result
|
Just waiting for result
|
||||||
"""
|
"""
|
||||||
def test(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
c = self.mbed.serial_read(512)
|
c = self.mbed.serial_read(512)
|
||||||
if c is None:
|
if c is None:
|
||||||
return self.RESULT_IO_SERIAL
|
self.print_result(self.RESULT_IO_SERIAL)
|
||||||
|
break
|
||||||
stdout.write(c)
|
stdout.write(c)
|
||||||
stdout.flush()
|
stdout.flush()
|
||||||
except KeyboardInterrupt, _:
|
except KeyboardInterrupt, _:
|
||||||
self.notify("\r\n[CTRL+C] exit")
|
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__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -76,9 +76,6 @@ GOANNA_PATH = "c:/Program Files (x86)/RedLizards/Goanna Central 3.2.3/bin"
|
||||||
CPPCHECK_CMD = ["cppcheck", "--enable=all"]
|
CPPCHECK_CMD = ["cppcheck", "--enable=all"]
|
||||||
CPPCHECK_MSG_FORMAT = ["--template=[{severity}] {file}@{line}: {id}:{message}"]
|
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 = []
|
BUILD_OPTIONS = []
|
||||||
|
|
||||||
# mbed.org username
|
# mbed.org username
|
||||||
|
|
|
@ -32,10 +32,9 @@ from prettytable import PrettyTable
|
||||||
|
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
from shutil import copy
|
|
||||||
from os.path import join, exists, basename
|
from os.path import join, exists, basename
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from subprocess import Popen, PIPE, call
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
# Imports related to mbed build api
|
# Imports related to mbed build api
|
||||||
from workspace_tools.tests import TESTS
|
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.utils import construct_enum
|
||||||
from workspace_tools.targets import TARGET_MAP
|
from workspace_tools.targets import TARGET_MAP
|
||||||
from workspace_tools.test_db import BaseDBAccess
|
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 build_project, build_mbed_libs, build_lib
|
||||||
from workspace_tools.build_api import get_target_supported_toolchains
|
from workspace_tools.build_api import get_target_supported_toolchains
|
||||||
from workspace_tools.libraries import LIBRARIES, LIBRARY_MAP
|
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
|
from workspace_tools.test_exporters import ReportExporter, ResultExporterType
|
||||||
|
|
||||||
|
|
||||||
|
import workspace_tools.host_tests.host_tests_plugins as host_tests_plugins
|
||||||
|
|
||||||
|
|
||||||
class ProcessObserver(Thread):
|
class ProcessObserver(Thread):
|
||||||
def __init__(self, proc):
|
def __init__(self, proc):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
|
@ -591,22 +592,6 @@ class SingleTestRunner(object):
|
||||||
result = self.TEST_LOOPS_DICT[test_id]
|
result = self.TEST_LOOPS_DICT[test_id]
|
||||||
return result
|
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,
|
def image_copy_method_selector(self, target_name, image_path, disk, copy_method,
|
||||||
images_config=None, image_dest=None, verbose=False):
|
images_config=None, image_dest=None, verbose=False):
|
||||||
""" Function copied image file and fiddles with image configuration files in needed.
|
""" 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 ''
|
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)
|
_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
|
return _copy_res, _err_msg, _copy_method
|
||||||
|
|
||||||
def file_copy_method_selector(self, image_path, disk, copy_method, image_dest='', verbose=False):
|
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
|
""" Copy file depending on method you want to use. Handles exception
|
||||||
and return code from shell copy commands.
|
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:
|
else:
|
||||||
copy_method = "shutils.copy()"
|
copy_method = 'default'
|
||||||
# Default python method
|
result = host_tests_plugins.call_plugin('CopyMethod', copy_method, image_path=image_path, destination_disk=disk)
|
||||||
try:
|
|
||||||
if not disk.endswith('/') and not disk.endswith('\\'):
|
|
||||||
disk += '/'
|
|
||||||
copy(image_path, disk)
|
|
||||||
except Exception, e:
|
|
||||||
resutl_msg = e
|
|
||||||
result = False
|
|
||||||
return result, resutl_msg, copy_method
|
return result, resutl_msg, copy_method
|
||||||
|
|
||||||
def delete_file(self, file_path):
|
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)
|
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():
|
class TestLogger():
|
||||||
""" Super-class for logging and printing ongoing events for test suite pass
|
""" Super-class for logging and printing ongoing events for test suite pass
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue