Skip to content

Commit 655c377

Browse files
committed
Handling output of parallelized test building.
This makes use of the reports generated by the building of tests to prevent output from interleaving when the build is parallelized. This required some changes to memap to return a generated string from the 'generate_output' function. I also had an option to stop the prints from memap to prevent text from interleaving
1 parent 14aff06 commit 655c377

File tree

3 files changed

+70
-31
lines changed

3 files changed

+70
-31
lines changed

tools/memap.py

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import json
1010
import argparse
1111
from prettytable import PrettyTable
12+
from StringIO import StringIO
1213

1314
from utils import argparse_filestring_type, \
1415
argparse_lowercase_hyphen_type, argparse_uppercase_type
@@ -385,7 +386,7 @@ def search_objects(self, path):
385386

386387
export_formats = ["json", "csv-ci", "table"]
387388

388-
def generate_output(self, export_format, file_output=None):
389+
def generate_output(self, export_format, file_output=None, silent=False):
389390
""" Generates summary of memory map data
390391
391392
Positional arguments:
@@ -396,38 +397,48 @@ def generate_output(self, export_format, file_output=None):
396397
"""
397398

398399
try:
399-
if file_output:
400-
file_desc = open(file_output, 'wb')
400+
if silent:
401+
file_desc = None
401402
else:
402-
file_desc = sys.stdout
403+
if file_output:
404+
file_desc = open(file_output, 'wb')
405+
else:
406+
file_desc = sys.stdout
403407
except IOError as error:
404408
print "I/O error({0}): {1}".format(error.errno, error.strerror)
405409
return False
406410

407411
to_call = {'json': self.generate_json,
408412
'csv-ci': self.generate_csv,
409413
'table': self.generate_table}[export_format]
410-
to_call(file_desc)
414+
output_string = to_call(file_desc)
411415

412-
if file_desc is not sys.stdout:
416+
if file_desc is not sys.stdout and file_desc is not None:
413417
file_desc.close()
414418

419+
return output_string
420+
415421
def generate_json(self, file_desc):
416422
"""Generate a json file from a memory map
417423
418424
Positional arguments:
419425
file_desc - the file to write out the final report to
420426
"""
421-
file_desc.write(json.dumps(self.mem_report, indent=4))
422-
file_desc.write('\n')
427+
output = json.dumps(self.mem_report, indent=4)
428+
if file_desc:
429+
file_desc.write(output)
430+
file_desc.write('\n')
431+
432+
return output
423433

424434
def generate_csv(self, file_desc):
425435
"""Generate a CSV file from a memoy map
426436
427437
Positional arguments:
428438
file_desc - the file to write out the final report to
429439
"""
430-
csv_writer = csv.writer(file_desc, delimiter=',',
440+
string_io = StringIO()
441+
csv_writer = csv.writer(string_io, delimiter=',',
431442
quoting=csv.QUOTE_MINIMAL)
432443

433444
csv_module_section = []
@@ -461,6 +472,11 @@ def generate_csv(self, file_desc):
461472
csv_writer.writerow(csv_module_section)
462473
csv_writer.writerow(csv_sizes)
463474

475+
if file_desc:
476+
file_desc.write(string_io.getvalue())
477+
478+
return string_io.getvalue()
479+
464480
def generate_table(self, file_desc):
465481
"""Generate a table from a memoy map
466482
@@ -501,28 +517,32 @@ def generate_table(self, file_desc):
501517

502518
table.add_row(subtotal_row)
503519

504-
file_desc.write(table.get_string())
505-
file_desc.write('\n')
520+
output = table.get_string()
521+
output += '\n'
506522

507523
if self.mem_summary['heap'] == 0:
508-
file_desc.write("Allocated Heap: unknown\n")
524+
output += "Allocated Heap: unknown\n"
509525
else:
510-
file_desc.write("Allocated Heap: %s bytes\n" %
511-
str(self.mem_summary['heap']))
526+
output += "Allocated Heap: %s bytes\n" % \
527+
str(self.mem_summary['heap'])
512528

513529
if self.mem_summary['stack'] == 0:
514-
file_desc.write("Allocated Stack: unknown\n")
530+
output += "Allocated Stack: unknown\n"
515531
else:
516-
file_desc.write("Allocated Stack: %s bytes\n" %
517-
str(self.mem_summary['stack']))
518-
519-
file_desc.write("Total Static RAM memory (data + bss): %s bytes\n" %
520-
(str(self.mem_summary['static_ram'])))
521-
file_desc.write(
522-
"Total RAM memory (data + bss + heap + stack): %s bytes\n"
523-
% (str(self.mem_summary['total_ram'])))
524-
file_desc.write("Total Flash memory (text + data + misc): %s bytes\n" %
525-
(str(self.mem_summary['total_flash'])))
532+
output += "Allocated Stack: %s bytes\n" % \
533+
str(self.mem_summary['stack'])
534+
535+
output += "Total Static RAM memory (data + bss): %s bytes\n" % \
536+
str(self.mem_summary['static_ram'])
537+
output += "Total RAM memory (data + bss + heap + stack): %s bytes\n" % \
538+
str(self.mem_summary['total_ram'])
539+
output += "Total Flash memory (text + data + misc): %s bytes\n" % \
540+
str(self.mem_summary['total_flash'])
541+
542+
if file_desc:
543+
file_desc.write(output)
544+
545+
return output
526546

527547
toolchains = ["ARM", "ARM_STD", "ARM_MICRO", "GCC_ARM", "IAR"]
528548

tools/test_api.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,19 @@ def norm_relative_path(path, start):
20712071

20722072

20732073
def build_test_worker(*args, **kwargs):
2074+
"""This is a worker function for the parallel building of tests. The `args`
2075+
and `kwargs` are passed directly to `build_project`. It returns a dictionary
2076+
with the following structure:
2077+
2078+
{
2079+
'result': `True` if no exceptions were thrown, `False` otherwise
2080+
'reason': Instance of exception that was thrown on failure
2081+
'bin_file': Path to the created binary if `build_project` was
2082+
successful. Not present otherwise
2083+
'kwargs': The keyword arguments that were passed to `build_project`.
2084+
This includes arguments that were modified (ex. report)
2085+
}
2086+
"""
20742087
bin_file = None
20752088
ret = {
20762089
'result': False,
@@ -2138,7 +2151,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
21382151
'properties': properties,
21392152
'verbose': verbose,
21402153
'app_config': app_config,
2141-
'build_profile': build_profile
2154+
'build_profile': build_profile,
2155+
'silent': True
21422156
}
21432157

21442158
results.append(p.apply_async(build_test_worker, args, kwargs))
@@ -2161,13 +2175,16 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
21612175
worker_result = r.get()
21622176
results.remove(r)
21632177

2178+
# Take report from the kwargs and merge it into existing report
2179+
report_entry = worker_result['kwargs']['report'][target_name][toolchain_name]
2180+
for test_key in report_entry.keys():
2181+
report[target_name][toolchain_name][test_key] = report_entry[test_key]
21642182

2165-
for test_key in worker_result['kwargs']['report'][target_name][toolchain_name].keys():
2166-
report[target_name][toolchain_name][test_key] = worker_result['kwargs']['report'][target_name][toolchain_name][test_key]
2167-
2183+
# Set the overall result to a failure if a build failure occurred
21682184
if not worker_result['result'] and not isinstance(worker_result['reason'], NotSupportedException):
21692185
result = False
21702186

2187+
# Adding binary path to test build result
21712188
if worker_result['result'] and 'bin_file' in worker_result:
21722189
bin_file = norm_relative_path(worker_result['bin_file'], execution_directory)
21732190

@@ -2179,7 +2196,9 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
21792196
]
21802197
}
21812198

2182-
# TODO: add 'Image: bin_file' print statement here
2199+
test_key = worker_result['kwargs']['project_id'].upper()
2200+
print report[target_name][toolchain_name][test_key][0][0]['output'].rstrip()
2201+
print 'Image: %s\n' % bin_file
21832202

21842203
except ToolException, err:
21852204
if p._taskqueue.queue:

tools/toolchains/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ def mem_stats(self, map):
10761076
return None
10771077

10781078
# Write output to stdout in text (pretty table) format
1079-
memap.generate_output('table')
1079+
self.info(memap.generate_output('table', silent=True))
10801080

10811081
# Write output to file in JSON format
10821082
map_out = splitext(map)[0] + "_map.json"

0 commit comments

Comments
 (0)