1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #pragma once
24 
25 #include <inttypes.h>
26 
27 #include <lib/unittest/unittest.h>
28 #include "trusty_bench_option_cb.h"
29 
30 /*
31  * Up this by one if any change to the output is performed in a way that prevent
32  * schema validation. Schema is available in the same folder as this file
33  * "trusty_bench_json_schema.vXXX.json"
34  */
35 #define BENCH_SCHEMA_VERSION "3"
36 
37 /**
38  * trusty_bench_print_json_metric_list -  Prints a machine readable json of all
39  * statistical aggregates for all param/metric in the last BENCH
40  * @metric_list:        List of metrics aggregated during all BENCH runs.
41  * @nb_params:          Number of Parameters in the param array of BENCH.
42  * @suite_name:         Name of the Bench Suite
43  * @bench_name:         Name of the Bench
44  */
trusty_bench_print_json_metric_list(struct list_node * metric_list,size_t nb_params,const char * suite_name,const char * bench_name)45 static inline void trusty_bench_print_json_metric_list(
46         struct list_node* metric_list,
47         size_t nb_params,
48         const char* suite_name,
49         const char* bench_name) {
50     trusty_unittest_printf("{");
51     trusty_unittest_printf("\"schema_version\": " BENCH_SCHEMA_VERSION ",\n");
52     trusty_unittest_printf("\"suite_name\": \"%s\",\n", suite_name);
53     trusty_unittest_printf("\"bench_name\": \"%s\",\n", bench_name);
54 
55     trusty_unittest_printf("\"results\": [");
56     struct bench_metric_list_node* entry;
57     char buf[BENCH_MAX_COL_SIZE];
58     bool first_iter = true;
59 
60     list_for_every_entry(metric_list, entry, struct bench_metric_list_node,
61                          node) {
62         if (!first_iter) {
63             trusty_unittest_printf(",");
64         }
65         first_iter = false;
66         trusty_unittest_printf("{");
67         trusty_unittest_printf("\"metric_name\": \"%s\", ", entry->name);
68         if (nb_params > 1 || trusty_bench_nb_cpu > 1) {
69             trusty_unittest_printf("\"param_id\": %zu, ",
70                                    entry->param_idx % entry->nb_params);
71             if (entry->param_name_cb) {
72                 entry->param_name_cb(buf, sizeof(buf),
73                                      entry->param_idx % entry->nb_params);
74                 trusty_unittest_printf("\"param_name\": \"%s\", ", buf);
75             } else if (trusty_bench_get_param_name_cb) {
76                 trusty_bench_get_param_name_cb(
77                         buf, sizeof(buf), entry->param_idx % entry->nb_params);
78                 trusty_unittest_printf("\"param_name\": \"%s\", ", buf);
79             }
80         }
81         /* print formatted values */
82         trusty_bench_sprint_col_stat(
83                 buf, sizeof(buf), entry->metric.aggregates[BENCH_AGGREGATE_MIN],
84                 entry->name);
85         trusty_unittest_printf("\"min\": \"%s\",", buf);
86         trusty_bench_sprint_col_stat(
87                 buf, sizeof(buf), entry->metric.aggregates[BENCH_AGGREGATE_MAX],
88                 entry->name);
89         trusty_unittest_printf("\"max\": \"%s\",", buf);
90         trusty_bench_sprint_col_stat(
91                 buf, sizeof(buf), entry->metric.aggregates[BENCH_AGGREGATE_AVG],
92                 entry->name);
93         trusty_unittest_printf("\"avg\": \"%s\",", buf);
94         trusty_bench_sprint_col_stat(buf, sizeof(buf), entry->metric.cold,
95                                      entry->name);
96         trusty_unittest_printf("\"cold\": \"%s\",", buf);
97 
98         /* Formatting is conditional to Metric Name, so we always print raw
99          * values even when a formatter callback is present
100          */
101         trusty_unittest_printf("\"raw_min\": %" PRId64 ", ",
102                                entry->metric.aggregates[BENCH_AGGREGATE_MIN]);
103         trusty_unittest_printf("\"raw_max\": %" PRId64 ", ",
104                                entry->metric.aggregates[BENCH_AGGREGATE_MAX]);
105         trusty_unittest_printf("\"raw_avg\": %" PRId64 ", ",
106                                entry->metric.aggregates[BENCH_AGGREGATE_AVG]);
107         trusty_unittest_printf("\"raw_cold\": %" PRId64, entry->metric.cold);
108         trusty_unittest_printf("}\n");
109     }
110     trusty_unittest_printf("]");
111     trusty_unittest_printf("}\n");
112 }
113