133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright 2014 The Chromium Authors. All rights reserved. 233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Use of this source code is governed by a BSD-style license that can be 333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# found in the LICENSE file. 433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport os 533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport StringIO 633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport unittest 733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport mock 933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry import story 1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.internal.results import csv_pivot_table_output_formatter 1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.internal.results import page_test_results 1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry import page as page_module 1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.value import improvement_direction 1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.value import scalar 1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckfrom telemetry.value import trace 17a0e5c0de428e9dea6d07dd57c5594fb1f1c17c20Chris Craikfrom tracing.trace_data import trace_data 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef _MakeStorySet(): 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck story_set = story.StorySet(base_dir=os.path.dirname(__file__)) 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck story_set.AddStory( 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck page_module.Page('http://www.foo.com/', story_set, story_set.base_dir)) 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck story_set.AddStory( 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck page_module.Page('http://www.bar.com/', story_set, story_set.base_dir)) 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return story_set 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass CsvPivotTableOutputFormatterTest(unittest.TestCase): 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # The line separator used by CSV formatter. 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck _LINE_SEPARATOR = '\r\n' 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def setUp(self): 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._output = StringIO.StringIO() 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._story_set = _MakeStorySet() 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._results = page_test_results.PageTestResults() 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._formatter = None 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.MakeFormatter() 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def MakeFormatter(self, trace_tag=''): 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._formatter = ( 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck csv_pivot_table_output_formatter.CsvPivotTableOutputFormatter( 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._output, trace_tag)) 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def SimulateBenchmarkRun(self, list_of_page_and_values): 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Simulate one run of a benchmark, using the supplied values. 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Args: 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck list_of_pages_and_values: a list of tuple (page, list of values) 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for page, values in list_of_page_and_values: 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._results.WillRunPage(page) 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for v in values: 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck v.page = page 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._results.AddValue(v) 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._results.DidRunPage(page) 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def Format(self): 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self._formatter.Format(self._results) 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self._output.getvalue() 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testSimple(self): 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Test a simple benchmark with only one value: 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.SimulateBenchmarkRun([ 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (self._story_set[0], [scalar.ScalarValue( 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'foo', 'seconds', 3, 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN)])]) 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck expected = self._LINE_SEPARATOR.join([ 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 'story_set,page,name,value,units,run_index', 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 'story_set,http://www.foo.com/,foo,3,seconds,0', 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck '']) 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEqual(expected, self.Format()) 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @mock.patch('py_utils.cloud_storage.Insert') 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testMultiplePagesAndValues(self, cs_insert_mock): 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck cs_insert_mock.return_value = 'https://cloud_storage_url/foo' 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck trace_value = trace.TraceValue( 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, trace_data.CreateTraceDataFromRawData('{"traceEvents": []}')) 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck trace_value.UploadToCloud(bucket='foo') 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.SimulateBenchmarkRun([ 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (self._story_set[0], [ 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'foo', 'seconds', 4, 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN)]), 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (self._story_set[1], [ 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'foo', 'seconds', 3.4, 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN), 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck trace_value, 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'bar', 'km', 10, 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN), 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'baz', 'count', 5, 9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN)])]) 9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Parse CSV output into list of lists. 10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck csv_string = self.Format() 10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck lines = csv_string.split(self._LINE_SEPARATOR) 10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck values = [s.split(',') for s in lines[1:-1]] 10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEquals(len(values), 5) # We expect 5 value in total. 10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEquals(len(set((v[1] for v in values))), 2) # 2 pages. 10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEquals(len(set((v[2] for v in values))), 4) # 4 value names. 10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertEquals(values[2], 10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ['story_set', 'http://www.bar.com/', 'trace', 10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 'https://cloud_storage_url/foo', '', '1']) 11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def testTraceTag(self): 11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.MakeFormatter(trace_tag='date,option') 11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.SimulateBenchmarkRun([ 11433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (self._story_set[0], [ 11533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 11633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'foo', 'seconds', 3, 11733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN), 11833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck scalar.ScalarValue( 11933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck None, 'bar', 'tons', 5, 12033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck improvement_direction=improvement_direction.DOWN)])]) 12133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck output = self.Format().split(self._LINE_SEPARATOR) 12233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 12333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(output[0].endswith(',trace_tag_0,trace_tag_1')) 12433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for line in output[1:-1]: 12533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.assertTrue(line.endswith(',date,option')) 126