quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

test_generate_test_code.py (58959B)


      1 #!/usr/bin/env python3
      2 # Unit test for generate_test_code.py
      3 #
      4 # Copyright The Mbed TLS Contributors
      5 # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
      6 
      7 """
      8 Unit tests for generate_test_code.py
      9 """
     10 
     11 from io import StringIO
     12 from unittest import TestCase, main as unittest_main
     13 from unittest.mock import patch
     14 
     15 from generate_test_code import gen_dependencies, gen_dependencies_one_line
     16 from generate_test_code import gen_function_wrapper, gen_dispatch
     17 from generate_test_code import parse_until_pattern, GeneratorInputError
     18 from generate_test_code import parse_suite_dependencies
     19 from generate_test_code import parse_function_dependencies
     20 from generate_test_code import parse_function_arguments, parse_function_code
     21 from generate_test_code import parse_functions, END_HEADER_REGEX
     22 from generate_test_code import END_SUITE_HELPERS_REGEX, escaped_split
     23 from generate_test_code import parse_test_data, gen_dep_check
     24 from generate_test_code import gen_expression_check, write_dependencies
     25 from generate_test_code import write_parameters, gen_suite_dep_checks
     26 from generate_test_code import gen_from_test_data
     27 
     28 
     29 class GenDep(TestCase):
     30     """
     31     Test suite for function gen_dep()
     32     """
     33 
     34     def test_dependencies_list(self):
     35         """
     36         Test that gen_dep() correctly creates dependencies for given
     37         dependency list.
     38         :return:
     39         """
     40         dependencies = ['DEP1', 'DEP2']
     41         dep_start, dep_end = gen_dependencies(dependencies)
     42         preprocessor1, preprocessor2 = dep_start.splitlines()
     43         endif1, endif2 = dep_end.splitlines()
     44         self.assertEqual(preprocessor1, '#if defined(DEP1)',
     45                          'Preprocessor generated incorrectly')
     46         self.assertEqual(preprocessor2, '#if defined(DEP2)',
     47                          'Preprocessor generated incorrectly')
     48         self.assertEqual(endif1, '#endif /* DEP2 */',
     49                          'Preprocessor generated incorrectly')
     50         self.assertEqual(endif2, '#endif /* DEP1 */',
     51                          'Preprocessor generated incorrectly')
     52 
     53     def test_disabled_dependencies_list(self):
     54         """
     55         Test that gen_dep() correctly creates dependencies for given
     56         dependency list.
     57         :return:
     58         """
     59         dependencies = ['!DEP1', '!DEP2']
     60         dep_start, dep_end = gen_dependencies(dependencies)
     61         preprocessor1, preprocessor2 = dep_start.splitlines()
     62         endif1, endif2 = dep_end.splitlines()
     63         self.assertEqual(preprocessor1, '#if !defined(DEP1)',
     64                          'Preprocessor generated incorrectly')
     65         self.assertEqual(preprocessor2, '#if !defined(DEP2)',
     66                          'Preprocessor generated incorrectly')
     67         self.assertEqual(endif1, '#endif /* !DEP2 */',
     68                          'Preprocessor generated incorrectly')
     69         self.assertEqual(endif2, '#endif /* !DEP1 */',
     70                          'Preprocessor generated incorrectly')
     71 
     72     def test_mixed_dependencies_list(self):
     73         """
     74         Test that gen_dep() correctly creates dependencies for given
     75         dependency list.
     76         :return:
     77         """
     78         dependencies = ['!DEP1', 'DEP2']
     79         dep_start, dep_end = gen_dependencies(dependencies)
     80         preprocessor1, preprocessor2 = dep_start.splitlines()
     81         endif1, endif2 = dep_end.splitlines()
     82         self.assertEqual(preprocessor1, '#if !defined(DEP1)',
     83                          'Preprocessor generated incorrectly')
     84         self.assertEqual(preprocessor2, '#if defined(DEP2)',
     85                          'Preprocessor generated incorrectly')
     86         self.assertEqual(endif1, '#endif /* DEP2 */',
     87                          'Preprocessor generated incorrectly')
     88         self.assertEqual(endif2, '#endif /* !DEP1 */',
     89                          'Preprocessor generated incorrectly')
     90 
     91     def test_empty_dependencies_list(self):
     92         """
     93         Test that gen_dep() correctly creates dependencies for given
     94         dependency list.
     95         :return:
     96         """
     97         dependencies = []
     98         dep_start, dep_end = gen_dependencies(dependencies)
     99         self.assertEqual(dep_start, '', 'Preprocessor generated incorrectly')
    100         self.assertEqual(dep_end, '', 'Preprocessor generated incorrectly')
    101 
    102     def test_large_dependencies_list(self):
    103         """
    104         Test that gen_dep() correctly creates dependencies for given
    105         dependency list.
    106         :return:
    107         """
    108         dependencies = []
    109         count = 10
    110         for i in range(count):
    111             dependencies.append('DEP%d' % i)
    112         dep_start, dep_end = gen_dependencies(dependencies)
    113         self.assertEqual(len(dep_start.splitlines()), count,
    114                          'Preprocessor generated incorrectly')
    115         self.assertEqual(len(dep_end.splitlines()), count,
    116                          'Preprocessor generated incorrectly')
    117 
    118 
    119 class GenDepOneLine(TestCase):
    120     """
    121     Test Suite for testing gen_dependencies_one_line()
    122     """
    123 
    124     def test_dependencies_list(self):
    125         """
    126         Test that gen_dep() correctly creates dependencies for given
    127         dependency list.
    128         :return:
    129         """
    130         dependencies = ['DEP1', 'DEP2']
    131         dep_str = gen_dependencies_one_line(dependencies)
    132         self.assertEqual(dep_str, '#if defined(DEP1) && defined(DEP2)',
    133                          'Preprocessor generated incorrectly')
    134 
    135     def test_disabled_dependencies_list(self):
    136         """
    137         Test that gen_dep() correctly creates dependencies for given
    138         dependency list.
    139         :return:
    140         """
    141         dependencies = ['!DEP1', '!DEP2']
    142         dep_str = gen_dependencies_one_line(dependencies)
    143         self.assertEqual(dep_str, '#if !defined(DEP1) && !defined(DEP2)',
    144                          'Preprocessor generated incorrectly')
    145 
    146     def test_mixed_dependencies_list(self):
    147         """
    148         Test that gen_dep() correctly creates dependencies for given
    149         dependency list.
    150         :return:
    151         """
    152         dependencies = ['!DEP1', 'DEP2']
    153         dep_str = gen_dependencies_one_line(dependencies)
    154         self.assertEqual(dep_str, '#if !defined(DEP1) && defined(DEP2)',
    155                          'Preprocessor generated incorrectly')
    156 
    157     def test_empty_dependencies_list(self):
    158         """
    159         Test that gen_dep() correctly creates dependencies for given
    160         dependency list.
    161         :return:
    162         """
    163         dependencies = []
    164         dep_str = gen_dependencies_one_line(dependencies)
    165         self.assertEqual(dep_str, '', 'Preprocessor generated incorrectly')
    166 
    167     def test_large_dependencies_list(self):
    168         """
    169         Test that gen_dep() correctly creates dependencies for given
    170         dependency list.
    171         :return:
    172         """
    173         dependencies = []
    174         count = 10
    175         for i in range(count):
    176             dependencies.append('DEP%d' % i)
    177         dep_str = gen_dependencies_one_line(dependencies)
    178         expected = '#if ' + ' && '.join(['defined(%s)' %
    179                                          x for x in dependencies])
    180         self.assertEqual(dep_str, expected,
    181                          'Preprocessor generated incorrectly')
    182 
    183 
    184 class GenFunctionWrapper(TestCase):
    185     """
    186     Test Suite for testing gen_function_wrapper()
    187     """
    188 
    189     def test_params_unpack(self):
    190         """
    191         Test that params are properly unpacked in the function call.
    192 
    193         :return:
    194         """
    195         code = gen_function_wrapper('test_a', '', ('a', 'b', 'c', 'd'))
    196         expected = '''
    197 static void test_a_wrapper( void ** params )
    198 {
    199 
    200     test_a( a, b, c, d );
    201 }
    202 '''
    203         self.assertEqual(code, expected)
    204 
    205     def test_local(self):
    206         """
    207         Test that params are properly unpacked in the function call.
    208 
    209         :return:
    210         """
    211         code = gen_function_wrapper('test_a',
    212                                     'int x = 1;', ('x', 'b', 'c', 'd'))
    213         expected = '''
    214 static void test_a_wrapper( void ** params )
    215 {
    216 int x = 1;
    217     test_a( x, b, c, d );
    218 }
    219 '''
    220         self.assertEqual(code, expected)
    221 
    222     def test_empty_params(self):
    223         """
    224         Test that params are properly unpacked in the function call.
    225 
    226         :return:
    227         """
    228         code = gen_function_wrapper('test_a', '', ())
    229         expected = '''
    230 static void test_a_wrapper( void ** params )
    231 {
    232     (void)params;
    233 
    234     test_a(  );
    235 }
    236 '''
    237         self.assertEqual(code, expected)
    238 
    239 
    240 class GenDispatch(TestCase):
    241     """
    242     Test suite for testing gen_dispatch()
    243     """
    244 
    245     def test_dispatch(self):
    246         """
    247         Test that dispatch table entry is generated correctly.
    248         :return:
    249         """
    250         code = gen_dispatch('test_a', ['DEP1', 'DEP2'])
    251         expected = '''
    252 #if defined(DEP1) && defined(DEP2)
    253     test_a_wrapper,
    254 #else
    255     NULL,
    256 #endif
    257 '''
    258         self.assertEqual(code, expected)
    259 
    260     def test_empty_dependencies(self):
    261         """
    262         Test empty dependency list.
    263         :return:
    264         """
    265         code = gen_dispatch('test_a', [])
    266         expected = '''
    267     test_a_wrapper,
    268 '''
    269         self.assertEqual(code, expected)
    270 
    271 
    272 class StringIOWrapper(StringIO):
    273     """
    274     file like class to mock file object in tests.
    275     """
    276     def __init__(self, file_name, data, line_no=0):
    277         """
    278         Init file handle.
    279 
    280         :param file_name:
    281         :param data:
    282         :param line_no:
    283         """
    284         super(StringIOWrapper, self).__init__(data)
    285         self.line_no = line_no
    286         self.name = file_name
    287 
    288     def next(self):
    289         """
    290         Iterator method. This method overrides base class's
    291         next method and extends the next method to count the line
    292         numbers as each line is read.
    293 
    294         :return: Line read from file.
    295         """
    296         parent = super(StringIOWrapper, self)
    297         line = parent.__next__()
    298         return line
    299 
    300     def readline(self, _length=0):
    301         """
    302         Wrap the base class readline.
    303 
    304         :param length:
    305         :return:
    306         """
    307         line = super(StringIOWrapper, self).readline()
    308         if line is not None:
    309             self.line_no += 1
    310         return line
    311 
    312 
    313 class ParseUntilPattern(TestCase):
    314     """
    315     Test Suite for testing parse_until_pattern().
    316     """
    317 
    318     def test_suite_headers(self):
    319         """
    320         Test that suite headers are parsed correctly.
    321 
    322         :return:
    323         """
    324         data = '''#include "mbedtls/ecp.h"
    325 
    326 #define ECP_PF_UNKNOWN     -1
    327 /* END_HEADER */
    328 '''
    329         expected = '''#line 1 "test_suite_ut.function"
    330 #include "mbedtls/ecp.h"
    331 
    332 #define ECP_PF_UNKNOWN     -1
    333 '''
    334         stream = StringIOWrapper('test_suite_ut.function', data, line_no=0)
    335         headers = parse_until_pattern(stream, END_HEADER_REGEX)
    336         self.assertEqual(headers, expected)
    337 
    338     def test_line_no(self):
    339         """
    340         Test that #line is set to correct line no. in source .function file.
    341 
    342         :return:
    343         """
    344         data = '''#include "mbedtls/ecp.h"
    345 
    346 #define ECP_PF_UNKNOWN     -1
    347 /* END_HEADER */
    348 '''
    349         offset_line_no = 5
    350         expected = '''#line %d "test_suite_ut.function"
    351 #include "mbedtls/ecp.h"
    352 
    353 #define ECP_PF_UNKNOWN     -1
    354 ''' % (offset_line_no + 1)
    355         stream = StringIOWrapper('test_suite_ut.function', data,
    356                                  offset_line_no)
    357         headers = parse_until_pattern(stream, END_HEADER_REGEX)
    358         self.assertEqual(headers, expected)
    359 
    360     def test_no_end_header_comment(self):
    361         """
    362         Test that InvalidFileFormat is raised when end header comment is
    363         missing.
    364         :return:
    365         """
    366         data = '''#include "mbedtls/ecp.h"
    367 
    368 #define ECP_PF_UNKNOWN     -1
    369 
    370 '''
    371         stream = StringIOWrapper('test_suite_ut.function', data)
    372         self.assertRaises(GeneratorInputError, parse_until_pattern, stream,
    373                           END_HEADER_REGEX)
    374 
    375 
    376 class ParseSuiteDependencies(TestCase):
    377     """
    378     Test Suite for testing parse_suite_dependencies().
    379     """
    380 
    381     def test_suite_dependencies(self):
    382         """
    383 
    384         :return:
    385         """
    386         data = '''
    387  * depends_on:MBEDTLS_ECP_C
    388  * END_DEPENDENCIES
    389  */
    390 '''
    391         expected = ['MBEDTLS_ECP_C']
    392         stream = StringIOWrapper('test_suite_ut.function', data)
    393         dependencies = parse_suite_dependencies(stream)
    394         self.assertEqual(dependencies, expected)
    395 
    396     def test_no_end_dep_comment(self):
    397         """
    398         Test that InvalidFileFormat is raised when end dep comment is missing.
    399         :return:
    400         """
    401         data = '''
    402 * depends_on:MBEDTLS_ECP_C
    403 '''
    404         stream = StringIOWrapper('test_suite_ut.function', data)
    405         self.assertRaises(GeneratorInputError, parse_suite_dependencies,
    406                           stream)
    407 
    408     def test_dependencies_split(self):
    409         """
    410         Test that InvalidFileFormat is raised when end dep comment is missing.
    411         :return:
    412         """
    413         data = '''
    414  * depends_on:MBEDTLS_ECP_C:A:B:   C  : D :F : G: !H
    415  * END_DEPENDENCIES
    416  */
    417 '''
    418         expected = ['MBEDTLS_ECP_C', 'A', 'B', 'C', 'D', 'F', 'G', '!H']
    419         stream = StringIOWrapper('test_suite_ut.function', data)
    420         dependencies = parse_suite_dependencies(stream)
    421         self.assertEqual(dependencies, expected)
    422 
    423 
    424 class ParseFuncDependencies(TestCase):
    425     """
    426     Test Suite for testing parse_function_dependencies()
    427     """
    428 
    429     def test_function_dependencies(self):
    430         """
    431         Test that parse_function_dependencies() correctly parses function
    432         dependencies.
    433         :return:
    434         """
    435         line = '/* BEGIN_CASE ' \
    436                'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */'
    437         expected = ['MBEDTLS_ENTROPY_NV_SEED', 'MBEDTLS_FS_IO']
    438         dependencies = parse_function_dependencies(line)
    439         self.assertEqual(dependencies, expected)
    440 
    441     def test_no_dependencies(self):
    442         """
    443         Test that parse_function_dependencies() correctly parses function
    444         dependencies.
    445         :return:
    446         """
    447         line = '/* BEGIN_CASE */'
    448         dependencies = parse_function_dependencies(line)
    449         self.assertEqual(dependencies, [])
    450 
    451     def test_tolerance(self):
    452         """
    453         Test that parse_function_dependencies() correctly parses function
    454         dependencies.
    455         :return:
    456         """
    457         line = '/* BEGIN_CASE depends_on:MBEDTLS_FS_IO: A : !B:C : F*/'
    458         dependencies = parse_function_dependencies(line)
    459         self.assertEqual(dependencies, ['MBEDTLS_FS_IO', 'A', '!B', 'C', 'F'])
    460 
    461 
    462 class ParseFuncSignature(TestCase):
    463     """
    464     Test Suite for parse_function_arguments().
    465     """
    466 
    467     def test_int_and_char_params(self):
    468         """
    469         Test int and char parameters parsing
    470         :return:
    471         """
    472         line = 'void entropy_threshold( char * a, int b, int result )'
    473         args, local, arg_dispatch = parse_function_arguments(line)
    474         self.assertEqual(args, ['char*', 'int', 'int'])
    475         self.assertEqual(local, '')
    476         self.assertEqual(arg_dispatch,
    477                          ['(char *) params[0]',
    478                           '((mbedtls_test_argument_t *) params[1])->sint',
    479                           '((mbedtls_test_argument_t *) params[2])->sint'])
    480 
    481     def test_hex_params(self):
    482         """
    483         Test hex parameters parsing
    484         :return:
    485         """
    486         line = 'void entropy_threshold( char * a, data_t * h, int result )'
    487         args, local, arg_dispatch = parse_function_arguments(line)
    488         self.assertEqual(args, ['char*', 'hex', 'int'])
    489         self.assertEqual(local,
    490                          '    data_t data1 = {(uint8_t *) params[1], '
    491                          '((mbedtls_test_argument_t *) params[2])->len};\n')
    492         self.assertEqual(arg_dispatch, ['(char *) params[0]',
    493                                         '&data1',
    494                                         '((mbedtls_test_argument_t *) params[3])->sint'])
    495 
    496     def test_unsupported_arg(self):
    497         """
    498         Test unsupported argument type
    499         :return:
    500         """
    501         line = 'void entropy_threshold( char * a, data_t * h, unknown_t result )'
    502         self.assertRaises(ValueError, parse_function_arguments, line)
    503 
    504     def test_empty_params(self):
    505         """
    506         Test no parameters (nothing between parentheses).
    507         :return:
    508         """
    509         line = 'void entropy_threshold()'
    510         args, local, arg_dispatch = parse_function_arguments(line)
    511         self.assertEqual(args, [])
    512         self.assertEqual(local, '')
    513         self.assertEqual(arg_dispatch, [])
    514 
    515     def test_blank_params(self):
    516         """
    517         Test no parameters (space between parentheses).
    518         :return:
    519         """
    520         line = 'void entropy_threshold( )'
    521         args, local, arg_dispatch = parse_function_arguments(line)
    522         self.assertEqual(args, [])
    523         self.assertEqual(local, '')
    524         self.assertEqual(arg_dispatch, [])
    525 
    526     def test_void_params(self):
    527         """
    528         Test no parameters (void keyword).
    529         :return:
    530         """
    531         line = 'void entropy_threshold(void)'
    532         args, local, arg_dispatch = parse_function_arguments(line)
    533         self.assertEqual(args, [])
    534         self.assertEqual(local, '')
    535         self.assertEqual(arg_dispatch, [])
    536 
    537     def test_void_space_params(self):
    538         """
    539         Test no parameters (void with spaces).
    540         :return:
    541         """
    542         line = 'void entropy_threshold( void )'
    543         args, local, arg_dispatch = parse_function_arguments(line)
    544         self.assertEqual(args, [])
    545         self.assertEqual(local, '')
    546         self.assertEqual(arg_dispatch, [])
    547 
    548 
    549 class ParseFunctionCode(TestCase):
    550     """
    551     Test suite for testing parse_function_code()
    552     """
    553 
    554     def test_no_function(self):
    555         """
    556         Test no test function found.
    557         :return:
    558         """
    559         data = '''
    560 No
    561 test
    562 function
    563 '''
    564         stream = StringIOWrapper('test_suite_ut.function', data)
    565         err_msg = 'file: test_suite_ut.function - Test functions not found!'
    566         self.assertRaisesRegex(GeneratorInputError, err_msg,
    567                                parse_function_code, stream, [], [])
    568 
    569     def test_no_end_case_comment(self):
    570         """
    571         Test missing end case.
    572         :return:
    573         """
    574         data = '''
    575 void test_func()
    576 {
    577 }
    578 '''
    579         stream = StringIOWrapper('test_suite_ut.function', data)
    580         err_msg = r'file: test_suite_ut.function - '\
    581                   'end case pattern .*? not found!'
    582         self.assertRaisesRegex(GeneratorInputError, err_msg,
    583                                parse_function_code, stream, [], [])
    584 
    585     @patch("generate_test_code.parse_function_arguments")
    586     def test_function_called(self,
    587                              parse_function_arguments_mock):
    588         """
    589         Test parse_function_code()
    590         :return:
    591         """
    592         parse_function_arguments_mock.return_value = ([], '', [])
    593         data = '''
    594 void test_func()
    595 {
    596 }
    597 '''
    598         stream = StringIOWrapper('test_suite_ut.function', data)
    599         self.assertRaises(GeneratorInputError, parse_function_code,
    600                           stream, [], [])
    601         self.assertTrue(parse_function_arguments_mock.called)
    602         parse_function_arguments_mock.assert_called_with('void test_func()\n')
    603 
    604     @patch("generate_test_code.gen_dispatch")
    605     @patch("generate_test_code.gen_dependencies")
    606     @patch("generate_test_code.gen_function_wrapper")
    607     @patch("generate_test_code.parse_function_arguments")
    608     def test_return(self, parse_function_arguments_mock,
    609                     gen_function_wrapper_mock,
    610                     gen_dependencies_mock,
    611                     gen_dispatch_mock):
    612         """
    613         Test generated code.
    614         :return:
    615         """
    616         parse_function_arguments_mock.return_value = ([], '', [])
    617         gen_function_wrapper_mock.return_value = ''
    618         gen_dependencies_mock.side_effect = gen_dependencies
    619         gen_dispatch_mock.side_effect = gen_dispatch
    620         data = '''
    621 void func()
    622 {
    623     ba ba black sheep
    624     have you any wool
    625 }
    626 /* END_CASE */
    627 '''
    628         stream = StringIOWrapper('test_suite_ut.function', data)
    629         name, arg, code, dispatch_code = parse_function_code(stream, [], [])
    630 
    631         self.assertTrue(parse_function_arguments_mock.called)
    632         parse_function_arguments_mock.assert_called_with('void func()\n')
    633         gen_function_wrapper_mock.assert_called_with('test_func', '', [])
    634         self.assertEqual(name, 'test_func')
    635         self.assertEqual(arg, [])
    636         expected = '''#line 1 "test_suite_ut.function"
    637 
    638 static void test_func(void)
    639 {
    640     ba ba black sheep
    641     have you any wool
    642 exit:
    643     ;
    644 }
    645 '''
    646         self.assertEqual(code, expected)
    647         self.assertEqual(dispatch_code, "\n    test_func_wrapper,\n")
    648 
    649     @patch("generate_test_code.gen_dispatch")
    650     @patch("generate_test_code.gen_dependencies")
    651     @patch("generate_test_code.gen_function_wrapper")
    652     @patch("generate_test_code.parse_function_arguments")
    653     def test_with_exit_label(self, parse_function_arguments_mock,
    654                              gen_function_wrapper_mock,
    655                              gen_dependencies_mock,
    656                              gen_dispatch_mock):
    657         """
    658         Test when exit label is present.
    659         :return:
    660         """
    661         parse_function_arguments_mock.return_value = ([], '', [])
    662         gen_function_wrapper_mock.return_value = ''
    663         gen_dependencies_mock.side_effect = gen_dependencies
    664         gen_dispatch_mock.side_effect = gen_dispatch
    665         data = '''
    666 void func()
    667 {
    668     ba ba black sheep
    669     have you any wool
    670 exit:
    671     yes sir yes sir
    672     3 bags full
    673 }
    674 /* END_CASE */
    675 '''
    676         stream = StringIOWrapper('test_suite_ut.function', data)
    677         _, _, code, _ = parse_function_code(stream, [], [])
    678 
    679         expected = '''#line 1 "test_suite_ut.function"
    680 
    681 static void test_func(void)
    682 {
    683     ba ba black sheep
    684     have you any wool
    685 exit:
    686     yes sir yes sir
    687     3 bags full
    688 }
    689 '''
    690         self.assertEqual(code, expected)
    691 
    692     def test_non_void_function(self):
    693         """
    694         Test invalid signature (non void).
    695         :return:
    696         """
    697         data = 'int entropy_threshold( char * a, data_t * h, int result )'
    698         err_msg = 'file: test_suite_ut.function - Test functions not found!'
    699         stream = StringIOWrapper('test_suite_ut.function', data)
    700         self.assertRaisesRegex(GeneratorInputError, err_msg,
    701                                parse_function_code, stream, [], [])
    702 
    703     @patch("generate_test_code.gen_dispatch")
    704     @patch("generate_test_code.gen_dependencies")
    705     @patch("generate_test_code.gen_function_wrapper")
    706     @patch("generate_test_code.parse_function_arguments")
    707     def test_function_name_on_newline(self, parse_function_arguments_mock,
    708                                       gen_function_wrapper_mock,
    709                                       gen_dependencies_mock,
    710                                       gen_dispatch_mock):
    711         """
    712         Test with line break before the function name.
    713         :return:
    714         """
    715         parse_function_arguments_mock.return_value = ([], '', [])
    716         gen_function_wrapper_mock.return_value = ''
    717         gen_dependencies_mock.side_effect = gen_dependencies
    718         gen_dispatch_mock.side_effect = gen_dispatch
    719         data = '''
    720 void
    721 
    722 
    723 func()
    724 {
    725     ba ba black sheep
    726     have you any wool
    727 exit:
    728     yes sir yes sir
    729     3 bags full
    730 }
    731 /* END_CASE */
    732 '''
    733         stream = StringIOWrapper('test_suite_ut.function', data)
    734         _, _, code, _ = parse_function_code(stream, [], [])
    735 
    736         expected = '''#line 1 "test_suite_ut.function"
    737 
    738 static void
    739 
    740 
    741 test_func(void)
    742 {
    743     ba ba black sheep
    744     have you any wool
    745 exit:
    746     yes sir yes sir
    747     3 bags full
    748 }
    749 '''
    750         self.assertEqual(code, expected)
    751 
    752     @patch("generate_test_code.gen_dispatch")
    753     @patch("generate_test_code.gen_dependencies")
    754     @patch("generate_test_code.gen_function_wrapper")
    755     @patch("generate_test_code.parse_function_arguments")
    756     def test_case_starting_with_comment(self, parse_function_arguments_mock,
    757                                         gen_function_wrapper_mock,
    758                                         gen_dependencies_mock,
    759                                         gen_dispatch_mock):
    760         """
    761         Test with comments before the function signature
    762         :return:
    763         """
    764         parse_function_arguments_mock.return_value = ([], '', [])
    765         gen_function_wrapper_mock.return_value = ''
    766         gen_dependencies_mock.side_effect = gen_dependencies
    767         gen_dispatch_mock.side_effect = gen_dispatch
    768         data = '''/* comment */
    769 /* more
    770  * comment */
    771 // this is\\
    772 still \\
    773 a comment
    774 void func()
    775 {
    776     ba ba black sheep
    777     have you any wool
    778 exit:
    779     yes sir yes sir
    780     3 bags full
    781 }
    782 /* END_CASE */
    783 '''
    784         stream = StringIOWrapper('test_suite_ut.function', data)
    785         _, _, code, _ = parse_function_code(stream, [], [])
    786 
    787         expected = '''#line 1 "test_suite_ut.function"
    788 
    789 
    790 
    791 
    792 
    793 
    794 static void test_func(void)
    795 {
    796     ba ba black sheep
    797     have you any wool
    798 exit:
    799     yes sir yes sir
    800     3 bags full
    801 }
    802 '''
    803         self.assertEqual(code, expected)
    804 
    805     @patch("generate_test_code.gen_dispatch")
    806     @patch("generate_test_code.gen_dependencies")
    807     @patch("generate_test_code.gen_function_wrapper")
    808     @patch("generate_test_code.parse_function_arguments")
    809     def test_comment_in_prototype(self, parse_function_arguments_mock,
    810                                   gen_function_wrapper_mock,
    811                                   gen_dependencies_mock,
    812                                   gen_dispatch_mock):
    813         """
    814         Test with comments in the function prototype
    815         :return:
    816         """
    817         parse_function_arguments_mock.return_value = ([], '', [])
    818         gen_function_wrapper_mock.return_value = ''
    819         gen_dependencies_mock.side_effect = gen_dependencies
    820         gen_dispatch_mock.side_effect = gen_dispatch
    821         data = '''
    822 void func( int x, // (line \\
    823                      comment)
    824            int y /* lone closing parenthesis) */ )
    825 {
    826     ba ba black sheep
    827     have you any wool
    828 exit:
    829     yes sir yes sir
    830     3 bags full
    831 }
    832 /* END_CASE */
    833 '''
    834         stream = StringIOWrapper('test_suite_ut.function', data)
    835         _, _, code, _ = parse_function_code(stream, [], [])
    836 
    837         expected = '''#line 1 "test_suite_ut.function"
    838 
    839 static void test_func( int x,
    840 
    841            int y                                 )
    842 {
    843     ba ba black sheep
    844     have you any wool
    845 exit:
    846     yes sir yes sir
    847     3 bags full
    848 }
    849 '''
    850         self.assertEqual(code, expected)
    851 
    852     @patch("generate_test_code.gen_dispatch")
    853     @patch("generate_test_code.gen_dependencies")
    854     @patch("generate_test_code.gen_function_wrapper")
    855     @patch("generate_test_code.parse_function_arguments")
    856     def test_line_comment_in_block_comment(self, parse_function_arguments_mock,
    857                                            gen_function_wrapper_mock,
    858                                            gen_dependencies_mock,
    859                                            gen_dispatch_mock):
    860         """
    861         Test with line comment in block comment.
    862         :return:
    863         """
    864         parse_function_arguments_mock.return_value = ([], '', [])
    865         gen_function_wrapper_mock.return_value = ''
    866         gen_dependencies_mock.side_effect = gen_dependencies
    867         gen_dispatch_mock.side_effect = gen_dispatch
    868         data = '''
    869 void func( int x /* // */ )
    870 {
    871     ba ba black sheep
    872     have you any wool
    873 exit:
    874     yes sir yes sir
    875     3 bags full
    876 }
    877 /* END_CASE */
    878 '''
    879         stream = StringIOWrapper('test_suite_ut.function', data)
    880         _, _, code, _ = parse_function_code(stream, [], [])
    881 
    882         expected = '''#line 1 "test_suite_ut.function"
    883 
    884 static void test_func( int x          )
    885 {
    886     ba ba black sheep
    887     have you any wool
    888 exit:
    889     yes sir yes sir
    890     3 bags full
    891 }
    892 '''
    893         self.assertEqual(code, expected)
    894 
    895     @patch("generate_test_code.gen_dispatch")
    896     @patch("generate_test_code.gen_dependencies")
    897     @patch("generate_test_code.gen_function_wrapper")
    898     @patch("generate_test_code.parse_function_arguments")
    899     def test_block_comment_in_line_comment(self, parse_function_arguments_mock,
    900                                            gen_function_wrapper_mock,
    901                                            gen_dependencies_mock,
    902                                            gen_dispatch_mock):
    903         """
    904         Test with block comment in line comment.
    905         :return:
    906         """
    907         parse_function_arguments_mock.return_value = ([], '', [])
    908         gen_function_wrapper_mock.return_value = ''
    909         gen_dependencies_mock.side_effect = gen_dependencies
    910         gen_dispatch_mock.side_effect = gen_dispatch
    911         data = '''
    912 // /*
    913 void func( int x )
    914 {
    915     ba ba black sheep
    916     have you any wool
    917 exit:
    918     yes sir yes sir
    919     3 bags full
    920 }
    921 /* END_CASE */
    922 '''
    923         stream = StringIOWrapper('test_suite_ut.function', data)
    924         _, _, code, _ = parse_function_code(stream, [], [])
    925 
    926         expected = '''#line 1 "test_suite_ut.function"
    927 
    928 
    929 static void test_func( int x )
    930 {
    931     ba ba black sheep
    932     have you any wool
    933 exit:
    934     yes sir yes sir
    935     3 bags full
    936 }
    937 '''
    938         self.assertEqual(code, expected)
    939 
    940 
    941 class ParseFunction(TestCase):
    942     """
    943     Test Suite for testing parse_functions()
    944     """
    945 
    946     @patch("generate_test_code.parse_until_pattern")
    947     def test_begin_header(self, parse_until_pattern_mock):
    948         """
    949         Test that begin header is checked and parse_until_pattern() is called.
    950         :return:
    951         """
    952         def stop(*_unused):
    953             """Stop when parse_until_pattern is called."""
    954             raise Exception
    955         parse_until_pattern_mock.side_effect = stop
    956         data = '''/* BEGIN_HEADER */
    957 #include "mbedtls/ecp.h"
    958 
    959 #define ECP_PF_UNKNOWN     -1
    960 /* END_HEADER */
    961 '''
    962         stream = StringIOWrapper('test_suite_ut.function', data)
    963         self.assertRaises(Exception, parse_functions, stream)
    964         parse_until_pattern_mock.assert_called_with(stream, END_HEADER_REGEX)
    965         self.assertEqual(stream.line_no, 1)
    966 
    967     @patch("generate_test_code.parse_until_pattern")
    968     def test_begin_helper(self, parse_until_pattern_mock):
    969         """
    970         Test that begin helper is checked and parse_until_pattern() is called.
    971         :return:
    972         """
    973         def stop(*_unused):
    974             """Stop when parse_until_pattern is called."""
    975             raise Exception
    976         parse_until_pattern_mock.side_effect = stop
    977         data = '''/* BEGIN_SUITE_HELPERS */
    978 static void print_hello_world()
    979 {
    980     printf("Hello World!\n");
    981 }
    982 /* END_SUITE_HELPERS */
    983 '''
    984         stream = StringIOWrapper('test_suite_ut.function', data)
    985         self.assertRaises(Exception, parse_functions, stream)
    986         parse_until_pattern_mock.assert_called_with(stream,
    987                                                     END_SUITE_HELPERS_REGEX)
    988         self.assertEqual(stream.line_no, 1)
    989 
    990     @patch("generate_test_code.parse_suite_dependencies")
    991     def test_begin_dep(self, parse_suite_dependencies_mock):
    992         """
    993         Test that begin dep is checked and parse_suite_dependencies() is
    994         called.
    995         :return:
    996         """
    997         def stop(*_unused):
    998             """Stop when parse_until_pattern is called."""
    999             raise Exception
   1000         parse_suite_dependencies_mock.side_effect = stop
   1001         data = '''/* BEGIN_DEPENDENCIES
   1002  * depends_on:MBEDTLS_ECP_C
   1003  * END_DEPENDENCIES
   1004  */
   1005 '''
   1006         stream = StringIOWrapper('test_suite_ut.function', data)
   1007         self.assertRaises(Exception, parse_functions, stream)
   1008         parse_suite_dependencies_mock.assert_called_with(stream)
   1009         self.assertEqual(stream.line_no, 1)
   1010 
   1011     @patch("generate_test_code.parse_function_dependencies")
   1012     def test_begin_function_dep(self, func_mock):
   1013         """
   1014         Test that begin dep is checked and parse_function_dependencies() is
   1015         called.
   1016         :return:
   1017         """
   1018         def stop(*_unused):
   1019             """Stop when parse_until_pattern is called."""
   1020             raise Exception
   1021         func_mock.side_effect = stop
   1022 
   1023         dependencies_str = '/* BEGIN_CASE ' \
   1024             'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
   1025         data = '''%sstatic void test_func()
   1026 {
   1027 }
   1028 ''' % dependencies_str
   1029         stream = StringIOWrapper('test_suite_ut.function', data)
   1030         self.assertRaises(Exception, parse_functions, stream)
   1031         func_mock.assert_called_with(dependencies_str)
   1032         self.assertEqual(stream.line_no, 1)
   1033 
   1034     @patch("generate_test_code.parse_function_code")
   1035     @patch("generate_test_code.parse_function_dependencies")
   1036     def test_return(self, func_mock1, func_mock2):
   1037         """
   1038         Test that begin case is checked and parse_function_code() is called.
   1039         :return:
   1040         """
   1041         func_mock1.return_value = []
   1042         in_func_code = '''static void test_func()
   1043 {
   1044 }
   1045 '''
   1046         func_dispatch = '''
   1047     test_func_wrapper,
   1048 '''
   1049         func_mock2.return_value = 'test_func', [],\
   1050             in_func_code, func_dispatch
   1051         dependencies_str = '/* BEGIN_CASE ' \
   1052             'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
   1053         data = '''%sstatic void test_func()
   1054 {
   1055 }
   1056 ''' % dependencies_str
   1057         stream = StringIOWrapper('test_suite_ut.function', data)
   1058         suite_dependencies, dispatch_code, func_code, func_info = \
   1059             parse_functions(stream)
   1060         func_mock1.assert_called_with(dependencies_str)
   1061         func_mock2.assert_called_with(stream, [], [])
   1062         self.assertEqual(stream.line_no, 5)
   1063         self.assertEqual(suite_dependencies, [])
   1064         expected_dispatch_code = '''/* Function Id: 0 */
   1065 
   1066     test_func_wrapper,
   1067 '''
   1068         self.assertEqual(dispatch_code, expected_dispatch_code)
   1069         self.assertEqual(func_code, in_func_code)
   1070         self.assertEqual(func_info, {'test_func': (0, [])})
   1071 
   1072     def test_parsing(self):
   1073         """
   1074         Test case parsing.
   1075         :return:
   1076         """
   1077         data = '''/* BEGIN_HEADER */
   1078 #include "mbedtls/ecp.h"
   1079 
   1080 #define ECP_PF_UNKNOWN     -1
   1081 /* END_HEADER */
   1082 
   1083 /* BEGIN_DEPENDENCIES
   1084  * depends_on:MBEDTLS_ECP_C
   1085  * END_DEPENDENCIES
   1086  */
   1087 
   1088 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
   1089 void func1()
   1090 {
   1091 }
   1092 /* END_CASE */
   1093 
   1094 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
   1095 void func2()
   1096 {
   1097 }
   1098 /* END_CASE */
   1099 '''
   1100         stream = StringIOWrapper('test_suite_ut.function', data)
   1101         suite_dependencies, dispatch_code, func_code, func_info = \
   1102             parse_functions(stream)
   1103         self.assertEqual(stream.line_no, 23)
   1104         self.assertEqual(suite_dependencies, ['MBEDTLS_ECP_C'])
   1105 
   1106         expected_dispatch_code = '''/* Function Id: 0 */
   1107 
   1108 #if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
   1109     test_func1_wrapper,
   1110 #else
   1111     NULL,
   1112 #endif
   1113 /* Function Id: 1 */
   1114 
   1115 #if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
   1116     test_func2_wrapper,
   1117 #else
   1118     NULL,
   1119 #endif
   1120 '''
   1121         self.assertEqual(dispatch_code, expected_dispatch_code)
   1122         expected_func_code = '''#if defined(MBEDTLS_ECP_C)
   1123 #line 2 "test_suite_ut.function"
   1124 #include "mbedtls/ecp.h"
   1125 
   1126 #define ECP_PF_UNKNOWN     -1
   1127 #if defined(MBEDTLS_ENTROPY_NV_SEED)
   1128 #if defined(MBEDTLS_FS_IO)
   1129 #line 13 "test_suite_ut.function"
   1130 static void test_func1(void)
   1131 {
   1132 exit:
   1133     ;
   1134 }
   1135 
   1136 static void test_func1_wrapper( void ** params )
   1137 {
   1138     (void)params;
   1139 
   1140     test_func1(  );
   1141 }
   1142 #endif /* MBEDTLS_FS_IO */
   1143 #endif /* MBEDTLS_ENTROPY_NV_SEED */
   1144 #if defined(MBEDTLS_ENTROPY_NV_SEED)
   1145 #if defined(MBEDTLS_FS_IO)
   1146 #line 19 "test_suite_ut.function"
   1147 static void test_func2(void)
   1148 {
   1149 exit:
   1150     ;
   1151 }
   1152 
   1153 static void test_func2_wrapper( void ** params )
   1154 {
   1155     (void)params;
   1156 
   1157     test_func2(  );
   1158 }
   1159 #endif /* MBEDTLS_FS_IO */
   1160 #endif /* MBEDTLS_ENTROPY_NV_SEED */
   1161 #endif /* MBEDTLS_ECP_C */
   1162 '''
   1163         self.assertEqual(func_code, expected_func_code)
   1164         self.assertEqual(func_info, {'test_func1': (0, []),
   1165                                      'test_func2': (1, [])})
   1166 
   1167     def test_same_function_name(self):
   1168         """
   1169         Test name conflict.
   1170         :return:
   1171         """
   1172         data = '''/* BEGIN_HEADER */
   1173 #include "mbedtls/ecp.h"
   1174 
   1175 #define ECP_PF_UNKNOWN     -1
   1176 /* END_HEADER */
   1177 
   1178 /* BEGIN_DEPENDENCIES
   1179  * depends_on:MBEDTLS_ECP_C
   1180  * END_DEPENDENCIES
   1181  */
   1182 
   1183 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
   1184 void func()
   1185 {
   1186 }
   1187 /* END_CASE */
   1188 
   1189 /* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
   1190 void func()
   1191 {
   1192 }
   1193 /* END_CASE */
   1194 '''
   1195         stream = StringIOWrapper('test_suite_ut.function', data)
   1196         self.assertRaises(GeneratorInputError, parse_functions, stream)
   1197 
   1198 
   1199 class EscapedSplit(TestCase):
   1200     """
   1201     Test suite for testing escaped_split().
   1202     Note: Since escaped_split() output is used to write back to the
   1203     intermediate data file. Any escape characters in the input are
   1204     retained in the output.
   1205     """
   1206 
   1207     def test_invalid_input(self):
   1208         """
   1209         Test when input split character is not a character.
   1210         :return:
   1211         """
   1212         self.assertRaises(ValueError, escaped_split, '', 'string')
   1213 
   1214     def test_empty_string(self):
   1215         """
   1216         Test empty string input.
   1217         :return:
   1218         """
   1219         splits = escaped_split('', ':')
   1220         self.assertEqual(splits, [])
   1221 
   1222     def test_no_escape(self):
   1223         """
   1224         Test with no escape character. The behaviour should be same as
   1225         str.split()
   1226         :return:
   1227         """
   1228         test_str = 'yahoo:google'
   1229         splits = escaped_split(test_str, ':')
   1230         self.assertEqual(splits, test_str.split(':'))
   1231 
   1232     def test_escaped_input(self):
   1233         """
   1234         Test input that has escaped delimiter.
   1235         :return:
   1236         """
   1237         test_str = r'yahoo\:google:facebook'
   1238         splits = escaped_split(test_str, ':')
   1239         self.assertEqual(splits, [r'yahoo\:google', 'facebook'])
   1240 
   1241     def test_escaped_escape(self):
   1242         """
   1243         Test input that has escaped delimiter.
   1244         :return:
   1245         """
   1246         test_str = r'yahoo\\:google:facebook'
   1247         splits = escaped_split(test_str, ':')
   1248         self.assertEqual(splits, [r'yahoo\\', 'google', 'facebook'])
   1249 
   1250     def test_all_at_once(self):
   1251         """
   1252         Test input that has escaped delimiter.
   1253         :return:
   1254         """
   1255         test_str = r'yahoo\\:google:facebook\:instagram\\:bbc\\:wikipedia'
   1256         splits = escaped_split(test_str, ':')
   1257         self.assertEqual(splits, [r'yahoo\\', r'google',
   1258                                   r'facebook\:instagram\\',
   1259                                   r'bbc\\', r'wikipedia'])
   1260 
   1261 
   1262 class ParseTestData(TestCase):
   1263     """
   1264     Test suite for parse test data.
   1265     """
   1266 
   1267     def test_parser(self):
   1268         """
   1269         Test that tests are parsed correctly from data file.
   1270         :return:
   1271         """
   1272         data = """
   1273 Diffie-Hellman full exchange #1
   1274 dhm_do_dhm:10:"23":10:"5"
   1275 
   1276 Diffie-Hellman full exchange #2
   1277 dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
   1278 
   1279 Diffie-Hellman full exchange #3
   1280 dhm_do_dhm:10:"9345098382739712938719287391879381271":10:"9345098792137312973297123912791271"
   1281 
   1282 Diffie-Hellman selftest
   1283 dhm_selftest:
   1284 """
   1285         stream = StringIOWrapper('test_suite_ut.function', data)
   1286         # List of (name, function_name, dependencies, args)
   1287         tests = list(parse_test_data(stream))
   1288         test1, test2, test3, test4 = tests
   1289         self.assertEqual(test1[0], 3)
   1290         self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
   1291         self.assertEqual(test1[2], 'dhm_do_dhm')
   1292         self.assertEqual(test1[3], [])
   1293         self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
   1294 
   1295         self.assertEqual(test2[0], 6)
   1296         self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
   1297         self.assertEqual(test2[2], 'dhm_do_dhm')
   1298         self.assertEqual(test2[3], [])
   1299         self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
   1300                                     '10', '"9345098304850938450983409622"'])
   1301 
   1302         self.assertEqual(test3[0], 9)
   1303         self.assertEqual(test3[1], 'Diffie-Hellman full exchange #3')
   1304         self.assertEqual(test3[2], 'dhm_do_dhm')
   1305         self.assertEqual(test3[3], [])
   1306         self.assertEqual(test3[4], ['10',
   1307                                     '"9345098382739712938719287391879381271"',
   1308                                     '10',
   1309                                     '"9345098792137312973297123912791271"'])
   1310 
   1311         self.assertEqual(test4[0], 12)
   1312         self.assertEqual(test4[1], 'Diffie-Hellman selftest')
   1313         self.assertEqual(test4[2], 'dhm_selftest')
   1314         self.assertEqual(test4[3], [])
   1315         self.assertEqual(test4[4], [])
   1316 
   1317     def test_with_dependencies(self):
   1318         """
   1319         Test that tests with dependencies are parsed.
   1320         :return:
   1321         """
   1322         data = """
   1323 Diffie-Hellman full exchange #1
   1324 depends_on:YAHOO
   1325 dhm_do_dhm:10:"23":10:"5"
   1326 
   1327 Diffie-Hellman full exchange #2
   1328 dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
   1329 
   1330 """
   1331         stream = StringIOWrapper('test_suite_ut.function', data)
   1332         # List of (name, function_name, dependencies, args)
   1333         tests = list(parse_test_data(stream))
   1334         test1, test2 = tests
   1335         self.assertEqual(test1[0], 4)
   1336         self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
   1337         self.assertEqual(test1[2], 'dhm_do_dhm')
   1338         self.assertEqual(test1[3], ['YAHOO'])
   1339         self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
   1340 
   1341         self.assertEqual(test2[0], 7)
   1342         self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
   1343         self.assertEqual(test2[2], 'dhm_do_dhm')
   1344         self.assertEqual(test2[3], [])
   1345         self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
   1346                                     '10', '"9345098304850938450983409622"'])
   1347 
   1348     def test_no_args(self):
   1349         """
   1350         Test GeneratorInputError is raised when test function name and
   1351         args line is missing.
   1352         :return:
   1353         """
   1354         data = """
   1355 Diffie-Hellman full exchange #1
   1356 depends_on:YAHOO
   1357 
   1358 
   1359 Diffie-Hellman full exchange #2
   1360 dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
   1361 
   1362 """
   1363         stream = StringIOWrapper('test_suite_ut.function', data)
   1364         err = None
   1365         try:
   1366             for _, _, _, _, _ in parse_test_data(stream):
   1367                 pass
   1368         except GeneratorInputError as err:
   1369             self.assertEqual(type(err), GeneratorInputError)
   1370 
   1371     def test_incomplete_data(self):
   1372         """
   1373         Test GeneratorInputError is raised when test function name
   1374         and args line is missing.
   1375         :return:
   1376         """
   1377         data = """
   1378 Diffie-Hellman full exchange #1
   1379 depends_on:YAHOO
   1380 """
   1381         stream = StringIOWrapper('test_suite_ut.function', data)
   1382         err = None
   1383         try:
   1384             for _, _, _, _, _ in parse_test_data(stream):
   1385                 pass
   1386         except GeneratorInputError as err:
   1387             self.assertEqual(type(err), GeneratorInputError)
   1388 
   1389 
   1390 class GenDepCheck(TestCase):
   1391     """
   1392     Test suite for gen_dep_check(). It is assumed this function is
   1393     called with valid inputs.
   1394     """
   1395 
   1396     def test_gen_dep_check(self):
   1397         """
   1398         Test that dependency check code generated correctly.
   1399         :return:
   1400         """
   1401         expected = """
   1402         case 5:
   1403             {
   1404 #if defined(YAHOO)
   1405                 ret = DEPENDENCY_SUPPORTED;
   1406 #else
   1407                 ret = DEPENDENCY_NOT_SUPPORTED;
   1408 #endif
   1409             }
   1410             break;"""
   1411         out = gen_dep_check(5, 'YAHOO')
   1412         self.assertEqual(out, expected)
   1413 
   1414     def test_not_defined_dependency(self):
   1415         """
   1416         Test dependency with !.
   1417         :return:
   1418         """
   1419         expected = """
   1420         case 5:
   1421             {
   1422 #if !defined(YAHOO)
   1423                 ret = DEPENDENCY_SUPPORTED;
   1424 #else
   1425                 ret = DEPENDENCY_NOT_SUPPORTED;
   1426 #endif
   1427             }
   1428             break;"""
   1429         out = gen_dep_check(5, '!YAHOO')
   1430         self.assertEqual(out, expected)
   1431 
   1432     def test_empty_dependency(self):
   1433         """
   1434         Test invalid dependency input.
   1435         :return:
   1436         """
   1437         self.assertRaises(GeneratorInputError, gen_dep_check, 5, '!')
   1438 
   1439     def test_negative_dep_id(self):
   1440         """
   1441         Test invalid dependency input.
   1442         :return:
   1443         """
   1444         self.assertRaises(GeneratorInputError, gen_dep_check, -1, 'YAHOO')
   1445 
   1446 
   1447 class GenExpCheck(TestCase):
   1448     """
   1449     Test suite for gen_expression_check(). It is assumed this function
   1450     is called with valid inputs.
   1451     """
   1452 
   1453     def test_gen_exp_check(self):
   1454         """
   1455         Test that expression check code generated correctly.
   1456         :return:
   1457         """
   1458         expected = """
   1459         case 5:
   1460             {
   1461                 *out_value = YAHOO;
   1462             }
   1463             break;"""
   1464         out = gen_expression_check(5, 'YAHOO')
   1465         self.assertEqual(out, expected)
   1466 
   1467     def test_invalid_expression(self):
   1468         """
   1469         Test invalid expression input.
   1470         :return:
   1471         """
   1472         self.assertRaises(GeneratorInputError, gen_expression_check, 5, '')
   1473 
   1474     def test_negative_exp_id(self):
   1475         """
   1476         Test invalid expression id.
   1477         :return:
   1478         """
   1479         self.assertRaises(GeneratorInputError, gen_expression_check,
   1480                           -1, 'YAHOO')
   1481 
   1482 
   1483 class WriteDependencies(TestCase):
   1484     """
   1485     Test suite for testing write_dependencies.
   1486     """
   1487 
   1488     def test_no_test_dependencies(self):
   1489         """
   1490         Test when test dependencies input is empty.
   1491         :return:
   1492         """
   1493         stream = StringIOWrapper('test_suite_ut.data', '')
   1494         unique_dependencies = []
   1495         dep_check_code = write_dependencies(stream, [], unique_dependencies)
   1496         self.assertEqual(dep_check_code, '')
   1497         self.assertEqual(len(unique_dependencies), 0)
   1498         self.assertEqual(stream.getvalue(), '')
   1499 
   1500     def test_unique_dep_ids(self):
   1501         """
   1502 
   1503         :return:
   1504         """
   1505         stream = StringIOWrapper('test_suite_ut.data', '')
   1506         unique_dependencies = []
   1507         dep_check_code = write_dependencies(stream, ['DEP3', 'DEP2', 'DEP1'],
   1508                                             unique_dependencies)
   1509         expect_dep_check_code = '''
   1510         case 0:
   1511             {
   1512 #if defined(DEP3)
   1513                 ret = DEPENDENCY_SUPPORTED;
   1514 #else
   1515                 ret = DEPENDENCY_NOT_SUPPORTED;
   1516 #endif
   1517             }
   1518             break;
   1519         case 1:
   1520             {
   1521 #if defined(DEP2)
   1522                 ret = DEPENDENCY_SUPPORTED;
   1523 #else
   1524                 ret = DEPENDENCY_NOT_SUPPORTED;
   1525 #endif
   1526             }
   1527             break;
   1528         case 2:
   1529             {
   1530 #if defined(DEP1)
   1531                 ret = DEPENDENCY_SUPPORTED;
   1532 #else
   1533                 ret = DEPENDENCY_NOT_SUPPORTED;
   1534 #endif
   1535             }
   1536             break;'''
   1537         self.assertEqual(dep_check_code, expect_dep_check_code)
   1538         self.assertEqual(len(unique_dependencies), 3)
   1539         self.assertEqual(stream.getvalue(), 'depends_on:0:1:2\n')
   1540 
   1541     def test_dep_id_repeat(self):
   1542         """
   1543 
   1544         :return:
   1545         """
   1546         stream = StringIOWrapper('test_suite_ut.data', '')
   1547         unique_dependencies = []
   1548         dep_check_code = ''
   1549         dep_check_code += write_dependencies(stream, ['DEP3', 'DEP2'],
   1550                                              unique_dependencies)
   1551         dep_check_code += write_dependencies(stream, ['DEP2', 'DEP1'],
   1552                                              unique_dependencies)
   1553         dep_check_code += write_dependencies(stream, ['DEP1', 'DEP3'],
   1554                                              unique_dependencies)
   1555         expect_dep_check_code = '''
   1556         case 0:
   1557             {
   1558 #if defined(DEP3)
   1559                 ret = DEPENDENCY_SUPPORTED;
   1560 #else
   1561                 ret = DEPENDENCY_NOT_SUPPORTED;
   1562 #endif
   1563             }
   1564             break;
   1565         case 1:
   1566             {
   1567 #if defined(DEP2)
   1568                 ret = DEPENDENCY_SUPPORTED;
   1569 #else
   1570                 ret = DEPENDENCY_NOT_SUPPORTED;
   1571 #endif
   1572             }
   1573             break;
   1574         case 2:
   1575             {
   1576 #if defined(DEP1)
   1577                 ret = DEPENDENCY_SUPPORTED;
   1578 #else
   1579                 ret = DEPENDENCY_NOT_SUPPORTED;
   1580 #endif
   1581             }
   1582             break;'''
   1583         self.assertEqual(dep_check_code, expect_dep_check_code)
   1584         self.assertEqual(len(unique_dependencies), 3)
   1585         self.assertEqual(stream.getvalue(),
   1586                          'depends_on:0:1\ndepends_on:1:2\ndepends_on:2:0\n')
   1587 
   1588 
   1589 class WriteParams(TestCase):
   1590     """
   1591     Test Suite for testing write_parameters().
   1592     """
   1593 
   1594     def test_no_params(self):
   1595         """
   1596         Test with empty test_args
   1597         :return:
   1598         """
   1599         stream = StringIOWrapper('test_suite_ut.data', '')
   1600         unique_expressions = []
   1601         expression_code = write_parameters(stream, [], [], unique_expressions)
   1602         self.assertEqual(len(unique_expressions), 0)
   1603         self.assertEqual(expression_code, '')
   1604         self.assertEqual(stream.getvalue(), '\n')
   1605 
   1606     def test_no_exp_param(self):
   1607         """
   1608         Test when there is no macro or expression in the params.
   1609         :return:
   1610         """
   1611         stream = StringIOWrapper('test_suite_ut.data', '')
   1612         unique_expressions = []
   1613         expression_code = write_parameters(stream, ['"Yahoo"', '"abcdef00"',
   1614                                                     '0'],
   1615                                            ['char*', 'hex', 'int'],
   1616                                            unique_expressions)
   1617         self.assertEqual(len(unique_expressions), 0)
   1618         self.assertEqual(expression_code, '')
   1619         self.assertEqual(stream.getvalue(),
   1620                          ':char*:"Yahoo":hex:"abcdef00":int:0\n')
   1621 
   1622     def test_hex_format_int_param(self):
   1623         """
   1624         Test int parameter in hex format.
   1625         :return:
   1626         """
   1627         stream = StringIOWrapper('test_suite_ut.data', '')
   1628         unique_expressions = []
   1629         expression_code = write_parameters(stream,
   1630                                            ['"Yahoo"', '"abcdef00"', '0xAA'],
   1631                                            ['char*', 'hex', 'int'],
   1632                                            unique_expressions)
   1633         self.assertEqual(len(unique_expressions), 0)
   1634         self.assertEqual(expression_code, '')
   1635         self.assertEqual(stream.getvalue(),
   1636                          ':char*:"Yahoo":hex:"abcdef00":int:0xAA\n')
   1637 
   1638     def test_with_exp_param(self):
   1639         """
   1640         Test when there is macro or expression in the params.
   1641         :return:
   1642         """
   1643         stream = StringIOWrapper('test_suite_ut.data', '')
   1644         unique_expressions = []
   1645         expression_code = write_parameters(stream,
   1646                                            ['"Yahoo"', '"abcdef00"', '0',
   1647                                             'MACRO1', 'MACRO2', 'MACRO3'],
   1648                                            ['char*', 'hex', 'int',
   1649                                             'int', 'int', 'int'],
   1650                                            unique_expressions)
   1651         self.assertEqual(len(unique_expressions), 3)
   1652         self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
   1653         expected_expression_code = '''
   1654         case 0:
   1655             {
   1656                 *out_value = MACRO1;
   1657             }
   1658             break;
   1659         case 1:
   1660             {
   1661                 *out_value = MACRO2;
   1662             }
   1663             break;
   1664         case 2:
   1665             {
   1666                 *out_value = MACRO3;
   1667             }
   1668             break;'''
   1669         self.assertEqual(expression_code, expected_expression_code)
   1670         self.assertEqual(stream.getvalue(),
   1671                          ':char*:"Yahoo":hex:"abcdef00":int:0:exp:0:exp:1'
   1672                          ':exp:2\n')
   1673 
   1674     def test_with_repeat_calls(self):
   1675         """
   1676         Test when write_parameter() is called with same macro or expression.
   1677         :return:
   1678         """
   1679         stream = StringIOWrapper('test_suite_ut.data', '')
   1680         unique_expressions = []
   1681         expression_code = ''
   1682         expression_code += write_parameters(stream,
   1683                                             ['"Yahoo"', 'MACRO1', 'MACRO2'],
   1684                                             ['char*', 'int', 'int'],
   1685                                             unique_expressions)
   1686         expression_code += write_parameters(stream,
   1687                                             ['"abcdef00"', 'MACRO2', 'MACRO3'],
   1688                                             ['hex', 'int', 'int'],
   1689                                             unique_expressions)
   1690         expression_code += write_parameters(stream,
   1691                                             ['0', 'MACRO3', 'MACRO1'],
   1692                                             ['int', 'int', 'int'],
   1693                                             unique_expressions)
   1694         self.assertEqual(len(unique_expressions), 3)
   1695         self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
   1696         expected_expression_code = '''
   1697         case 0:
   1698             {
   1699                 *out_value = MACRO1;
   1700             }
   1701             break;
   1702         case 1:
   1703             {
   1704                 *out_value = MACRO2;
   1705             }
   1706             break;
   1707         case 2:
   1708             {
   1709                 *out_value = MACRO3;
   1710             }
   1711             break;'''
   1712         self.assertEqual(expression_code, expected_expression_code)
   1713         expected_data_file = ''':char*:"Yahoo":exp:0:exp:1
   1714 :hex:"abcdef00":exp:1:exp:2
   1715 :int:0:exp:2:exp:0
   1716 '''
   1717         self.assertEqual(stream.getvalue(), expected_data_file)
   1718 
   1719 
   1720 class GenTestSuiteDependenciesChecks(TestCase):
   1721     """
   1722     Test suite for testing gen_suite_dep_checks()
   1723     """
   1724     def test_empty_suite_dependencies(self):
   1725         """
   1726         Test with empty suite_dependencies list.
   1727 
   1728         :return:
   1729         """
   1730         dep_check_code, expression_code = \
   1731             gen_suite_dep_checks([], 'DEP_CHECK_CODE', 'EXPRESSION_CODE')
   1732         self.assertEqual(dep_check_code, 'DEP_CHECK_CODE')
   1733         self.assertEqual(expression_code, 'EXPRESSION_CODE')
   1734 
   1735     def test_suite_dependencies(self):
   1736         """
   1737         Test with suite_dependencies list.
   1738 
   1739         :return:
   1740         """
   1741         dep_check_code, expression_code = \
   1742             gen_suite_dep_checks(['SUITE_DEP'], 'DEP_CHECK_CODE',
   1743                                  'EXPRESSION_CODE')
   1744         expected_dep_check_code = '''
   1745 #if defined(SUITE_DEP)
   1746 DEP_CHECK_CODE
   1747 #endif
   1748 '''
   1749         expected_expression_code = '''
   1750 #if defined(SUITE_DEP)
   1751 EXPRESSION_CODE
   1752 #endif
   1753 '''
   1754         self.assertEqual(dep_check_code, expected_dep_check_code)
   1755         self.assertEqual(expression_code, expected_expression_code)
   1756 
   1757     def test_no_dep_no_exp(self):
   1758         """
   1759         Test when there are no dependency and expression code.
   1760         :return:
   1761         """
   1762         dep_check_code, expression_code = gen_suite_dep_checks([], '', '')
   1763         self.assertEqual(dep_check_code, '')
   1764         self.assertEqual(expression_code, '')
   1765 
   1766 
   1767 class GenFromTestData(TestCase):
   1768     """
   1769     Test suite for gen_from_test_data()
   1770     """
   1771 
   1772     @staticmethod
   1773     @patch("generate_test_code.write_dependencies")
   1774     @patch("generate_test_code.write_parameters")
   1775     @patch("generate_test_code.gen_suite_dep_checks")
   1776     def test_intermediate_data_file(func_mock1,
   1777                                     write_parameters_mock,
   1778                                     write_dependencies_mock):
   1779         """
   1780         Test that intermediate data file is written with expected data.
   1781         :return:
   1782         """
   1783         data = '''
   1784 My test
   1785 depends_on:DEP1
   1786 func1:0
   1787 '''
   1788         data_f = StringIOWrapper('test_suite_ut.data', data)
   1789         out_data_f = StringIOWrapper('test_suite_ut.datax', '')
   1790         func_info = {'test_func1': (1, ('int',))}
   1791         suite_dependencies = []
   1792         write_parameters_mock.side_effect = write_parameters
   1793         write_dependencies_mock.side_effect = write_dependencies
   1794         func_mock1.side_effect = gen_suite_dep_checks
   1795         gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies)
   1796         write_dependencies_mock.assert_called_with(out_data_f,
   1797                                                    ['DEP1'], ['DEP1'])
   1798         write_parameters_mock.assert_called_with(out_data_f, ['0'],
   1799                                                  ('int',), [])
   1800         expected_dep_check_code = '''
   1801         case 0:
   1802             {
   1803 #if defined(DEP1)
   1804                 ret = DEPENDENCY_SUPPORTED;
   1805 #else
   1806                 ret = DEPENDENCY_NOT_SUPPORTED;
   1807 #endif
   1808             }
   1809             break;'''
   1810         func_mock1.assert_called_with(
   1811             suite_dependencies, expected_dep_check_code, '')
   1812 
   1813     def test_function_not_found(self):
   1814         """
   1815         Test that AssertError is raised when function info in not found.
   1816         :return:
   1817         """
   1818         data = '''
   1819 My test
   1820 depends_on:DEP1
   1821 func1:0
   1822 '''
   1823         data_f = StringIOWrapper('test_suite_ut.data', data)
   1824         out_data_f = StringIOWrapper('test_suite_ut.datax', '')
   1825         func_info = {'test_func2': (1, ('int',))}
   1826         suite_dependencies = []
   1827         self.assertRaises(GeneratorInputError, gen_from_test_data,
   1828                           data_f, out_data_f, func_info, suite_dependencies)
   1829 
   1830     def test_different_func_args(self):
   1831         """
   1832         Test that AssertError is raised when no. of parameters and
   1833         function args differ.
   1834         :return:
   1835         """
   1836         data = '''
   1837 My test
   1838 depends_on:DEP1
   1839 func1:0
   1840 '''
   1841         data_f = StringIOWrapper('test_suite_ut.data', data)
   1842         out_data_f = StringIOWrapper('test_suite_ut.datax', '')
   1843         func_info = {'test_func2': (1, ('int', 'hex'))}
   1844         suite_dependencies = []
   1845         self.assertRaises(GeneratorInputError, gen_from_test_data, data_f,
   1846                           out_data_f, func_info, suite_dependencies)
   1847 
   1848     def test_output(self):
   1849         """
   1850         Test that intermediate data file is written with expected data.
   1851         :return:
   1852         """
   1853         data = '''
   1854 My test 1
   1855 depends_on:DEP1
   1856 func1:0:0xfa:MACRO1:MACRO2
   1857 
   1858 My test 2
   1859 depends_on:DEP1:DEP2
   1860 func2:"yahoo":88:MACRO1
   1861 '''
   1862         data_f = StringIOWrapper('test_suite_ut.data', data)
   1863         out_data_f = StringIOWrapper('test_suite_ut.datax', '')
   1864         func_info = {'test_func1': (0, ('int', 'int', 'int', 'int')),
   1865                      'test_func2': (1, ('char*', 'int', 'int'))}
   1866         suite_dependencies = []
   1867         dep_check_code, expression_code = \
   1868             gen_from_test_data(data_f, out_data_f, func_info,
   1869                                suite_dependencies)
   1870         expected_dep_check_code = '''
   1871         case 0:
   1872             {
   1873 #if defined(DEP1)
   1874                 ret = DEPENDENCY_SUPPORTED;
   1875 #else
   1876                 ret = DEPENDENCY_NOT_SUPPORTED;
   1877 #endif
   1878             }
   1879             break;
   1880         case 1:
   1881             {
   1882 #if defined(DEP2)
   1883                 ret = DEPENDENCY_SUPPORTED;
   1884 #else
   1885                 ret = DEPENDENCY_NOT_SUPPORTED;
   1886 #endif
   1887             }
   1888             break;'''
   1889         expected_data = '''My test 1
   1890 depends_on:0
   1891 0:int:0:int:0xfa:exp:0:exp:1
   1892 
   1893 My test 2
   1894 depends_on:0:1
   1895 1:char*:"yahoo":int:88:exp:0
   1896 
   1897 '''
   1898         expected_expression_code = '''
   1899         case 0:
   1900             {
   1901                 *out_value = MACRO1;
   1902             }
   1903             break;
   1904         case 1:
   1905             {
   1906                 *out_value = MACRO2;
   1907             }
   1908             break;'''
   1909         self.assertEqual(dep_check_code, expected_dep_check_code)
   1910         self.assertEqual(out_data_f.getvalue(), expected_data)
   1911         self.assertEqual(expression_code, expected_expression_code)
   1912 
   1913 
   1914 if __name__ == '__main__':
   1915     unittest_main()