1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Tests for the tabulator module."""
8
9from __future__ import print_function
10
11__author__ = 'asharif@google.com (Ahmad Sharif)'
12
13# System modules
14import unittest
15
16# Local modules
17from cros_utils import tabulator
18
19
20class TabulatorTest(unittest.TestCase):
21  """Tests for the Tabulator class."""
22
23  def testResult(self):
24    table = ['k1', ['1', '3'], ['55']]
25    result = tabulator.Result()
26    cell = tabulator.Cell()
27    result.Compute(cell, table[2], table[1])
28    expected = ' '.join([str(float(v)) for v in table[2]])
29    self.assertTrue(cell.value == expected)
30
31    result = tabulator.AmeanResult()
32    cell = tabulator.Cell()
33    result.Compute(cell, table[2], table[1])
34    self.assertTrue(cell.value == float(table[2][0]))
35
36  def testStdResult(self):
37    table = ['k1', [], ['1', '2']]
38    result = tabulator.StdResult()
39    cell = tabulator.Cell()
40    result.Compute(cell, table[2], table[1])
41    self.assertTrue(cell.value == 0.5)
42
43  def testStdResultOfSampleSize1(self):
44    table = ['k1', [], ['1']]
45    result = tabulator.StdResult()
46    cell = tabulator.Cell()
47    result.Compute(cell, table[2], table[1])
48    self.assertTrue(cell.value == 0.0)
49
50  def testStringMean(self):
51    smr = tabulator.StringMeanResult()
52    cell = tabulator.Cell()
53    value = 'PASS'
54    values = [value for _ in range(3)]
55    smr.Compute(cell, values, None)
56    self.assertTrue(cell.value == value)
57    values.append('FAIL')
58    smr.Compute(cell, values, None)
59    self.assertTrue(cell.value == '?')
60
61  def testStorageFormat(self):
62    sf = tabulator.StorageFormat()
63    cell = tabulator.Cell()
64    base = 1024.0
65    cell.value = base
66    sf.Compute(cell)
67    self.assertTrue(cell.string_value == '1.0K')
68    cell.value = base**2
69    sf.Compute(cell)
70    self.assertTrue(cell.string_value == '1.0M')
71    cell.value = base**3
72    sf.Compute(cell)
73    self.assertTrue(cell.string_value == '1.0G')
74
75  def testLerp(self):
76    c1 = tabulator.Color(0, 0, 0, 0)
77    c2 = tabulator.Color(255, 0, 0, 0)
78    c3 = tabulator.Color.Lerp(0.5, c1, c2)
79    self.assertTrue(c3.r == 127.5)
80    self.assertTrue(c3.g == 0)
81    self.assertTrue(c3.b == 0)
82    self.assertTrue(c3.a == 0)
83    c3.Round()
84    self.assertTrue(c3.r == 127)
85
86  def testGmean(self):
87    a = [1.0e+308] * 3
88    # pylint: disable=protected-access
89    b = tabulator.Result()._GetGmean(a)
90    self.assertTrue(0.99e+308 <= b <= 1.01e+308)
91
92  def testIgnoreMinMax(self):
93    amr = tabulator.AmeanResult(ignore_min_max=True)
94    cell = tabulator.Cell()
95    values = [1, 2]
96    amr.Compute(cell, values, None)
97    self.assertTrue(cell.value == 1.5)
98    values = [1, 2, 8]
99    amr.Compute(cell, values, None)
100    self.assertTrue(cell.value == 2)
101
102  def testTableGenerator(self):
103    # yapf: disable
104    runs = [[{'k1': '10', 'k2': '12'},
105             {'k1': '13', 'k2': '14', 'k3': '15'}],
106            [{'k1': '50', 'k2': '51', 'k3': '52', 'k4': '53'}]]
107    # yapf: enable
108    labels = ['vanilla', 'modified']
109    tg = tabulator.TableGenerator(runs, labels)
110    table = tg.GetTable()
111    header = table.pop(0)
112
113    self.assertTrue(header == ['keys', 'vanilla', 'modified'])
114    row = table.pop(0)
115    self.assertTrue(row == ['k1', ['10', '13'], ['50']])
116    row = table.pop(0)
117    self.assertTrue(row == ['k2', ['12', '14'], ['51']])
118    row = table.pop(0)
119    self.assertTrue(row == ['k3', [None, '15'], ['52']])
120    row = table.pop(0)
121    self.assertTrue(row == ['k4', [None, None], ['53']])
122
123    table = tg.GetTable()
124    columns = [
125        tabulator.Column(tabulator.AmeanResult(), tabulator.Format()),
126        tabulator.Column(tabulator.AmeanRatioResult(),
127                         tabulator.PercentFormat()),
128    ]
129    tf = tabulator.TableFormatter(table, columns)
130    table = tf.GetCellTable()
131    self.assertTrue(table)
132
133  def testSamplesTableGenerator(self):
134    # yapf: disable
135    keyvals = {
136        'bench1': [[{'samples': 1}, {'samples': 2}],
137                   [{'samples': 3}, {'samples': 4}]],
138        'bench2': [[{'samples': 5}, {}],
139                   [{'samples': 6}, {'samples': 7}]]
140    }
141    # yapf: enable
142    weights = {'bench1': 0.2, 'bench2': 0.7}
143    iter_counts = {'bench1': 2, 'bench2': 2}
144    labels = ['vanilla', 'modified']
145    tg = tabulator.SamplesTableGenerator(keyvals, labels, iter_counts, weights)
146    (table, new_keyvals, new_iter_counts) = tg.GetTable()
147
148    columns = [
149        tabulator.Column(tabulator.IterationResult(), tabulator.Format()),
150        tabulator.Column(tabulator.AmeanResult(), tabulator.Format()),
151        tabulator.Column(tabulator.AmeanRatioResult(),
152                         tabulator.PercentFormat()),
153    ]
154    # This is the function to load column info.
155    tf = tabulator.TableFormatter(table, columns, samples_table=True)
156    # This is the function where to do all weighting calculation.
157    cell_table = tf.GetCellTable('summary')
158    self.assertTrue(cell_table)
159
160    header = table.pop(0)
161    self.assertTrue(header == ['Benchmarks', 'Weights', 'vanilla', 'modified'])
162    row = table.pop(0)
163    # yapf: disable
164    self.assertTrue(row == ['bench1', 0.2,
165                            ((2, 0), [1 * 0.2, 2 * 0.2]),
166                            ((2, 0), [3 * 0.2, 4 * 0.2])])
167    row = table.pop(0)
168    self.assertTrue(row == ['bench2', 0.7,
169                            ((1, 1), [5 * 0.7, None]),
170                            ((2, 0), [6 * 0.7, 7 * 0.7])])
171    row = table.pop(0)
172    self.assertTrue(row == ['Composite Benchmark (samples)', 'N/A',
173                            ((1, 1), [1 * 0.2 + 5 * 0.7, None]),
174                            ((2, 0), [3 * 0.2 + 6 * 0.7, 4 * 0.2 + 7 * 0.7])])
175    # yapf: enable
176    self.assertTrue('Composite Benchmark' in new_keyvals.keys())
177    self.assertTrue('Composite Benchmark' in new_iter_counts.keys())
178
179  def testColspan(self):
180    simple_table = [
181        ['binary', 'b1', 'b2', 'b3'],
182        ['size', 100, 105, 108],
183        ['rodata', 100, 80, 70],
184        ['data', 100, 100, 100],
185        ['debug', 100, 140, 60],
186    ]
187    columns = [
188        tabulator.Column(tabulator.AmeanResult(), tabulator.Format()),
189        tabulator.Column(tabulator.MinResult(), tabulator.Format()),
190        tabulator.Column(tabulator.AmeanRatioResult(),
191                         tabulator.PercentFormat()),
192        tabulator.Column(tabulator.AmeanRatioResult(),
193                         tabulator.ColorBoxFormat()),
194    ]
195    our_table = [simple_table[0]]
196    for row in simple_table[1:]:
197      our_row = [row[0]]
198      for v in row[1:]:
199        our_row.append([v])
200      our_table.append(our_row)
201
202    tf = tabulator.TableFormatter(our_table, columns)
203    cell_table = tf.GetCellTable()
204    self.assertTrue(cell_table[0][0].colspan == 1)
205    self.assertTrue(cell_table[0][1].colspan == 2)
206    self.assertTrue(cell_table[0][2].colspan == 4)
207    self.assertTrue(cell_table[0][3].colspan == 4)
208    for row in cell_table[1:]:
209      for cell in row:
210        self.assertTrue(cell.colspan == 1)
211
212
213if __name__ == '__main__':
214  unittest.main()
215