Permalink
Browse files

Support combining several result sets into one with multiple -i optio…

…ns (csv and org table formatter).
  • Loading branch information...
tohojo committed Dec 9, 2012
1 parent e1053ec commit ae3df3e29399b7ec72dd41a162b0ae79a0893dea
Showing with 58 additions and 27 deletions.
  1. +3 −3 netperf-wrapper
  2. +39 −16 netperf_wrapper/formatters.py
  3. +16 −8 netperf_wrapper/settings.py
View
@@ -57,9 +57,9 @@ try:
else:
raise RuntimeError("Formatter not found.")
- if not results:
- results = agg.postprocess(agg.aggregate(results))
- results.dump_dir(os.path.dirname(settings.OUTPUT) or ".")
+ if not results[0]:
+ results[0] = agg.postprocess(agg.aggregate(results[0]))
+ results[0].dump_dir(os.path.dirname(settings.OUTPUT) or ".")
formatter.format(results)
except RuntimeError as e:
@@ -63,23 +63,49 @@ def __init__(self, output):
self.output = output
def format(self, results):
- sys.stderr.write("No output formatter selected.\nTest data is in %s (use with -i to format).\n" % results.dump_file)
+ sys.stderr.write("No output formatter selected.\nTest data is in %s (use with -i to format).\n" % results[0].dump_file)
DefaultFormatter = Formatter
+class TableFormatter(Formatter):
-class OrgTableFormatter(Formatter):
+ def get_header(self, results):
+ name = results[0].meta("NAME")
+ keys = list(settings.DATA_SETS.keys())
+ header_row = [name]
+
+ if len(results) > 1:
+ for r in results:
+ header_row += [k + ' - ' + r.meta("TITLE") for k in keys]
+ else:
+ header_row += keys
+ return header_row
+
+ def combine_results(self, results):
+ """Generator to combine several result sets into one list of rows, by
+ concatenating them."""
+ keys = list(settings.DATA_SETS.keys())
+ for row in list(zip(*[list(r.zipped(keys)) for r in results])):
+ out_row = [row[0][0]]
+ for r in row:
+ if r[0] != out_row[0]:
+ raise RuntimeError("x-value mismatch: %s/%s. Incompatible data sets?" % (out_row[0], r[0]))
+ out_row += r[1:]
+ yield out_row
+
+
+class OrgTableFormatter(TableFormatter):
"""Format the output for an Org mode table. The formatter is pretty crude
and does not align the table properly, but it should be sufficient to create
something that Org mode can correctly realign."""
def format(self, results):
- name = results.meta("NAME")
+ name = results[0].meta("NAME")
- if not results:
+ if not results[0]:
self.output.write(str(name) + " -- empty\n")
- keys = list(settings.DATA_SETS.keys())
- header_row = [name] + keys
+ return
+ header_row = self.get_header(results)
self.output.write("| " + " | ".join(header_row) + " |\n")
self.output.write("|-" + "-+-".join(["-"*len(i) for i in header_row]) + "-|\n")
@@ -88,33 +114,30 @@ def format_item(item):
return "%.2f" % item
return str(item)
- for row in results.zipped(keys):
+ for row in self.combine_results(results):
self.output.write("| ")
self.output.write(" | ".join(map(format_item, row)))
self.output.write(" |\n")
-class CsvFormatter(Formatter):
+class CsvFormatter(TableFormatter):
"""Format the output as csv."""
def format(self, results):
- name = results.meta("NAME")
-
- if not results:
+ if not results[0]:
return
writer = csv.writer(self.output)
- keys = list(settings.DATA_SETS.keys())
- header_row = [name] + keys
+ header_row = self.get_header(results)
writer.writerow(header_row)
def format_item(item):
if item is None:
return ""
return str(item)
- for row in results.zipped(keys):
+ for row in self.combine_results(results):
writer.writerow(list(map(format_item, row)))
class PlotFormatter(Formatter):
@@ -310,10 +333,10 @@ def _do_meta_plot(self, results):
getattr(self, '_do_%s_plot' % config['type'])(results, config=config)
def format(self, results):
- if not results:
+ if not results[0]:
return
- getattr(self, '_do_%s_plot' % self.config['type'])(results)
+ getattr(self, '_do_%s_plot' % self.config['type'])(results[0])
self._annotate_plot()
@@ -42,7 +42,7 @@
'FORMAT': 'default',
'TITLE': '',
'LOG_FILE': None,
- 'INPUT': None,
+ 'INPUT': [],
'DESCRIPTION': 'No description',
'PLOTS': {},
'IP_VERSION': None,
@@ -132,7 +132,7 @@ def require_host_count(self, count):
parser.add_option("-o", "--output", action="store", type="string", dest="OUTPUT",
help="file to write output to (default standard out)")
-parser.add_option("-i", "--input", action="store", type="string", dest="INPUT",
+parser.add_option("-i", "--input", action="append", type="string", dest="INPUT",
help="file to read input from (instead of running tests)")
parser.add_option("-f", "--format", action="store", type="string", dest="FORMAT",
help="select output format (plot, csv, org_table)")
@@ -211,11 +211,19 @@ def load():
if hasattr(settings, 'PLOT'):
settings.FORMAT = 'plot'
- if settings.INPUT is not None:
- results = ResultSet.load_file(settings.INPUT)
+ if settings.INPUT:
+ results = []
+ test_name = None
+ for filename in settings.INPUT:
+ r = ResultSet.load_file(filename)
+ if test_name is not None and test_name != r.meta("NAME"):
+ raise RuntimeError("Result sets must be from same test (found %s/%s)" % (test_name, r.meta("NAME")))
+ test_name = r.meta("NAME")
+ results.append(r)
+
- settings.load_test(results.meta("NAME"))
- settings.update(results.meta())
+ settings.load_test(test_name)
+ settings.update(results[0].meta())
else:
if len(args) < 1:
parser.error("Missing test name.")
@@ -226,14 +234,14 @@ def load():
test_name = os.path.splitext(os.path.basename(test_file))[0]
settings.load_test(test_name)
- results = ResultSet(NAME=settings.NAME,
+ results = [ResultSet(NAME=settings.NAME,
HOST=settings.HOST,
TIME=settings.TIME,
LOCAL_HOST=settings.LOCAL_HOST,
TITLE=settings.TITLE,
LENGTH=settings.LENGTH,
TOTAL_LENGTH=settings.TOTAL_LENGTH,
- STEP_SIZE=settings.STEP_SIZE,)
+ STEP_SIZE=settings.STEP_SIZE,)]
if settings.SCALE_DATA:
scale_data = []

0 comments on commit ae3df3e

Please sign in to comment.