/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <getopt.h>
#include "VtsCoverageProcessor.h"
#include "VtsTraceProcessor.h"
static constexpr const char* kDefaultMode = "noop";
static constexpr const char* kDefaultOutputFile =
"/temp/vts_trace_processor_output";
using namespace std;
enum mode_code {
// Trace related operations.
CLEANUP_TRACE,
CONVERT_TRACE,
DEDUPE_TRACE,
GET_TEST_LIST_FROM_TRACE,
PARSE_TRACE,
PROFILING_TRACE,
SELECT_TRACE,
// Coverage related operations.
COMPARE_COVERAGE,
GET_COVERGAGE_SUMMARY,
GET_SUBSET_COVERAGE,
MERGE_COVERAGE,
};
mode_code getModeCode(const std::string& str) {
if (str == "cleanup_trace") return mode_code::CLEANUP_TRACE;
if (str == "convert_trace") return mode_code::CONVERT_TRACE;
if (str == "dedup_trace") return mode_code::DEDUPE_TRACE;
if (str == "get_test_list_from_trace")
return mode_code::GET_TEST_LIST_FROM_TRACE;
if (str == "parse_trace") return mode_code::PARSE_TRACE;
if (str == "profiling_trace") return mode_code::PROFILING_TRACE;
if (str == "select_trace") return mode_code::SELECT_TRACE;
if (str == "compare_coverage") return mode_code::COMPARE_COVERAGE;
if (str == "get_coverage_summary") return mode_code::GET_COVERGAGE_SUMMARY;
if (str == "get_subset_coverage") return mode_code::GET_SUBSET_COVERAGE;
if (str == "merge_coverage") return mode_code::MERGE_COVERAGE;
printf("Unknown operation mode: %s\n", str.c_str());
exit(-1);
}
void ShowUsage() {
printf(
"Usage: trace_processor [options] <input>\n"
"--mode: The operation applied to the trace file.\n"
"\t cleanup_trace: cleanup trace for replay (remove duplicate events "
"etc.).\n"
"\t convert_trace: convert a text format trace file into a binary format "
"trace.\n"
"\t dedup_trace: remove duplicate trace file in the given directory. A "
"trace is considered duplicated if there exists a trace that contains "
"the "
"same API call sequence as the given trace and the input parameters for "
"each API call are all the same.\n"
"\t get_test_list_from_trace: parse all trace files under the given "
"directory and create a list of test modules for each hal@version that "
"access all apis covered by the whole test set. (i.e. such list should "
"be a subset of the whole test list that access the corresponding "
"hal@version)\n"
"\t parse_trace: parse the binary format trace file and print the text "
"format trace. \n"
"\t profiling_trace: parse the trace file to get the latency of each api "
"call.\n"
"\t select_trace: select a subset of trace files from a give trace set "
"based on their corresponding coverage data, the goal is to pick up the "
"minimal num of trace files that to maximize the total coverage.\n"
"\t compare_coverage: compare a coverage report with a reference "
"coverage report and print the additional file/lines covered.\n"
"\t get_coverage_summary: print the summary of the coverage file (e.g. "
"covered lines, total lines, coverage rate.) \n"
"\t get_subset_coverage: extract coverage measurement from coverage "
"report for files covered in the reference coverage report. It is used "
"in cases when we have an aggregated coverage report for all files but "
"are only interested in the coverage measurement of a subset of files in "
"that report.\n"
"\t merge_coverage: merge all coverage reports under the given directory "
"and generate a merged report.\n"
"--output: The file path to store the output results.\n"
"--help: Show help\n");
exit(-1);
}
int main(int argc, char** argv) {
string mode = kDefaultMode;
string output = kDefaultOutputFile;
bool verbose_output = false;
android::vts::VtsCoverageProcessor coverage_processor;
android::vts::VtsTraceProcessor trace_processor(&coverage_processor);
const char* const short_opts = "hm:o:v:";
const option long_opts[] = {
{"help", no_argument, nullptr, 'h'},
{"mode", required_argument, nullptr, 'm'},
{"output", required_argument, nullptr, 'o'},
{"verbose", no_argument, nullptr, 'v'},
{nullptr, 0, nullptr, 0},
};
while (true) {
int opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);
if (opt == -1) {
break;
}
switch (opt) {
case 'h':
case '?':
ShowUsage();
return 0;
case 'm': {
mode = string(optarg);
break;
}
case 'o': {
output = string(optarg);
break;
}
case 'v': {
verbose_output = true;
break;
}
default:
printf("getopt_long returned unexpected value: %d\n", opt);
return -1;
}
}
if (optind == argc - 1) {
string trace_path = argv[optind];
switch (getModeCode(mode)) {
case mode_code::CLEANUP_TRACE:
trace_processor.CleanupTraces(trace_path);
break;
case mode_code::CONVERT_TRACE:
trace_processor.ConvertTrace(trace_path);
break;
case mode_code::DEDUPE_TRACE:
trace_processor.DedupTraces(trace_path);
break;
case mode_code::GET_TEST_LIST_FROM_TRACE:
trace_processor.GetTestListForHal(trace_path, output, verbose_output);
break;
case mode_code::PARSE_TRACE:
trace_processor.ParseTrace(trace_path);
break;
case mode_code::PROFILING_TRACE:
trace_processor.ProcessTraceForLatencyProfiling(trace_path);
break;
case mode_code::GET_COVERGAGE_SUMMARY:
coverage_processor.GetCoverageSummary(trace_path);
break;
case mode_code::MERGE_COVERAGE:
coverage_processor.MergeCoverage(trace_path, output);
break;
default:
printf("Invalid argument.");
return -1;
}
} else if (optind == argc - 2) {
switch (getModeCode(mode)) {
case mode_code::SELECT_TRACE: {
string coverage_dir = argv[optind];
string trace_dir = argv[optind + 1];
trace_processor.SelectTraces(coverage_dir, trace_dir);
break;
}
case mode_code::COMPARE_COVERAGE: {
string ref_coverage_path = argv[optind];
string coverage_path = argv[optind + 1];
coverage_processor.CompareCoverage(ref_coverage_path, coverage_path);
break;
}
case mode_code::GET_SUBSET_COVERAGE: {
string ref_coverage_path = argv[optind];
string coverage_path = argv[optind + 1];
coverage_processor.GetSubsetCoverage(ref_coverage_path, coverage_path,
output);
break;
}
default:
printf("Invalid argument.");
return -1;
}
}
return 0;
}