xref: /aosp_15_r20/external/google-benchmark/tools/gbench/report.py (revision dbb99499c3810fa1611fa2242a2fc446be01a57c)
1*dbb99499SAndroid Build Coastguard Worker# type: ignore
2*dbb99499SAndroid Build Coastguard Worker
3*dbb99499SAndroid Build Coastguard Worker"""
4*dbb99499SAndroid Build Coastguard Workerreport.py - Utilities for reporting statistics about benchmark results
5*dbb99499SAndroid Build Coastguard Worker"""
6*dbb99499SAndroid Build Coastguard Worker
7*dbb99499SAndroid Build Coastguard Workerimport copy
8*dbb99499SAndroid Build Coastguard Workerimport os
9*dbb99499SAndroid Build Coastguard Workerimport random
10*dbb99499SAndroid Build Coastguard Workerimport re
11*dbb99499SAndroid Build Coastguard Workerimport unittest
12*dbb99499SAndroid Build Coastguard Worker
13*dbb99499SAndroid Build Coastguard Workerfrom numpy import array
14*dbb99499SAndroid Build Coastguard Workerfrom scipy.stats import gmean, mannwhitneyu
15*dbb99499SAndroid Build Coastguard Worker
16*dbb99499SAndroid Build Coastguard Worker
17*dbb99499SAndroid Build Coastguard Workerclass BenchmarkColor(object):
18*dbb99499SAndroid Build Coastguard Worker    def __init__(self, name, code):
19*dbb99499SAndroid Build Coastguard Worker        self.name = name
20*dbb99499SAndroid Build Coastguard Worker        self.code = code
21*dbb99499SAndroid Build Coastguard Worker
22*dbb99499SAndroid Build Coastguard Worker    def __repr__(self):
23*dbb99499SAndroid Build Coastguard Worker        return "%s%r" % (self.__class__.__name__, (self.name, self.code))
24*dbb99499SAndroid Build Coastguard Worker
25*dbb99499SAndroid Build Coastguard Worker    def __format__(self, format):
26*dbb99499SAndroid Build Coastguard Worker        return self.code
27*dbb99499SAndroid Build Coastguard Worker
28*dbb99499SAndroid Build Coastguard Worker
29*dbb99499SAndroid Build Coastguard Worker# Benchmark Colors Enumeration
30*dbb99499SAndroid Build Coastguard WorkerBC_NONE = BenchmarkColor("NONE", "")
31*dbb99499SAndroid Build Coastguard WorkerBC_MAGENTA = BenchmarkColor("MAGENTA", "\033[95m")
32*dbb99499SAndroid Build Coastguard WorkerBC_CYAN = BenchmarkColor("CYAN", "\033[96m")
33*dbb99499SAndroid Build Coastguard WorkerBC_OKBLUE = BenchmarkColor("OKBLUE", "\033[94m")
34*dbb99499SAndroid Build Coastguard WorkerBC_OKGREEN = BenchmarkColor("OKGREEN", "\033[32m")
35*dbb99499SAndroid Build Coastguard WorkerBC_HEADER = BenchmarkColor("HEADER", "\033[92m")
36*dbb99499SAndroid Build Coastguard WorkerBC_WARNING = BenchmarkColor("WARNING", "\033[93m")
37*dbb99499SAndroid Build Coastguard WorkerBC_WHITE = BenchmarkColor("WHITE", "\033[97m")
38*dbb99499SAndroid Build Coastguard WorkerBC_FAIL = BenchmarkColor("FAIL", "\033[91m")
39*dbb99499SAndroid Build Coastguard WorkerBC_ENDC = BenchmarkColor("ENDC", "\033[0m")
40*dbb99499SAndroid Build Coastguard WorkerBC_BOLD = BenchmarkColor("BOLD", "\033[1m")
41*dbb99499SAndroid Build Coastguard WorkerBC_UNDERLINE = BenchmarkColor("UNDERLINE", "\033[4m")
42*dbb99499SAndroid Build Coastguard Worker
43*dbb99499SAndroid Build Coastguard WorkerUTEST_MIN_REPETITIONS = 2
44*dbb99499SAndroid Build Coastguard WorkerUTEST_OPTIMAL_REPETITIONS = 9  # Lowest reasonable number, More is better.
45*dbb99499SAndroid Build Coastguard WorkerUTEST_COL_NAME = "_pvalue"
46*dbb99499SAndroid Build Coastguard Worker
47*dbb99499SAndroid Build Coastguard Worker_TIME_UNIT_TO_SECONDS_MULTIPLIER = {
48*dbb99499SAndroid Build Coastguard Worker    "s": 1.0,
49*dbb99499SAndroid Build Coastguard Worker    "ms": 1e-3,
50*dbb99499SAndroid Build Coastguard Worker    "us": 1e-6,
51*dbb99499SAndroid Build Coastguard Worker    "ns": 1e-9,
52*dbb99499SAndroid Build Coastguard Worker}
53*dbb99499SAndroid Build Coastguard Worker
54*dbb99499SAndroid Build Coastguard Worker
55*dbb99499SAndroid Build Coastguard Workerdef color_format(use_color, fmt_str, *args, **kwargs):
56*dbb99499SAndroid Build Coastguard Worker    """
57*dbb99499SAndroid Build Coastguard Worker    Return the result of 'fmt_str.format(*args, **kwargs)' after transforming
58*dbb99499SAndroid Build Coastguard Worker    'args' and 'kwargs' according to the value of 'use_color'. If 'use_color'
59*dbb99499SAndroid Build Coastguard Worker    is False then all color codes in 'args' and 'kwargs' are replaced with
60*dbb99499SAndroid Build Coastguard Worker    the empty string.
61*dbb99499SAndroid Build Coastguard Worker    """
62*dbb99499SAndroid Build Coastguard Worker    assert use_color is True or use_color is False
63*dbb99499SAndroid Build Coastguard Worker    if not use_color:
64*dbb99499SAndroid Build Coastguard Worker        args = [
65*dbb99499SAndroid Build Coastguard Worker            arg if not isinstance(arg, BenchmarkColor) else BC_NONE
66*dbb99499SAndroid Build Coastguard Worker            for arg in args
67*dbb99499SAndroid Build Coastguard Worker        ]
68*dbb99499SAndroid Build Coastguard Worker        kwargs = {
69*dbb99499SAndroid Build Coastguard Worker            key: arg if not isinstance(arg, BenchmarkColor) else BC_NONE
70*dbb99499SAndroid Build Coastguard Worker            for key, arg in kwargs.items()
71*dbb99499SAndroid Build Coastguard Worker        }
72*dbb99499SAndroid Build Coastguard Worker    return fmt_str.format(*args, **kwargs)
73*dbb99499SAndroid Build Coastguard Worker
74*dbb99499SAndroid Build Coastguard Worker
75*dbb99499SAndroid Build Coastguard Workerdef find_longest_name(benchmark_list):
76*dbb99499SAndroid Build Coastguard Worker    """
77*dbb99499SAndroid Build Coastguard Worker    Return the length of the longest benchmark name in a given list of
78*dbb99499SAndroid Build Coastguard Worker    benchmark JSON objects
79*dbb99499SAndroid Build Coastguard Worker    """
80*dbb99499SAndroid Build Coastguard Worker    longest_name = 1
81*dbb99499SAndroid Build Coastguard Worker    for bc in benchmark_list:
82*dbb99499SAndroid Build Coastguard Worker        if len(bc["name"]) > longest_name:
83*dbb99499SAndroid Build Coastguard Worker            longest_name = len(bc["name"])
84*dbb99499SAndroid Build Coastguard Worker    return longest_name
85*dbb99499SAndroid Build Coastguard Worker
86*dbb99499SAndroid Build Coastguard Worker
87*dbb99499SAndroid Build Coastguard Workerdef calculate_change(old_val, new_val):
88*dbb99499SAndroid Build Coastguard Worker    """
89*dbb99499SAndroid Build Coastguard Worker    Return a float representing the decimal change between old_val and new_val.
90*dbb99499SAndroid Build Coastguard Worker    """
91*dbb99499SAndroid Build Coastguard Worker    if old_val == 0 and new_val == 0:
92*dbb99499SAndroid Build Coastguard Worker        return 0.0
93*dbb99499SAndroid Build Coastguard Worker    if old_val == 0:
94*dbb99499SAndroid Build Coastguard Worker        return float(new_val - old_val) / (float(old_val + new_val) / 2)
95*dbb99499SAndroid Build Coastguard Worker    return float(new_val - old_val) / abs(old_val)
96*dbb99499SAndroid Build Coastguard Worker
97*dbb99499SAndroid Build Coastguard Worker
98*dbb99499SAndroid Build Coastguard Workerdef filter_benchmark(json_orig, family, replacement=""):
99*dbb99499SAndroid Build Coastguard Worker    """
100*dbb99499SAndroid Build Coastguard Worker    Apply a filter to the json, and only leave the 'family' of benchmarks.
101*dbb99499SAndroid Build Coastguard Worker    """
102*dbb99499SAndroid Build Coastguard Worker    regex = re.compile(family)
103*dbb99499SAndroid Build Coastguard Worker    filtered = {}
104*dbb99499SAndroid Build Coastguard Worker    filtered["benchmarks"] = []
105*dbb99499SAndroid Build Coastguard Worker    for be in json_orig["benchmarks"]:
106*dbb99499SAndroid Build Coastguard Worker        if not regex.search(be["name"]):
107*dbb99499SAndroid Build Coastguard Worker            continue
108*dbb99499SAndroid Build Coastguard Worker        filteredbench = copy.deepcopy(be)  # Do NOT modify the old name!
109*dbb99499SAndroid Build Coastguard Worker        filteredbench["name"] = regex.sub(replacement, filteredbench["name"])
110*dbb99499SAndroid Build Coastguard Worker        filtered["benchmarks"].append(filteredbench)
111*dbb99499SAndroid Build Coastguard Worker    return filtered
112*dbb99499SAndroid Build Coastguard Worker
113*dbb99499SAndroid Build Coastguard Worker
114*dbb99499SAndroid Build Coastguard Workerdef get_unique_benchmark_names(json):
115*dbb99499SAndroid Build Coastguard Worker    """
116*dbb99499SAndroid Build Coastguard Worker    While *keeping* the order, give all the unique 'names' used for benchmarks.
117*dbb99499SAndroid Build Coastguard Worker    """
118*dbb99499SAndroid Build Coastguard Worker    seen = set()
119*dbb99499SAndroid Build Coastguard Worker    uniqued = [
120*dbb99499SAndroid Build Coastguard Worker        x["name"]
121*dbb99499SAndroid Build Coastguard Worker        for x in json["benchmarks"]
122*dbb99499SAndroid Build Coastguard Worker        if x["name"] not in seen and (seen.add(x["name"]) or True)
123*dbb99499SAndroid Build Coastguard Worker    ]
124*dbb99499SAndroid Build Coastguard Worker    return uniqued
125*dbb99499SAndroid Build Coastguard Worker
126*dbb99499SAndroid Build Coastguard Worker
127*dbb99499SAndroid Build Coastguard Workerdef intersect(list1, list2):
128*dbb99499SAndroid Build Coastguard Worker    """
129*dbb99499SAndroid Build Coastguard Worker    Given two lists, get a new list consisting of the elements only contained
130*dbb99499SAndroid Build Coastguard Worker    in *both of the input lists*, while preserving the ordering.
131*dbb99499SAndroid Build Coastguard Worker    """
132*dbb99499SAndroid Build Coastguard Worker    return [x for x in list1 if x in list2]
133*dbb99499SAndroid Build Coastguard Worker
134*dbb99499SAndroid Build Coastguard Worker
135*dbb99499SAndroid Build Coastguard Workerdef is_potentially_comparable_benchmark(x):
136*dbb99499SAndroid Build Coastguard Worker    return "time_unit" in x and "real_time" in x and "cpu_time" in x
137*dbb99499SAndroid Build Coastguard Worker
138*dbb99499SAndroid Build Coastguard Worker
139*dbb99499SAndroid Build Coastguard Workerdef partition_benchmarks(json1, json2):
140*dbb99499SAndroid Build Coastguard Worker    """
141*dbb99499SAndroid Build Coastguard Worker    While preserving the ordering, find benchmarks with the same names in
142*dbb99499SAndroid Build Coastguard Worker    both of the inputs, and group them.
143*dbb99499SAndroid Build Coastguard Worker    (i.e. partition/filter into groups with common name)
144*dbb99499SAndroid Build Coastguard Worker    """
145*dbb99499SAndroid Build Coastguard Worker    json1_unique_names = get_unique_benchmark_names(json1)
146*dbb99499SAndroid Build Coastguard Worker    json2_unique_names = get_unique_benchmark_names(json2)
147*dbb99499SAndroid Build Coastguard Worker    names = intersect(json1_unique_names, json2_unique_names)
148*dbb99499SAndroid Build Coastguard Worker    partitions = []
149*dbb99499SAndroid Build Coastguard Worker    for name in names:
150*dbb99499SAndroid Build Coastguard Worker        time_unit = None
151*dbb99499SAndroid Build Coastguard Worker        # Pick the time unit from the first entry of the lhs benchmark.
152*dbb99499SAndroid Build Coastguard Worker        # We should be careful not to crash with unexpected input.
153*dbb99499SAndroid Build Coastguard Worker        for x in json1["benchmarks"]:
154*dbb99499SAndroid Build Coastguard Worker            if x["name"] == name and is_potentially_comparable_benchmark(x):
155*dbb99499SAndroid Build Coastguard Worker                time_unit = x["time_unit"]
156*dbb99499SAndroid Build Coastguard Worker                break
157*dbb99499SAndroid Build Coastguard Worker        if time_unit is None:
158*dbb99499SAndroid Build Coastguard Worker            continue
159*dbb99499SAndroid Build Coastguard Worker        # Filter by name and time unit.
160*dbb99499SAndroid Build Coastguard Worker        # All the repetitions are assumed to be comparable.
161*dbb99499SAndroid Build Coastguard Worker        lhs = [
162*dbb99499SAndroid Build Coastguard Worker            x
163*dbb99499SAndroid Build Coastguard Worker            for x in json1["benchmarks"]
164*dbb99499SAndroid Build Coastguard Worker            if x["name"] == name and x["time_unit"] == time_unit
165*dbb99499SAndroid Build Coastguard Worker        ]
166*dbb99499SAndroid Build Coastguard Worker        rhs = [
167*dbb99499SAndroid Build Coastguard Worker            x
168*dbb99499SAndroid Build Coastguard Worker            for x in json2["benchmarks"]
169*dbb99499SAndroid Build Coastguard Worker            if x["name"] == name and x["time_unit"] == time_unit
170*dbb99499SAndroid Build Coastguard Worker        ]
171*dbb99499SAndroid Build Coastguard Worker        partitions.append([lhs, rhs])
172*dbb99499SAndroid Build Coastguard Worker    return partitions
173*dbb99499SAndroid Build Coastguard Worker
174*dbb99499SAndroid Build Coastguard Worker
175*dbb99499SAndroid Build Coastguard Workerdef get_timedelta_field_as_seconds(benchmark, field_name):
176*dbb99499SAndroid Build Coastguard Worker    """
177*dbb99499SAndroid Build Coastguard Worker    Get value of field_name field of benchmark, which is time with time unit
178*dbb99499SAndroid Build Coastguard Worker    time_unit, as time in seconds.
179*dbb99499SAndroid Build Coastguard Worker    """
180*dbb99499SAndroid Build Coastguard Worker    timedelta = benchmark[field_name]
181*dbb99499SAndroid Build Coastguard Worker    time_unit = benchmark.get("time_unit", "s")
182*dbb99499SAndroid Build Coastguard Worker    return timedelta * _TIME_UNIT_TO_SECONDS_MULTIPLIER.get(time_unit)
183*dbb99499SAndroid Build Coastguard Worker
184*dbb99499SAndroid Build Coastguard Worker
185*dbb99499SAndroid Build Coastguard Workerdef calculate_geomean(json):
186*dbb99499SAndroid Build Coastguard Worker    """
187*dbb99499SAndroid Build Coastguard Worker    Extract all real/cpu times from all the benchmarks as seconds,
188*dbb99499SAndroid Build Coastguard Worker    and calculate their geomean.
189*dbb99499SAndroid Build Coastguard Worker    """
190*dbb99499SAndroid Build Coastguard Worker    times = []
191*dbb99499SAndroid Build Coastguard Worker    for benchmark in json["benchmarks"]:
192*dbb99499SAndroid Build Coastguard Worker        if "run_type" in benchmark and benchmark["run_type"] == "aggregate":
193*dbb99499SAndroid Build Coastguard Worker            continue
194*dbb99499SAndroid Build Coastguard Worker        times.append(
195*dbb99499SAndroid Build Coastguard Worker            [
196*dbb99499SAndroid Build Coastguard Worker                get_timedelta_field_as_seconds(benchmark, "real_time"),
197*dbb99499SAndroid Build Coastguard Worker                get_timedelta_field_as_seconds(benchmark, "cpu_time"),
198*dbb99499SAndroid Build Coastguard Worker            ]
199*dbb99499SAndroid Build Coastguard Worker        )
200*dbb99499SAndroid Build Coastguard Worker    return gmean(times) if times else array([])
201*dbb99499SAndroid Build Coastguard Worker
202*dbb99499SAndroid Build Coastguard Worker
203*dbb99499SAndroid Build Coastguard Workerdef extract_field(partition, field_name):
204*dbb99499SAndroid Build Coastguard Worker    # The count of elements may be different. We want *all* of them.
205*dbb99499SAndroid Build Coastguard Worker    lhs = [x[field_name] for x in partition[0]]
206*dbb99499SAndroid Build Coastguard Worker    rhs = [x[field_name] for x in partition[1]]
207*dbb99499SAndroid Build Coastguard Worker    return [lhs, rhs]
208*dbb99499SAndroid Build Coastguard Worker
209*dbb99499SAndroid Build Coastguard Worker
210*dbb99499SAndroid Build Coastguard Workerdef calc_utest(timings_cpu, timings_time):
211*dbb99499SAndroid Build Coastguard Worker    min_rep_cnt = min(
212*dbb99499SAndroid Build Coastguard Worker        len(timings_time[0]),
213*dbb99499SAndroid Build Coastguard Worker        len(timings_time[1]),
214*dbb99499SAndroid Build Coastguard Worker        len(timings_cpu[0]),
215*dbb99499SAndroid Build Coastguard Worker        len(timings_cpu[1]),
216*dbb99499SAndroid Build Coastguard Worker    )
217*dbb99499SAndroid Build Coastguard Worker
218*dbb99499SAndroid Build Coastguard Worker    # Does *everything* has at least UTEST_MIN_REPETITIONS repetitions?
219*dbb99499SAndroid Build Coastguard Worker    if min_rep_cnt < UTEST_MIN_REPETITIONS:
220*dbb99499SAndroid Build Coastguard Worker        return False, None, None
221*dbb99499SAndroid Build Coastguard Worker
222*dbb99499SAndroid Build Coastguard Worker    time_pvalue = mannwhitneyu(
223*dbb99499SAndroid Build Coastguard Worker        timings_time[0], timings_time[1], alternative="two-sided"
224*dbb99499SAndroid Build Coastguard Worker    ).pvalue
225*dbb99499SAndroid Build Coastguard Worker    cpu_pvalue = mannwhitneyu(
226*dbb99499SAndroid Build Coastguard Worker        timings_cpu[0], timings_cpu[1], alternative="two-sided"
227*dbb99499SAndroid Build Coastguard Worker    ).pvalue
228*dbb99499SAndroid Build Coastguard Worker
229*dbb99499SAndroid Build Coastguard Worker    return (min_rep_cnt >= UTEST_OPTIMAL_REPETITIONS), cpu_pvalue, time_pvalue
230*dbb99499SAndroid Build Coastguard Worker
231*dbb99499SAndroid Build Coastguard Worker
232*dbb99499SAndroid Build Coastguard Workerdef print_utest(bc_name, utest, utest_alpha, first_col_width, use_color=True):
233*dbb99499SAndroid Build Coastguard Worker    def get_utest_color(pval):
234*dbb99499SAndroid Build Coastguard Worker        return BC_FAIL if pval >= utest_alpha else BC_OKGREEN
235*dbb99499SAndroid Build Coastguard Worker
236*dbb99499SAndroid Build Coastguard Worker    # Check if we failed miserably with minimum required repetitions for utest
237*dbb99499SAndroid Build Coastguard Worker    if (
238*dbb99499SAndroid Build Coastguard Worker        not utest["have_optimal_repetitions"]
239*dbb99499SAndroid Build Coastguard Worker        and utest["cpu_pvalue"] is None
240*dbb99499SAndroid Build Coastguard Worker        and utest["time_pvalue"] is None
241*dbb99499SAndroid Build Coastguard Worker    ):
242*dbb99499SAndroid Build Coastguard Worker        return []
243*dbb99499SAndroid Build Coastguard Worker
244*dbb99499SAndroid Build Coastguard Worker    dsc = "U Test, Repetitions: {} vs {}".format(
245*dbb99499SAndroid Build Coastguard Worker        utest["nr_of_repetitions"], utest["nr_of_repetitions_other"]
246*dbb99499SAndroid Build Coastguard Worker    )
247*dbb99499SAndroid Build Coastguard Worker    dsc_color = BC_OKGREEN
248*dbb99499SAndroid Build Coastguard Worker
249*dbb99499SAndroid Build Coastguard Worker    # We still got some results to show but issue a warning about it.
250*dbb99499SAndroid Build Coastguard Worker    if not utest["have_optimal_repetitions"]:
251*dbb99499SAndroid Build Coastguard Worker        dsc_color = BC_WARNING
252*dbb99499SAndroid Build Coastguard Worker        dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format(
253*dbb99499SAndroid Build Coastguard Worker            UTEST_OPTIMAL_REPETITIONS
254*dbb99499SAndroid Build Coastguard Worker        )
255*dbb99499SAndroid Build Coastguard Worker
256*dbb99499SAndroid Build Coastguard Worker    special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{}      {}"
257*dbb99499SAndroid Build Coastguard Worker
258*dbb99499SAndroid Build Coastguard Worker    return [
259*dbb99499SAndroid Build Coastguard Worker        color_format(
260*dbb99499SAndroid Build Coastguard Worker            use_color,
261*dbb99499SAndroid Build Coastguard Worker            special_str,
262*dbb99499SAndroid Build Coastguard Worker            BC_HEADER,
263*dbb99499SAndroid Build Coastguard Worker            "{}{}".format(bc_name, UTEST_COL_NAME),
264*dbb99499SAndroid Build Coastguard Worker            first_col_width,
265*dbb99499SAndroid Build Coastguard Worker            get_utest_color(utest["time_pvalue"]),
266*dbb99499SAndroid Build Coastguard Worker            utest["time_pvalue"],
267*dbb99499SAndroid Build Coastguard Worker            get_utest_color(utest["cpu_pvalue"]),
268*dbb99499SAndroid Build Coastguard Worker            utest["cpu_pvalue"],
269*dbb99499SAndroid Build Coastguard Worker            dsc_color,
270*dbb99499SAndroid Build Coastguard Worker            dsc,
271*dbb99499SAndroid Build Coastguard Worker            endc=BC_ENDC,
272*dbb99499SAndroid Build Coastguard Worker        )
273*dbb99499SAndroid Build Coastguard Worker    ]
274*dbb99499SAndroid Build Coastguard Worker
275*dbb99499SAndroid Build Coastguard Worker
276*dbb99499SAndroid Build Coastguard Workerdef get_difference_report(json1, json2, utest=False):
277*dbb99499SAndroid Build Coastguard Worker    """
278*dbb99499SAndroid Build Coastguard Worker    Calculate and report the difference between each test of two benchmarks
279*dbb99499SAndroid Build Coastguard Worker    runs specified as 'json1' and 'json2'. Output is another json containing
280*dbb99499SAndroid Build Coastguard Worker    relevant details for each test run.
281*dbb99499SAndroid Build Coastguard Worker    """
282*dbb99499SAndroid Build Coastguard Worker    assert utest is True or utest is False
283*dbb99499SAndroid Build Coastguard Worker
284*dbb99499SAndroid Build Coastguard Worker    diff_report = []
285*dbb99499SAndroid Build Coastguard Worker    partitions = partition_benchmarks(json1, json2)
286*dbb99499SAndroid Build Coastguard Worker    for partition in partitions:
287*dbb99499SAndroid Build Coastguard Worker        benchmark_name = partition[0][0]["name"]
288*dbb99499SAndroid Build Coastguard Worker        label = partition[0][0]["label"] if "label" in partition[0][0] else ""
289*dbb99499SAndroid Build Coastguard Worker        time_unit = partition[0][0]["time_unit"]
290*dbb99499SAndroid Build Coastguard Worker        measurements = []
291*dbb99499SAndroid Build Coastguard Worker        utest_results = {}
292*dbb99499SAndroid Build Coastguard Worker        # Careful, we may have different repetition count.
293*dbb99499SAndroid Build Coastguard Worker        for i in range(min(len(partition[0]), len(partition[1]))):
294*dbb99499SAndroid Build Coastguard Worker            bn = partition[0][i]
295*dbb99499SAndroid Build Coastguard Worker            other_bench = partition[1][i]
296*dbb99499SAndroid Build Coastguard Worker            measurements.append(
297*dbb99499SAndroid Build Coastguard Worker                {
298*dbb99499SAndroid Build Coastguard Worker                    "real_time": bn["real_time"],
299*dbb99499SAndroid Build Coastguard Worker                    "cpu_time": bn["cpu_time"],
300*dbb99499SAndroid Build Coastguard Worker                    "real_time_other": other_bench["real_time"],
301*dbb99499SAndroid Build Coastguard Worker                    "cpu_time_other": other_bench["cpu_time"],
302*dbb99499SAndroid Build Coastguard Worker                    "time": calculate_change(
303*dbb99499SAndroid Build Coastguard Worker                        bn["real_time"], other_bench["real_time"]
304*dbb99499SAndroid Build Coastguard Worker                    ),
305*dbb99499SAndroid Build Coastguard Worker                    "cpu": calculate_change(
306*dbb99499SAndroid Build Coastguard Worker                        bn["cpu_time"], other_bench["cpu_time"]
307*dbb99499SAndroid Build Coastguard Worker                    ),
308*dbb99499SAndroid Build Coastguard Worker                }
309*dbb99499SAndroid Build Coastguard Worker            )
310*dbb99499SAndroid Build Coastguard Worker
311*dbb99499SAndroid Build Coastguard Worker        # After processing the whole partition, if requested, do the U test.
312*dbb99499SAndroid Build Coastguard Worker        if utest:
313*dbb99499SAndroid Build Coastguard Worker            timings_cpu = extract_field(partition, "cpu_time")
314*dbb99499SAndroid Build Coastguard Worker            timings_time = extract_field(partition, "real_time")
315*dbb99499SAndroid Build Coastguard Worker            have_optimal_repetitions, cpu_pvalue, time_pvalue = calc_utest(
316*dbb99499SAndroid Build Coastguard Worker                timings_cpu, timings_time
317*dbb99499SAndroid Build Coastguard Worker            )
318*dbb99499SAndroid Build Coastguard Worker            if cpu_pvalue is not None and time_pvalue is not None:
319*dbb99499SAndroid Build Coastguard Worker                utest_results = {
320*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": have_optimal_repetitions,
321*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": cpu_pvalue,
322*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": time_pvalue,
323*dbb99499SAndroid Build Coastguard Worker                    "nr_of_repetitions": len(timings_cpu[0]),
324*dbb99499SAndroid Build Coastguard Worker                    "nr_of_repetitions_other": len(timings_cpu[1]),
325*dbb99499SAndroid Build Coastguard Worker                }
326*dbb99499SAndroid Build Coastguard Worker
327*dbb99499SAndroid Build Coastguard Worker        # Store only if we had any measurements for given benchmark.
328*dbb99499SAndroid Build Coastguard Worker        # E.g. partition_benchmarks will filter out the benchmarks having
329*dbb99499SAndroid Build Coastguard Worker        # time units which are not compatible with other time units in the
330*dbb99499SAndroid Build Coastguard Worker        # benchmark suite.
331*dbb99499SAndroid Build Coastguard Worker        if measurements:
332*dbb99499SAndroid Build Coastguard Worker            run_type = (
333*dbb99499SAndroid Build Coastguard Worker                partition[0][0]["run_type"]
334*dbb99499SAndroid Build Coastguard Worker                if "run_type" in partition[0][0]
335*dbb99499SAndroid Build Coastguard Worker                else ""
336*dbb99499SAndroid Build Coastguard Worker            )
337*dbb99499SAndroid Build Coastguard Worker            aggregate_name = (
338*dbb99499SAndroid Build Coastguard Worker                partition[0][0]["aggregate_name"]
339*dbb99499SAndroid Build Coastguard Worker                if run_type == "aggregate"
340*dbb99499SAndroid Build Coastguard Worker                and "aggregate_name" in partition[0][0]
341*dbb99499SAndroid Build Coastguard Worker                else ""
342*dbb99499SAndroid Build Coastguard Worker            )
343*dbb99499SAndroid Build Coastguard Worker            diff_report.append(
344*dbb99499SAndroid Build Coastguard Worker                {
345*dbb99499SAndroid Build Coastguard Worker                    "name": benchmark_name,
346*dbb99499SAndroid Build Coastguard Worker                    "label": label,
347*dbb99499SAndroid Build Coastguard Worker                    "measurements": measurements,
348*dbb99499SAndroid Build Coastguard Worker                    "time_unit": time_unit,
349*dbb99499SAndroid Build Coastguard Worker                    "run_type": run_type,
350*dbb99499SAndroid Build Coastguard Worker                    "aggregate_name": aggregate_name,
351*dbb99499SAndroid Build Coastguard Worker                    "utest": utest_results,
352*dbb99499SAndroid Build Coastguard Worker                }
353*dbb99499SAndroid Build Coastguard Worker            )
354*dbb99499SAndroid Build Coastguard Worker
355*dbb99499SAndroid Build Coastguard Worker    lhs_gmean = calculate_geomean(json1)
356*dbb99499SAndroid Build Coastguard Worker    rhs_gmean = calculate_geomean(json2)
357*dbb99499SAndroid Build Coastguard Worker    if lhs_gmean.any() and rhs_gmean.any():
358*dbb99499SAndroid Build Coastguard Worker        diff_report.append(
359*dbb99499SAndroid Build Coastguard Worker            {
360*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
361*dbb99499SAndroid Build Coastguard Worker                "label": "",
362*dbb99499SAndroid Build Coastguard Worker                "measurements": [
363*dbb99499SAndroid Build Coastguard Worker                    {
364*dbb99499SAndroid Build Coastguard Worker                        "real_time": lhs_gmean[0],
365*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": lhs_gmean[1],
366*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": rhs_gmean[0],
367*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": rhs_gmean[1],
368*dbb99499SAndroid Build Coastguard Worker                        "time": calculate_change(lhs_gmean[0], rhs_gmean[0]),
369*dbb99499SAndroid Build Coastguard Worker                        "cpu": calculate_change(lhs_gmean[1], rhs_gmean[1]),
370*dbb99499SAndroid Build Coastguard Worker                    }
371*dbb99499SAndroid Build Coastguard Worker                ],
372*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
373*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
374*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
375*dbb99499SAndroid Build Coastguard Worker                "utest": {},
376*dbb99499SAndroid Build Coastguard Worker            }
377*dbb99499SAndroid Build Coastguard Worker        )
378*dbb99499SAndroid Build Coastguard Worker
379*dbb99499SAndroid Build Coastguard Worker    return diff_report
380*dbb99499SAndroid Build Coastguard Worker
381*dbb99499SAndroid Build Coastguard Worker
382*dbb99499SAndroid Build Coastguard Workerdef print_difference_report(
383*dbb99499SAndroid Build Coastguard Worker    json_diff_report,
384*dbb99499SAndroid Build Coastguard Worker    include_aggregates_only=False,
385*dbb99499SAndroid Build Coastguard Worker    utest=False,
386*dbb99499SAndroid Build Coastguard Worker    utest_alpha=0.05,
387*dbb99499SAndroid Build Coastguard Worker    use_color=True,
388*dbb99499SAndroid Build Coastguard Worker):
389*dbb99499SAndroid Build Coastguard Worker    """
390*dbb99499SAndroid Build Coastguard Worker    Calculate and report the difference between each test of two benchmarks
391*dbb99499SAndroid Build Coastguard Worker    runs specified as 'json1' and 'json2'.
392*dbb99499SAndroid Build Coastguard Worker    """
393*dbb99499SAndroid Build Coastguard Worker    assert utest is True or utest is False
394*dbb99499SAndroid Build Coastguard Worker
395*dbb99499SAndroid Build Coastguard Worker    def get_color(res):
396*dbb99499SAndroid Build Coastguard Worker        if res > 0.05:
397*dbb99499SAndroid Build Coastguard Worker            return BC_FAIL
398*dbb99499SAndroid Build Coastguard Worker        elif res > -0.07:
399*dbb99499SAndroid Build Coastguard Worker            return BC_WHITE
400*dbb99499SAndroid Build Coastguard Worker        else:
401*dbb99499SAndroid Build Coastguard Worker            return BC_CYAN
402*dbb99499SAndroid Build Coastguard Worker
403*dbb99499SAndroid Build Coastguard Worker    first_col_width = find_longest_name(json_diff_report)
404*dbb99499SAndroid Build Coastguard Worker    first_col_width = max(first_col_width, len("Benchmark"))
405*dbb99499SAndroid Build Coastguard Worker    first_col_width += len(UTEST_COL_NAME)
406*dbb99499SAndroid Build Coastguard Worker    first_line = "{:<{}s}Time             CPU      Time Old      Time New       CPU Old       CPU New".format(
407*dbb99499SAndroid Build Coastguard Worker        "Benchmark", 12 + first_col_width
408*dbb99499SAndroid Build Coastguard Worker    )
409*dbb99499SAndroid Build Coastguard Worker    output_strs = [first_line, "-" * len(first_line)]
410*dbb99499SAndroid Build Coastguard Worker
411*dbb99499SAndroid Build Coastguard Worker    fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}"
412*dbb99499SAndroid Build Coastguard Worker    for benchmark in json_diff_report:
413*dbb99499SAndroid Build Coastguard Worker        # *If* we were asked to only include aggregates,
414*dbb99499SAndroid Build Coastguard Worker        # and if it is non-aggregate, then don't print it.
415*dbb99499SAndroid Build Coastguard Worker        if (
416*dbb99499SAndroid Build Coastguard Worker            not include_aggregates_only
417*dbb99499SAndroid Build Coastguard Worker            or "run_type" not in benchmark
418*dbb99499SAndroid Build Coastguard Worker            or benchmark["run_type"] == "aggregate"
419*dbb99499SAndroid Build Coastguard Worker        ):
420*dbb99499SAndroid Build Coastguard Worker            for measurement in benchmark["measurements"]:
421*dbb99499SAndroid Build Coastguard Worker                output_strs += [
422*dbb99499SAndroid Build Coastguard Worker                    color_format(
423*dbb99499SAndroid Build Coastguard Worker                        use_color,
424*dbb99499SAndroid Build Coastguard Worker                        fmt_str,
425*dbb99499SAndroid Build Coastguard Worker                        BC_HEADER,
426*dbb99499SAndroid Build Coastguard Worker                        benchmark["name"],
427*dbb99499SAndroid Build Coastguard Worker                        first_col_width,
428*dbb99499SAndroid Build Coastguard Worker                        get_color(measurement["time"]),
429*dbb99499SAndroid Build Coastguard Worker                        measurement["time"],
430*dbb99499SAndroid Build Coastguard Worker                        get_color(measurement["cpu"]),
431*dbb99499SAndroid Build Coastguard Worker                        measurement["cpu"],
432*dbb99499SAndroid Build Coastguard Worker                        measurement["real_time"],
433*dbb99499SAndroid Build Coastguard Worker                        measurement["real_time_other"],
434*dbb99499SAndroid Build Coastguard Worker                        measurement["cpu_time"],
435*dbb99499SAndroid Build Coastguard Worker                        measurement["cpu_time_other"],
436*dbb99499SAndroid Build Coastguard Worker                        endc=BC_ENDC,
437*dbb99499SAndroid Build Coastguard Worker                    )
438*dbb99499SAndroid Build Coastguard Worker                ]
439*dbb99499SAndroid Build Coastguard Worker
440*dbb99499SAndroid Build Coastguard Worker        # After processing the measurements, if requested and
441*dbb99499SAndroid Build Coastguard Worker        # if applicable (e.g. u-test exists for given benchmark),
442*dbb99499SAndroid Build Coastguard Worker        # print the U test.
443*dbb99499SAndroid Build Coastguard Worker        if utest and benchmark["utest"]:
444*dbb99499SAndroid Build Coastguard Worker            output_strs += print_utest(
445*dbb99499SAndroid Build Coastguard Worker                benchmark["name"],
446*dbb99499SAndroid Build Coastguard Worker                benchmark["utest"],
447*dbb99499SAndroid Build Coastguard Worker                utest_alpha=utest_alpha,
448*dbb99499SAndroid Build Coastguard Worker                first_col_width=first_col_width,
449*dbb99499SAndroid Build Coastguard Worker                use_color=use_color,
450*dbb99499SAndroid Build Coastguard Worker            )
451*dbb99499SAndroid Build Coastguard Worker
452*dbb99499SAndroid Build Coastguard Worker    return output_strs
453*dbb99499SAndroid Build Coastguard Worker
454*dbb99499SAndroid Build Coastguard Worker
455*dbb99499SAndroid Build Coastguard Worker###############################################################################
456*dbb99499SAndroid Build Coastguard Worker# Unit tests
457*dbb99499SAndroid Build Coastguard Worker
458*dbb99499SAndroid Build Coastguard Worker
459*dbb99499SAndroid Build Coastguard Workerclass TestGetUniqueBenchmarkNames(unittest.TestCase):
460*dbb99499SAndroid Build Coastguard Worker    def load_results(self):
461*dbb99499SAndroid Build Coastguard Worker        import json
462*dbb99499SAndroid Build Coastguard Worker
463*dbb99499SAndroid Build Coastguard Worker        testInputs = os.path.join(
464*dbb99499SAndroid Build Coastguard Worker            os.path.dirname(os.path.realpath(__file__)), "Inputs"
465*dbb99499SAndroid Build Coastguard Worker        )
466*dbb99499SAndroid Build Coastguard Worker        testOutput = os.path.join(testInputs, "test3_run0.json")
467*dbb99499SAndroid Build Coastguard Worker        with open(testOutput, "r") as f:
468*dbb99499SAndroid Build Coastguard Worker            json = json.load(f)
469*dbb99499SAndroid Build Coastguard Worker        return json
470*dbb99499SAndroid Build Coastguard Worker
471*dbb99499SAndroid Build Coastguard Worker    def test_basic(self):
472*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
473*dbb99499SAndroid Build Coastguard Worker            "BM_One",
474*dbb99499SAndroid Build Coastguard Worker            "BM_Two",
475*dbb99499SAndroid Build Coastguard Worker            "short",  # These two are not sorted
476*dbb99499SAndroid Build Coastguard Worker            "medium",  # These two are not sorted
477*dbb99499SAndroid Build Coastguard Worker        ]
478*dbb99499SAndroid Build Coastguard Worker        json = self.load_results()
479*dbb99499SAndroid Build Coastguard Worker        output_lines = get_unique_benchmark_names(json)
480*dbb99499SAndroid Build Coastguard Worker        print("\n")
481*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines))
482*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
483*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
484*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], output_lines[i])
485*dbb99499SAndroid Build Coastguard Worker
486*dbb99499SAndroid Build Coastguard Worker
487*dbb99499SAndroid Build Coastguard Workerclass TestReportDifference(unittest.TestCase):
488*dbb99499SAndroid Build Coastguard Worker    @classmethod
489*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
490*dbb99499SAndroid Build Coastguard Worker        def load_results():
491*dbb99499SAndroid Build Coastguard Worker            import json
492*dbb99499SAndroid Build Coastguard Worker
493*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
494*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
495*dbb99499SAndroid Build Coastguard Worker            )
496*dbb99499SAndroid Build Coastguard Worker            testOutput1 = os.path.join(testInputs, "test1_run1.json")
497*dbb99499SAndroid Build Coastguard Worker            testOutput2 = os.path.join(testInputs, "test1_run2.json")
498*dbb99499SAndroid Build Coastguard Worker            with open(testOutput1, "r") as f:
499*dbb99499SAndroid Build Coastguard Worker                json1 = json.load(f)
500*dbb99499SAndroid Build Coastguard Worker            with open(testOutput2, "r") as f:
501*dbb99499SAndroid Build Coastguard Worker                json2 = json.load(f)
502*dbb99499SAndroid Build Coastguard Worker            return json1, json2
503*dbb99499SAndroid Build Coastguard Worker
504*dbb99499SAndroid Build Coastguard Worker        json1, json2 = load_results()
505*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2)
506*dbb99499SAndroid Build Coastguard Worker
507*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
508*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
509*dbb99499SAndroid Build Coastguard Worker            ["BM_SameTimes", "+0.0000", "+0.0000", "10", "10", "10", "10"],
510*dbb99499SAndroid Build Coastguard Worker            ["BM_2xFaster", "-0.5000", "-0.5000", "50", "25", "50", "25"],
511*dbb99499SAndroid Build Coastguard Worker            ["BM_2xSlower", "+1.0000", "+1.0000", "50", "100", "50", "100"],
512*dbb99499SAndroid Build Coastguard Worker            [
513*dbb99499SAndroid Build Coastguard Worker                "BM_1PercentFaster",
514*dbb99499SAndroid Build Coastguard Worker                "-0.0100",
515*dbb99499SAndroid Build Coastguard Worker                "-0.0100",
516*dbb99499SAndroid Build Coastguard Worker                "100",
517*dbb99499SAndroid Build Coastguard Worker                "99",
518*dbb99499SAndroid Build Coastguard Worker                "100",
519*dbb99499SAndroid Build Coastguard Worker                "99",
520*dbb99499SAndroid Build Coastguard Worker            ],
521*dbb99499SAndroid Build Coastguard Worker            [
522*dbb99499SAndroid Build Coastguard Worker                "BM_1PercentSlower",
523*dbb99499SAndroid Build Coastguard Worker                "+0.0100",
524*dbb99499SAndroid Build Coastguard Worker                "+0.0100",
525*dbb99499SAndroid Build Coastguard Worker                "100",
526*dbb99499SAndroid Build Coastguard Worker                "101",
527*dbb99499SAndroid Build Coastguard Worker                "100",
528*dbb99499SAndroid Build Coastguard Worker                "101",
529*dbb99499SAndroid Build Coastguard Worker            ],
530*dbb99499SAndroid Build Coastguard Worker            [
531*dbb99499SAndroid Build Coastguard Worker                "BM_10PercentFaster",
532*dbb99499SAndroid Build Coastguard Worker                "-0.1000",
533*dbb99499SAndroid Build Coastguard Worker                "-0.1000",
534*dbb99499SAndroid Build Coastguard Worker                "100",
535*dbb99499SAndroid Build Coastguard Worker                "90",
536*dbb99499SAndroid Build Coastguard Worker                "100",
537*dbb99499SAndroid Build Coastguard Worker                "90",
538*dbb99499SAndroid Build Coastguard Worker            ],
539*dbb99499SAndroid Build Coastguard Worker            [
540*dbb99499SAndroid Build Coastguard Worker                "BM_10PercentSlower",
541*dbb99499SAndroid Build Coastguard Worker                "+0.1000",
542*dbb99499SAndroid Build Coastguard Worker                "+0.1000",
543*dbb99499SAndroid Build Coastguard Worker                "100",
544*dbb99499SAndroid Build Coastguard Worker                "110",
545*dbb99499SAndroid Build Coastguard Worker                "100",
546*dbb99499SAndroid Build Coastguard Worker                "110",
547*dbb99499SAndroid Build Coastguard Worker            ],
548*dbb99499SAndroid Build Coastguard Worker            [
549*dbb99499SAndroid Build Coastguard Worker                "BM_100xSlower",
550*dbb99499SAndroid Build Coastguard Worker                "+99.0000",
551*dbb99499SAndroid Build Coastguard Worker                "+99.0000",
552*dbb99499SAndroid Build Coastguard Worker                "100",
553*dbb99499SAndroid Build Coastguard Worker                "10000",
554*dbb99499SAndroid Build Coastguard Worker                "100",
555*dbb99499SAndroid Build Coastguard Worker                "10000",
556*dbb99499SAndroid Build Coastguard Worker            ],
557*dbb99499SAndroid Build Coastguard Worker            [
558*dbb99499SAndroid Build Coastguard Worker                "BM_100xFaster",
559*dbb99499SAndroid Build Coastguard Worker                "-0.9900",
560*dbb99499SAndroid Build Coastguard Worker                "-0.9900",
561*dbb99499SAndroid Build Coastguard Worker                "10000",
562*dbb99499SAndroid Build Coastguard Worker                "100",
563*dbb99499SAndroid Build Coastguard Worker                "10000",
564*dbb99499SAndroid Build Coastguard Worker                "100",
565*dbb99499SAndroid Build Coastguard Worker            ],
566*dbb99499SAndroid Build Coastguard Worker            [
567*dbb99499SAndroid Build Coastguard Worker                "BM_10PercentCPUToTime",
568*dbb99499SAndroid Build Coastguard Worker                "+0.1000",
569*dbb99499SAndroid Build Coastguard Worker                "-0.1000",
570*dbb99499SAndroid Build Coastguard Worker                "100",
571*dbb99499SAndroid Build Coastguard Worker                "110",
572*dbb99499SAndroid Build Coastguard Worker                "100",
573*dbb99499SAndroid Build Coastguard Worker                "90",
574*dbb99499SAndroid Build Coastguard Worker            ],
575*dbb99499SAndroid Build Coastguard Worker            ["BM_ThirdFaster", "-0.3333", "-0.3334", "100", "67", "100", "67"],
576*dbb99499SAndroid Build Coastguard Worker            ["BM_NotBadTimeUnit", "-0.9000", "+0.2000", "0", "0", "0", "1"],
577*dbb99499SAndroid Build Coastguard Worker            ["BM_hasLabel", "+0.0000", "+0.0000", "1", "1", "1", "1"],
578*dbb99499SAndroid Build Coastguard Worker            ["OVERALL_GEOMEAN", "-0.8113", "-0.7779", "0", "0", "0", "0"],
579*dbb99499SAndroid Build Coastguard Worker        ]
580*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
581*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, use_color=False
582*dbb99499SAndroid Build Coastguard Worker        )
583*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
584*dbb99499SAndroid Build Coastguard Worker        print("\n")
585*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
586*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
587*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
588*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
589*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(len(parts), 7)
590*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
591*dbb99499SAndroid Build Coastguard Worker
592*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_output(self):
593*dbb99499SAndroid Build Coastguard Worker        expected_output = [
594*dbb99499SAndroid Build Coastguard Worker            {
595*dbb99499SAndroid Build Coastguard Worker                "name": "BM_SameTimes",
596*dbb99499SAndroid Build Coastguard Worker                "label": "",
597*dbb99499SAndroid Build Coastguard Worker                "measurements": [
598*dbb99499SAndroid Build Coastguard Worker                    {
599*dbb99499SAndroid Build Coastguard Worker                        "time": 0.0000,
600*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.0000,
601*dbb99499SAndroid Build Coastguard Worker                        "real_time": 10,
602*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 10,
603*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 10,
604*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 10,
605*dbb99499SAndroid Build Coastguard Worker                    }
606*dbb99499SAndroid Build Coastguard Worker                ],
607*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
608*dbb99499SAndroid Build Coastguard Worker                "utest": {},
609*dbb99499SAndroid Build Coastguard Worker            },
610*dbb99499SAndroid Build Coastguard Worker            {
611*dbb99499SAndroid Build Coastguard Worker                "name": "BM_2xFaster",
612*dbb99499SAndroid Build Coastguard Worker                "label": "",
613*dbb99499SAndroid Build Coastguard Worker                "measurements": [
614*dbb99499SAndroid Build Coastguard Worker                    {
615*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5000,
616*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5000,
617*dbb99499SAndroid Build Coastguard Worker                        "real_time": 50,
618*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 25,
619*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 50,
620*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 25,
621*dbb99499SAndroid Build Coastguard Worker                    }
622*dbb99499SAndroid Build Coastguard Worker                ],
623*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
624*dbb99499SAndroid Build Coastguard Worker                "utest": {},
625*dbb99499SAndroid Build Coastguard Worker            },
626*dbb99499SAndroid Build Coastguard Worker            {
627*dbb99499SAndroid Build Coastguard Worker                "name": "BM_2xSlower",
628*dbb99499SAndroid Build Coastguard Worker                "label": "",
629*dbb99499SAndroid Build Coastguard Worker                "measurements": [
630*dbb99499SAndroid Build Coastguard Worker                    {
631*dbb99499SAndroid Build Coastguard Worker                        "time": 1.0000,
632*dbb99499SAndroid Build Coastguard Worker                        "cpu": 1.0000,
633*dbb99499SAndroid Build Coastguard Worker                        "real_time": 50,
634*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 100,
635*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 50,
636*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 100,
637*dbb99499SAndroid Build Coastguard Worker                    }
638*dbb99499SAndroid Build Coastguard Worker                ],
639*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
640*dbb99499SAndroid Build Coastguard Worker                "utest": {},
641*dbb99499SAndroid Build Coastguard Worker            },
642*dbb99499SAndroid Build Coastguard Worker            {
643*dbb99499SAndroid Build Coastguard Worker                "name": "BM_1PercentFaster",
644*dbb99499SAndroid Build Coastguard Worker                "label": "",
645*dbb99499SAndroid Build Coastguard Worker                "measurements": [
646*dbb99499SAndroid Build Coastguard Worker                    {
647*dbb99499SAndroid Build Coastguard Worker                        "time": -0.0100,
648*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.0100,
649*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
650*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 98.9999999,
651*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
652*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 98.9999999,
653*dbb99499SAndroid Build Coastguard Worker                    }
654*dbb99499SAndroid Build Coastguard Worker                ],
655*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
656*dbb99499SAndroid Build Coastguard Worker                "utest": {},
657*dbb99499SAndroid Build Coastguard Worker            },
658*dbb99499SAndroid Build Coastguard Worker            {
659*dbb99499SAndroid Build Coastguard Worker                "name": "BM_1PercentSlower",
660*dbb99499SAndroid Build Coastguard Worker                "label": "",
661*dbb99499SAndroid Build Coastguard Worker                "measurements": [
662*dbb99499SAndroid Build Coastguard Worker                    {
663*dbb99499SAndroid Build Coastguard Worker                        "time": 0.0100,
664*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.0100,
665*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
666*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 101,
667*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
668*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 101,
669*dbb99499SAndroid Build Coastguard Worker                    }
670*dbb99499SAndroid Build Coastguard Worker                ],
671*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
672*dbb99499SAndroid Build Coastguard Worker                "utest": {},
673*dbb99499SAndroid Build Coastguard Worker            },
674*dbb99499SAndroid Build Coastguard Worker            {
675*dbb99499SAndroid Build Coastguard Worker                "name": "BM_10PercentFaster",
676*dbb99499SAndroid Build Coastguard Worker                "label": "",
677*dbb99499SAndroid Build Coastguard Worker                "measurements": [
678*dbb99499SAndroid Build Coastguard Worker                    {
679*dbb99499SAndroid Build Coastguard Worker                        "time": -0.1000,
680*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.1000,
681*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
682*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 90,
683*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
684*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 90,
685*dbb99499SAndroid Build Coastguard Worker                    }
686*dbb99499SAndroid Build Coastguard Worker                ],
687*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
688*dbb99499SAndroid Build Coastguard Worker                "utest": {},
689*dbb99499SAndroid Build Coastguard Worker            },
690*dbb99499SAndroid Build Coastguard Worker            {
691*dbb99499SAndroid Build Coastguard Worker                "name": "BM_10PercentSlower",
692*dbb99499SAndroid Build Coastguard Worker                "label": "",
693*dbb99499SAndroid Build Coastguard Worker                "measurements": [
694*dbb99499SAndroid Build Coastguard Worker                    {
695*dbb99499SAndroid Build Coastguard Worker                        "time": 0.1000,
696*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.1000,
697*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
698*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 110,
699*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
700*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 110,
701*dbb99499SAndroid Build Coastguard Worker                    }
702*dbb99499SAndroid Build Coastguard Worker                ],
703*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
704*dbb99499SAndroid Build Coastguard Worker                "utest": {},
705*dbb99499SAndroid Build Coastguard Worker            },
706*dbb99499SAndroid Build Coastguard Worker            {
707*dbb99499SAndroid Build Coastguard Worker                "name": "BM_100xSlower",
708*dbb99499SAndroid Build Coastguard Worker                "label": "",
709*dbb99499SAndroid Build Coastguard Worker                "measurements": [
710*dbb99499SAndroid Build Coastguard Worker                    {
711*dbb99499SAndroid Build Coastguard Worker                        "time": 99.0000,
712*dbb99499SAndroid Build Coastguard Worker                        "cpu": 99.0000,
713*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
714*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 10000,
715*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
716*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 10000,
717*dbb99499SAndroid Build Coastguard Worker                    }
718*dbb99499SAndroid Build Coastguard Worker                ],
719*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
720*dbb99499SAndroid Build Coastguard Worker                "utest": {},
721*dbb99499SAndroid Build Coastguard Worker            },
722*dbb99499SAndroid Build Coastguard Worker            {
723*dbb99499SAndroid Build Coastguard Worker                "name": "BM_100xFaster",
724*dbb99499SAndroid Build Coastguard Worker                "label": "",
725*dbb99499SAndroid Build Coastguard Worker                "measurements": [
726*dbb99499SAndroid Build Coastguard Worker                    {
727*dbb99499SAndroid Build Coastguard Worker                        "time": -0.9900,
728*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.9900,
729*dbb99499SAndroid Build Coastguard Worker                        "real_time": 10000,
730*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 100,
731*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 10000,
732*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 100,
733*dbb99499SAndroid Build Coastguard Worker                    }
734*dbb99499SAndroid Build Coastguard Worker                ],
735*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
736*dbb99499SAndroid Build Coastguard Worker                "utest": {},
737*dbb99499SAndroid Build Coastguard Worker            },
738*dbb99499SAndroid Build Coastguard Worker            {
739*dbb99499SAndroid Build Coastguard Worker                "name": "BM_10PercentCPUToTime",
740*dbb99499SAndroid Build Coastguard Worker                "label": "",
741*dbb99499SAndroid Build Coastguard Worker                "measurements": [
742*dbb99499SAndroid Build Coastguard Worker                    {
743*dbb99499SAndroid Build Coastguard Worker                        "time": 0.1000,
744*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.1000,
745*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
746*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 110,
747*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
748*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 90,
749*dbb99499SAndroid Build Coastguard Worker                    }
750*dbb99499SAndroid Build Coastguard Worker                ],
751*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
752*dbb99499SAndroid Build Coastguard Worker                "utest": {},
753*dbb99499SAndroid Build Coastguard Worker            },
754*dbb99499SAndroid Build Coastguard Worker            {
755*dbb99499SAndroid Build Coastguard Worker                "name": "BM_ThirdFaster",
756*dbb99499SAndroid Build Coastguard Worker                "label": "",
757*dbb99499SAndroid Build Coastguard Worker                "measurements": [
758*dbb99499SAndroid Build Coastguard Worker                    {
759*dbb99499SAndroid Build Coastguard Worker                        "time": -0.3333,
760*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.3334,
761*dbb99499SAndroid Build Coastguard Worker                        "real_time": 100,
762*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 67,
763*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
764*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 67,
765*dbb99499SAndroid Build Coastguard Worker                    }
766*dbb99499SAndroid Build Coastguard Worker                ],
767*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
768*dbb99499SAndroid Build Coastguard Worker                "utest": {},
769*dbb99499SAndroid Build Coastguard Worker            },
770*dbb99499SAndroid Build Coastguard Worker            {
771*dbb99499SAndroid Build Coastguard Worker                "name": "BM_NotBadTimeUnit",
772*dbb99499SAndroid Build Coastguard Worker                "label": "",
773*dbb99499SAndroid Build Coastguard Worker                "measurements": [
774*dbb99499SAndroid Build Coastguard Worker                    {
775*dbb99499SAndroid Build Coastguard Worker                        "time": -0.9000,
776*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.2000,
777*dbb99499SAndroid Build Coastguard Worker                        "real_time": 0.4,
778*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 0.04,
779*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 0.5,
780*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 0.6,
781*dbb99499SAndroid Build Coastguard Worker                    }
782*dbb99499SAndroid Build Coastguard Worker                ],
783*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
784*dbb99499SAndroid Build Coastguard Worker                "utest": {},
785*dbb99499SAndroid Build Coastguard Worker            },
786*dbb99499SAndroid Build Coastguard Worker            {
787*dbb99499SAndroid Build Coastguard Worker                "name": "BM_hasLabel",
788*dbb99499SAndroid Build Coastguard Worker                "label": "a label",
789*dbb99499SAndroid Build Coastguard Worker                "measurements": [
790*dbb99499SAndroid Build Coastguard Worker                    {
791*dbb99499SAndroid Build Coastguard Worker                        "time": 0.0000,
792*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.0000,
793*dbb99499SAndroid Build Coastguard Worker                        "real_time": 1,
794*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 1,
795*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 1,
796*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 1,
797*dbb99499SAndroid Build Coastguard Worker                    }
798*dbb99499SAndroid Build Coastguard Worker                ],
799*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
800*dbb99499SAndroid Build Coastguard Worker                "utest": {},
801*dbb99499SAndroid Build Coastguard Worker            },
802*dbb99499SAndroid Build Coastguard Worker            {
803*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
804*dbb99499SAndroid Build Coastguard Worker                "label": "",
805*dbb99499SAndroid Build Coastguard Worker                "measurements": [
806*dbb99499SAndroid Build Coastguard Worker                    {
807*dbb99499SAndroid Build Coastguard Worker                        "real_time": 3.1622776601683826e-06,
808*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 3.2130844755623912e-06,
809*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 1.9768988699420897e-07,
810*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 2.397447755209533e-07,
811*dbb99499SAndroid Build Coastguard Worker                        "time": -0.8112976497120911,
812*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.7778551721181174,
813*dbb99499SAndroid Build Coastguard Worker                    }
814*dbb99499SAndroid Build Coastguard Worker                ],
815*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
816*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
817*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
818*dbb99499SAndroid Build Coastguard Worker                "utest": {},
819*dbb99499SAndroid Build Coastguard Worker            },
820*dbb99499SAndroid Build Coastguard Worker        ]
821*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
822*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
823*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
824*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["label"], expected["label"])
825*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
826*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
827*dbb99499SAndroid Build Coastguard Worker            assert_measurements(self, out, expected)
828*dbb99499SAndroid Build Coastguard Worker
829*dbb99499SAndroid Build Coastguard Worker
830*dbb99499SAndroid Build Coastguard Workerclass TestReportDifferenceBetweenFamilies(unittest.TestCase):
831*dbb99499SAndroid Build Coastguard Worker    @classmethod
832*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
833*dbb99499SAndroid Build Coastguard Worker        def load_result():
834*dbb99499SAndroid Build Coastguard Worker            import json
835*dbb99499SAndroid Build Coastguard Worker
836*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
837*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
838*dbb99499SAndroid Build Coastguard Worker            )
839*dbb99499SAndroid Build Coastguard Worker            testOutput = os.path.join(testInputs, "test2_run.json")
840*dbb99499SAndroid Build Coastguard Worker            with open(testOutput, "r") as f:
841*dbb99499SAndroid Build Coastguard Worker                json = json.load(f)
842*dbb99499SAndroid Build Coastguard Worker            return json
843*dbb99499SAndroid Build Coastguard Worker
844*dbb99499SAndroid Build Coastguard Worker        json = load_result()
845*dbb99499SAndroid Build Coastguard Worker        json1 = filter_benchmark(json, "BM_Z.ro", ".")
846*dbb99499SAndroid Build Coastguard Worker        json2 = filter_benchmark(json, "BM_O.e", ".")
847*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2)
848*dbb99499SAndroid Build Coastguard Worker
849*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
850*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
851*dbb99499SAndroid Build Coastguard Worker            [".", "-0.5000", "-0.5000", "10", "5", "10", "5"],
852*dbb99499SAndroid Build Coastguard Worker            ["./4", "-0.5000", "-0.5000", "40", "20", "40", "20"],
853*dbb99499SAndroid Build Coastguard Worker            ["Prefix/.", "-0.5000", "-0.5000", "20", "10", "20", "10"],
854*dbb99499SAndroid Build Coastguard Worker            ["Prefix/./3", "-0.5000", "-0.5000", "30", "15", "30", "15"],
855*dbb99499SAndroid Build Coastguard Worker            ["OVERALL_GEOMEAN", "-0.5000", "-0.5000", "0", "0", "0", "0"],
856*dbb99499SAndroid Build Coastguard Worker        ]
857*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
858*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, use_color=False
859*dbb99499SAndroid Build Coastguard Worker        )
860*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
861*dbb99499SAndroid Build Coastguard Worker        print("\n")
862*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
863*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
864*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
865*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
866*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(len(parts), 7)
867*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
868*dbb99499SAndroid Build Coastguard Worker
869*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report(self):
870*dbb99499SAndroid Build Coastguard Worker        expected_output = [
871*dbb99499SAndroid Build Coastguard Worker            {
872*dbb99499SAndroid Build Coastguard Worker                "name": ".",
873*dbb99499SAndroid Build Coastguard Worker                "measurements": [
874*dbb99499SAndroid Build Coastguard Worker                    {
875*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5,
876*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5,
877*dbb99499SAndroid Build Coastguard Worker                        "real_time": 10,
878*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 5,
879*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 10,
880*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 5,
881*dbb99499SAndroid Build Coastguard Worker                    }
882*dbb99499SAndroid Build Coastguard Worker                ],
883*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
884*dbb99499SAndroid Build Coastguard Worker                "utest": {},
885*dbb99499SAndroid Build Coastguard Worker            },
886*dbb99499SAndroid Build Coastguard Worker            {
887*dbb99499SAndroid Build Coastguard Worker                "name": "./4",
888*dbb99499SAndroid Build Coastguard Worker                "measurements": [
889*dbb99499SAndroid Build Coastguard Worker                    {
890*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5,
891*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5,
892*dbb99499SAndroid Build Coastguard Worker                        "real_time": 40,
893*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 20,
894*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 40,
895*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 20,
896*dbb99499SAndroid Build Coastguard Worker                    }
897*dbb99499SAndroid Build Coastguard Worker                ],
898*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
899*dbb99499SAndroid Build Coastguard Worker                "utest": {},
900*dbb99499SAndroid Build Coastguard Worker            },
901*dbb99499SAndroid Build Coastguard Worker            {
902*dbb99499SAndroid Build Coastguard Worker                "name": "Prefix/.",
903*dbb99499SAndroid Build Coastguard Worker                "measurements": [
904*dbb99499SAndroid Build Coastguard Worker                    {
905*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5,
906*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5,
907*dbb99499SAndroid Build Coastguard Worker                        "real_time": 20,
908*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 10,
909*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 20,
910*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 10,
911*dbb99499SAndroid Build Coastguard Worker                    }
912*dbb99499SAndroid Build Coastguard Worker                ],
913*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
914*dbb99499SAndroid Build Coastguard Worker                "utest": {},
915*dbb99499SAndroid Build Coastguard Worker            },
916*dbb99499SAndroid Build Coastguard Worker            {
917*dbb99499SAndroid Build Coastguard Worker                "name": "Prefix/./3",
918*dbb99499SAndroid Build Coastguard Worker                "measurements": [
919*dbb99499SAndroid Build Coastguard Worker                    {
920*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5,
921*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5,
922*dbb99499SAndroid Build Coastguard Worker                        "real_time": 30,
923*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 15,
924*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 30,
925*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 15,
926*dbb99499SAndroid Build Coastguard Worker                    }
927*dbb99499SAndroid Build Coastguard Worker                ],
928*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
929*dbb99499SAndroid Build Coastguard Worker                "utest": {},
930*dbb99499SAndroid Build Coastguard Worker            },
931*dbb99499SAndroid Build Coastguard Worker            {
932*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
933*dbb99499SAndroid Build Coastguard Worker                "measurements": [
934*dbb99499SAndroid Build Coastguard Worker                    {
935*dbb99499SAndroid Build Coastguard Worker                        "real_time": 2.213363839400641e-08,
936*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 2.213363839400641e-08,
937*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 1.1066819197003185e-08,
938*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 1.1066819197003185e-08,
939*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5000000000000009,
940*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.5000000000000009,
941*dbb99499SAndroid Build Coastguard Worker                    }
942*dbb99499SAndroid Build Coastguard Worker                ],
943*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
944*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
945*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
946*dbb99499SAndroid Build Coastguard Worker                "utest": {},
947*dbb99499SAndroid Build Coastguard Worker            },
948*dbb99499SAndroid Build Coastguard Worker        ]
949*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
950*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
951*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
952*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
953*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
954*dbb99499SAndroid Build Coastguard Worker            assert_measurements(self, out, expected)
955*dbb99499SAndroid Build Coastguard Worker
956*dbb99499SAndroid Build Coastguard Worker
957*dbb99499SAndroid Build Coastguard Workerclass TestReportDifferenceWithUTest(unittest.TestCase):
958*dbb99499SAndroid Build Coastguard Worker    @classmethod
959*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
960*dbb99499SAndroid Build Coastguard Worker        def load_results():
961*dbb99499SAndroid Build Coastguard Worker            import json
962*dbb99499SAndroid Build Coastguard Worker
963*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
964*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
965*dbb99499SAndroid Build Coastguard Worker            )
966*dbb99499SAndroid Build Coastguard Worker            testOutput1 = os.path.join(testInputs, "test3_run0.json")
967*dbb99499SAndroid Build Coastguard Worker            testOutput2 = os.path.join(testInputs, "test3_run1.json")
968*dbb99499SAndroid Build Coastguard Worker            with open(testOutput1, "r") as f:
969*dbb99499SAndroid Build Coastguard Worker                json1 = json.load(f)
970*dbb99499SAndroid Build Coastguard Worker            with open(testOutput2, "r") as f:
971*dbb99499SAndroid Build Coastguard Worker                json2 = json.load(f)
972*dbb99499SAndroid Build Coastguard Worker            return json1, json2
973*dbb99499SAndroid Build Coastguard Worker
974*dbb99499SAndroid Build Coastguard Worker        json1, json2 = load_results()
975*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2, utest=True)
976*dbb99499SAndroid Build Coastguard Worker
977*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
978*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
979*dbb99499SAndroid Build Coastguard Worker            ["BM_One", "-0.1000", "+0.1000", "10", "9", "100", "110"],
980*dbb99499SAndroid Build Coastguard Worker            ["BM_Two", "+0.1111", "-0.0111", "9", "10", "90", "89"],
981*dbb99499SAndroid Build Coastguard Worker            ["BM_Two", "-0.1250", "-0.1628", "8", "7", "86", "72"],
982*dbb99499SAndroid Build Coastguard Worker            [
983*dbb99499SAndroid Build Coastguard Worker                "BM_Two_pvalue",
984*dbb99499SAndroid Build Coastguard Worker                "1.0000",
985*dbb99499SAndroid Build Coastguard Worker                "0.6667",
986*dbb99499SAndroid Build Coastguard Worker                "U",
987*dbb99499SAndroid Build Coastguard Worker                "Test,",
988*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
989*dbb99499SAndroid Build Coastguard Worker                "2",
990*dbb99499SAndroid Build Coastguard Worker                "vs",
991*dbb99499SAndroid Build Coastguard Worker                "2.",
992*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
993*dbb99499SAndroid Build Coastguard Worker                "Results",
994*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
995*dbb99499SAndroid Build Coastguard Worker                "9+",
996*dbb99499SAndroid Build Coastguard Worker                "repetitions",
997*dbb99499SAndroid Build Coastguard Worker                "recommended.",
998*dbb99499SAndroid Build Coastguard Worker            ],
999*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.1250", "-0.0625", "8", "7", "80", "75"],
1000*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.4325", "-0.1351", "8", "5", "77", "67"],
1001*dbb99499SAndroid Build Coastguard Worker            [
1002*dbb99499SAndroid Build Coastguard Worker                "short_pvalue",
1003*dbb99499SAndroid Build Coastguard Worker                "0.7671",
1004*dbb99499SAndroid Build Coastguard Worker                "0.2000",
1005*dbb99499SAndroid Build Coastguard Worker                "U",
1006*dbb99499SAndroid Build Coastguard Worker                "Test,",
1007*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
1008*dbb99499SAndroid Build Coastguard Worker                "2",
1009*dbb99499SAndroid Build Coastguard Worker                "vs",
1010*dbb99499SAndroid Build Coastguard Worker                "3.",
1011*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
1012*dbb99499SAndroid Build Coastguard Worker                "Results",
1013*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
1014*dbb99499SAndroid Build Coastguard Worker                "9+",
1015*dbb99499SAndroid Build Coastguard Worker                "repetitions",
1016*dbb99499SAndroid Build Coastguard Worker                "recommended.",
1017*dbb99499SAndroid Build Coastguard Worker            ],
1018*dbb99499SAndroid Build Coastguard Worker            ["medium", "-0.3750", "-0.3375", "8", "5", "80", "53"],
1019*dbb99499SAndroid Build Coastguard Worker            ["OVERALL_GEOMEAN", "+1.6405", "-0.6985", "0", "0", "0", "0"],
1020*dbb99499SAndroid Build Coastguard Worker        ]
1021*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
1022*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False
1023*dbb99499SAndroid Build Coastguard Worker        )
1024*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
1025*dbb99499SAndroid Build Coastguard Worker        print("\n")
1026*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
1027*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
1028*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
1029*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
1030*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
1031*dbb99499SAndroid Build Coastguard Worker
1032*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing_aggregates_only(self):
1033*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
1034*dbb99499SAndroid Build Coastguard Worker            ["BM_One", "-0.1000", "+0.1000", "10", "9", "100", "110"],
1035*dbb99499SAndroid Build Coastguard Worker            [
1036*dbb99499SAndroid Build Coastguard Worker                "BM_Two_pvalue",
1037*dbb99499SAndroid Build Coastguard Worker                "1.0000",
1038*dbb99499SAndroid Build Coastguard Worker                "0.6667",
1039*dbb99499SAndroid Build Coastguard Worker                "U",
1040*dbb99499SAndroid Build Coastguard Worker                "Test,",
1041*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
1042*dbb99499SAndroid Build Coastguard Worker                "2",
1043*dbb99499SAndroid Build Coastguard Worker                "vs",
1044*dbb99499SAndroid Build Coastguard Worker                "2.",
1045*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
1046*dbb99499SAndroid Build Coastguard Worker                "Results",
1047*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
1048*dbb99499SAndroid Build Coastguard Worker                "9+",
1049*dbb99499SAndroid Build Coastguard Worker                "repetitions",
1050*dbb99499SAndroid Build Coastguard Worker                "recommended.",
1051*dbb99499SAndroid Build Coastguard Worker            ],
1052*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.1250", "-0.0625", "8", "7", "80", "75"],
1053*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.4325", "-0.1351", "8", "5", "77", "67"],
1054*dbb99499SAndroid Build Coastguard Worker            [
1055*dbb99499SAndroid Build Coastguard Worker                "short_pvalue",
1056*dbb99499SAndroid Build Coastguard Worker                "0.7671",
1057*dbb99499SAndroid Build Coastguard Worker                "0.2000",
1058*dbb99499SAndroid Build Coastguard Worker                "U",
1059*dbb99499SAndroid Build Coastguard Worker                "Test,",
1060*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
1061*dbb99499SAndroid Build Coastguard Worker                "2",
1062*dbb99499SAndroid Build Coastguard Worker                "vs",
1063*dbb99499SAndroid Build Coastguard Worker                "3.",
1064*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
1065*dbb99499SAndroid Build Coastguard Worker                "Results",
1066*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
1067*dbb99499SAndroid Build Coastguard Worker                "9+",
1068*dbb99499SAndroid Build Coastguard Worker                "repetitions",
1069*dbb99499SAndroid Build Coastguard Worker                "recommended.",
1070*dbb99499SAndroid Build Coastguard Worker            ],
1071*dbb99499SAndroid Build Coastguard Worker            ["OVERALL_GEOMEAN", "+1.6405", "-0.6985", "0", "0", "0", "0"],
1072*dbb99499SAndroid Build Coastguard Worker        ]
1073*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
1074*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report,
1075*dbb99499SAndroid Build Coastguard Worker            include_aggregates_only=True,
1076*dbb99499SAndroid Build Coastguard Worker            utest=True,
1077*dbb99499SAndroid Build Coastguard Worker            utest_alpha=0.05,
1078*dbb99499SAndroid Build Coastguard Worker            use_color=False,
1079*dbb99499SAndroid Build Coastguard Worker        )
1080*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
1081*dbb99499SAndroid Build Coastguard Worker        print("\n")
1082*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
1083*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
1084*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
1085*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
1086*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
1087*dbb99499SAndroid Build Coastguard Worker
1088*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report(self):
1089*dbb99499SAndroid Build Coastguard Worker        expected_output = [
1090*dbb99499SAndroid Build Coastguard Worker            {
1091*dbb99499SAndroid Build Coastguard Worker                "name": "BM_One",
1092*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1093*dbb99499SAndroid Build Coastguard Worker                    {
1094*dbb99499SAndroid Build Coastguard Worker                        "time": -0.1,
1095*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.1,
1096*dbb99499SAndroid Build Coastguard Worker                        "real_time": 10,
1097*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 9,
1098*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
1099*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 110,
1100*dbb99499SAndroid Build Coastguard Worker                    }
1101*dbb99499SAndroid Build Coastguard Worker                ],
1102*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1103*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1104*dbb99499SAndroid Build Coastguard Worker            },
1105*dbb99499SAndroid Build Coastguard Worker            {
1106*dbb99499SAndroid Build Coastguard Worker                "name": "BM_Two",
1107*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1108*dbb99499SAndroid Build Coastguard Worker                    {
1109*dbb99499SAndroid Build Coastguard Worker                        "time": 0.1111111111111111,
1110*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.011111111111111112,
1111*dbb99499SAndroid Build Coastguard Worker                        "real_time": 9,
1112*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 10,
1113*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 90,
1114*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 89,
1115*dbb99499SAndroid Build Coastguard Worker                    },
1116*dbb99499SAndroid Build Coastguard Worker                    {
1117*dbb99499SAndroid Build Coastguard Worker                        "time": -0.125,
1118*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.16279069767441862,
1119*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1120*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 7,
1121*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 86,
1122*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 72,
1123*dbb99499SAndroid Build Coastguard Worker                    },
1124*dbb99499SAndroid Build Coastguard Worker                ],
1125*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1126*dbb99499SAndroid Build Coastguard Worker                "utest": {
1127*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": False,
1128*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": 0.6666666666666666,
1129*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": 1.0,
1130*dbb99499SAndroid Build Coastguard Worker                },
1131*dbb99499SAndroid Build Coastguard Worker            },
1132*dbb99499SAndroid Build Coastguard Worker            {
1133*dbb99499SAndroid Build Coastguard Worker                "name": "short",
1134*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1135*dbb99499SAndroid Build Coastguard Worker                    {
1136*dbb99499SAndroid Build Coastguard Worker                        "time": -0.125,
1137*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.0625,
1138*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1139*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 7,
1140*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 80,
1141*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 75,
1142*dbb99499SAndroid Build Coastguard Worker                    },
1143*dbb99499SAndroid Build Coastguard Worker                    {
1144*dbb99499SAndroid Build Coastguard Worker                        "time": -0.4325,
1145*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.13506493506493514,
1146*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1147*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 4.54,
1148*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 77,
1149*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 66.6,
1150*dbb99499SAndroid Build Coastguard Worker                    },
1151*dbb99499SAndroid Build Coastguard Worker                ],
1152*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1153*dbb99499SAndroid Build Coastguard Worker                "utest": {
1154*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": False,
1155*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": 0.2,
1156*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": 0.7670968684102772,
1157*dbb99499SAndroid Build Coastguard Worker                },
1158*dbb99499SAndroid Build Coastguard Worker            },
1159*dbb99499SAndroid Build Coastguard Worker            {
1160*dbb99499SAndroid Build Coastguard Worker                "name": "medium",
1161*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1162*dbb99499SAndroid Build Coastguard Worker                    {
1163*dbb99499SAndroid Build Coastguard Worker                        "time": -0.375,
1164*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.3375,
1165*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1166*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 5,
1167*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 80,
1168*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 53,
1169*dbb99499SAndroid Build Coastguard Worker                    }
1170*dbb99499SAndroid Build Coastguard Worker                ],
1171*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1172*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1173*dbb99499SAndroid Build Coastguard Worker            },
1174*dbb99499SAndroid Build Coastguard Worker            {
1175*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
1176*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1177*dbb99499SAndroid Build Coastguard Worker                    {
1178*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8.48528137423858e-09,
1179*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 8.441336246629233e-08,
1180*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 2.2405267593145244e-08,
1181*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 2.5453661413660466e-08,
1182*dbb99499SAndroid Build Coastguard Worker                        "time": 1.6404861082353634,
1183*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.6984640740519662,
1184*dbb99499SAndroid Build Coastguard Worker                    }
1185*dbb99499SAndroid Build Coastguard Worker                ],
1186*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
1187*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
1188*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
1189*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1190*dbb99499SAndroid Build Coastguard Worker            },
1191*dbb99499SAndroid Build Coastguard Worker        ]
1192*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
1193*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
1194*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
1195*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
1196*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
1197*dbb99499SAndroid Build Coastguard Worker            assert_measurements(self, out, expected)
1198*dbb99499SAndroid Build Coastguard Worker
1199*dbb99499SAndroid Build Coastguard Worker
1200*dbb99499SAndroid Build Coastguard Workerclass TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly(
1201*dbb99499SAndroid Build Coastguard Worker    unittest.TestCase
1202*dbb99499SAndroid Build Coastguard Worker):
1203*dbb99499SAndroid Build Coastguard Worker    @classmethod
1204*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
1205*dbb99499SAndroid Build Coastguard Worker        def load_results():
1206*dbb99499SAndroid Build Coastguard Worker            import json
1207*dbb99499SAndroid Build Coastguard Worker
1208*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
1209*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
1210*dbb99499SAndroid Build Coastguard Worker            )
1211*dbb99499SAndroid Build Coastguard Worker            testOutput1 = os.path.join(testInputs, "test3_run0.json")
1212*dbb99499SAndroid Build Coastguard Worker            testOutput2 = os.path.join(testInputs, "test3_run1.json")
1213*dbb99499SAndroid Build Coastguard Worker            with open(testOutput1, "r") as f:
1214*dbb99499SAndroid Build Coastguard Worker                json1 = json.load(f)
1215*dbb99499SAndroid Build Coastguard Worker            with open(testOutput2, "r") as f:
1216*dbb99499SAndroid Build Coastguard Worker                json2 = json.load(f)
1217*dbb99499SAndroid Build Coastguard Worker            return json1, json2
1218*dbb99499SAndroid Build Coastguard Worker
1219*dbb99499SAndroid Build Coastguard Worker        json1, json2 = load_results()
1220*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2, utest=True)
1221*dbb99499SAndroid Build Coastguard Worker
1222*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
1223*dbb99499SAndroid Build Coastguard Worker        expect_lines = [
1224*dbb99499SAndroid Build Coastguard Worker            ["BM_One", "-0.1000", "+0.1000", "10", "9", "100", "110"],
1225*dbb99499SAndroid Build Coastguard Worker            ["BM_Two", "+0.1111", "-0.0111", "9", "10", "90", "89"],
1226*dbb99499SAndroid Build Coastguard Worker            ["BM_Two", "-0.1250", "-0.1628", "8", "7", "86", "72"],
1227*dbb99499SAndroid Build Coastguard Worker            [
1228*dbb99499SAndroid Build Coastguard Worker                "BM_Two_pvalue",
1229*dbb99499SAndroid Build Coastguard Worker                "1.0000",
1230*dbb99499SAndroid Build Coastguard Worker                "0.6667",
1231*dbb99499SAndroid Build Coastguard Worker                "U",
1232*dbb99499SAndroid Build Coastguard Worker                "Test,",
1233*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
1234*dbb99499SAndroid Build Coastguard Worker                "2",
1235*dbb99499SAndroid Build Coastguard Worker                "vs",
1236*dbb99499SAndroid Build Coastguard Worker                "2.",
1237*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
1238*dbb99499SAndroid Build Coastguard Worker                "Results",
1239*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
1240*dbb99499SAndroid Build Coastguard Worker                "9+",
1241*dbb99499SAndroid Build Coastguard Worker                "repetitions",
1242*dbb99499SAndroid Build Coastguard Worker                "recommended.",
1243*dbb99499SAndroid Build Coastguard Worker            ],
1244*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.1250", "-0.0625", "8", "7", "80", "75"],
1245*dbb99499SAndroid Build Coastguard Worker            ["short", "-0.4325", "-0.1351", "8", "5", "77", "67"],
1246*dbb99499SAndroid Build Coastguard Worker            [
1247*dbb99499SAndroid Build Coastguard Worker                "short_pvalue",
1248*dbb99499SAndroid Build Coastguard Worker                "0.7671",
1249*dbb99499SAndroid Build Coastguard Worker                "0.2000",
1250*dbb99499SAndroid Build Coastguard Worker                "U",
1251*dbb99499SAndroid Build Coastguard Worker                "Test,",
1252*dbb99499SAndroid Build Coastguard Worker                "Repetitions:",
1253*dbb99499SAndroid Build Coastguard Worker                "2",
1254*dbb99499SAndroid Build Coastguard Worker                "vs",
1255*dbb99499SAndroid Build Coastguard Worker                "3.",
1256*dbb99499SAndroid Build Coastguard Worker                "WARNING:",
1257*dbb99499SAndroid Build Coastguard Worker                "Results",
1258*dbb99499SAndroid Build Coastguard Worker                "unreliable!",
1259*dbb99499SAndroid Build Coastguard Worker                "9+",
1260*dbb99499SAndroid Build Coastguard Worker                "repetitions",
1261*dbb99499SAndroid Build Coastguard Worker                "recommended.",
1262*dbb99499SAndroid Build Coastguard Worker            ],
1263*dbb99499SAndroid Build Coastguard Worker            ["medium", "-0.3750", "-0.3375", "8", "5", "80", "53"],
1264*dbb99499SAndroid Build Coastguard Worker            ["OVERALL_GEOMEAN", "+1.6405", "-0.6985", "0", "0", "0", "0"],
1265*dbb99499SAndroid Build Coastguard Worker        ]
1266*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
1267*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False
1268*dbb99499SAndroid Build Coastguard Worker        )
1269*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
1270*dbb99499SAndroid Build Coastguard Worker        print("\n")
1271*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
1272*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
1273*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
1274*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
1275*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
1276*dbb99499SAndroid Build Coastguard Worker
1277*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report(self):
1278*dbb99499SAndroid Build Coastguard Worker        expected_output = [
1279*dbb99499SAndroid Build Coastguard Worker            {
1280*dbb99499SAndroid Build Coastguard Worker                "name": "BM_One",
1281*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1282*dbb99499SAndroid Build Coastguard Worker                    {
1283*dbb99499SAndroid Build Coastguard Worker                        "time": -0.1,
1284*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.1,
1285*dbb99499SAndroid Build Coastguard Worker                        "real_time": 10,
1286*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 9,
1287*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 100,
1288*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 110,
1289*dbb99499SAndroid Build Coastguard Worker                    }
1290*dbb99499SAndroid Build Coastguard Worker                ],
1291*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1292*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1293*dbb99499SAndroid Build Coastguard Worker            },
1294*dbb99499SAndroid Build Coastguard Worker            {
1295*dbb99499SAndroid Build Coastguard Worker                "name": "BM_Two",
1296*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1297*dbb99499SAndroid Build Coastguard Worker                    {
1298*dbb99499SAndroid Build Coastguard Worker                        "time": 0.1111111111111111,
1299*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.011111111111111112,
1300*dbb99499SAndroid Build Coastguard Worker                        "real_time": 9,
1301*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 10,
1302*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 90,
1303*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 89,
1304*dbb99499SAndroid Build Coastguard Worker                    },
1305*dbb99499SAndroid Build Coastguard Worker                    {
1306*dbb99499SAndroid Build Coastguard Worker                        "time": -0.125,
1307*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.16279069767441862,
1308*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1309*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 7,
1310*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 86,
1311*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 72,
1312*dbb99499SAndroid Build Coastguard Worker                    },
1313*dbb99499SAndroid Build Coastguard Worker                ],
1314*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1315*dbb99499SAndroid Build Coastguard Worker                "utest": {
1316*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": False,
1317*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": 0.6666666666666666,
1318*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": 1.0,
1319*dbb99499SAndroid Build Coastguard Worker                },
1320*dbb99499SAndroid Build Coastguard Worker            },
1321*dbb99499SAndroid Build Coastguard Worker            {
1322*dbb99499SAndroid Build Coastguard Worker                "name": "short",
1323*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1324*dbb99499SAndroid Build Coastguard Worker                    {
1325*dbb99499SAndroid Build Coastguard Worker                        "time": -0.125,
1326*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.0625,
1327*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1328*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 7,
1329*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 80,
1330*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 75,
1331*dbb99499SAndroid Build Coastguard Worker                    },
1332*dbb99499SAndroid Build Coastguard Worker                    {
1333*dbb99499SAndroid Build Coastguard Worker                        "time": -0.4325,
1334*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.13506493506493514,
1335*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1336*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 4.54,
1337*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 77,
1338*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 66.6,
1339*dbb99499SAndroid Build Coastguard Worker                    },
1340*dbb99499SAndroid Build Coastguard Worker                ],
1341*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1342*dbb99499SAndroid Build Coastguard Worker                "utest": {
1343*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": False,
1344*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": 0.2,
1345*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": 0.7670968684102772,
1346*dbb99499SAndroid Build Coastguard Worker                },
1347*dbb99499SAndroid Build Coastguard Worker            },
1348*dbb99499SAndroid Build Coastguard Worker            {
1349*dbb99499SAndroid Build Coastguard Worker                "name": "medium",
1350*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1351*dbb99499SAndroid Build Coastguard Worker                    {
1352*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 5,
1353*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 80,
1354*dbb99499SAndroid Build Coastguard Worker                        "time": -0.375,
1355*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8,
1356*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 53,
1357*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.3375,
1358*dbb99499SAndroid Build Coastguard Worker                    }
1359*dbb99499SAndroid Build Coastguard Worker                ],
1360*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1361*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1362*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "",
1363*dbb99499SAndroid Build Coastguard Worker            },
1364*dbb99499SAndroid Build Coastguard Worker            {
1365*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
1366*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1367*dbb99499SAndroid Build Coastguard Worker                    {
1368*dbb99499SAndroid Build Coastguard Worker                        "real_time": 8.48528137423858e-09,
1369*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 8.441336246629233e-08,
1370*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 2.2405267593145244e-08,
1371*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 2.5453661413660466e-08,
1372*dbb99499SAndroid Build Coastguard Worker                        "time": 1.6404861082353634,
1373*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.6984640740519662,
1374*dbb99499SAndroid Build Coastguard Worker                    }
1375*dbb99499SAndroid Build Coastguard Worker                ],
1376*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
1377*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
1378*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
1379*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1380*dbb99499SAndroid Build Coastguard Worker            },
1381*dbb99499SAndroid Build Coastguard Worker        ]
1382*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
1383*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
1384*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
1385*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
1386*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
1387*dbb99499SAndroid Build Coastguard Worker            assert_measurements(self, out, expected)
1388*dbb99499SAndroid Build Coastguard Worker
1389*dbb99499SAndroid Build Coastguard Worker
1390*dbb99499SAndroid Build Coastguard Workerclass TestReportDifferenceForPercentageAggregates(unittest.TestCase):
1391*dbb99499SAndroid Build Coastguard Worker    @classmethod
1392*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
1393*dbb99499SAndroid Build Coastguard Worker        def load_results():
1394*dbb99499SAndroid Build Coastguard Worker            import json
1395*dbb99499SAndroid Build Coastguard Worker
1396*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
1397*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
1398*dbb99499SAndroid Build Coastguard Worker            )
1399*dbb99499SAndroid Build Coastguard Worker            testOutput1 = os.path.join(testInputs, "test4_run0.json")
1400*dbb99499SAndroid Build Coastguard Worker            testOutput2 = os.path.join(testInputs, "test4_run1.json")
1401*dbb99499SAndroid Build Coastguard Worker            with open(testOutput1, "r") as f:
1402*dbb99499SAndroid Build Coastguard Worker                json1 = json.load(f)
1403*dbb99499SAndroid Build Coastguard Worker            with open(testOutput2, "r") as f:
1404*dbb99499SAndroid Build Coastguard Worker                json2 = json.load(f)
1405*dbb99499SAndroid Build Coastguard Worker            return json1, json2
1406*dbb99499SAndroid Build Coastguard Worker
1407*dbb99499SAndroid Build Coastguard Worker        json1, json2 = load_results()
1408*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2, utest=True)
1409*dbb99499SAndroid Build Coastguard Worker
1410*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
1411*dbb99499SAndroid Build Coastguard Worker        expect_lines = [["whocares", "-0.5000", "+0.5000", "0", "0", "0", "0"]]
1412*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
1413*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False
1414*dbb99499SAndroid Build Coastguard Worker        )
1415*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
1416*dbb99499SAndroid Build Coastguard Worker        print("\n")
1417*dbb99499SAndroid Build Coastguard Worker        print("\n".join(output_lines_with_header))
1418*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(output_lines), len(expect_lines))
1419*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
1420*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
1421*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(expect_lines[i], parts)
1422*dbb99499SAndroid Build Coastguard Worker
1423*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report(self):
1424*dbb99499SAndroid Build Coastguard Worker        expected_output = [
1425*dbb99499SAndroid Build Coastguard Worker            {
1426*dbb99499SAndroid Build Coastguard Worker                "name": "whocares",
1427*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1428*dbb99499SAndroid Build Coastguard Worker                    {
1429*dbb99499SAndroid Build Coastguard Worker                        "time": -0.5,
1430*dbb99499SAndroid Build Coastguard Worker                        "cpu": 0.5,
1431*dbb99499SAndroid Build Coastguard Worker                        "real_time": 0.01,
1432*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 0.005,
1433*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 0.10,
1434*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 0.15,
1435*dbb99499SAndroid Build Coastguard Worker                    }
1436*dbb99499SAndroid Build Coastguard Worker                ],
1437*dbb99499SAndroid Build Coastguard Worker                "time_unit": "ns",
1438*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1439*dbb99499SAndroid Build Coastguard Worker            }
1440*dbb99499SAndroid Build Coastguard Worker        ]
1441*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
1442*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
1443*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
1444*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
1445*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
1446*dbb99499SAndroid Build Coastguard Worker            assert_measurements(self, out, expected)
1447*dbb99499SAndroid Build Coastguard Worker
1448*dbb99499SAndroid Build Coastguard Worker
1449*dbb99499SAndroid Build Coastguard Workerclass TestReportSorting(unittest.TestCase):
1450*dbb99499SAndroid Build Coastguard Worker    @classmethod
1451*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
1452*dbb99499SAndroid Build Coastguard Worker        def load_result():
1453*dbb99499SAndroid Build Coastguard Worker            import json
1454*dbb99499SAndroid Build Coastguard Worker
1455*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
1456*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
1457*dbb99499SAndroid Build Coastguard Worker            )
1458*dbb99499SAndroid Build Coastguard Worker            testOutput = os.path.join(testInputs, "test4_run.json")
1459*dbb99499SAndroid Build Coastguard Worker            with open(testOutput, "r") as f:
1460*dbb99499SAndroid Build Coastguard Worker                json = json.load(f)
1461*dbb99499SAndroid Build Coastguard Worker            return json
1462*dbb99499SAndroid Build Coastguard Worker
1463*dbb99499SAndroid Build Coastguard Worker        cls.json = load_result()
1464*dbb99499SAndroid Build Coastguard Worker
1465*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
1466*dbb99499SAndroid Build Coastguard Worker        import util
1467*dbb99499SAndroid Build Coastguard Worker
1468*dbb99499SAndroid Build Coastguard Worker        expected_names = [
1469*dbb99499SAndroid Build Coastguard Worker            "99 family 0 instance 0 repetition 0",
1470*dbb99499SAndroid Build Coastguard Worker            "98 family 0 instance 0 repetition 1",
1471*dbb99499SAndroid Build Coastguard Worker            "97 family 0 instance 0 aggregate",
1472*dbb99499SAndroid Build Coastguard Worker            "96 family 0 instance 1 repetition 0",
1473*dbb99499SAndroid Build Coastguard Worker            "95 family 0 instance 1 repetition 1",
1474*dbb99499SAndroid Build Coastguard Worker            "94 family 0 instance 1 aggregate",
1475*dbb99499SAndroid Build Coastguard Worker            "93 family 1 instance 0 repetition 0",
1476*dbb99499SAndroid Build Coastguard Worker            "92 family 1 instance 0 repetition 1",
1477*dbb99499SAndroid Build Coastguard Worker            "91 family 1 instance 0 aggregate",
1478*dbb99499SAndroid Build Coastguard Worker            "90 family 1 instance 1 repetition 0",
1479*dbb99499SAndroid Build Coastguard Worker            "89 family 1 instance 1 repetition 1",
1480*dbb99499SAndroid Build Coastguard Worker            "88 family 1 instance 1 aggregate",
1481*dbb99499SAndroid Build Coastguard Worker        ]
1482*dbb99499SAndroid Build Coastguard Worker
1483*dbb99499SAndroid Build Coastguard Worker        for n in range(len(self.json["benchmarks"]) ** 2):
1484*dbb99499SAndroid Build Coastguard Worker            random.shuffle(self.json["benchmarks"])
1485*dbb99499SAndroid Build Coastguard Worker            sorted_benchmarks = util.sort_benchmark_results(self.json)[
1486*dbb99499SAndroid Build Coastguard Worker                "benchmarks"
1487*dbb99499SAndroid Build Coastguard Worker            ]
1488*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(len(expected_names), len(sorted_benchmarks))
1489*dbb99499SAndroid Build Coastguard Worker            for out, expected in zip(sorted_benchmarks, expected_names):
1490*dbb99499SAndroid Build Coastguard Worker                self.assertEqual(out["name"], expected)
1491*dbb99499SAndroid Build Coastguard Worker
1492*dbb99499SAndroid Build Coastguard Worker
1493*dbb99499SAndroid Build Coastguard Workerclass TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly2(
1494*dbb99499SAndroid Build Coastguard Worker    unittest.TestCase
1495*dbb99499SAndroid Build Coastguard Worker):
1496*dbb99499SAndroid Build Coastguard Worker    @classmethod
1497*dbb99499SAndroid Build Coastguard Worker    def setUpClass(cls):
1498*dbb99499SAndroid Build Coastguard Worker        def load_results():
1499*dbb99499SAndroid Build Coastguard Worker            import json
1500*dbb99499SAndroid Build Coastguard Worker
1501*dbb99499SAndroid Build Coastguard Worker            testInputs = os.path.join(
1502*dbb99499SAndroid Build Coastguard Worker                os.path.dirname(os.path.realpath(__file__)), "Inputs"
1503*dbb99499SAndroid Build Coastguard Worker            )
1504*dbb99499SAndroid Build Coastguard Worker            testOutput1 = os.path.join(testInputs, "test5_run0.json")
1505*dbb99499SAndroid Build Coastguard Worker            testOutput2 = os.path.join(testInputs, "test5_run1.json")
1506*dbb99499SAndroid Build Coastguard Worker            with open(testOutput1, "r") as f:
1507*dbb99499SAndroid Build Coastguard Worker                json1 = json.load(f)
1508*dbb99499SAndroid Build Coastguard Worker                json1["benchmarks"] = [
1509*dbb99499SAndroid Build Coastguard Worker                    json1["benchmarks"][0] for i in range(1000)
1510*dbb99499SAndroid Build Coastguard Worker                ]
1511*dbb99499SAndroid Build Coastguard Worker            with open(testOutput2, "r") as f:
1512*dbb99499SAndroid Build Coastguard Worker                json2 = json.load(f)
1513*dbb99499SAndroid Build Coastguard Worker                json2["benchmarks"] = [
1514*dbb99499SAndroid Build Coastguard Worker                    json2["benchmarks"][0] for i in range(1000)
1515*dbb99499SAndroid Build Coastguard Worker                ]
1516*dbb99499SAndroid Build Coastguard Worker            return json1, json2
1517*dbb99499SAndroid Build Coastguard Worker
1518*dbb99499SAndroid Build Coastguard Worker        json1, json2 = load_results()
1519*dbb99499SAndroid Build Coastguard Worker        cls.json_diff_report = get_difference_report(json1, json2, utest=True)
1520*dbb99499SAndroid Build Coastguard Worker
1521*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report_pretty_printing(self):
1522*dbb99499SAndroid Build Coastguard Worker        expect_line = [
1523*dbb99499SAndroid Build Coastguard Worker            "BM_ManyRepetitions_pvalue",
1524*dbb99499SAndroid Build Coastguard Worker            "0.0000",
1525*dbb99499SAndroid Build Coastguard Worker            "0.0000",
1526*dbb99499SAndroid Build Coastguard Worker            "U",
1527*dbb99499SAndroid Build Coastguard Worker            "Test,",
1528*dbb99499SAndroid Build Coastguard Worker            "Repetitions:",
1529*dbb99499SAndroid Build Coastguard Worker            "1000",
1530*dbb99499SAndroid Build Coastguard Worker            "vs",
1531*dbb99499SAndroid Build Coastguard Worker            "1000",
1532*dbb99499SAndroid Build Coastguard Worker        ]
1533*dbb99499SAndroid Build Coastguard Worker        output_lines_with_header = print_difference_report(
1534*dbb99499SAndroid Build Coastguard Worker            self.json_diff_report, utest=True, utest_alpha=0.05, use_color=False
1535*dbb99499SAndroid Build Coastguard Worker        )
1536*dbb99499SAndroid Build Coastguard Worker        output_lines = output_lines_with_header[2:]
1537*dbb99499SAndroid Build Coastguard Worker        found = False
1538*dbb99499SAndroid Build Coastguard Worker        for i in range(0, len(output_lines)):
1539*dbb99499SAndroid Build Coastguard Worker            parts = [x for x in output_lines[i].split(" ") if x]
1540*dbb99499SAndroid Build Coastguard Worker            found = expect_line == parts
1541*dbb99499SAndroid Build Coastguard Worker            if found:
1542*dbb99499SAndroid Build Coastguard Worker                break
1543*dbb99499SAndroid Build Coastguard Worker        self.assertTrue(found)
1544*dbb99499SAndroid Build Coastguard Worker
1545*dbb99499SAndroid Build Coastguard Worker    def test_json_diff_report(self):
1546*dbb99499SAndroid Build Coastguard Worker        expected_output = [
1547*dbb99499SAndroid Build Coastguard Worker            {
1548*dbb99499SAndroid Build Coastguard Worker                "name": "BM_ManyRepetitions",
1549*dbb99499SAndroid Build Coastguard Worker                "label": "",
1550*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
1551*dbb99499SAndroid Build Coastguard Worker                "run_type": "",
1552*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "",
1553*dbb99499SAndroid Build Coastguard Worker                "utest": {
1554*dbb99499SAndroid Build Coastguard Worker                    "have_optimal_repetitions": True,
1555*dbb99499SAndroid Build Coastguard Worker                    "cpu_pvalue": 0.0,
1556*dbb99499SAndroid Build Coastguard Worker                    "time_pvalue": 0.0,
1557*dbb99499SAndroid Build Coastguard Worker                    "nr_of_repetitions": 1000,
1558*dbb99499SAndroid Build Coastguard Worker                    "nr_of_repetitions_other": 1000,
1559*dbb99499SAndroid Build Coastguard Worker                },
1560*dbb99499SAndroid Build Coastguard Worker            },
1561*dbb99499SAndroid Build Coastguard Worker            {
1562*dbb99499SAndroid Build Coastguard Worker                "name": "OVERALL_GEOMEAN",
1563*dbb99499SAndroid Build Coastguard Worker                "label": "",
1564*dbb99499SAndroid Build Coastguard Worker                "measurements": [
1565*dbb99499SAndroid Build Coastguard Worker                    {
1566*dbb99499SAndroid Build Coastguard Worker                        "real_time": 1.0,
1567*dbb99499SAndroid Build Coastguard Worker                        "cpu_time": 1000.000000000069,
1568*dbb99499SAndroid Build Coastguard Worker                        "real_time_other": 1000.000000000069,
1569*dbb99499SAndroid Build Coastguard Worker                        "cpu_time_other": 1.0,
1570*dbb99499SAndroid Build Coastguard Worker                        "time": 999.000000000069,
1571*dbb99499SAndroid Build Coastguard Worker                        "cpu": -0.9990000000000001,
1572*dbb99499SAndroid Build Coastguard Worker                    }
1573*dbb99499SAndroid Build Coastguard Worker                ],
1574*dbb99499SAndroid Build Coastguard Worker                "time_unit": "s",
1575*dbb99499SAndroid Build Coastguard Worker                "run_type": "aggregate",
1576*dbb99499SAndroid Build Coastguard Worker                "aggregate_name": "geomean",
1577*dbb99499SAndroid Build Coastguard Worker                "utest": {},
1578*dbb99499SAndroid Build Coastguard Worker            },
1579*dbb99499SAndroid Build Coastguard Worker        ]
1580*dbb99499SAndroid Build Coastguard Worker        self.assertEqual(len(self.json_diff_report), len(expected_output))
1581*dbb99499SAndroid Build Coastguard Worker        for out, expected in zip(self.json_diff_report, expected_output):
1582*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["name"], expected["name"])
1583*dbb99499SAndroid Build Coastguard Worker            self.assertEqual(out["time_unit"], expected["time_unit"])
1584*dbb99499SAndroid Build Coastguard Worker            assert_utest(self, out, expected)
1585*dbb99499SAndroid Build Coastguard Worker
1586*dbb99499SAndroid Build Coastguard Worker
1587*dbb99499SAndroid Build Coastguard Workerdef assert_utest(unittest_instance, lhs, rhs):
1588*dbb99499SAndroid Build Coastguard Worker    if lhs["utest"]:
1589*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertAlmostEqual(
1590*dbb99499SAndroid Build Coastguard Worker            lhs["utest"]["cpu_pvalue"], rhs["utest"]["cpu_pvalue"]
1591*dbb99499SAndroid Build Coastguard Worker        )
1592*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertAlmostEqual(
1593*dbb99499SAndroid Build Coastguard Worker            lhs["utest"]["time_pvalue"], rhs["utest"]["time_pvalue"]
1594*dbb99499SAndroid Build Coastguard Worker        )
1595*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertEqual(
1596*dbb99499SAndroid Build Coastguard Worker            lhs["utest"]["have_optimal_repetitions"],
1597*dbb99499SAndroid Build Coastguard Worker            rhs["utest"]["have_optimal_repetitions"],
1598*dbb99499SAndroid Build Coastguard Worker        )
1599*dbb99499SAndroid Build Coastguard Worker    else:
1600*dbb99499SAndroid Build Coastguard Worker        # lhs is empty. assert if rhs is not.
1601*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertEqual(lhs["utest"], rhs["utest"])
1602*dbb99499SAndroid Build Coastguard Worker
1603*dbb99499SAndroid Build Coastguard Worker
1604*dbb99499SAndroid Build Coastguard Workerdef assert_measurements(unittest_instance, lhs, rhs):
1605*dbb99499SAndroid Build Coastguard Worker    for m1, m2 in zip(lhs["measurements"], rhs["measurements"]):
1606*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertEqual(m1["real_time"], m2["real_time"])
1607*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertEqual(m1["cpu_time"], m2["cpu_time"])
1608*dbb99499SAndroid Build Coastguard Worker        # m1['time'] and m1['cpu'] hold values which are being calculated,
1609*dbb99499SAndroid Build Coastguard Worker        # and therefore we must use almost-equal pattern.
1610*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertAlmostEqual(m1["time"], m2["time"], places=4)
1611*dbb99499SAndroid Build Coastguard Worker        unittest_instance.assertAlmostEqual(m1["cpu"], m2["cpu"], places=4)
1612*dbb99499SAndroid Build Coastguard Worker
1613*dbb99499SAndroid Build Coastguard Worker
1614*dbb99499SAndroid Build Coastguard Workerif __name__ == "__main__":
1615*dbb99499SAndroid Build Coastguard Worker    unittest.main()
1616*dbb99499SAndroid Build Coastguard Worker
1617*dbb99499SAndroid Build Coastguard Worker# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
1618*dbb99499SAndroid Build Coastguard Worker# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
1619*dbb99499SAndroid Build Coastguard Worker# kate: indent-mode python; remove-trailing-spaces modified;
1620