|  | #!/usr/bin/env python3 | 
|  | # Unit test for generate_test_code.py | 
|  | # | 
|  | # Copyright The Mbed TLS Contributors | 
|  | # SPDX-License-Identifier: Apache-2.0 | 
|  | # | 
|  | # 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. | 
|  |  | 
|  | """ | 
|  | Unit tests for generate_test_code.py | 
|  | """ | 
|  |  | 
|  | from io import StringIO | 
|  | from unittest import TestCase, main as unittest_main | 
|  | from unittest.mock import patch | 
|  |  | 
|  | from generate_test_code import gen_dependencies, gen_dependencies_one_line | 
|  | from generate_test_code import gen_function_wrapper, gen_dispatch | 
|  | from generate_test_code import parse_until_pattern, GeneratorInputError | 
|  | from generate_test_code import parse_suite_dependencies | 
|  | from generate_test_code import parse_function_dependencies | 
|  | from generate_test_code import parse_function_arguments, parse_function_code | 
|  | from generate_test_code import parse_functions, END_HEADER_REGEX | 
|  | from generate_test_code import END_SUITE_HELPERS_REGEX, escaped_split | 
|  | from generate_test_code import parse_test_data, gen_dep_check | 
|  | from generate_test_code import gen_expression_check, write_dependencies | 
|  | from generate_test_code import write_parameters, gen_suite_dep_checks | 
|  | from generate_test_code import gen_from_test_data | 
|  |  | 
|  |  | 
|  | class GenDep(TestCase): | 
|  | """ | 
|  | Test suite for function gen_dep() | 
|  | """ | 
|  |  | 
|  | def test_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['DEP1', 'DEP2'] | 
|  | dep_start, dep_end = gen_dependencies(dependencies) | 
|  | preprocessor1, preprocessor2 = dep_start.splitlines() | 
|  | endif1, endif2 = dep_end.splitlines() | 
|  | self.assertEqual(preprocessor1, '#if defined(DEP1)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(preprocessor2, '#if defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif1, '#endif /* DEP2 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif2, '#endif /* DEP1 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_disabled_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['!DEP1', '!DEP2'] | 
|  | dep_start, dep_end = gen_dependencies(dependencies) | 
|  | preprocessor1, preprocessor2 = dep_start.splitlines() | 
|  | endif1, endif2 = dep_end.splitlines() | 
|  | self.assertEqual(preprocessor1, '#if !defined(DEP1)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(preprocessor2, '#if !defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif1, '#endif /* !DEP2 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif2, '#endif /* !DEP1 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_mixed_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['!DEP1', 'DEP2'] | 
|  | dep_start, dep_end = gen_dependencies(dependencies) | 
|  | preprocessor1, preprocessor2 = dep_start.splitlines() | 
|  | endif1, endif2 = dep_end.splitlines() | 
|  | self.assertEqual(preprocessor1, '#if !defined(DEP1)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(preprocessor2, '#if defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif1, '#endif /* DEP2 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(endif2, '#endif /* !DEP1 */', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_empty_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = [] | 
|  | dep_start, dep_end = gen_dependencies(dependencies) | 
|  | self.assertEqual(dep_start, '', 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(dep_end, '', 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_large_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = [] | 
|  | count = 10 | 
|  | for i in range(count): | 
|  | dependencies.append('DEP%d' % i) | 
|  | dep_start, dep_end = gen_dependencies(dependencies) | 
|  | self.assertEqual(len(dep_start.splitlines()), count, | 
|  | 'Preprocessor generated incorrectly') | 
|  | self.assertEqual(len(dep_end.splitlines()), count, | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  |  | 
|  | class GenDepOneLine(TestCase): | 
|  | """ | 
|  | Test Suite for testing gen_dependencies_one_line() | 
|  | """ | 
|  |  | 
|  | def test_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['DEP1', 'DEP2'] | 
|  | dep_str = gen_dependencies_one_line(dependencies) | 
|  | self.assertEqual(dep_str, '#if defined(DEP1) && defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_disabled_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['!DEP1', '!DEP2'] | 
|  | dep_str = gen_dependencies_one_line(dependencies) | 
|  | self.assertEqual(dep_str, '#if !defined(DEP1) && !defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_mixed_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = ['!DEP1', 'DEP2'] | 
|  | dep_str = gen_dependencies_one_line(dependencies) | 
|  | self.assertEqual(dep_str, '#if !defined(DEP1) && defined(DEP2)', | 
|  | 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_empty_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = [] | 
|  | dep_str = gen_dependencies_one_line(dependencies) | 
|  | self.assertEqual(dep_str, '', 'Preprocessor generated incorrectly') | 
|  |  | 
|  | def test_large_dependencies_list(self): | 
|  | """ | 
|  | Test that gen_dep() correctly creates dependencies for given | 
|  | dependency list. | 
|  | :return: | 
|  | """ | 
|  | dependencies = [] | 
|  | count = 10 | 
|  | for i in range(count): | 
|  | dependencies.append('DEP%d' % i) | 
|  | dep_str = gen_dependencies_one_line(dependencies) | 
|  | expected = '#if ' + ' && '.join(['defined(%s)' % | 
|  | x for x in dependencies]) | 
|  | self.assertEqual(dep_str, expected, | 
|  | 'Preprocessor 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_dependencies(self): | 
|  | """ | 
|  | Test empty dependency list. | 
|  | :return: | 
|  | """ | 
|  | code = gen_dispatch('test_a', []) | 
|  | expected = ''' | 
|  | test_a_wrapper, | 
|  | ''' | 
|  | self.assertEqual(code, expected) | 
|  |  | 
|  |  | 
|  | class StringIOWrapper(StringIO): | 
|  | """ | 
|  | file like class to mock file object in tests. | 
|  | """ | 
|  | def __init__(self, file_name, data, line_no=0): | 
|  | """ | 
|  | 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 method. This method overrides base class's | 
|  | next method and extends the next method to count the line | 
|  | numbers as each line is read. | 
|  |  | 
|  | :return: Line read from file. | 
|  | """ | 
|  | parent = super(StringIOWrapper, self) | 
|  | line = parent.__next__() | 
|  | return line | 
|  |  | 
|  | def readline(self, _length=0): | 
|  | """ | 
|  | Wrap the base class readline. | 
|  |  | 
|  | :param length: | 
|  | :return: | 
|  | """ | 
|  | line = super(StringIOWrapper, self).readline() | 
|  | if line is not None: | 
|  | self.line_no += 1 | 
|  | return line | 
|  |  | 
|  |  | 
|  | class ParseUntilPattern(TestCase): | 
|  | """ | 
|  | Test Suite for testing parse_until_pattern(). | 
|  | """ | 
|  |  | 
|  | 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 | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data, line_no=0) | 
|  | headers = parse_until_pattern(stream, END_HEADER_REGEX) | 
|  | 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) | 
|  | stream = StringIOWrapper('test_suite_ut.function', data, | 
|  | offset_line_no) | 
|  | headers = parse_until_pattern(stream, END_HEADER_REGEX) | 
|  | 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 | 
|  |  | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(GeneratorInputError, parse_until_pattern, stream, | 
|  | END_HEADER_REGEX) | 
|  |  | 
|  |  | 
|  | class ParseSuiteDependencies(TestCase): | 
|  | """ | 
|  | Test Suite for testing parse_suite_dependencies(). | 
|  | """ | 
|  |  | 
|  | def test_suite_dependencies(self): | 
|  | """ | 
|  |  | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | * depends_on:MBEDTLS_ECP_C | 
|  | * END_DEPENDENCIES | 
|  | */ | 
|  | ''' | 
|  | expected = ['MBEDTLS_ECP_C'] | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | dependencies = parse_suite_dependencies(stream) | 
|  | self.assertEqual(dependencies, 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 | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(GeneratorInputError, parse_suite_dependencies, | 
|  | stream) | 
|  |  | 
|  | def test_dependencies_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'] | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | dependencies = parse_suite_dependencies(stream) | 
|  | self.assertEqual(dependencies, expected) | 
|  |  | 
|  |  | 
|  | class ParseFuncDependencies(TestCase): | 
|  | """ | 
|  | Test Suite for testing parse_function_dependencies() | 
|  | """ | 
|  |  | 
|  | def test_function_dependencies(self): | 
|  | """ | 
|  | Test that parse_function_dependencies() 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'] | 
|  | dependencies = parse_function_dependencies(line) | 
|  | self.assertEqual(dependencies, expected) | 
|  |  | 
|  | def test_no_dependencies(self): | 
|  | """ | 
|  | Test that parse_function_dependencies() correctly parses function | 
|  | dependencies. | 
|  | :return: | 
|  | """ | 
|  | line = '/* BEGIN_CASE */' | 
|  | dependencies = parse_function_dependencies(line) | 
|  | self.assertEqual(dependencies, []) | 
|  |  | 
|  | def test_tolerance(self): | 
|  | """ | 
|  | Test that parse_function_dependencies() correctly parses function | 
|  | dependencies. | 
|  | :return: | 
|  | """ | 
|  | line = '/* BEGIN_CASE depends_on:MBEDTLS_FS_IO: A : !B:C : F*/' | 
|  | dependencies = parse_function_dependencies(line) | 
|  | self.assertEqual(dependencies, ['MBEDTLS_FS_IO', 'A', '!B', 'C', 'F']) | 
|  |  | 
|  |  | 
|  | class ParseFuncSignature(TestCase): | 
|  | """ | 
|  | Test Suite for parse_function_arguments(). | 
|  | """ | 
|  |  | 
|  | def test_int_and_char_params(self): | 
|  | """ | 
|  | Test int and char parameters parsing | 
|  | :return: | 
|  | """ | 
|  | line = 'void entropy_threshold( char * a, int b, int result )' | 
|  | args, local, arg_dispatch = parse_function_arguments(line) | 
|  | 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): | 
|  | """ | 
|  | Test hex parameters parsing | 
|  | :return: | 
|  | """ | 
|  | line = 'void entropy_threshold( char * a, data_t * h, int result )' | 
|  | args, local, arg_dispatch = parse_function_arguments(line) | 
|  | self.assertEqual(args, ['char*', 'hex', 'int']) | 
|  | self.assertEqual(local, | 
|  | '    data_t data1 = {(uint8_t *) params[1], ' | 
|  | '*( (uint32_t *) params[2] )};\n') | 
|  | self.assertEqual(arg_dispatch, ['(char *) params[0]', | 
|  | '&data1', | 
|  | '*( (int *) params[3] )']) | 
|  |  | 
|  | def test_unsupported_arg(self): | 
|  | """ | 
|  | Test unsupported arguments (not among int, char * and data_t) | 
|  | :return: | 
|  | """ | 
|  | line = 'void entropy_threshold( char * a, data_t * h, char result )' | 
|  | self.assertRaises(ValueError, parse_function_arguments, line) | 
|  |  | 
|  | def test_no_params(self): | 
|  | """ | 
|  | Test no parameters. | 
|  | :return: | 
|  | """ | 
|  | line = 'void entropy_threshold()' | 
|  | args, local, arg_dispatch = parse_function_arguments(line) | 
|  | 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): | 
|  | """ | 
|  | Test no test function found. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | No | 
|  | test | 
|  | function | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | err_msg = 'file: test_suite_ut.function - Test functions not found!' | 
|  | self.assertRaisesRegex(GeneratorInputError, err_msg, | 
|  | parse_function_code, stream, [], []) | 
|  |  | 
|  | def test_no_end_case_comment(self): | 
|  | """ | 
|  | Test missing end case. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | void test_func() | 
|  | { | 
|  | } | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | err_msg = r'file: test_suite_ut.function - '\ | 
|  | 'end case pattern .*? not found!' | 
|  | self.assertRaisesRegex(GeneratorInputError, err_msg, | 
|  | parse_function_code, stream, [], []) | 
|  |  | 
|  | @patch("generate_test_code.parse_function_arguments") | 
|  | def test_function_called(self, | 
|  | parse_function_arguments_mock): | 
|  | """ | 
|  | Test parse_function_code() | 
|  | :return: | 
|  | """ | 
|  | parse_function_arguments_mock.return_value = ([], '', []) | 
|  | data = ''' | 
|  | void test_func() | 
|  | { | 
|  | } | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(GeneratorInputError, parse_function_code, | 
|  | stream, [], []) | 
|  | self.assertTrue(parse_function_arguments_mock.called) | 
|  | parse_function_arguments_mock.assert_called_with('void test_func()\n') | 
|  |  | 
|  | @patch("generate_test_code.gen_dispatch") | 
|  | @patch("generate_test_code.gen_dependencies") | 
|  | @patch("generate_test_code.gen_function_wrapper") | 
|  | @patch("generate_test_code.parse_function_arguments") | 
|  | def test_return(self, parse_function_arguments_mock, | 
|  | gen_function_wrapper_mock, | 
|  | gen_dependencies_mock, | 
|  | gen_dispatch_mock): | 
|  | """ | 
|  | Test generated code. | 
|  | :return: | 
|  | """ | 
|  | parse_function_arguments_mock.return_value = ([], '', []) | 
|  | gen_function_wrapper_mock.return_value = '' | 
|  | gen_dependencies_mock.side_effect = gen_dependencies | 
|  | gen_dispatch_mock.side_effect = gen_dispatch | 
|  | data = ''' | 
|  | void func() | 
|  | { | 
|  | ba ba black sheep | 
|  | have you any wool | 
|  | } | 
|  | /* END_CASE */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | name, arg, code, dispatch_code = parse_function_code(stream, [], []) | 
|  |  | 
|  | self.assertTrue(parse_function_arguments_mock.called) | 
|  | parse_function_arguments_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 1 "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_test_code.gen_dispatch") | 
|  | @patch("generate_test_code.gen_dependencies") | 
|  | @patch("generate_test_code.gen_function_wrapper") | 
|  | @patch("generate_test_code.parse_function_arguments") | 
|  | def test_with_exit_label(self, parse_function_arguments_mock, | 
|  | gen_function_wrapper_mock, | 
|  | gen_dependencies_mock, | 
|  | gen_dispatch_mock): | 
|  | """ | 
|  | Test when exit label is present. | 
|  | :return: | 
|  | """ | 
|  | parse_function_arguments_mock.return_value = ([], '', []) | 
|  | gen_function_wrapper_mock.return_value = '' | 
|  | gen_dependencies_mock.side_effect = gen_dependencies | 
|  | 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 */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | _, _, code, _ = parse_function_code(stream, [], []) | 
|  |  | 
|  | expected = '''#line 1 "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) | 
|  |  | 
|  | def test_non_void_function(self): | 
|  | """ | 
|  | Test invalid signature (non void). | 
|  | :return: | 
|  | """ | 
|  | data = 'int entropy_threshold( char * a, data_t * h, int result )' | 
|  | err_msg = 'file: test_suite_ut.function - Test functions not found!' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaisesRegex(GeneratorInputError, err_msg, | 
|  | parse_function_code, stream, [], []) | 
|  |  | 
|  | @patch("generate_test_code.gen_dispatch") | 
|  | @patch("generate_test_code.gen_dependencies") | 
|  | @patch("generate_test_code.gen_function_wrapper") | 
|  | @patch("generate_test_code.parse_function_arguments") | 
|  | def test_functio_name_on_newline(self, parse_function_arguments_mock, | 
|  | gen_function_wrapper_mock, | 
|  | gen_dependencies_mock, | 
|  | gen_dispatch_mock): | 
|  | """ | 
|  | Test when exit label is present. | 
|  | :return: | 
|  | """ | 
|  | parse_function_arguments_mock.return_value = ([], '', []) | 
|  | gen_function_wrapper_mock.return_value = '' | 
|  | gen_dependencies_mock.side_effect = gen_dependencies | 
|  | 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 */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | _, _, code, _ = parse_function_code(stream, [], []) | 
|  |  | 
|  | expected = '''#line 1 "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_test_code.parse_until_pattern") | 
|  | def test_begin_header(self, parse_until_pattern_mock): | 
|  | """ | 
|  | Test that begin header is checked and parse_until_pattern() is called. | 
|  | :return: | 
|  | """ | 
|  | def stop(*_unused): | 
|  | """Stop when parse_until_pattern is called.""" | 
|  | raise Exception | 
|  | parse_until_pattern_mock.side_effect = stop | 
|  | data = '''/* BEGIN_HEADER */ | 
|  | #include "mbedtls/ecp.h" | 
|  |  | 
|  | #define ECP_PF_UNKNOWN     -1 | 
|  | /* END_HEADER */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(Exception, parse_functions, stream) | 
|  | parse_until_pattern_mock.assert_called_with(stream, END_HEADER_REGEX) | 
|  | self.assertEqual(stream.line_no, 1) | 
|  |  | 
|  | @patch("generate_test_code.parse_until_pattern") | 
|  | def test_begin_helper(self, parse_until_pattern_mock): | 
|  | """ | 
|  | Test that begin helper is checked and parse_until_pattern() is called. | 
|  | :return: | 
|  | """ | 
|  | def stop(*_unused): | 
|  | """Stop when parse_until_pattern is called.""" | 
|  | raise Exception | 
|  | parse_until_pattern_mock.side_effect = stop | 
|  | data = '''/* BEGIN_SUITE_HELPERS */ | 
|  | void print_hello_world() | 
|  | { | 
|  | printf("Hello World!\n"); | 
|  | } | 
|  | /* END_SUITE_HELPERS */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(Exception, parse_functions, stream) | 
|  | parse_until_pattern_mock.assert_called_with(stream, | 
|  | END_SUITE_HELPERS_REGEX) | 
|  | self.assertEqual(stream.line_no, 1) | 
|  |  | 
|  | @patch("generate_test_code.parse_suite_dependencies") | 
|  | def test_begin_dep(self, parse_suite_dependencies_mock): | 
|  | """ | 
|  | Test that begin dep is checked and parse_suite_dependencies() is | 
|  | called. | 
|  | :return: | 
|  | """ | 
|  | def stop(*_unused): | 
|  | """Stop when parse_until_pattern is called.""" | 
|  | raise Exception | 
|  | parse_suite_dependencies_mock.side_effect = stop | 
|  | data = '''/* BEGIN_DEPENDENCIES | 
|  | * depends_on:MBEDTLS_ECP_C | 
|  | * END_DEPENDENCIES | 
|  | */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(Exception, parse_functions, stream) | 
|  | parse_suite_dependencies_mock.assert_called_with(stream) | 
|  | self.assertEqual(stream.line_no, 1) | 
|  |  | 
|  | @patch("generate_test_code.parse_function_dependencies") | 
|  | def test_begin_function_dep(self, func_mock): | 
|  | """ | 
|  | Test that begin dep is checked and parse_function_dependencies() is | 
|  | called. | 
|  | :return: | 
|  | """ | 
|  | def stop(*_unused): | 
|  | """Stop when parse_until_pattern is called.""" | 
|  | raise Exception | 
|  | func_mock.side_effect = stop | 
|  |  | 
|  | dependencies_str = '/* BEGIN_CASE ' \ | 
|  | 'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n' | 
|  | data = '''%svoid test_func() | 
|  | { | 
|  | } | 
|  | ''' % dependencies_str | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(Exception, parse_functions, stream) | 
|  | func_mock.assert_called_with(dependencies_str) | 
|  | self.assertEqual(stream.line_no, 1) | 
|  |  | 
|  | @patch("generate_test_code.parse_function_code") | 
|  | @patch("generate_test_code.parse_function_dependencies") | 
|  | def test_return(self, func_mock1, func_mock2): | 
|  | """ | 
|  | Test that begin case is checked and parse_function_code() is called. | 
|  | :return: | 
|  | """ | 
|  | func_mock1.return_value = [] | 
|  | in_func_code = '''void test_func() | 
|  | { | 
|  | } | 
|  | ''' | 
|  | func_dispatch = ''' | 
|  | test_func_wrapper, | 
|  | ''' | 
|  | func_mock2.return_value = 'test_func', [],\ | 
|  | in_func_code, func_dispatch | 
|  | dependencies_str = '/* BEGIN_CASE ' \ | 
|  | 'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n' | 
|  | data = '''%svoid test_func() | 
|  | { | 
|  | } | 
|  | ''' % dependencies_str | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | suite_dependencies, dispatch_code, func_code, func_info = \ | 
|  | parse_functions(stream) | 
|  | func_mock1.assert_called_with(dependencies_str) | 
|  | func_mock2.assert_called_with(stream, [], []) | 
|  | self.assertEqual(stream.line_no, 5) | 
|  | self.assertEqual(suite_dependencies, []) | 
|  | 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 case parsing. | 
|  | :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 */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | suite_dependencies, dispatch_code, func_code, func_info = \ | 
|  | parse_functions(stream) | 
|  | self.assertEqual(stream.line_no, 23) | 
|  | self.assertEqual(suite_dependencies, ['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 2 "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 13 "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 19 "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 name conflict. | 
|  | :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 */ | 
|  | ''' | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | self.assertRaises(GeneratorInputError, parse_functions, stream) | 
|  |  | 
|  |  | 
|  | class EscapedSplit(TestCase): | 
|  | """ | 
|  | Test suite for testing escaped_split(). | 
|  | Note: Since escaped_split() output is used to write back to the | 
|  | intermediate data file. Any escape characters in the input are | 
|  | retained in the output. | 
|  | """ | 
|  |  | 
|  | def test_invalid_input(self): | 
|  | """ | 
|  | Test when input split character is not a character. | 
|  | :return: | 
|  | """ | 
|  | self.assertRaises(ValueError, escaped_split, '', 'string') | 
|  |  | 
|  | def test_empty_string(self): | 
|  | """ | 
|  | Test empty string input. | 
|  | :return: | 
|  | """ | 
|  | splits = escaped_split('', ':') | 
|  | self.assertEqual(splits, []) | 
|  |  | 
|  | def test_no_escape(self): | 
|  | """ | 
|  | Test with no escape character. The behaviour should be same as | 
|  | str.split() | 
|  | :return: | 
|  | """ | 
|  | test_str = 'yahoo:google' | 
|  | splits = escaped_split(test_str, ':') | 
|  | self.assertEqual(splits, test_str.split(':')) | 
|  |  | 
|  | def test_escaped_input(self): | 
|  | """ | 
|  | Test input that has escaped delimiter. | 
|  | :return: | 
|  | """ | 
|  | test_str = r'yahoo\:google:facebook' | 
|  | splits = escaped_split(test_str, ':') | 
|  | self.assertEqual(splits, [r'yahoo\:google', 'facebook']) | 
|  |  | 
|  | def test_escaped_escape(self): | 
|  | """ | 
|  | Test input that has escaped delimiter. | 
|  | :return: | 
|  | """ | 
|  | test_str = r'yahoo\\:google:facebook' | 
|  | splits = escaped_split(test_str, ':') | 
|  | self.assertEqual(splits, [r'yahoo\\', 'google', 'facebook']) | 
|  |  | 
|  | def test_all_at_once(self): | 
|  | """ | 
|  | Test input that has escaped delimiter. | 
|  | :return: | 
|  | """ | 
|  | test_str = r'yahoo\\:google:facebook\:instagram\\:bbc\\:wikipedia' | 
|  | splits = escaped_split(test_str, ':') | 
|  | self.assertEqual(splits, [r'yahoo\\', r'google', | 
|  | r'facebook\:instagram\\', | 
|  | r'bbc\\', r'wikipedia']) | 
|  |  | 
|  |  | 
|  | class ParseTestData(TestCase): | 
|  | """ | 
|  | Test suite for parse test data. | 
|  | """ | 
|  |  | 
|  | def test_parser(self): | 
|  | """ | 
|  | Test that tests are parsed correctly from data file. | 
|  | :return: | 
|  | """ | 
|  | data = """ | 
|  | Diffie-Hellman full exchange #1 | 
|  | dhm_do_dhm:10:"23":10:"5" | 
|  |  | 
|  | Diffie-Hellman full exchange #2 | 
|  | dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" | 
|  |  | 
|  | Diffie-Hellman full exchange #3 | 
|  | dhm_do_dhm:10:"9345098382739712938719287391879381271":10:"9345098792137312973297123912791271" | 
|  |  | 
|  | Diffie-Hellman selftest | 
|  | dhm_selftest: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | # List of (name, function_name, dependencies, args) | 
|  | tests = list(parse_test_data(stream)) | 
|  | test1, test2, test3, test4 = tests | 
|  | self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1') | 
|  | self.assertEqual(test1[1], 'dhm_do_dhm') | 
|  | self.assertEqual(test1[2], []) | 
|  | self.assertEqual(test1[3], ['10', '"23"', '10', '"5"']) | 
|  |  | 
|  | self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2') | 
|  | self.assertEqual(test2[1], 'dhm_do_dhm') | 
|  | self.assertEqual(test2[2], []) | 
|  | self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"', | 
|  | '10', '"9345098304850938450983409622"']) | 
|  |  | 
|  | self.assertEqual(test3[0], 'Diffie-Hellman full exchange #3') | 
|  | self.assertEqual(test3[1], 'dhm_do_dhm') | 
|  | self.assertEqual(test3[2], []) | 
|  | self.assertEqual(test3[3], ['10', | 
|  | '"9345098382739712938719287391879381271"', | 
|  | '10', | 
|  | '"9345098792137312973297123912791271"']) | 
|  |  | 
|  | self.assertEqual(test4[0], 'Diffie-Hellman selftest') | 
|  | self.assertEqual(test4[1], 'dhm_selftest') | 
|  | self.assertEqual(test4[2], []) | 
|  | self.assertEqual(test4[3], []) | 
|  |  | 
|  | def test_with_dependencies(self): | 
|  | """ | 
|  | Test that tests with dependencies are parsed. | 
|  | :return: | 
|  | """ | 
|  | data = """ | 
|  | Diffie-Hellman full exchange #1 | 
|  | depends_on:YAHOO | 
|  | dhm_do_dhm:10:"23":10:"5" | 
|  |  | 
|  | Diffie-Hellman full exchange #2 | 
|  | dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" | 
|  |  | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | # List of (name, function_name, dependencies, args) | 
|  | tests = list(parse_test_data(stream)) | 
|  | test1, test2 = tests | 
|  | self.assertEqual(test1[0], 'Diffie-Hellman full exchange #1') | 
|  | self.assertEqual(test1[1], 'dhm_do_dhm') | 
|  | self.assertEqual(test1[2], ['YAHOO']) | 
|  | self.assertEqual(test1[3], ['10', '"23"', '10', '"5"']) | 
|  |  | 
|  | self.assertEqual(test2[0], 'Diffie-Hellman full exchange #2') | 
|  | self.assertEqual(test2[1], 'dhm_do_dhm') | 
|  | self.assertEqual(test2[2], []) | 
|  | self.assertEqual(test2[3], ['10', '"93450983094850938450983409623"', | 
|  | '10', '"9345098304850938450983409622"']) | 
|  |  | 
|  | def test_no_args(self): | 
|  | """ | 
|  | Test GeneratorInputError is raised when test function name and | 
|  | args line is missing. | 
|  | :return: | 
|  | """ | 
|  | data = """ | 
|  | Diffie-Hellman full exchange #1 | 
|  | depends_on:YAHOO | 
|  |  | 
|  |  | 
|  | Diffie-Hellman full exchange #2 | 
|  | dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622" | 
|  |  | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | err = None | 
|  | try: | 
|  | for _, _, _, _ in parse_test_data(stream): | 
|  | pass | 
|  | except GeneratorInputError as err: | 
|  | self.assertEqual(type(err), GeneratorInputError) | 
|  |  | 
|  | def test_incomplete_data(self): | 
|  | """ | 
|  | Test GeneratorInputError is raised when test function name | 
|  | and args line is missing. | 
|  | :return: | 
|  | """ | 
|  | data = """ | 
|  | Diffie-Hellman full exchange #1 | 
|  | depends_on:YAHOO | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.function', data) | 
|  | err = None | 
|  | try: | 
|  | for _, _, _, _ in parse_test_data(stream): | 
|  | pass | 
|  | except GeneratorInputError as err: | 
|  | self.assertEqual(type(err), GeneratorInputError) | 
|  |  | 
|  |  | 
|  | class GenDepCheck(TestCase): | 
|  | """ | 
|  | Test suite for gen_dep_check(). It is assumed this function is | 
|  | called with valid inputs. | 
|  | """ | 
|  |  | 
|  | def test_gen_dep_check(self): | 
|  | """ | 
|  | Test that dependency check code generated correctly. | 
|  | :return: | 
|  | """ | 
|  | expected = """ | 
|  | case 5: | 
|  | { | 
|  | #if defined(YAHOO) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;""" | 
|  | out = gen_dep_check(5, 'YAHOO') | 
|  | self.assertEqual(out, expected) | 
|  |  | 
|  | def test_not_defined_dependency(self): | 
|  | """ | 
|  | Test dependency with !. | 
|  | :return: | 
|  | """ | 
|  | expected = """ | 
|  | case 5: | 
|  | { | 
|  | #if !defined(YAHOO) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;""" | 
|  | out = gen_dep_check(5, '!YAHOO') | 
|  | self.assertEqual(out, expected) | 
|  |  | 
|  | def test_empty_dependency(self): | 
|  | """ | 
|  | Test invalid dependency input. | 
|  | :return: | 
|  | """ | 
|  | self.assertRaises(GeneratorInputError, gen_dep_check, 5, '!') | 
|  |  | 
|  | def test_negative_dep_id(self): | 
|  | """ | 
|  | Test invalid dependency input. | 
|  | :return: | 
|  | """ | 
|  | self.assertRaises(GeneratorInputError, gen_dep_check, -1, 'YAHOO') | 
|  |  | 
|  |  | 
|  | class GenExpCheck(TestCase): | 
|  | """ | 
|  | Test suite for gen_expression_check(). It is assumed this function | 
|  | is called with valid inputs. | 
|  | """ | 
|  |  | 
|  | def test_gen_exp_check(self): | 
|  | """ | 
|  | Test that expression check code generated correctly. | 
|  | :return: | 
|  | """ | 
|  | expected = """ | 
|  | case 5: | 
|  | { | 
|  | *out_value = YAHOO; | 
|  | } | 
|  | break;""" | 
|  | out = gen_expression_check(5, 'YAHOO') | 
|  | self.assertEqual(out, expected) | 
|  |  | 
|  | def test_invalid_expression(self): | 
|  | """ | 
|  | Test invalid expression input. | 
|  | :return: | 
|  | """ | 
|  | self.assertRaises(GeneratorInputError, gen_expression_check, 5, '') | 
|  |  | 
|  | def test_negative_exp_id(self): | 
|  | """ | 
|  | Test invalid expression id. | 
|  | :return: | 
|  | """ | 
|  | self.assertRaises(GeneratorInputError, gen_expression_check, | 
|  | -1, 'YAHOO') | 
|  |  | 
|  |  | 
|  | class WriteDependencies(TestCase): | 
|  | """ | 
|  | Test suite for testing write_dependencies. | 
|  | """ | 
|  |  | 
|  | def test_no_test_dependencies(self): | 
|  | """ | 
|  | Test when test dependencies input is empty. | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_dependencies = [] | 
|  | dep_check_code = write_dependencies(stream, [], unique_dependencies) | 
|  | self.assertEqual(dep_check_code, '') | 
|  | self.assertEqual(len(unique_dependencies), 0) | 
|  | self.assertEqual(stream.getvalue(), '') | 
|  |  | 
|  | def test_unique_dep_ids(self): | 
|  | """ | 
|  |  | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_dependencies = [] | 
|  | dep_check_code = write_dependencies(stream, ['DEP3', 'DEP2', 'DEP1'], | 
|  | unique_dependencies) | 
|  | expect_dep_check_code = ''' | 
|  | case 0: | 
|  | { | 
|  | #if defined(DEP3) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | #if defined(DEP2) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break; | 
|  | case 2: | 
|  | { | 
|  | #if defined(DEP1) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;''' | 
|  | self.assertEqual(dep_check_code, expect_dep_check_code) | 
|  | self.assertEqual(len(unique_dependencies), 3) | 
|  | self.assertEqual(stream.getvalue(), 'depends_on:0:1:2\n') | 
|  |  | 
|  | def test_dep_id_repeat(self): | 
|  | """ | 
|  |  | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_dependencies = [] | 
|  | dep_check_code = '' | 
|  | dep_check_code += write_dependencies(stream, ['DEP3', 'DEP2'], | 
|  | unique_dependencies) | 
|  | dep_check_code += write_dependencies(stream, ['DEP2', 'DEP1'], | 
|  | unique_dependencies) | 
|  | dep_check_code += write_dependencies(stream, ['DEP1', 'DEP3'], | 
|  | unique_dependencies) | 
|  | expect_dep_check_code = ''' | 
|  | case 0: | 
|  | { | 
|  | #if defined(DEP3) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | #if defined(DEP2) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break; | 
|  | case 2: | 
|  | { | 
|  | #if defined(DEP1) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;''' | 
|  | self.assertEqual(dep_check_code, expect_dep_check_code) | 
|  | self.assertEqual(len(unique_dependencies), 3) | 
|  | self.assertEqual(stream.getvalue(), | 
|  | 'depends_on:0:1\ndepends_on:1:2\ndepends_on:2:0\n') | 
|  |  | 
|  |  | 
|  | class WriteParams(TestCase): | 
|  | """ | 
|  | Test Suite for testing write_parameters(). | 
|  | """ | 
|  |  | 
|  | def test_no_params(self): | 
|  | """ | 
|  | Test with empty test_args | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_expressions = [] | 
|  | expression_code = write_parameters(stream, [], [], unique_expressions) | 
|  | self.assertEqual(len(unique_expressions), 0) | 
|  | self.assertEqual(expression_code, '') | 
|  | self.assertEqual(stream.getvalue(), '\n') | 
|  |  | 
|  | def test_no_exp_param(self): | 
|  | """ | 
|  | Test when there is no macro or expression in the params. | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_expressions = [] | 
|  | expression_code = write_parameters(stream, ['"Yahoo"', '"abcdef00"', | 
|  | '0'], | 
|  | ['char*', 'hex', 'int'], | 
|  | unique_expressions) | 
|  | self.assertEqual(len(unique_expressions), 0) | 
|  | self.assertEqual(expression_code, '') | 
|  | self.assertEqual(stream.getvalue(), | 
|  | ':char*:"Yahoo":hex:"abcdef00":int:0\n') | 
|  |  | 
|  | def test_hex_format_int_param(self): | 
|  | """ | 
|  | Test int parameter in hex format. | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_expressions = [] | 
|  | expression_code = write_parameters(stream, | 
|  | ['"Yahoo"', '"abcdef00"', '0xAA'], | 
|  | ['char*', 'hex', 'int'], | 
|  | unique_expressions) | 
|  | self.assertEqual(len(unique_expressions), 0) | 
|  | self.assertEqual(expression_code, '') | 
|  | self.assertEqual(stream.getvalue(), | 
|  | ':char*:"Yahoo":hex:"abcdef00":int:0xAA\n') | 
|  |  | 
|  | def test_with_exp_param(self): | 
|  | """ | 
|  | Test when there is macro or expression in the params. | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_expressions = [] | 
|  | expression_code = write_parameters(stream, | 
|  | ['"Yahoo"', '"abcdef00"', '0', | 
|  | 'MACRO1', 'MACRO2', 'MACRO3'], | 
|  | ['char*', 'hex', 'int', | 
|  | 'int', 'int', 'int'], | 
|  | unique_expressions) | 
|  | self.assertEqual(len(unique_expressions), 3) | 
|  | self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3']) | 
|  | expected_expression_code = ''' | 
|  | case 0: | 
|  | { | 
|  | *out_value = MACRO1; | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | *out_value = MACRO2; | 
|  | } | 
|  | break; | 
|  | case 2: | 
|  | { | 
|  | *out_value = MACRO3; | 
|  | } | 
|  | break;''' | 
|  | self.assertEqual(expression_code, expected_expression_code) | 
|  | self.assertEqual(stream.getvalue(), | 
|  | ':char*:"Yahoo":hex:"abcdef00":int:0:exp:0:exp:1' | 
|  | ':exp:2\n') | 
|  |  | 
|  | def test_with_repeat_calls(self): | 
|  | """ | 
|  | Test when write_parameter() is called with same macro or expression. | 
|  | :return: | 
|  | """ | 
|  | stream = StringIOWrapper('test_suite_ut.data', '') | 
|  | unique_expressions = [] | 
|  | expression_code = '' | 
|  | expression_code += write_parameters(stream, | 
|  | ['"Yahoo"', 'MACRO1', 'MACRO2'], | 
|  | ['char*', 'int', 'int'], | 
|  | unique_expressions) | 
|  | expression_code += write_parameters(stream, | 
|  | ['"abcdef00"', 'MACRO2', 'MACRO3'], | 
|  | ['hex', 'int', 'int'], | 
|  | unique_expressions) | 
|  | expression_code += write_parameters(stream, | 
|  | ['0', 'MACRO3', 'MACRO1'], | 
|  | ['int', 'int', 'int'], | 
|  | unique_expressions) | 
|  | self.assertEqual(len(unique_expressions), 3) | 
|  | self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3']) | 
|  | expected_expression_code = ''' | 
|  | case 0: | 
|  | { | 
|  | *out_value = MACRO1; | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | *out_value = MACRO2; | 
|  | } | 
|  | break; | 
|  | case 2: | 
|  | { | 
|  | *out_value = MACRO3; | 
|  | } | 
|  | break;''' | 
|  | self.assertEqual(expression_code, expected_expression_code) | 
|  | expected_data_file = ''':char*:"Yahoo":exp:0:exp:1 | 
|  | :hex:"abcdef00":exp:1:exp:2 | 
|  | :int:0:exp:2:exp:0 | 
|  | ''' | 
|  | self.assertEqual(stream.getvalue(), expected_data_file) | 
|  |  | 
|  |  | 
|  | class GenTestSuiteDependenciesChecks(TestCase): | 
|  | """ | 
|  | Test suite for testing gen_suite_dep_checks() | 
|  | """ | 
|  | def test_empty_suite_dependencies(self): | 
|  | """ | 
|  | Test with empty suite_dependencies list. | 
|  |  | 
|  | :return: | 
|  | """ | 
|  | dep_check_code, expression_code = \ | 
|  | gen_suite_dep_checks([], 'DEP_CHECK_CODE', 'EXPRESSION_CODE') | 
|  | self.assertEqual(dep_check_code, 'DEP_CHECK_CODE') | 
|  | self.assertEqual(expression_code, 'EXPRESSION_CODE') | 
|  |  | 
|  | def test_suite_dependencies(self): | 
|  | """ | 
|  | Test with suite_dependencies list. | 
|  |  | 
|  | :return: | 
|  | """ | 
|  | dep_check_code, expression_code = \ | 
|  | gen_suite_dep_checks(['SUITE_DEP'], 'DEP_CHECK_CODE', | 
|  | 'EXPRESSION_CODE') | 
|  | expected_dep_check_code = ''' | 
|  | #if defined(SUITE_DEP) | 
|  | DEP_CHECK_CODE | 
|  | #endif | 
|  | ''' | 
|  | expected_expression_code = ''' | 
|  | #if defined(SUITE_DEP) | 
|  | EXPRESSION_CODE | 
|  | #endif | 
|  | ''' | 
|  | self.assertEqual(dep_check_code, expected_dep_check_code) | 
|  | self.assertEqual(expression_code, expected_expression_code) | 
|  |  | 
|  | def test_no_dep_no_exp(self): | 
|  | """ | 
|  | Test when there are no dependency and expression code. | 
|  | :return: | 
|  | """ | 
|  | dep_check_code, expression_code = gen_suite_dep_checks([], '', '') | 
|  | self.assertEqual(dep_check_code, '') | 
|  | self.assertEqual(expression_code, '') | 
|  |  | 
|  |  | 
|  | class GenFromTestData(TestCase): | 
|  | """ | 
|  | Test suite for gen_from_test_data() | 
|  | """ | 
|  |  | 
|  | @staticmethod | 
|  | @patch("generate_test_code.write_dependencies") | 
|  | @patch("generate_test_code.write_parameters") | 
|  | @patch("generate_test_code.gen_suite_dep_checks") | 
|  | def test_intermediate_data_file(func_mock1, | 
|  | write_parameters_mock, | 
|  | write_dependencies_mock): | 
|  | """ | 
|  | Test that intermediate data file is written with expected data. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | My test | 
|  | depends_on:DEP1 | 
|  | func1:0 | 
|  | ''' | 
|  | data_f = StringIOWrapper('test_suite_ut.data', data) | 
|  | out_data_f = StringIOWrapper('test_suite_ut.datax', '') | 
|  | func_info = {'test_func1': (1, ('int',))} | 
|  | suite_dependencies = [] | 
|  | write_parameters_mock.side_effect = write_parameters | 
|  | write_dependencies_mock.side_effect = write_dependencies | 
|  | func_mock1.side_effect = gen_suite_dep_checks | 
|  | gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies) | 
|  | write_dependencies_mock.assert_called_with(out_data_f, | 
|  | ['DEP1'], ['DEP1']) | 
|  | write_parameters_mock.assert_called_with(out_data_f, ['0'], | 
|  | ('int',), []) | 
|  | expected_dep_check_code = ''' | 
|  | case 0: | 
|  | { | 
|  | #if defined(DEP1) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;''' | 
|  | func_mock1.assert_called_with( | 
|  | suite_dependencies, expected_dep_check_code, '') | 
|  |  | 
|  | def test_function_not_found(self): | 
|  | """ | 
|  | Test that AssertError is raised when function info in not found. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | My test | 
|  | depends_on:DEP1 | 
|  | func1:0 | 
|  | ''' | 
|  | data_f = StringIOWrapper('test_suite_ut.data', data) | 
|  | out_data_f = StringIOWrapper('test_suite_ut.datax', '') | 
|  | func_info = {'test_func2': (1, ('int',))} | 
|  | suite_dependencies = [] | 
|  | self.assertRaises(GeneratorInputError, gen_from_test_data, | 
|  | data_f, out_data_f, func_info, suite_dependencies) | 
|  |  | 
|  | def test_different_func_args(self): | 
|  | """ | 
|  | Test that AssertError is raised when no. of parameters and | 
|  | function args differ. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | My test | 
|  | depends_on:DEP1 | 
|  | func1:0 | 
|  | ''' | 
|  | data_f = StringIOWrapper('test_suite_ut.data', data) | 
|  | out_data_f = StringIOWrapper('test_suite_ut.datax', '') | 
|  | func_info = {'test_func2': (1, ('int', 'hex'))} | 
|  | suite_dependencies = [] | 
|  | self.assertRaises(GeneratorInputError, gen_from_test_data, data_f, | 
|  | out_data_f, func_info, suite_dependencies) | 
|  |  | 
|  | def test_output(self): | 
|  | """ | 
|  | Test that intermediate data file is written with expected data. | 
|  | :return: | 
|  | """ | 
|  | data = ''' | 
|  | My test 1 | 
|  | depends_on:DEP1 | 
|  | func1:0:0xfa:MACRO1:MACRO2 | 
|  |  | 
|  | My test 2 | 
|  | depends_on:DEP1:DEP2 | 
|  | func2:"yahoo":88:MACRO1 | 
|  | ''' | 
|  | data_f = StringIOWrapper('test_suite_ut.data', data) | 
|  | out_data_f = StringIOWrapper('test_suite_ut.datax', '') | 
|  | func_info = {'test_func1': (0, ('int', 'int', 'int', 'int')), | 
|  | 'test_func2': (1, ('char*', 'int', 'int'))} | 
|  | suite_dependencies = [] | 
|  | dep_check_code, expression_code = \ | 
|  | gen_from_test_data(data_f, out_data_f, func_info, | 
|  | suite_dependencies) | 
|  | expected_dep_check_code = ''' | 
|  | case 0: | 
|  | { | 
|  | #if defined(DEP1) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | #if defined(DEP2) | 
|  | ret = DEPENDENCY_SUPPORTED; | 
|  | #else | 
|  | ret = DEPENDENCY_NOT_SUPPORTED; | 
|  | #endif | 
|  | } | 
|  | break;''' | 
|  | expected_data = '''My test 1 | 
|  | depends_on:0 | 
|  | 0:int:0:int:0xfa:exp:0:exp:1 | 
|  |  | 
|  | My test 2 | 
|  | depends_on:0:1 | 
|  | 1:char*:"yahoo":int:88:exp:0 | 
|  |  | 
|  | ''' | 
|  | expected_expression_code = ''' | 
|  | case 0: | 
|  | { | 
|  | *out_value = MACRO1; | 
|  | } | 
|  | break; | 
|  | case 1: | 
|  | { | 
|  | *out_value = MACRO2; | 
|  | } | 
|  | break;''' | 
|  | self.assertEqual(dep_check_code, expected_dep_check_code) | 
|  | self.assertEqual(out_data_f.getvalue(), expected_data) | 
|  | self.assertEqual(expression_code, expected_expression_code) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | unittest_main() |