1cef7893435aa41160dd1255c43cb8498279738ccChris Craik# Copyright 2014 The Chromium Authors. All rights reserved.
2cef7893435aa41160dd1255c43cb8498279738ccChris Craik# Use of this source code is governed by a BSD-style license that can be
3cef7893435aa41160dd1255c43cb8498279738ccChris Craik# found in the LICENSE file.
4cef7893435aa41160dd1255c43cb8498279738ccChris Craikimport os
5cef7893435aa41160dd1255c43cb8498279738ccChris Craikimport StringIO
6cef7893435aa41160dd1255c43cb8498279738ccChris Craikimport unittest
7cef7893435aa41160dd1255c43cb8498279738ccChris Craik
8cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry import story
9cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry.internal.results import csv_pivot_table_output_formatter
10cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry.internal.results import page_test_results
11cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry import page as page_module
12cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry.value import improvement_direction
13cef7893435aa41160dd1255c43cb8498279738ccChris Craikfrom telemetry.value import scalar
14cef7893435aa41160dd1255c43cb8498279738ccChris Craik
15cef7893435aa41160dd1255c43cb8498279738ccChris Craik
16cef7893435aa41160dd1255c43cb8498279738ccChris Craikdef _MakeStorySet():
17cef7893435aa41160dd1255c43cb8498279738ccChris Craik  story_set = story.StorySet(base_dir=os.path.dirname(__file__))
18cef7893435aa41160dd1255c43cb8498279738ccChris Craik  story_set.AddStory(
19cef7893435aa41160dd1255c43cb8498279738ccChris Craik      page_module.Page('http://www.foo.com/', story_set, story_set.base_dir))
20cef7893435aa41160dd1255c43cb8498279738ccChris Craik  story_set.AddStory(
21cef7893435aa41160dd1255c43cb8498279738ccChris Craik      page_module.Page('http://www.bar.com/', story_set, story_set.base_dir))
22cef7893435aa41160dd1255c43cb8498279738ccChris Craik  return story_set
23cef7893435aa41160dd1255c43cb8498279738ccChris Craik
24cef7893435aa41160dd1255c43cb8498279738ccChris Craik
25cef7893435aa41160dd1255c43cb8498279738ccChris Craikclass CsvPivotTableOutputFormatterTest(unittest.TestCase):
26cef7893435aa41160dd1255c43cb8498279738ccChris Craik
27cef7893435aa41160dd1255c43cb8498279738ccChris Craik  # The line separator used by CSV formatter.
28cef7893435aa41160dd1255c43cb8498279738ccChris Craik  _LINE_SEPARATOR = '\r\n'
29cef7893435aa41160dd1255c43cb8498279738ccChris Craik
30cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def setUp(self):
31cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._output = StringIO.StringIO()
32cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._story_set = _MakeStorySet()
33cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._results = page_test_results.PageTestResults()
34cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._formatter = None
35cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.MakeFormatter()
36cef7893435aa41160dd1255c43cb8498279738ccChris Craik
37cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def MakeFormatter(self, trace_tag=''):
38cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._formatter = (
39cef7893435aa41160dd1255c43cb8498279738ccChris Craik        csv_pivot_table_output_formatter.CsvPivotTableOutputFormatter(
40cef7893435aa41160dd1255c43cb8498279738ccChris Craik            self._output, trace_tag))
41cef7893435aa41160dd1255c43cb8498279738ccChris Craik
42cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def SimulateBenchmarkRun(self, dict_of_values):
43cef7893435aa41160dd1255c43cb8498279738ccChris Craik    """Simulate one run of a benchmark, using the supplied values.
44cef7893435aa41160dd1255c43cb8498279738ccChris Craik
45cef7893435aa41160dd1255c43cb8498279738ccChris Craik    Args:
46cef7893435aa41160dd1255c43cb8498279738ccChris Craik      dict_of_values: dictionary w/ Page instance as key, a list of Values
47cef7893435aa41160dd1255c43cb8498279738ccChris Craik          as value.
48cef7893435aa41160dd1255c43cb8498279738ccChris Craik    """
49cef7893435aa41160dd1255c43cb8498279738ccChris Craik    for page, values in dict_of_values.iteritems():
50cef7893435aa41160dd1255c43cb8498279738ccChris Craik      self._results.WillRunPage(page)
51cef7893435aa41160dd1255c43cb8498279738ccChris Craik      for v in values:
52cef7893435aa41160dd1255c43cb8498279738ccChris Craik        v.page = page
53cef7893435aa41160dd1255c43cb8498279738ccChris Craik        self._results.AddValue(v)
54cef7893435aa41160dd1255c43cb8498279738ccChris Craik      self._results.DidRunPage(page)
55cef7893435aa41160dd1255c43cb8498279738ccChris Craik
56cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def Format(self):
57cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self._formatter.Format(self._results)
58cef7893435aa41160dd1255c43cb8498279738ccChris Craik    return self._output.getvalue()
59cef7893435aa41160dd1255c43cb8498279738ccChris Craik
60cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def testSimple(self):
61cef7893435aa41160dd1255c43cb8498279738ccChris Craik    # Test a simple benchmark with only one value:
62cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.SimulateBenchmarkRun({
63cef7893435aa41160dd1255c43cb8498279738ccChris Craik        self._story_set[0]: [scalar.ScalarValue(
64cef7893435aa41160dd1255c43cb8498279738ccChris Craik            None, 'foo', 'seconds', 3,
65cef7893435aa41160dd1255c43cb8498279738ccChris Craik            improvement_direction=improvement_direction.DOWN)]})
66cef7893435aa41160dd1255c43cb8498279738ccChris Craik    expected = self._LINE_SEPARATOR.join([
67cef7893435aa41160dd1255c43cb8498279738ccChris Craik        'story_set,page,name,value,units,run_index',
68cef7893435aa41160dd1255c43cb8498279738ccChris Craik        'story_set,http://www.foo.com/,foo,3,seconds,0',
69cef7893435aa41160dd1255c43cb8498279738ccChris Craik        ''])
70cef7893435aa41160dd1255c43cb8498279738ccChris Craik
71cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.assertEqual(expected, self.Format())
72cef7893435aa41160dd1255c43cb8498279738ccChris Craik
73cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def testMultiplePagesAndValues(self):
74cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.SimulateBenchmarkRun({
75cef7893435aa41160dd1255c43cb8498279738ccChris Craik        self._story_set[0]: [
76cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
77cef7893435aa41160dd1255c43cb8498279738ccChris Craik              None, 'foo', 'seconds', 4,
78cef7893435aa41160dd1255c43cb8498279738ccChris Craik              improvement_direction=improvement_direction.DOWN)],
79cef7893435aa41160dd1255c43cb8498279738ccChris Craik        self._story_set[1]: [
80cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
81cef7893435aa41160dd1255c43cb8498279738ccChris Craik                None, 'foo', 'seconds', 3.4,
82cef7893435aa41160dd1255c43cb8498279738ccChris Craik                improvement_direction=improvement_direction.DOWN),
83cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
84cef7893435aa41160dd1255c43cb8498279738ccChris Craik                None, 'bar', 'km', 10,
85cef7893435aa41160dd1255c43cb8498279738ccChris Craik                improvement_direction=improvement_direction.DOWN),
86cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
87cef7893435aa41160dd1255c43cb8498279738ccChris Craik                None, 'baz', 'count', 5,
88cef7893435aa41160dd1255c43cb8498279738ccChris Craik                improvement_direction=improvement_direction.DOWN)]})
89cef7893435aa41160dd1255c43cb8498279738ccChris Craik
90cef7893435aa41160dd1255c43cb8498279738ccChris Craik    # Parse CSV output into list of lists.
91cef7893435aa41160dd1255c43cb8498279738ccChris Craik    csv_string = self.Format()
92cef7893435aa41160dd1255c43cb8498279738ccChris Craik    lines = csv_string.split(self._LINE_SEPARATOR)
93cef7893435aa41160dd1255c43cb8498279738ccChris Craik    values = [s.split(',') for s in lines[1:-1]]
94cef7893435aa41160dd1255c43cb8498279738ccChris Craik
95cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.assertEquals(len(values), 4)  # We expect 4 value in total.
96cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.assertEquals(len(set((v[1] for v in values))), 2)  # 2 pages.
97cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.assertEquals(len(set((v[2] for v in values))), 3)  # 3 value names.
98cef7893435aa41160dd1255c43cb8498279738ccChris Craik
99cef7893435aa41160dd1255c43cb8498279738ccChris Craik  def testTraceTag(self):
100cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.MakeFormatter(trace_tag='date,option')
101cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.SimulateBenchmarkRun({
102cef7893435aa41160dd1255c43cb8498279738ccChris Craik        self._story_set[0]: [
103cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
104cef7893435aa41160dd1255c43cb8498279738ccChris Craik                None, 'foo', 'seconds', 3,
105cef7893435aa41160dd1255c43cb8498279738ccChris Craik                improvement_direction=improvement_direction.DOWN),
106cef7893435aa41160dd1255c43cb8498279738ccChris Craik            scalar.ScalarValue(
107cef7893435aa41160dd1255c43cb8498279738ccChris Craik                None, 'bar', 'tons', 5,
108cef7893435aa41160dd1255c43cb8498279738ccChris Craik                improvement_direction=improvement_direction.DOWN)]})
109cef7893435aa41160dd1255c43cb8498279738ccChris Craik    output = self.Format().split(self._LINE_SEPARATOR)
110cef7893435aa41160dd1255c43cb8498279738ccChris Craik
111cef7893435aa41160dd1255c43cb8498279738ccChris Craik    self.assertTrue(output[0].endswith(',trace_tag_0,trace_tag_1'))
112cef7893435aa41160dd1255c43cb8498279738ccChris Craik    for line in output[1:-1]:
113cef7893435aa41160dd1255c43cb8498279738ccChris Craik      self.assertTrue(line.endswith(',date,option'))
114