205 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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;
 | |
| }
 |