Unit test generate_copy.py

This commit is contained in:
Azim Khan 2017-06-30 09:35:21 +01:00 committed by Mohammad Azim Khan
parent 13c6bfbc2a
commit 4b54323bcb
2 changed files with 920 additions and 66 deletions

View file

@ -1,6 +1,6 @@
"""
mbed SDK
Copyright (c) 2017-2018 ARM Limited
mbed TLS
Copyright (c) 2017 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -25,17 +25,15 @@ import shutil
Generates code in following structure.
<output dir>/
|-- host_tests/
| |-- mbedtls_test.py
| |-- mbedtls/
| | |-- <test suite #1>/
| | | |-- main.c
| | | |-- *.data files
| | ...
| | |-- <test suite #n>/
| | | |-- main.c
| | | |-- *.data files
| | |
|-- mbedtls/
| |-- <test suite #1>/
| | |-- main.c
| | |-- *.data files
| ...
| |-- <test suite #n>/
| | |-- main.c
| | |-- *.data files
| |
"""
@ -56,6 +54,44 @@ class InvalidFileFormat(Exception):
pass
class FileWrapper(file):
"""
File wrapper class. Provides reading with line no. tracking.
"""
def __init__(self, file_name):
"""
Init file handle.
:param file_name:
"""
super(FileWrapper, self).__init__(file_name, 'r')
self.line_no = 0
def next(self):
"""
Iterator return impl.
:return:
"""
line = super(FileWrapper, self).next()
if line:
self.line_no += 1
return line
def readline(self, limit=0):
"""
Wrap the base class readline.
:param limit:
:return:
"""
return self.next()
def split_dep(dep):
return ('!', dep[1:]) if dep[0] == '!' else ('', dep)
def gen_deps(deps):
"""
Generates dependency i.e. if def and endif code
@ -63,16 +99,9 @@ def gen_deps(deps):
:param deps:
:return:
"""
dep_start = ''
dep_end = ''
for dep in deps:
if dep[0] == '!':
noT = '!'
dep = dep[1:]
else:
noT = ''
dep_start += '#if %sdefined(%s)\n' % (noT, dep)
dep_end = '#endif /* %s%s */\n' % (noT, dep) + dep_end
dep_start = ''.join(['#if %sdefined(%s)\n' % split_dep(x) for x in deps])
dep_end = ''.join(['#endif /* %s */\n' % x for x in reversed(deps)])
return dep_start, dep_end
@ -83,22 +112,16 @@ def gen_deps_one_line(deps):
:param deps:
:return:
"""
defines = []
for dep in deps:
if dep[0] == '!':
noT = '!'
dep = dep[1:]
else:
noT = ''
defines.append('%sdefined(%s)' % (noT, dep))
return '#if ' + ' && '.join(defines)
defines = ('#if ' if len(deps) else '') + ' && '.join(['%sdefined(%s)' % split_dep(x) for x in deps])
return defines
def gen_function_wrapper(name, args_dispatch):
def gen_function_wrapper(name, locals, args_dispatch):
"""
Creates test function code
:param name:
:param locals:
:param args_dispatch:
:return:
"""
@ -110,9 +133,9 @@ void {name}_wrapper( void ** params )
{locals}
{name}( {args} );
}}
'''.format(name=name, unused_params='(void)params;' if len(args_dispatch[1]) == 0 else '',
args=', '.join(args_dispatch[1]),
locals=args_dispatch[0])
'''.format(name=name, unused_params='(void)params;' if len(args_dispatch) == 0 else '',
args=', '.join(args_dispatch),
locals=locals)
return wrapper
@ -141,37 +164,33 @@ def gen_dispatch(name, deps):
return dispatch_code
def parse_suite_headers(line_no, funcs_f):
def parse_suite_headers(funcs_f):
"""
Parses function headers.
:param line_no:
:param funcs_f:
:return:
"""
headers = '#line %d "%s"\n' % (line_no + 1, funcs_f.name)
headers = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
for line in funcs_f:
line_no += 1
if re.search(END_HEADER_REGEX, line):
break
headers += line
else:
raise InvalidFileFormat("file: %s - end header pattern [%s] not found!" % (funcs_f.name, END_HEADER_REGEX))
return line_no, headers
return headers
def parse_suite_deps(line_no, funcs_f):
def parse_suite_deps(funcs_f):
"""
Parses function dependencies.
:param line_no:
:param funcs_f:
:return:
"""
deps = []
for line in funcs_f:
line_no += 1
m = re.search('depends_on\:(.*)', line.strip())
if m:
deps += [x.strip() for x in m.group(1).split(':')]
@ -180,7 +199,7 @@ def parse_suite_deps(line_no, funcs_f):
else:
raise InvalidFileFormat("file: %s - end dependency pattern [%s] not found!" % (funcs_f.name, END_DEP_REGEX))
return line_no, deps
return deps
def parse_function_deps(line):
@ -195,7 +214,7 @@ def parse_function_deps(line):
if len(dep_str):
m = re.search('depends_on:(.*)', dep_str)
if m:
deps = m.group(1).strip().split(':')
deps = [x.strip() for x in m.group(1).strip().split(':')]
return deps
@ -234,13 +253,13 @@ def parse_function_signature(line):
args_dispatch.append('&hex%d' % arg_idx)
arg_idx += 1
else:
raise ValueError("Test function arguments can only be 'int' or 'char *'\n%s" % line)
raise ValueError("Test function arguments can only be 'int', 'char *' or 'HexParam_t'\n%s" % line)
arg_idx += 1
return name, args, (locals, args_dispatch)
return name, args, locals, args_dispatch
def parse_function_code(line_no, funcs_f, deps, suite_deps):
def parse_function_code(funcs_f, deps, suite_deps):
"""
:param line_no:
@ -249,9 +268,8 @@ def parse_function_code(line_no, funcs_f, deps, suite_deps):
:param suite_deps:
:return:
"""
code = '#line %d "%s"\n' % (line_no + 1, funcs_f.name)
code = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
for line in funcs_f:
line_no += 1
# Check function signature
m = re.match('.*?\s+(\w+)\s*\(', line, re.I)
if m:
@ -259,10 +277,9 @@ def parse_function_code(line_no, funcs_f, deps, suite_deps):
if not re.match('.*\)', line):
for lin in funcs_f:
line += lin
line_no += 1
if re.search('.*?\)', line):
break
name, args, args_dispatch = parse_function_signature(line)
name, args, locals, args_dispatch = parse_function_signature(line)
code += line.replace(name, 'test_' + name)
name = 'test_' + name
break
@ -270,7 +287,6 @@ def parse_function_code(line_no, funcs_f, deps, suite_deps):
raise InvalidFileFormat("file: %s - Test functions not found!" % funcs_f.name)
for line in funcs_f:
line_no += 1
if re.search(END_CASE_REGEX, line):
break
code += line
@ -281,16 +297,14 @@ def parse_function_code(line_no, funcs_f, deps, suite_deps):
if code.find('exit:') == -1:
s = code.rsplit('}', 1)
if len(s) == 2:
code = """
exit:
code = """exit:
;;
}
""".join(s)
}""".join(s)
code += gen_function_wrapper(name, args_dispatch)
code += gen_function_wrapper(name, locals, args_dispatch)
ifdef, endif = gen_deps(deps)
dispatch_code = gen_dispatch(name, suite_deps + deps)
return line_no, name, args, ifdef + code + endif, dispatch_code
return name, args, ifdef + code + endif, dispatch_code
def parse_functions(funcs_f):
@ -300,7 +314,6 @@ def parse_functions(funcs_f):
:param funcs_f:
:return:
"""
line_no = 0
suite_headers = ''
suite_deps = []
suite_functions = ''
@ -308,20 +321,19 @@ def parse_functions(funcs_f):
function_idx = 0
dispatch_code = ''
for line in funcs_f:
line_no += 1
if re.search(BEGIN_HEADER_REGEX, line):
line_no, headers = parse_suite_headers(line_no, funcs_f)
headers = parse_suite_headers(funcs_f)
suite_headers += headers
elif re.search(BEGIN_DEP_REGEX, line):
line_no, deps = parse_suite_deps(line_no, funcs_f)
deps = parse_suite_deps(funcs_f)
suite_deps += deps
elif re.search(BEGIN_CASE_REGEX, line):
deps = parse_function_deps(line)
line_no, func_name, args, func_code, func_dispatch = parse_function_code(line_no, funcs_f, deps, suite_deps)
func_name, args, func_code, func_dispatch = parse_function_code(funcs_f, deps, suite_deps)
suite_functions += func_code
# Generate dispatch code and enumeration info
assert func_name not in func_info, "file: %s - function %s re-declared at line %d" % \
(funcs_f.name, func_name, line_no)
(funcs_f.name, func_name, funcs_f.line_no)
func_info[func_name] = (function_idx, args)
dispatch_code += '/* Function Id: %d */\n' % function_idx
dispatch_code += func_dispatch

View file

@ -0,0 +1,842 @@
"""
mbed TLS
Copyright (c) 2017 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 StringIO import StringIO
from unittest import TestCase, main as unittest_main
from mock import patch
from generate_code import *
"""
Unit tests for generate_code.py
"""
class GenDep(TestCase):
"""
Test suite for function gen_dep()
"""
def test_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['DEP1', 'DEP2']
dep_start, dep_end = gen_deps(deps)
ifdef1, ifdef2 = dep_start.splitlines()
endif1, endif2 = dep_end.splitlines()
self.assertEqual(ifdef1, '#if defined(DEP1)', 'ifdef generated incorrectly')
self.assertEqual(ifdef2, '#if defined(DEP2)', 'ifdef generated incorrectly')
self.assertEqual(endif1, '#endif /* DEP2 */', 'endif generated incorrectly')
self.assertEqual(endif2, '#endif /* DEP1 */', 'endif generated incorrectly')
def test_disabled_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['!DEP1', '!DEP2']
dep_start, dep_end = gen_deps(deps)
ifdef1, ifdef2 = dep_start.splitlines()
endif1, endif2 = dep_end.splitlines()
self.assertEqual(ifdef1, '#if !defined(DEP1)', 'ifdef generated incorrectly')
self.assertEqual(ifdef2, '#if !defined(DEP2)', 'ifdef generated incorrectly')
self.assertEqual(endif1, '#endif /* !DEP2 */', 'endif generated incorrectly')
self.assertEqual(endif2, '#endif /* !DEP1 */', 'endif generated incorrectly')
def test_mixed_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['!DEP1', 'DEP2']
dep_start, dep_end = gen_deps(deps)
ifdef1, ifdef2 = dep_start.splitlines()
endif1, endif2 = dep_end.splitlines()
self.assertEqual(ifdef1, '#if !defined(DEP1)', 'ifdef generated incorrectly')
self.assertEqual(ifdef2, '#if defined(DEP2)', 'ifdef generated incorrectly')
self.assertEqual(endif1, '#endif /* DEP2 */', 'endif generated incorrectly')
self.assertEqual(endif2, '#endif /* !DEP1 */', 'endif generated incorrectly')
def test_empty_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = []
dep_start, dep_end = gen_deps(deps)
self.assertEqual(dep_start, '', 'ifdef generated incorrectly')
self.assertEqual(dep_end, '', 'ifdef generated incorrectly')
def test_large_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = []
count = 10
for i in range(count):
deps.append('DEP%d' % i)
dep_start, dep_end = gen_deps(deps)
self.assertEqual(len(dep_start.splitlines()), count, 'ifdef generated incorrectly')
self.assertEqual(len(dep_end.splitlines()), count, 'ifdef generated incorrectly')
class GenDepOneLine(TestCase):
"""
Test Suite for testing gen_deps_one_line()
"""
def test_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['DEP1', 'DEP2']
dep_str = gen_deps_one_line(deps)
self.assertEqual(dep_str, '#if defined(DEP1) && defined(DEP2)', 'ifdef generated incorrectly')
def test_disabled_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['!DEP1', '!DEP2']
dep_str = gen_deps_one_line(deps)
self.assertEqual(dep_str, '#if !defined(DEP1) && !defined(DEP2)', 'ifdef generated incorrectly')
def test_mixed_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = ['!DEP1', 'DEP2']
dep_str = gen_deps_one_line(deps)
self.assertEqual(dep_str, '#if !defined(DEP1) && defined(DEP2)', 'ifdef generated incorrectly')
def test_empty_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = []
dep_str = gen_deps_one_line(deps)
self.assertEqual(dep_str, '', 'ifdef generated incorrectly')
def test_large_deps_list(self):
"""
Test that gen_dep() correctly creates deps for given dependency list.
:return:
"""
deps = []
count = 10
for i in range(count):
deps.append('DEP%d' % i)
dep_str = gen_deps_one_line(deps)
expected = '#if ' + ' && '.join(['defined(%s)' % x for x in deps])
self.assertEqual(dep_str, expected, 'ifdef generated incorrectly')
class GenFunctionWrapper(TestCase):
"""
Test Suite for testing gen_function_wrapper()
"""
def test_params_unpack(self):
"""
Test that params are properly unpacked in the function call.
:return:
"""
code = gen_function_wrapper('test_a', '', ('a', 'b', 'c', 'd'))
expected = '''
void test_a_wrapper( void ** params )
{
test_a( a, b, c, d );
}
'''
self.assertEqual(code, expected)
def test_local(self):
"""
Test that params are properly unpacked in the function call.
:return:
"""
code = gen_function_wrapper('test_a', 'int x = 1;', ('x', 'b', 'c', 'd'))
expected = '''
void test_a_wrapper( void ** params )
{
int x = 1;
test_a( x, b, c, d );
}
'''
self.assertEqual(code, expected)
def test_empty_params(self):
"""
Test that params are properly unpacked in the function call.
:return:
"""
code = gen_function_wrapper('test_a', '', ())
expected = '''
void test_a_wrapper( void ** params )
{
(void)params;
test_a( );
}
'''
self.assertEqual(code, expected)
class GenDispatch(TestCase):
"""
Test suite for testing gen_dispatch()
"""
def test_dispatch(self):
"""
Test that dispatch table entry is generated correctly.
:return:
"""
code = gen_dispatch('test_a', ['DEP1', 'DEP2'])
expected = '''
#if defined(DEP1) && defined(DEP2)
test_a_wrapper,
#else
NULL,
#endif
'''
self.assertEqual(code, expected)
def test_empty_deps(self):
"""
Test empty dependency list.
:return:
"""
code = gen_dispatch('test_a', [])
expected = '''
test_a_wrapper,
'''
self.assertEqual(code, expected)
class StringIOWrapper(StringIO, object):
"""
file like class to mock file object in tests.
"""
def __init__(self, file_name, data, line_no = 1):
"""
Init file handle.
:param file_name:
:param data:
:param line_no:
"""
super(StringIOWrapper, self).__init__(data)
self.line_no = line_no
self.name = file_name
def next(self):
"""
Iterator return impl.
:return:
"""
line = super(StringIOWrapper, self).next()
return line
def readline(self, limit=0):
"""
Wrap the base class readline.
:param limit:
:return:
"""
line = super(StringIOWrapper, self).readline()
if line:
self.line_no += 1
return line
class ParseSuiteHeaders(TestCase):
"""
Test Suite for testing parse_suite_headers().
"""
def test_suite_headers(self):
"""
Test that suite headers are parsed correctly.
:return:
"""
data = '''#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
/* END_HEADER */
'''
expected = '''#line 1 "test_suite_ut.function"
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
'''
s = StringIOWrapper('test_suite_ut.function', data, line_no=0)
headers = parse_suite_headers(s)
self.assertEqual(headers, expected)
def test_line_no(self):
"""
Test that #line is set to correct line no. in source .function file.
:return:
"""
data = '''#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
/* END_HEADER */
'''
offset_line_no = 5
expected = '''#line %d "test_suite_ut.function"
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
''' % (offset_line_no + 1)
s = StringIOWrapper('test_suite_ut.function', data, offset_line_no)
headers = parse_suite_headers(s)
self.assertEqual(headers, expected)
def test_no_end_header_comment(self):
"""
Test that InvalidFileFormat is raised when end header comment is missing.
:return:
"""
data = '''#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(InvalidFileFormat, parse_suite_headers, s)
class ParseSuiteDeps(TestCase):
"""
Test Suite for testing parse_suite_deps().
"""
def test_suite_deps(self):
"""
:return:
"""
data = '''
* depends_on:MBEDTLS_ECP_C
* END_DEPENDENCIES
*/
'''
expected = ['MBEDTLS_ECP_C']
s = StringIOWrapper('test_suite_ut.function', data)
deps = parse_suite_deps(s)
self.assertEqual(deps, expected)
def test_no_end_dep_comment(self):
"""
Test that InvalidFileFormat is raised when end dep comment is missing.
:return:
"""
data = '''
* depends_on:MBEDTLS_ECP_C
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(InvalidFileFormat, parse_suite_deps, s)
def test_deps_split(self):
"""
Test that InvalidFileFormat is raised when end dep comment is missing.
:return:
"""
data = '''
* depends_on:MBEDTLS_ECP_C:A:B: C : D :F : G: !H
* END_DEPENDENCIES
*/
'''
expected = ['MBEDTLS_ECP_C', 'A', 'B', 'C', 'D', 'F', 'G', '!H']
s = StringIOWrapper('test_suite_ut.function', data)
deps = parse_suite_deps(s)
self.assertEqual(deps, expected)
class ParseFuncDeps(TestCase):
"""
Test Suite for testing parse_function_deps()
"""
def test_function_deps(self):
"""
Test that parse_function_deps() correctly parses function dependencies.
:return:
"""
line = '/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */'
expected = ['MBEDTLS_ENTROPY_NV_SEED', 'MBEDTLS_FS_IO']
deps = parse_function_deps(line)
self.assertEqual(deps, expected)
def test_no_deps(self):
"""
Test that parse_function_deps() correctly parses function dependencies.
:return:
"""
line = '/* BEGIN_CASE */'
deps = parse_function_deps(line)
self.assertEqual(deps, [])
def test_poorly_defined_deps(self):
"""
Test that parse_function_deps() correctly parses function dependencies.
:return:
"""
line = '/* BEGIN_CASE depends_on:MBEDTLS_FS_IO: A : !B:C : F*/'
deps = parse_function_deps(line)
self.assertEqual(deps, ['MBEDTLS_FS_IO', 'A', '!B', 'C', 'F'])
class ParseFuncSignature(TestCase):
"""
Test Suite for parse_function_signature().
"""
def test_int_and_char_params(self):
"""
:return:
"""
line = 'void entropy_threshold( char * a, int b, int result )'
name, args, local, arg_dispatch = parse_function_signature(line)
self.assertEqual(name, 'entropy_threshold')
self.assertEqual(args, ['char*', 'int', 'int'])
self.assertEqual(local, '')
self.assertEqual(arg_dispatch, ['(char *) params[0]', '*( (int *) params[1] )', '*( (int *) params[2] )'])
def test_hex_params(self):
"""
:return:
"""
line = 'void entropy_threshold( char * a, HexParam_t * h, int result )'
name, args, local, arg_dispatch = parse_function_signature(line)
self.assertEqual(name, 'entropy_threshold')
self.assertEqual(args, ['char*', 'hex', 'int'])
self.assertEqual(local, ' HexParam_t hex1 = {(uint8_t *) params[1], *( (uint32_t *) params[2] )};\n')
self.assertEqual(arg_dispatch, ['(char *) params[0]', '&hex1', '*( (int *) params[3] )'])
def test_non_void_function(self):
"""
:return:
"""
line = 'int entropy_threshold( char * a, HexParam_t * h, int result )'
self.assertRaises(ValueError, parse_function_signature, line)
def test_unsupported_arg(self):
"""
:return:
"""
line = 'int entropy_threshold( char * a, HexParam_t * h, int * result )'
self.assertRaises(ValueError, parse_function_signature, line)
def test_no_params(self):
"""
:return:
"""
line = 'void entropy_threshold()'
name, args, local, arg_dispatch = parse_function_signature(line)
self.assertEqual(name, 'entropy_threshold')
self.assertEqual(args, [])
self.assertEqual(local, '')
self.assertEqual(arg_dispatch, [])
class ParseFunctionCode(TestCase):
"""
Test suite for testing parse_function_code()
"""
def test_no_function(self):
"""
:return:
"""
data = '''
No
test
function
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
def test_no_end_case_comment(self):
"""
:return:
"""
data = '''
void test_func()
{
}
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
@patch("generate_code.parse_function_signature")
def test_parse_function_signature_called(self, parse_function_signature_mock):
"""
:return:
"""
parse_function_signature_mock.return_value = ('test_func', [], '', [])
data = '''
void test_func()
{
}
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
self.assertTrue(parse_function_signature_mock.called)
parse_function_signature_mock.assert_called_with('void test_func()\n')
@patch("generate_code.gen_dispatch")
@patch("generate_code.gen_deps")
@patch("generate_code.gen_function_wrapper")
@patch("generate_code.parse_function_signature")
def test_return(self, parse_function_signature_mock,
gen_function_wrapper_mock,
gen_deps_mock,
gen_dispatch_mock):
"""
:return:
"""
parse_function_signature_mock.return_value = ('func', [], '', [])
gen_function_wrapper_mock.return_value = ''
gen_deps_mock.side_effect = gen_deps
gen_dispatch_mock.side_effect = gen_dispatch
data = '''
void func()
{
ba ba black sheep
have you any wool
}
/* END_CASE */
'''
s = StringIOWrapper('test_suite_ut.function', data)
name, arg, code, dispatch_code = parse_function_code(s, [], [])
#self.assertRaises(InvalidFileFormat, parse_function_code, s, [], [])
self.assertTrue(parse_function_signature_mock.called)
parse_function_signature_mock.assert_called_with('void func()\n')
gen_function_wrapper_mock.assert_called_with('test_func', '', [])
self.assertEqual(name, 'test_func')
self.assertEqual(arg, [])
expected = '''#line 2 "test_suite_ut.function"
void test_func()
{
ba ba black sheep
have you any wool
exit:
;;
}
'''
self.assertEqual(code, expected)
self.assertEqual(dispatch_code, "\n test_func_wrapper,\n")
@patch("generate_code.gen_dispatch")
@patch("generate_code.gen_deps")
@patch("generate_code.gen_function_wrapper")
@patch("generate_code.parse_function_signature")
def test_with_exit_label(self, parse_function_signature_mock,
gen_function_wrapper_mock,
gen_deps_mock,
gen_dispatch_mock):
"""
:return:
"""
parse_function_signature_mock.return_value = ('func', [], '', [])
gen_function_wrapper_mock.return_value = ''
gen_deps_mock.side_effect = gen_deps
gen_dispatch_mock.side_effect = gen_dispatch
data = '''
void func()
{
ba ba black sheep
have you any wool
exit:
yes sir yes sir
3 bags full
}
/* END_CASE */
'''
s = StringIOWrapper('test_suite_ut.function', data)
name, arg, code, dispatch_code = parse_function_code(s, [], [])
expected = '''#line 2 "test_suite_ut.function"
void test_func()
{
ba ba black sheep
have you any wool
exit:
yes sir yes sir
3 bags full
}
'''
self.assertEqual(code, expected)
class ParseFunction(TestCase):
"""
Test Suite for testing parse_functions()
"""
@patch("generate_code.parse_suite_headers")
def test_begin_header(self, parse_suite_headers_mock):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
def stop(this):
raise Exception
parse_suite_headers_mock.side_effect = stop
data = '''/* BEGIN_HEADER */
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
/* END_HEADER */
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(Exception, parse_functions, s)
parse_suite_headers_mock.assert_called_with(s)
self.assertEqual(s.line_no, 2)
@patch("generate_code.parse_suite_deps")
def test_begin_dep(self, parse_suite_deps_mock):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
def stop(this):
raise Exception
parse_suite_deps_mock.side_effect = stop
data = '''/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_ECP_C
* END_DEPENDENCIES
*/
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(Exception, parse_functions, s)
parse_suite_deps_mock.assert_called_with(s)
self.assertEqual(s.line_no, 2)
@patch("generate_code.parse_function_deps")
def test_begin_function_dep(self, parse_function_deps_mock):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
def stop(this):
raise Exception
parse_function_deps_mock.side_effect = stop
deps_str = '/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
data = '''%svoid test_func()
{
}
''' % deps_str
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(Exception, parse_functions, s)
parse_function_deps_mock.assert_called_with(deps_str)
self.assertEqual(s.line_no, 2)
@patch("generate_code.parse_function_code")
@patch("generate_code.parse_function_deps")
def test_return(self, parse_function_deps_mock, parse_function_code_mock):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
def stop(this):
raise Exception
parse_function_deps_mock.return_value = []
in_func_code= '''void test_func()
{
}
'''
func_dispatch = '''
test_func_wrapper,
'''
parse_function_code_mock.return_value = 'test_func', [], in_func_code, func_dispatch
deps_str = '/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
data = '''%svoid test_func()
{
}
''' % deps_str
s = StringIOWrapper('test_suite_ut.function', data)
suite_deps, dispatch_code, func_code, func_info = parse_functions(s)
parse_function_deps_mock.assert_called_with(deps_str)
parse_function_code_mock.assert_called_with(s, [], [])
self.assertEqual(s.line_no, 5)
self.assertEqual(suite_deps, [])
expected_dispatch_code = '''/* Function Id: 0 */
test_func_wrapper,
'''
self.assertEqual(dispatch_code, expected_dispatch_code)
self.assertEqual(func_code, in_func_code)
self.assertEqual(func_info, {'test_func': (0, [])})
def test_parsing(self):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
data = '''/* BEGIN_HEADER */
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_ECP_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void func1()
{
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void func2()
{
}
/* END_CASE */
'''
s = StringIOWrapper('test_suite_ut.function', data)
suite_deps, dispatch_code, func_code, func_info = parse_functions(s)
self.assertEqual(s.line_no, 23)
self.assertEqual(suite_deps, ['MBEDTLS_ECP_C'])
expected_dispatch_code = '''/* Function Id: 0 */
#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
test_func1_wrapper,
#else
NULL,
#endif
/* Function Id: 1 */
#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
test_func2_wrapper,
#else
NULL,
#endif
'''
self.assertEqual(dispatch_code, expected_dispatch_code)
expected_func_code = '''#if defined(MBEDTLS_ECP_C)
#line 3 "test_suite_ut.function"
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#if defined(MBEDTLS_FS_IO)
#line 14 "test_suite_ut.function"
void test_func1()
{
exit:
;;
}
void test_func1_wrapper( void ** params )
{
(void)params;
test_func1( );
}
#endif /* MBEDTLS_FS_IO */
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#if defined(MBEDTLS_FS_IO)
#line 20 "test_suite_ut.function"
void test_func2()
{
exit:
;;
}
void test_func2_wrapper( void ** params )
{
(void)params;
test_func2( );
}
#endif /* MBEDTLS_FS_IO */
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#endif /* MBEDTLS_ECP_C */
'''
self.assertEqual(func_code, expected_func_code)
self.assertEqual(func_info, {'test_func1': (0, []), 'test_func2': (1, [])})
def test_same_function_name(self):
"""
Test that begin header is checked and parse_suite_headers() is called.
:return:
"""
data = '''/* BEGIN_HEADER */
#include "mbedtls/ecp.h"
#define ECP_PF_UNKNOWN -1
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_ECP_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void func()
{
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
void func()
{
}
/* END_CASE */
'''
s = StringIOWrapper('test_suite_ut.function', data)
self.assertRaises(AssertionError, parse_functions, s)
if __name__=='__main__':
unittest_main()