blob: bc44b8cc061da70f481c10814313bfee837cb569 [file] [log] [blame]
Mohammad Azim Khanfff49042017-03-28 01:48:31 +01001"""
Azim Khan4b543232017-06-30 09:35:21 +01002mbed TLS
3Copyright (c) 2017 ARM Limited
Mohammad Azim Khanfff49042017-03-28 01:48:31 +01004
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16"""
17
18import os
19import re
20import argparse
21import shutil
22
23
24"""
25Generates code in following structure.
26
27<output dir>/
Azim Khan4b543232017-06-30 09:35:21 +010028 |-- mbedtls/
29 | |-- <test suite #1>/
30 | | |-- main.c
31 | | |-- *.data files
32 | ...
33 | |-- <test suite #n>/
34 | | |-- main.c
35 | | |-- *.data files
36 | |
Mohammad Azim Khanfff49042017-03-28 01:48:31 +010037"""
38
39
40BEGIN_HEADER_REGEX = '/\*\s*BEGIN_HEADER\s*\*/'
41END_HEADER_REGEX = '/\*\s*END_HEADER\s*\*/'
42
43BEGIN_DEP_REGEX = 'BEGIN_DEPENDENCIES'
44END_DEP_REGEX = 'END_DEPENDENCIES'
45
46BEGIN_CASE_REGEX = '/\*\s*BEGIN_CASE\s*(.*?)\s*\*/'
47END_CASE_REGEX = '/\*\s*END_CASE\s*\*/'
48
49
50class InvalidFileFormat(Exception):
51 """
52 Exception to indicate invalid file format.
53 """
54 pass
55
56
Azim Khan4b543232017-06-30 09:35:21 +010057class FileWrapper(file):
58 """
59 File wrapper class. Provides reading with line no. tracking.
60 """
61
62 def __init__(self, file_name):
63 """
64 Init file handle.
65
66 :param file_name:
67 """
68 super(FileWrapper, self).__init__(file_name, 'r')
69 self.line_no = 0
70
71 def next(self):
72 """
73 Iterator return impl.
74 :return:
75 """
76 line = super(FileWrapper, self).next()
77 if line:
78 self.line_no += 1
79 return line
80
81 def readline(self, limit=0):
82 """
83 Wrap the base class readline.
84
85 :param limit:
86 :return:
87 """
88 return self.next()
89
90
91def split_dep(dep):
92 return ('!', dep[1:]) if dep[0] == '!' else ('', dep)
93
94
Mohammad Azim Khanfff49042017-03-28 01:48:31 +010095def gen_deps(deps):
96 """
97 Generates dependency i.e. if def and endif code
98
99 :param deps:
100 :return:
101 """
Azim Khan4b543232017-06-30 09:35:21 +0100102 dep_start = ''.join(['#if %sdefined(%s)\n' % split_dep(x) for x in deps])
103 dep_end = ''.join(['#endif /* %s */\n' % x for x in reversed(deps)])
104
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100105 return dep_start, dep_end
106
107
108def gen_deps_one_line(deps):
109 """
110 Generates dependency checks in one line. Useful for writing code in #else case.
111
112 :param deps:
113 :return:
114 """
Azim Khan4b543232017-06-30 09:35:21 +0100115 defines = ('#if ' if len(deps) else '') + ' && '.join(['%sdefined(%s)' % split_dep(x) for x in deps])
116 return defines
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100117
118
Azim Khan4b543232017-06-30 09:35:21 +0100119def gen_function_wrapper(name, locals, args_dispatch):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100120 """
121 Creates test function code
122
123 :param name:
Azim Khan4b543232017-06-30 09:35:21 +0100124 :param locals:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100125 :param args_dispatch:
126 :return:
127 """
128 # Then create the wrapper
129 wrapper = '''
130void {name}_wrapper( void ** params )
131{{
132 {unused_params}
Azim Khan2397bba2017-06-09 04:35:03 +0100133{locals}
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100134 {name}( {args} );
135}}
Azim Khan4b543232017-06-30 09:35:21 +0100136'''.format(name=name, unused_params='(void)params;' if len(args_dispatch) == 0 else '',
137 args=', '.join(args_dispatch),
138 locals=locals)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100139 return wrapper
140
141
142def gen_dispatch(name, deps):
143 """
144 Generates dispatch condition for the functions.
145
146 :param name:
147 :param deps:
148 :return:
149 """
150 if len(deps):
151 ifdef = gen_deps_one_line(deps)
152 dispatch_code = '''
153{ifdef}
154 {name}_wrapper,
155#else
156 NULL,
157#endif
158'''.format(ifdef=ifdef, name=name)
159 else:
160 dispatch_code = '''
161 {name}_wrapper,
162'''.format(name=name)
163
164 return dispatch_code
165
166
Azim Khan4b543232017-06-30 09:35:21 +0100167def parse_suite_headers(funcs_f):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100168 """
169 Parses function headers.
170
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100171 :param funcs_f:
172 :return:
173 """
Azim Khan4b543232017-06-30 09:35:21 +0100174 headers = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100175 for line in funcs_f:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100176 if re.search(END_HEADER_REGEX, line):
177 break
178 headers += line
179 else:
180 raise InvalidFileFormat("file: %s - end header pattern [%s] not found!" % (funcs_f.name, END_HEADER_REGEX))
181
Azim Khan4b543232017-06-30 09:35:21 +0100182 return headers
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100183
184
Azim Khan4b543232017-06-30 09:35:21 +0100185def parse_suite_deps(funcs_f):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100186 """
187 Parses function dependencies.
188
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100189 :param funcs_f:
190 :return:
191 """
192 deps = []
193 for line in funcs_f:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100194 m = re.search('depends_on\:(.*)', line.strip())
195 if m:
196 deps += [x.strip() for x in m.group(1).split(':')]
197 if re.search(END_DEP_REGEX, line):
198 break
199 else:
200 raise InvalidFileFormat("file: %s - end dependency pattern [%s] not found!" % (funcs_f.name, END_DEP_REGEX))
201
Azim Khan4b543232017-06-30 09:35:21 +0100202 return deps
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100203
204
205def parse_function_deps(line):
206 """
207
208 :param line:
209 :return:
210 """
211 deps = []
212 m = re.search(BEGIN_CASE_REGEX, line)
213 dep_str = m.group(1)
214 if len(dep_str):
215 m = re.search('depends_on:(.*)', dep_str)
216 if m:
Azim Khan4b543232017-06-30 09:35:21 +0100217 deps = [x.strip() for x in m.group(1).strip().split(':')]
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100218 return deps
219
220
221def parse_function_signature(line):
222 """
223 Parsing function signature
224
225 :param line:
226 :return:
227 """
228 args = []
Azim Khan2397bba2017-06-09 04:35:03 +0100229 locals = ''
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100230 args_dispatch = []
231 m = re.search('\s*void\s+(\w+)\s*\(', line, re.I)
232 if not m:
233 raise ValueError("Test function should return 'void'\n%s" % line)
234 name = m.group(1)
235 line = line[len(m.group(0)):]
236 arg_idx = 0
237 for arg in line[:line.find(')')].split(','):
238 arg = arg.strip()
239 if arg == '':
240 continue
241 if re.search('int\s+.*', arg.strip()):
242 args.append('int')
243 args_dispatch.append('*( (int *) params[%d] )' % arg_idx)
244 elif re.search('char\s*\*\s*.*', arg.strip()):
245 args.append('char*')
246 args_dispatch.append('(char *) params[%d]' % arg_idx)
Azim Khan2397bba2017-06-09 04:35:03 +0100247 elif re.search('HexParam_t\s*\*\s*.*', arg.strip()):
Azim Khana57a4202017-05-31 20:32:32 +0100248 args.append('hex')
Azim Khan2397bba2017-06-09 04:35:03 +0100249 # create a structure
250 locals += """ HexParam_t hex%d = {%s, %s};
251""" % (arg_idx, '(uint8_t *) params[%d]' % arg_idx, '*( (uint32_t *) params[%d] )' % (arg_idx + 1))
252
253 args_dispatch.append('&hex%d' % arg_idx)
254 arg_idx += 1
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100255 else:
Azim Khan4b543232017-06-30 09:35:21 +0100256 raise ValueError("Test function arguments can only be 'int', 'char *' or 'HexParam_t'\n%s" % line)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100257 arg_idx += 1
258
Azim Khan4b543232017-06-30 09:35:21 +0100259 return name, args, locals, args_dispatch
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100260
261
Azim Khan4b543232017-06-30 09:35:21 +0100262def parse_function_code(funcs_f, deps, suite_deps):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100263 """
264
265 :param line_no:
266 :param funcs_f:
267 :param deps:
268 :param suite_deps:
269 :return:
270 """
Azim Khan4b543232017-06-30 09:35:21 +0100271 code = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100272 for line in funcs_f:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100273 # Check function signature
274 m = re.match('.*?\s+(\w+)\s*\(', line, re.I)
275 if m:
276 # check if we have full signature i.e. split in more lines
277 if not re.match('.*\)', line):
278 for lin in funcs_f:
279 line += lin
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100280 if re.search('.*?\)', line):
281 break
Azim Khan4b543232017-06-30 09:35:21 +0100282 name, args, locals, args_dispatch = parse_function_signature(line)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100283 code += line.replace(name, 'test_' + name)
284 name = 'test_' + name
285 break
286 else:
287 raise InvalidFileFormat("file: %s - Test functions not found!" % funcs_f.name)
288
289 for line in funcs_f:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100290 if re.search(END_CASE_REGEX, line):
291 break
292 code += line
293 else:
294 raise InvalidFileFormat("file: %s - end case pattern [%s] not found!" % (funcs_f.name, END_CASE_REGEX))
295
296 # Add exit label if not present
297 if code.find('exit:') == -1:
298 s = code.rsplit('}', 1)
299 if len(s) == 2:
Azim Khan4b543232017-06-30 09:35:21 +0100300 code = """exit:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100301 ;;
Azim Khan4b543232017-06-30 09:35:21 +0100302}""".join(s)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100303
Azim Khan4b543232017-06-30 09:35:21 +0100304 code += gen_function_wrapper(name, locals, args_dispatch)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100305 ifdef, endif = gen_deps(deps)
306 dispatch_code = gen_dispatch(name, suite_deps + deps)
Azim Khan4b543232017-06-30 09:35:21 +0100307 return name, args, ifdef + code + endif, dispatch_code
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100308
309
310def parse_functions(funcs_f):
311 """
312 Returns functions code pieces
313
314 :param funcs_f:
315 :return:
316 """
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100317 suite_headers = ''
318 suite_deps = []
319 suite_functions = ''
320 func_info = {}
321 function_idx = 0
322 dispatch_code = ''
323 for line in funcs_f:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100324 if re.search(BEGIN_HEADER_REGEX, line):
Azim Khan4b543232017-06-30 09:35:21 +0100325 headers = parse_suite_headers(funcs_f)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100326 suite_headers += headers
327 elif re.search(BEGIN_DEP_REGEX, line):
Azim Khan4b543232017-06-30 09:35:21 +0100328 deps = parse_suite_deps(funcs_f)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100329 suite_deps += deps
330 elif re.search(BEGIN_CASE_REGEX, line):
331 deps = parse_function_deps(line)
Azim Khan4b543232017-06-30 09:35:21 +0100332 func_name, args, func_code, func_dispatch = parse_function_code(funcs_f, deps, suite_deps)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100333 suite_functions += func_code
334 # Generate dispatch code and enumeration info
335 assert func_name not in func_info, "file: %s - function %s re-declared at line %d" % \
Azim Khan4b543232017-06-30 09:35:21 +0100336 (funcs_f.name, func_name, funcs_f.line_no)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100337 func_info[func_name] = (function_idx, args)
338 dispatch_code += '/* Function Id: %d */\n' % function_idx
339 dispatch_code += func_dispatch
340 function_idx += 1
341
342 ifdef, endif = gen_deps(suite_deps)
Azim Khan13c6bfb2017-06-15 14:45:56 +0100343 func_code = ifdef + suite_headers + suite_functions + endif
344 return suite_deps, dispatch_code, func_code, func_info
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100345
346
347def escaped_split(str, ch):
348 """
349 Split str on character ch but ignore escaped \{ch}
350
351 :param str:
352 :param ch:
353 :return:
354 """
355 if len(ch) > 1:
356 raise ValueError('Expected split character. Found string!')
357 out = []
358 part = ''
359 escape = False
360 for i in range(len(str)):
361 if not escape and str[i] == ch:
362 out.append(part)
363 part = ''
364 else:
Azim Khanacc54732017-07-03 14:06:45 +0100365 part += str[i]
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100366 escape = not escape and str[i] == '\\'
367 if len(part):
368 out.append(part)
369 return out
370
371
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100372def parse_test_data(data_f, debug=False):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100373 """
374 Parses .data file
375
376 :param data_f:
377 :return:
378 """
379 STATE_READ_NAME = 0
380 STATE_READ_ARGS = 1
381 state = STATE_READ_NAME
382 deps = []
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100383 name = ''
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100384 for line in data_f:
385 line = line.strip()
386 if len(line) and line[0] == '#': # Skip comments
387 continue
388
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100389 # Blank line indicates end of test
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100390 if len(line) == 0:
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100391 assert state != STATE_READ_ARGS, "Newline before arguments. " \
392 "Test function and arguments missing for %s" % name
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100393 continue
394
395 if state == STATE_READ_NAME:
396 # Read test name
397 name = line
398 state = STATE_READ_ARGS
399 elif state == STATE_READ_ARGS:
400 # Check dependencies
401 m = re.search('depends_on\:(.*)', line)
402 if m:
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100403 deps = [x.strip() for x in m.group(1).split(':') if len(x.strip())]
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100404 else:
405 # Read test vectors
406 parts = escaped_split(line, ':')
407 function = parts[0]
408 args = parts[1:]
409 yield name, function, deps, args
410 deps = []
411 state = STATE_READ_NAME
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100412 assert state != STATE_READ_ARGS, "Newline before arguments. " \
413 "Test function and arguments missing for %s" % name
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100414
415
416def gen_dep_check(dep_id, dep):
417 """
418 Generate code for the dependency.
419
420 :param dep_id:
421 :param dep:
422 :return:
423 """
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100424 assert dep_id > -1, "Dependency Id should be a positive integer."
425 noT, dep = ('!', dep[1:]) if dep[0] == '!' else ('', dep)
426 assert len(dep) > 0, "Dependency should not be an empty string."
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100427 dep_check = '''
428if ( dep_id == {id} )
429{{
430#if {noT}defined({macro})
431 return( DEPENDENCY_SUPPORTED );
432#else
433 return( DEPENDENCY_NOT_SUPPORTED );
434#endif
435}}
436else
437'''.format(noT=noT, macro=dep, id=dep_id)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100438 return dep_check
439
440
441def gen_expression_check(exp_id, exp):
442 """
443 Generates code for expression check
444
445 :param exp_id:
446 :param exp:
447 :return:
448 """
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100449 assert exp_id > -1, "Expression Id should be a positive integer."
450 assert len(exp) > 0, "Expression should not be an empty string."
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100451 exp_code = '''
452if ( exp_id == {exp_id} )
453{{
454 *out_value = {expression};
455}}
456else
457'''.format(exp_id=exp_id, expression=exp)
458 return exp_code
459
460
Azim Khan5e2ac1f2017-07-03 13:58:20 +0100461def find_unique_id(val, vals):
462 """
463 Check if val already in vals. Gives a unique Identifier for the val.
464 :param val:
465 :param vals:
466 :return:
467 """
468 if val not in vals:
469 vals.append(val)
470
471
Azim Khan13c6bfb2017-06-15 14:45:56 +0100472def gen_from_test_data(data_f, out_data_f, func_info, suite_deps):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100473 """
474 Generates dependency checks, expression code and intermediate data file from test data file.
475
476 :param data_f:
477 :param out_data_f:
478 :param func_info:
Azim Khan13c6bfb2017-06-15 14:45:56 +0100479 :param suite_deps:
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100480 :return:
481 """
482 unique_deps = []
483 unique_expressions = []
484 dep_check_code = ''
485 expression_code = ''
486 for test_name, function_name, test_deps, test_args in parse_test_data(data_f):
487 out_data_f.write(test_name + '\n')
488
489 func_id, func_args = func_info['test_' + function_name]
490 if len(test_deps):
491 out_data_f.write('depends_on')
492 for dep in test_deps:
493 if dep not in unique_deps:
494 unique_deps.append(dep)
495 dep_id = unique_deps.index(dep)
496 dep_check_code += gen_dep_check(dep_id, dep)
497 else:
498 dep_id = unique_deps.index(dep)
499 out_data_f.write(':' + str(dep_id))
500 out_data_f.write('\n')
501
502 assert len(test_args) == len(func_args), \
503 "Invalid number of arguments in test %s. See function %s signature." % (test_name, function_name)
504 out_data_f.write(str(func_id))
505 for i in xrange(len(test_args)):
506 typ = func_args[i]
507 val = test_args[i]
508
509 # check if val is a non literal int val
510 if typ == 'int' and not re.match('\d+', val): # its an expression # FIXME: Handle hex format. Tip: instead try converting int(str, 10) and int(str, 16)
511 typ = 'exp'
512 if val not in unique_expressions:
513 unique_expressions.append(val)
514 # exp_id can be derived from len(). But for readability and consistency with case of existing let's
515 # use index().
516 exp_id = unique_expressions.index(val)
517 expression_code += gen_expression_check(exp_id, val)
518 val = exp_id
519 else:
520 val = unique_expressions.index(val)
521 out_data_f.write(':' + typ + ':' + str(val))
522 out_data_f.write('\n\n')
523
524 # void unused params
525 if len(dep_check_code) == 0:
526 dep_check_code = '(void) dep_id;\n'
527 if len(expression_code) == 0:
528 expression_code = '(void) exp_id;\n'
529 expression_code += '(void) out_value;\n'
Azim Khan13c6bfb2017-06-15 14:45:56 +0100530 ifdef = gen_deps_one_line(suite_deps)
531 if len(suite_deps):
532 dep_check_code = '''
533{ifdef}
534{code}
535#else
536(void) dep_id;
537#endif
538'''.format(ifdef=ifdef, code=dep_check_code)
539 expression_code = '''
540{ifdef}
541{code}
542#else
543(void) exp_id;
544(void) out_value;
545#endif
546'''.format(ifdef=ifdef, code=expression_code)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100547 return dep_check_code, expression_code
548
549
Azim Khan1de892b2017-06-09 15:02:36 +0100550def generate_code(funcs_file, data_file, template_file, platform_file, help_file, suites_dir, c_file, out_data_file):
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100551 """
552 Generate mbed-os test code.
553
554 :param funcs_file:
555 :param dat a_file:
556 :param template_file:
557 :param platform_file:
558 :param help_file:
559 :param suites_dir:
560 :param c_file:
561 :param out_data_file:
562 :return:
563 """
564 for name, path in [('Functions file', funcs_file),
565 ('Data file', data_file),
566 ('Template file', template_file),
567 ('Platform file', platform_file),
568 ('Help code file', help_file),
569 ('Suites dir', suites_dir)]:
570 if not os.path.exists(path):
571 raise IOError("ERROR: %s [%s] not found!" % (name, path))
572
573 snippets = {'generator_script' : os.path.basename(__file__)}
574
575 # Read helpers
576 with open(help_file, 'r') as help_f, open(platform_file, 'r') as platform_f:
577 snippets['test_common_helper_file'] = help_file
578 snippets['test_common_helpers'] = help_f.read()
579 snippets['test_platform_file'] = platform_file
580 snippets['platform_code'] = platform_f.read().replace('DATA_FILE',
581 out_data_file.replace('\\', '\\\\')) # escape '\'
582
583 # Function code
Azim Khanacc54732017-07-03 14:06:45 +0100584 with FileWrapper(funcs_file) as funcs_f, open(data_file, 'r') as data_f, open(out_data_file, 'w') as out_data_f:
Azim Khan13c6bfb2017-06-15 14:45:56 +0100585 suite_deps, dispatch_code, func_code, func_info = parse_functions(funcs_f)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100586 snippets['functions_code'] = func_code
587 snippets['dispatch_code'] = dispatch_code
Azim Khan13c6bfb2017-06-15 14:45:56 +0100588 dep_check_code, expression_code = gen_from_test_data(data_f, out_data_f, func_info, suite_deps)
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100589 snippets['dep_check_code'] = dep_check_code
590 snippets['expression_code'] = expression_code
591
592 snippets['test_file'] = c_file
593 snippets['test_main_file'] = template_file
594 snippets['test_case_file'] = funcs_file
595 snippets['test_case_data_file'] = data_file
596 # Read Template
597 # Add functions
598 #
599 with open(template_file, 'r') as template_f, open(c_file, 'w') as c_f:
600 line_no = 1
601 for line in template_f.readlines():
602 snippets['line_no'] = line_no + 1 # Increment as it sets next line number
603 code = line.format(**snippets)
604 c_f.write(code)
605 line_no += 1
606
607
608def check_cmd():
609 """
610 Command line parser.
611
612 :return:
613 """
614 parser = argparse.ArgumentParser(description='Generate code for mbed-os tests.')
615
616 parser.add_argument("-f", "--functions-file",
617 dest="funcs_file",
618 help="Functions file",
619 metavar="FUNCTIONS",
620 required=True)
621
622 parser.add_argument("-d", "--data-file",
623 dest="data_file",
624 help="Data file",
625 metavar="DATA",
626 required=True)
627
628 parser.add_argument("-t", "--template-file",
629 dest="template_file",
630 help="Template file",
631 metavar="TEMPLATE",
632 required=True)
633
634 parser.add_argument("-s", "--suites-dir",
635 dest="suites_dir",
636 help="Suites dir",
637 metavar="SUITES",
638 required=True)
639
640 parser.add_argument("--help-file",
641 dest="help_file",
642 help="Help file",
643 metavar="HELPER",
644 required=True)
645
646 parser.add_argument("-p", "--platform-file",
647 dest="platform_file",
648 help="Platform code file",
649 metavar="PLATFORM_FILE",
650 required=True)
651
652 parser.add_argument("-o", "--out-dir",
653 dest="out_dir",
654 help="Dir where generated code and scripts are copied",
655 metavar="OUT_DIR",
656 required=True)
657
658 args = parser.parse_args()
659
660 data_file_name = os.path.basename(args.data_file)
661 data_name = os.path.splitext(data_file_name)[0]
662
663 out_c_file = os.path.join(args.out_dir, data_name + '.c')
664 out_data_file = os.path.join(args.out_dir, data_file_name)
665
666 out_c_file_dir = os.path.dirname(out_c_file)
667 out_data_file_dir = os.path.dirname(out_data_file)
668 for d in [out_c_file_dir, out_data_file_dir]:
669 if not os.path.exists(d):
670 os.makedirs(d)
671
Azim Khan1de892b2017-06-09 15:02:36 +0100672 generate_code(args.funcs_file, args.data_file, args.template_file, args.platform_file,
Mohammad Azim Khanfff49042017-03-28 01:48:31 +0100673 args.help_file, args.suites_dir, out_c_file, out_data_file)
674
675
676if __name__ == "__main__":
677 check_cmd()