Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[devel_transport] Async host test execition support #78

Merged
merged 30 commits into from
Mar 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ce92ac2
Add KiVi transport protocol support - draft
PrzemekWirkus Feb 5, 2016
63b5bcd
Polishing
PrzemekWirkus Feb 5, 2016
0b1cc56
Removed parallel tests
PrzemekWirkus Feb 5, 2016
d24242c
Merge Test Case reporting functionality - draft
PrzemekWirkus Feb 5, 2016
fca7efc
Remove copy_method from test case report
PrzemekWirkus Feb 5, 2016
71149d3
Ported Test Case reporting functionality
PrzemekWirkus Feb 5, 2016
9de37ed
Polishing
PrzemekWirkus Feb 5, 2016
10d5007
Update unit tests
PrzemekWirkus Feb 8, 2016
470c733
Add solution for extra new-line when dumping app output to file
PrzemekWirkus Feb 9, 2016
dcfd047
Test case report fixes
PrzemekWirkus Feb 10, 2016
7210f00
Force pySerial v3 usage
PrzemekWirkus Feb 11, 2016
c1219b2
v0.2.0
PrzemekWirkus Feb 11, 2016
151734f
Add test utest case summary support (+checks)
PrzemekWirkus Feb 11, 2016
0dd25c7
Add verbose flag to htrun on-screen logging
PrzemekWirkus Feb 11, 2016
836e330
Add alias for '-S' for CLI switch '--skip-build'
PrzemekWirkus Feb 11, 2016
dad9960
Add alias '-l' for CLI switch '--list'
PrzemekWirkus Feb 11, 2016
43abb3c
Add test case reporting to junit report
PrzemekWirkus Feb 15, 2016
c12a3ff
Add utest log parsing for JUnit results
PrzemekWirkus Feb 15, 2016
7d231c4
unit test polishing
PrzemekWirkus Feb 16, 2016
7280188
Remove extra line in Junit stdout log cut
PrzemekWirkus Feb 17, 2016
cd2bd4a
Typo
PrzemekWirkus Feb 22, 2016
65b7236
Add Test Suite -> Test Case mapping in case of no utest present
PrzemekWirkus Feb 23, 2016
3cda486
Refactore test suite -> test case mapping feature to be more generic
PrzemekWirkus Feb 23, 2016
9625991
Add unicode strip from JUnit report text
PrzemekWirkus Feb 23, 2016
e9efa7b
Add default test case report values for __testcase_finish
PrzemekWirkus Feb 23, 2016
6cdc12b
Test suite -> test case feature polishing
PrzemekWirkus Feb 26, 2016
c7c5f54
Add sorted results for test cases report
PrzemekWirkus Feb 26, 2016
8cf5dd0
Add Hooks & GCOV support
PrzemekWirkus Mar 1, 2016
ce8f693
Add htrun v0.2.0 dependency
PrzemekWirkus Mar 2, 2016
91492a0
Merge master
PrzemekWirkus Mar 2, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions mbed_greentea/mbed_coverage_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
mbed SDK
Copyright (c) 2011-2016 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.

Author: Przemyslaw Wirkus <[email protected]>
"""

import os

"""
def __default_coverage_start_callback(self, key, value, timestamp):
# {{__coverage_start;PATH;PAYLOAD}}
# PAYLAODED is HEX coded string
lcov_path, lcov_payload = value.split(';')
try:
bin_payload = coverage_pack_hex_payload(lcov_payload)
coverage_dump_file(lcov_path, bin_payload)

self.log("dumped %d bytes to '%s'"% (len(bin_payload), lcov_path))
except Exception as e:
self.log("LCOV:" + str(e))
"""

def coverage_pack_hex_payload(payload):
"""! Convert a block of hex string data back to binary and return the binary data
@param payload String with hex encoded ascii data, e.g.: '6164636772...'
@return bytearray with payload with data
"""
# This payload might be packed with dot compression
# where byte value 0x00 is coded as ".", and not as "00"
payload = payload.replace('.', '00')

hex_pairs = map(''.join, zip(*[iter(payload)] * 2)) # ['61', '64', '63', '67', '72', ... ]
bin_payload = bytearray([int(s, 16) for s in hex_pairs])
return bin_payload

def coverage_dump_file(path, payload):
"""! Creates file and dumps payload to it on specified path (even if path doesn't exist)
@param path Path to file
@param payload Binary data to store in a file
@return True if operation was completed
"""
result = True
try:
d = os.path.dirname(path)
if not os.path.exists(d):
os.makedirs(d)
with open(path, "wb") as f:
f.write(payload)
except IOError as e:
print str(e)
result = False
return result
218 changes: 191 additions & 27 deletions mbed_greentea/mbed_greentea_cli.py

Large diffs are not rendered by default.

175 changes: 175 additions & 0 deletions mbed_greentea/mbed_greentea_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
"""
mbed SDK
Copyright (c) 2011-2015 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.
Author: Przemyslaw Wirkus <[email protected]>
"""

import re
import json
from subprocess import Popen, PIPE
from mbed_greentea.mbed_greentea_log import gt_logger

"""
List of available hooks:
"""


class GreenteaTestHook():
"""! Class used to define
"""
name = None

def __init__(self, name):
self.name = name

def run(self, format=None):
pass

class GreenteaCliTestHook(GreenteaTestHook):
"""! Class used to define a hook which will call command line program
"""
cmd = None

def __init__(self, name, cmd):
GreenteaTestHook.__init__(self, name)
self.cmd = cmd

def run_cli_process(self, cmd):
"""! Runs command as a process and return stdout, stderr and ret code
@param cmd Command to execute
@return Tuple of (stdout, stderr, returncode)
"""
_stdout, _stderr, ret = None, None, -1
try:
p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
_stdout, _stderr = p.communicate()
ret = p.returncode
except OSError as e:
gt_logger.gt_log_err(str(e))
ret = -1
return _stdout, _stderr, ret

def run(self, format=None):
"""! Runs hook after command is formated with in-place {tags}
@format Pass format dictionary to replace hook {tags} with real values
@param format Used to format string with cmd, notation used is e.g: {build_name}
"""
gt_logger.gt_log("hook '%s' execution"% self.name)
cmd = self.format_before_run(self.cmd, format)
gt_logger.gt_log_tab("hook command: %s"% cmd)
(_stdout, _stderr, ret) = self.run_cli_process(cmd)
if _stdout:
print _stdout
if ret:
gt_logger.gt_log_err("hook exited with error: %d, dumping stderr..."% ret)
print _stderr
return ret

@staticmethod
def format_before_run(cmd, format, verbose=False):
if format:
# We will expand first
cmd_expand = GreenteaCliTestHook.expand_parameters(cmd, format)
if cmd_expand:
cmd = cmd_expand
if verbose:
gt_logger.gt_log_tab("hook expanded: %s"% cmd)

cmd = cmd.format(**format)
if verbose:
gt_logger.gt_log_tab("hook formated: %s"% cmd)
return cmd

@staticmethod
def expand_parameters(expr, expandables, delimiter=' '):
"""! Expands lists for multiple parameters in hook command
@param expr Expression to expand
@param expandables Dictionary of token: list_to_expand See details for more info
@param delimiter Delimiter used to combine expanded strings, space by default
@details
test_name_list = ['mbed-drivers-test-basic', 'mbed-drivers-test-hello', 'mbed-drivers-test-time_us']
build_path_list = ['./build/frdm-k64f-gcc', './build/frdm-k64f-armcc']
expandables = {
"{test_name_list}": test_name_list,
"{build_path_list}": build_path_list
}
expr = "lcov --gcov-tool arm-none-eabi-gcov [-a {build_path_list}/test/{test_name_list}.info] --output-file result.info"
'expr' expression [-a {build_path_list}/test/{test_name_list}.info] will expand to:
[
"-a ./build/frdm-k64f-gcc/test/mbed-drivers-test-basic.info",
"-a ./build/frdm-k64f-armcc/test/mbed-drivers-test-basic.info",
"-a ./build/frdm-k64f-gcc/test/mbed-drivers-test-hello.info",
"-a ./build/frdm-k64f-armcc/test/mbed-drivers-test-hello.info",
"-a ./build/frdm-k64f-gcc/test/mbed-drivers-test-time_us.info",
"-a ./build/frdm-k64f-armcc/test/mbed-drivers-test-time_us.info"
]
"""
result = None
if expandables:
expansion_result = []
m = re.search('\[.*?\]', expr)
if m:
expr_str_orig = m.group(0)
expr_str_base = m.group(0)[1:-1]
expr_str_list = [expr_str_base]
for token in expandables:
# We will expand only values which are lists (of strings)
if type(expandables[token]) is list:
# Use tokens with curly braces (Python string format like)
format_token = '{' + token + '}'
for expr_str in expr_str_list:
if format_token in expr_str:
patterns = expandables[token]
for pattern in patterns:
s = expr_str
s = s.replace(format_token, pattern)
expr_str_list.append(s)
# Nothing to extend/change in this string
if not any('{' + p + '}' in s for p in expandables.keys() if type(expandables[p]) is list):
expansion_result.append(s)
expansion_result.sort()
result = expr.replace(expr_str_orig, delimiter.join(expansion_result))
return result

class GreenteaHooks():
"""! Class used to store all hooks
@details Hooks command starts with '$' dollar sign
"""
HOOKS = {}
def __init__(self, path_to_hooks):
"""! Opens JSON file with
"""
try:
with open(path_to_hooks, 'r') as data_file:
hooks = json.load(data_file)
if 'hooks' in hooks:
for hook in hooks['hooks']:
hook_name = hook
hook_expression = hooks['hooks'][hook]
# This is a command line hook
if hook_expression.startswith('$'):
self.HOOKS[hook_name] = GreenteaCliTestHook(hook_name, hook_expression[1:])
except IOError as e:
print str(e)
self.HOOKS = None

def is_hooked_to(self, hook_name):
return hook_name in self.HOOKS

def run_hook(self, hook_name, format):
if hook_name in self.HOOKS:
return self.HOOKS[hook_name].run(format)

def run_hook_ext(self, hook_name, format):
if self.is_hooked_to(hook_name):
# We can execute this test hook just after all tests are finished ('hook_post_test_end')
self.run_hook(hook_name, format)
Loading