1*6fa2df46SAndroid Build Coastguard Worker // Copyright (C) 2021 The Android Open Source Project
2*6fa2df46SAndroid Build Coastguard Worker //
3*6fa2df46SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*6fa2df46SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*6fa2df46SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*6fa2df46SAndroid Build Coastguard Worker //
7*6fa2df46SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*6fa2df46SAndroid Build Coastguard Worker //
9*6fa2df46SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*6fa2df46SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*6fa2df46SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6fa2df46SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*6fa2df46SAndroid Build Coastguard Worker // limitations under the License.
14*6fa2df46SAndroid Build Coastguard Worker
15*6fa2df46SAndroid Build Coastguard Worker #include <getopt.h>
16*6fa2df46SAndroid Build Coastguard Worker
17*6fa2df46SAndroid Build Coastguard Worker #include <ditto/embedded_benchmarks.h>
18*6fa2df46SAndroid Build Coastguard Worker
19*6fa2df46SAndroid Build Coastguard Worker #include <ditto/arg_parser.h>
20*6fa2df46SAndroid Build Coastguard Worker
21*6fa2df46SAndroid Build Coastguard Worker namespace dittosuite {
22*6fa2df46SAndroid Build Coastguard Worker
ArgToResultsOutput(const std::string_view optarg)23*6fa2df46SAndroid Build Coastguard Worker ResultsOutput ArgToResultsOutput(const std::string_view optarg) {
24*6fa2df46SAndroid Build Coastguard Worker if (optarg == "report" || optarg == "0") {
25*6fa2df46SAndroid Build Coastguard Worker return ResultsOutput::kReport;
26*6fa2df46SAndroid Build Coastguard Worker }
27*6fa2df46SAndroid Build Coastguard Worker if (optarg == "csv" || optarg == "1") {
28*6fa2df46SAndroid Build Coastguard Worker return ResultsOutput::kCsv;
29*6fa2df46SAndroid Build Coastguard Worker }
30*6fa2df46SAndroid Build Coastguard Worker if (optarg == "pb" || optarg == "2") {
31*6fa2df46SAndroid Build Coastguard Worker return ResultsOutput::kPb;
32*6fa2df46SAndroid Build Coastguard Worker }
33*6fa2df46SAndroid Build Coastguard Worker if (optarg == "null" || optarg == "-1") {
34*6fa2df46SAndroid Build Coastguard Worker return ResultsOutput::kNull;
35*6fa2df46SAndroid Build Coastguard Worker }
36*6fa2df46SAndroid Build Coastguard Worker return ResultsOutput::kReport; // by default, the results output is the report (= 0)
37*6fa2df46SAndroid Build Coastguard Worker }
38*6fa2df46SAndroid Build Coastguard Worker
ArgToLogStream(const std::string_view optarg)39*6fa2df46SAndroid Build Coastguard Worker LogStream ArgToLogStream(const std::string_view optarg) {
40*6fa2df46SAndroid Build Coastguard Worker if (optarg == "logcat" || optarg == "1") {
41*6fa2df46SAndroid Build Coastguard Worker #ifdef __ANDROID__
42*6fa2df46SAndroid Build Coastguard Worker return LogStream::kLogcat;
43*6fa2df46SAndroid Build Coastguard Worker #else
44*6fa2df46SAndroid Build Coastguard Worker PLOGF("Cannot set log stream as logcat outside of Android");
45*6fa2df46SAndroid Build Coastguard Worker #endif
46*6fa2df46SAndroid Build Coastguard Worker }
47*6fa2df46SAndroid Build Coastguard Worker return LogStream::kStdout; // by default, the log stream is stdout
48*6fa2df46SAndroid Build Coastguard Worker }
49*6fa2df46SAndroid Build Coastguard Worker
ArgToLogLevel(const std::string_view optarg)50*6fa2df46SAndroid Build Coastguard Worker LogLevel ArgToLogLevel(const std::string_view optarg) {
51*6fa2df46SAndroid Build Coastguard Worker if (optarg == "VERBOSE" || optarg == "5") {
52*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kVerbose;
53*6fa2df46SAndroid Build Coastguard Worker }
54*6fa2df46SAndroid Build Coastguard Worker if (optarg == "DEBUG" || optarg == "4") {
55*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kDebug;
56*6fa2df46SAndroid Build Coastguard Worker }
57*6fa2df46SAndroid Build Coastguard Worker if (optarg == "INFO" || optarg == "3") {
58*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kInfo;
59*6fa2df46SAndroid Build Coastguard Worker }
60*6fa2df46SAndroid Build Coastguard Worker if (optarg == "WARNING" || optarg == "2") {
61*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kWarning;
62*6fa2df46SAndroid Build Coastguard Worker }
63*6fa2df46SAndroid Build Coastguard Worker if (optarg == "ERROR" || optarg == "1") {
64*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kError;
65*6fa2df46SAndroid Build Coastguard Worker }
66*6fa2df46SAndroid Build Coastguard Worker if (optarg == "FATAL" || optarg == "0") {
67*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kFatal;
68*6fa2df46SAndroid Build Coastguard Worker }
69*6fa2df46SAndroid Build Coastguard Worker return LogLevel::kInfo; // by default, the log level is info
70*6fa2df46SAndroid Build Coastguard Worker }
71*6fa2df46SAndroid Build Coastguard Worker
PrintHelpAndExit(std::string_view program_name,const std::string & help_arg)72*6fa2df46SAndroid Build Coastguard Worker void PrintHelpAndExit(std::string_view program_name, const std::string& help_arg) {
73*6fa2df46SAndroid Build Coastguard Worker if (help_arg.compare("workloads") == 0) {
74*6fa2df46SAndroid Build Coastguard Worker std::cerr << "The following workloads are available for execution:\n";
75*6fa2df46SAndroid Build Coastguard Worker for (const auto& c : ditto_static_config) {
76*6fa2df46SAndroid Build Coastguard Worker std::cerr << " - " << c.first << '\n';
77*6fa2df46SAndroid Build Coastguard Worker }
78*6fa2df46SAndroid Build Coastguard Worker } else {
79*6fa2df46SAndroid Build Coastguard Worker std::cerr << "Usage: " << program_name << " [OPTION]... [FILE]\n"
80*6fa2df46SAndroid Build Coastguard Worker << "Benchmarking tool for generic workloads.\n\n"
81*6fa2df46SAndroid Build Coastguard Worker
82*6fa2df46SAndroid Build Coastguard Worker << " -w, --workload[=WORKLOAD]"
83*6fa2df46SAndroid Build Coastguard Worker << " The workload to run. Full list with \"-h workloads\".\n"
84*6fa2df46SAndroid Build Coastguard Worker
85*6fa2df46SAndroid Build Coastguard Worker << " -f, --format[=FMT]" << "\tresults output format, where FMT can be one of:\n"
86*6fa2df46SAndroid Build Coastguard Worker << "\t\t\t - report (or 0, default): human readable summary;\n"
87*6fa2df46SAndroid Build Coastguard Worker << "\t\t\t - csv (or 1): for comma-separated detailed stats;\n"
88*6fa2df46SAndroid Build Coastguard Worker << "\t\t\t - pb (or 2): protocol-buffer text;\n"
89*6fa2df46SAndroid Build Coastguard Worker << "\t\t\t - null (-1): do not print.\n"
90*6fa2df46SAndroid Build Coastguard Worker
91*6fa2df46SAndroid Build Coastguard Worker << " -p, --param[=PAR]..."
92*6fa2df46SAndroid Build Coastguard Worker << "\tif the benchmark is parametric, all the parameters can be passed\n"
93*6fa2df46SAndroid Build Coastguard Worker << "\t\t\tthrough PAR (comma separated)\n"
94*6fa2df46SAndroid Build Coastguard Worker
95*6fa2df46SAndroid Build Coastguard Worker << " -l, --log[=LOG]" << "\toutput stream for the log messages.\n"
96*6fa2df46SAndroid Build Coastguard Worker << "\t\t\tLOG can be one of: stdout (or 0, default), logcat (or 1)\n"
97*6fa2df46SAndroid Build Coastguard Worker
98*6fa2df46SAndroid Build Coastguard Worker << " -v, --verbosity[=VER]" << "\toutput messages verbosity.\n"
99*6fa2df46SAndroid Build Coastguard Worker << "\t\t\tVER can be one of: VERBOSE (or 5), DEBUG (or 4), INFO (or 3, default),\n"
100*6fa2df46SAndroid Build Coastguard Worker << "\t\t\tWARNING (or 2), ERROR (or 1), FATAL (or 0)\n"
101*6fa2df46SAndroid Build Coastguard Worker
102*6fa2df46SAndroid Build Coastguard Worker << " -h, --help" << "\t\tdisplay this help and exit\n\n";
103*6fa2df46SAndroid Build Coastguard Worker }
104*6fa2df46SAndroid Build Coastguard Worker
105*6fa2df46SAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
106*6fa2df46SAndroid Build Coastguard Worker }
107*6fa2df46SAndroid Build Coastguard Worker
ParseArguments(int argc,char ** argv)108*6fa2df46SAndroid Build Coastguard Worker CmdArguments ParseArguments(int argc, char** argv) {
109*6fa2df46SAndroid Build Coastguard Worker CmdArguments arguments;
110*6fa2df46SAndroid Build Coastguard Worker bool is_embedded = false;
111*6fa2df46SAndroid Build Coastguard Worker std::string help_arg;
112*6fa2df46SAndroid Build Coastguard Worker
113*6fa2df46SAndroid Build Coastguard Worker while (true) {
114*6fa2df46SAndroid Build Coastguard Worker int option_index = 0;
115*6fa2df46SAndroid Build Coastguard Worker static struct option long_options[] = {{"workload", required_argument, 0, 'w'},
116*6fa2df46SAndroid Build Coastguard Worker {"format", required_argument, 0, 'f'},
117*6fa2df46SAndroid Build Coastguard Worker {"param", required_argument, 0, 'p'},
118*6fa2df46SAndroid Build Coastguard Worker {"log", required_argument, 0, 'l'},
119*6fa2df46SAndroid Build Coastguard Worker {"verbosity", required_argument, 0, 'v'},
120*6fa2df46SAndroid Build Coastguard Worker {"help", optional_argument, 0, 'h'},
121*6fa2df46SAndroid Build Coastguard Worker {0, 0, 0, 0}};
122*6fa2df46SAndroid Build Coastguard Worker
123*6fa2df46SAndroid Build Coastguard Worker int c = getopt_long(argc, argv, "w:f:l:v:p:h::", long_options, &option_index);
124*6fa2df46SAndroid Build Coastguard Worker if (c == -1) break;
125*6fa2df46SAndroid Build Coastguard Worker
126*6fa2df46SAndroid Build Coastguard Worker switch (c) {
127*6fa2df46SAndroid Build Coastguard Worker case 'w':
128*6fa2df46SAndroid Build Coastguard Worker arguments.embedded_benchmark = optarg;
129*6fa2df46SAndroid Build Coastguard Worker is_embedded = true;
130*6fa2df46SAndroid Build Coastguard Worker break;
131*6fa2df46SAndroid Build Coastguard Worker case 'f':
132*6fa2df46SAndroid Build Coastguard Worker arguments.results_output = ArgToResultsOutput(optarg);
133*6fa2df46SAndroid Build Coastguard Worker break;
134*6fa2df46SAndroid Build Coastguard Worker case 'l':
135*6fa2df46SAndroid Build Coastguard Worker dittosuite::Logger::GetInstance().SetLogStream(ArgToLogStream(optarg));
136*6fa2df46SAndroid Build Coastguard Worker break;
137*6fa2df46SAndroid Build Coastguard Worker case 'v':
138*6fa2df46SAndroid Build Coastguard Worker dittosuite::Logger::GetInstance().SetLogLevel(ArgToLogLevel(optarg));
139*6fa2df46SAndroid Build Coastguard Worker break;
140*6fa2df46SAndroid Build Coastguard Worker case 'p': {
141*6fa2df46SAndroid Build Coastguard Worker char* token = strtok(optarg, ",");
142*6fa2df46SAndroid Build Coastguard Worker while (token != nullptr) {
143*6fa2df46SAndroid Build Coastguard Worker arguments.parameters.push_back(token);
144*6fa2df46SAndroid Build Coastguard Worker token = strtok(nullptr, ",");
145*6fa2df46SAndroid Build Coastguard Worker }
146*6fa2df46SAndroid Build Coastguard Worker break;
147*6fa2df46SAndroid Build Coastguard Worker }
148*6fa2df46SAndroid Build Coastguard Worker case 'h':
149*6fa2df46SAndroid Build Coastguard Worker if (!optarg && optind < argc // make sure optind is valid
150*6fa2df46SAndroid Build Coastguard Worker && nullptr != argv[optind] // make sure it's not a null string
151*6fa2df46SAndroid Build Coastguard Worker && '\0' != argv[optind][0] // ... or an empty string
152*6fa2df46SAndroid Build Coastguard Worker && '-' != argv[optind][0] // ... or another option
153*6fa2df46SAndroid Build Coastguard Worker ) {
154*6fa2df46SAndroid Build Coastguard Worker help_arg = argv[optind++];
155*6fa2df46SAndroid Build Coastguard Worker }
156*6fa2df46SAndroid Build Coastguard Worker [[fallthrough]];
157*6fa2df46SAndroid Build Coastguard Worker default: {
158*6fa2df46SAndroid Build Coastguard Worker PrintHelpAndExit(argv[0], help_arg);
159*6fa2df46SAndroid Build Coastguard Worker break;
160*6fa2df46SAndroid Build Coastguard Worker }
161*6fa2df46SAndroid Build Coastguard Worker }
162*6fa2df46SAndroid Build Coastguard Worker }
163*6fa2df46SAndroid Build Coastguard Worker
164*6fa2df46SAndroid Build Coastguard Worker if (is_embedded && optind < argc) {
165*6fa2df46SAndroid Build Coastguard Worker LOGE("Unexpected both embedded benchmark and .ditto file");
166*6fa2df46SAndroid Build Coastguard Worker PrintHelpAndExit(argv[0], help_arg);
167*6fa2df46SAndroid Build Coastguard Worker }
168*6fa2df46SAndroid Build Coastguard Worker if (!is_embedded) {
169*6fa2df46SAndroid Build Coastguard Worker if (optind >= argc) {
170*6fa2df46SAndroid Build Coastguard Worker LOGE("Expected either embedded benchmark or .ditto file");
171*6fa2df46SAndroid Build Coastguard Worker PrintHelpAndExit(argv[0], help_arg);
172*6fa2df46SAndroid Build Coastguard Worker } else {
173*6fa2df46SAndroid Build Coastguard Worker arguments.file_path = argv[optind];
174*6fa2df46SAndroid Build Coastguard Worker }
175*6fa2df46SAndroid Build Coastguard Worker }
176*6fa2df46SAndroid Build Coastguard Worker
177*6fa2df46SAndroid Build Coastguard Worker return arguments;
178*6fa2df46SAndroid Build Coastguard Worker }
179*6fa2df46SAndroid Build Coastguard Worker
180*6fa2df46SAndroid Build Coastguard Worker } // namespace dittosuite
181