1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <getopt.h>
17 
18 #include "VtsCoverageProcessor.h"
19 #include "VtsTraceProcessor.h"
20 
21 static constexpr const char* kDefaultMode = "noop";
22 static constexpr const char* kDefaultOutputFile =
23     "/temp/vts_trace_processor_output";
24 
25 using namespace std;
26 
27 enum mode_code {
28   // Trace related operations.
29   CLEANUP_TRACE,
30   CONVERT_TRACE,
31   DEDUPE_TRACE,
32   GET_TEST_LIST_FROM_TRACE,
33   PARSE_TRACE,
34   PROFILING_TRACE,
35   SELECT_TRACE,
36   // Coverage related operations.
37   COMPARE_COVERAGE,
38   GET_COVERGAGE_SUMMARY,
39   GET_SUBSET_COVERAGE,
40   MERGE_COVERAGE,
41 };
42 
getModeCode(const std::string & str)43 mode_code getModeCode(const std::string& str) {
44   if (str == "cleanup_trace") return mode_code::CLEANUP_TRACE;
45   if (str == "convert_trace") return mode_code::CONVERT_TRACE;
46   if (str == "dedup_trace") return mode_code::DEDUPE_TRACE;
47   if (str == "get_test_list_from_trace")
48     return mode_code::GET_TEST_LIST_FROM_TRACE;
49   if (str == "parse_trace") return mode_code::PARSE_TRACE;
50   if (str == "profiling_trace") return mode_code::PROFILING_TRACE;
51   if (str == "select_trace") return mode_code::SELECT_TRACE;
52   if (str == "compare_coverage") return mode_code::COMPARE_COVERAGE;
53   if (str == "get_coverage_summary") return mode_code::GET_COVERGAGE_SUMMARY;
54   if (str == "get_subset_coverage") return mode_code::GET_SUBSET_COVERAGE;
55   if (str == "merge_coverage") return mode_code::MERGE_COVERAGE;
56   printf("Unknown operation mode: %s\n", str.c_str());
57   exit(-1);
58 }
59 
ShowUsage()60 void ShowUsage() {
61   printf(
62       "Usage:   trace_processor [options] <input>\n"
63       "--mode:  The operation applied to the trace file.\n"
64       "\t cleanup_trace: cleanup trace for replay (remove duplicate events "
65       "etc.).\n"
66       "\t convert_trace: convert a text format trace file into a binary format "
67       "trace.\n"
68       "\t dedup_trace: remove duplicate trace file in the given directory. A "
69       "trace is considered duplicated if there exists a trace that contains "
70       "the "
71       "same API call sequence as the given trace and the input parameters for "
72       "each API call are all the same.\n"
73       "\t get_test_list_from_trace: parse all trace files under the given "
74       "directory and create a list of test modules for each hal@version that "
75       "access all apis covered by the whole test set. (i.e. such list should "
76       "be a subset of the whole test list that access the corresponding "
77       "hal@version)\n"
78       "\t parse_trace: parse the binary format trace file and print the text "
79       "format trace. \n"
80       "\t profiling_trace: parse the trace file to get the latency of each api "
81       "call.\n"
82       "\t select_trace: select a subset of trace files from a give trace set "
83       "based on their corresponding coverage data, the goal is to pick up the "
84       "minimal num of trace files that to maximize the total coverage.\n"
85       "\t compare_coverage: compare a coverage report with a reference "
86       "coverage report and print the additional file/lines covered.\n"
87       "\t get_coverage_summary: print the summary of the coverage file (e.g. "
88       "covered lines, total lines, coverage rate.) \n"
89       "\t get_subset_coverage: extract coverage measurement from coverage "
90       "report for files covered in the reference coverage report. It is used "
91       "in cases when we have an aggregated coverage report for all files but "
92       "are only interested in the coverage measurement of a subset of files in "
93       "that report.\n"
94       "\t merge_coverage: merge all coverage reports under the given directory "
95       "and generate a merged report.\n"
96       "--output: The file path to store the output results.\n"
97       "--help:   Show help\n");
98   exit(-1);
99 }
100 
main(int argc,char ** argv)101 int main(int argc, char** argv) {
102   string mode = kDefaultMode;
103   string output = kDefaultOutputFile;
104   bool verbose_output = false;
105 
106   android::vts::VtsCoverageProcessor coverage_processor;
107   android::vts::VtsTraceProcessor trace_processor(&coverage_processor);
108 
109   const char* const short_opts = "hm:o:v:";
110   const option long_opts[] = {
111       {"help", no_argument, nullptr, 'h'},
112       {"mode", required_argument, nullptr, 'm'},
113       {"output", required_argument, nullptr, 'o'},
114       {"verbose", no_argument, nullptr, 'v'},
115       {nullptr, 0, nullptr, 0},
116   };
117 
118   while (true) {
119     int opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);
120     if (opt == -1) {
121       break;
122     }
123     switch (opt) {
124       case 'h':
125       case '?':
126         ShowUsage();
127         return 0;
128       case 'm': {
129         mode = string(optarg);
130         break;
131       }
132       case 'o': {
133         output = string(optarg);
134         break;
135       }
136       case 'v': {
137         verbose_output = true;
138         break;
139       }
140       default:
141         printf("getopt_long returned unexpected value: %d\n", opt);
142         return -1;
143     }
144   }
145 
146   if (optind == argc - 1) {
147     string trace_path = argv[optind];
148     switch (getModeCode(mode)) {
149       case mode_code::CLEANUP_TRACE:
150         trace_processor.CleanupTraces(trace_path);
151         break;
152       case mode_code::CONVERT_TRACE:
153         trace_processor.ConvertTrace(trace_path);
154         break;
155       case mode_code::DEDUPE_TRACE:
156         trace_processor.DedupTraces(trace_path);
157         break;
158       case mode_code::GET_TEST_LIST_FROM_TRACE:
159         trace_processor.GetTestListForHal(trace_path, output, verbose_output);
160         break;
161       case mode_code::PARSE_TRACE:
162         trace_processor.ParseTrace(trace_path);
163         break;
164       case mode_code::PROFILING_TRACE:
165         trace_processor.ProcessTraceForLatencyProfiling(trace_path);
166         break;
167       case mode_code::GET_COVERGAGE_SUMMARY:
168         coverage_processor.GetCoverageSummary(trace_path);
169         break;
170       case mode_code::MERGE_COVERAGE:
171         coverage_processor.MergeCoverage(trace_path, output);
172         break;
173       default:
174         printf("Invalid argument.");
175         return -1;
176     }
177   } else if (optind == argc - 2) {
178     switch (getModeCode(mode)) {
179       case mode_code::SELECT_TRACE: {
180         string coverage_dir = argv[optind];
181         string trace_dir = argv[optind + 1];
182         trace_processor.SelectTraces(coverage_dir, trace_dir);
183         break;
184       }
185       case mode_code::COMPARE_COVERAGE: {
186         string ref_coverage_path = argv[optind];
187         string coverage_path = argv[optind + 1];
188         coverage_processor.CompareCoverage(ref_coverage_path, coverage_path);
189         break;
190       }
191       case mode_code::GET_SUBSET_COVERAGE: {
192         string ref_coverage_path = argv[optind];
193         string coverage_path = argv[optind + 1];
194         coverage_processor.GetSubsetCoverage(ref_coverage_path, coverage_path,
195                                              output);
196         break;
197       }
198       default:
199         printf("Invalid argument.");
200         return -1;
201     }
202   }
203   return 0;
204 }
205