Coverage for /Syzygy/grinder/grinder_app.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
79.3%65820.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/grinder/grinder_app.h"
  16    :  
  17    :  #include "base/file_util.h"
  18    :  #include "base/logging.h"
  19    :  #include "base/string_util.h"
  20    :  #include "base/stringprintf.h"
  21    :  #include "syzygy/grinder/grinders/basic_block_entry_count_grinder.h"
  22    :  #include "syzygy/grinder/grinders/coverage_grinder.h"
  23    :  #include "syzygy/grinder/grinders/profile_grinder.h"
  24    :  
  25    :  namespace grinder {
  26    :  
  27    :  namespace {
  28    :  
  29    :  const char kUsageFormatStr[] =
  30    :      "Usage: %ls <trace files> [options]\n"
  31    :      "\n"
  32    :      "  A tool that parses trace files and produces summary output.\n"
  33    :      "\n"
  34    :      "  In 'profile' mode it outputs KCacheGrind-compatible output files for\n"
  35    :      "  visualization.\n"
  36    :      "\n"
  37    :      "  In 'coverage' mode it outputs GCOV/LCOV-compatible or\n"
  38    :      "  KCacheGrind-compatible output files for further processing with code\n"
  39    :      "  coverage or line profiler visualization tools.\n"
  40    :      "\n"
  41    :      "Required parameters\n"
  42    :      "  --mode=<mode>\n"
  43    :      "    The processing mode. Must be one of 'bbentry', 'coverage' or \n"
  44    :      "    or 'profile'.\n"
  45    :      "Optional parameters\n"
  46    :      "  --output-file=<output file>\n"
  47    :      "    The location of output file. If not specified, output is to stdout.\n"
  48    :      "coverage mode optional parameters\n"
  49    :      "  --output-format=<output format>\n"
  50    :      "    Output format must be one of 'lcov' or 'cachegrind'. Defaults to\n"
  51    :      "    'lcov' if not explicitly specified.\n"
  52    :      "profile mode optional parameters\n"
  53    :      "  --thread-parts\n"
  54    :      "    Aggregate and output separate parts for each thread seen in the\n"
  55    :      "    trace files.\n";
  56    :  
  57    :  }  // namespace
  58    :  
  59  E :  GrinderApp::GrinderApp() : common::AppImplBase("Grinder"), mode_(kProfile) {
  60  E :  }
  61    :  
  62    :  void GrinderApp::PrintUsage(const base::FilePath& program,
  63  E :                              const base::StringPiece& message) {
  64  E :    if (!message.empty()) {
  65  E :      ::fwrite(message.data(), 1, message.length(), out());
  66  E :      ::fprintf(out(), "\n\n");
  67    :    }
  68    :  
  69  E :    ::fprintf(out(), kUsageFormatStr, program.BaseName().value().c_str());
  70  E :  }
  71    :  
  72  E :  bool GrinderApp::ParseCommandLine(const CommandLine* command_line) {
  73  E :    DCHECK(command_line != NULL);
  74    :  
  75  E :    CommandLine::StringVector args = command_line->GetArgs();
  76  E :    if (args.empty()) {
  77    :      PrintUsage(command_line->GetProgram(),
  78  E :                 "You must provide at least one trace file.");
  79  E :      return false;
  80    :    }
  81    :  
  82  E :    if (!command_line->HasSwitch("mode")) {
  83    :      PrintUsage(command_line->GetProgram(),
  84  E :                 "You must specify the processing mode.");
  85  E :      return false;
  86    :    }
  87    :  
  88  E :    for (size_t i = 0; i < args.size(); ++i) {
  89  E :      if (!AppendMatchingPaths(base::FilePath(args[i]), &trace_files_)) {
  90    :        PrintUsage(command_line->GetProgram(),
  91  i :                   base::StringPrintf("No such file '%ws'.", args[i].c_str()));
  92  i :        return false;
  93    :      }
  94  E :    }
  95    :  
  96    :    // Parse the processing mode.
  97  E :    std::string mode = command_line->GetSwitchValueASCII("mode");
  98  E :    if (LowerCaseEqualsASCII(mode, "profile")) {
  99  E :      mode_ = kProfile;
 100  E :      grinder_.reset(new grinders::ProfileGrinder());
 101  E :    } else if (LowerCaseEqualsASCII(mode, "coverage")) {
 102  E :      mode_ = kCoverage;
 103  E :      grinder_.reset(new grinders::CoverageGrinder());
 104  E :    } else if (LowerCaseEqualsASCII(mode, "bbentry")) {
 105  E :      mode_ = kBasicBlockEntry;
 106  E :      grinder_.reset(new grinders::BasicBlockEntryCountGrinder());
 107  E :    } else {
 108    :      PrintUsage(command_line->GetProgram(),
 109  i :                 base::StringPrintf("Unknown mode: %s.", mode.c_str()));
 110  i :      return false;
 111    :    }
 112  E :    DCHECK(grinder_.get() != NULL);
 113    :  
 114    :    // Parse the command-line for the grinder.
 115  E :    if (!grinder_->ParseCommandLine(command_line)) {
 116    :      PrintUsage(command_line->GetProgram(),
 117    :                 base::StringPrintf("Failed to parse %s parameters.",
 118  i :                                    mode.c_str()));
 119  i :      return false;
 120    :    }
 121    :  
 122  E :    output_file_ = command_line->GetSwitchValuePath("output-file");
 123    :  
 124  E :    return true;
 125  E :  }
 126    :  
 127  E :  int GrinderApp::Run() {
 128  E :    DCHECK(grinder_.get() != NULL);
 129    :  
 130  E :    trace::parser::Parser parser;
 131  E :    grinder_->SetParser(&parser);
 132  E :    if (!parser.Init(grinder_.get()))
 133  i :      return 1;
 134    :  
 135    :    // Open the input files.
 136  E :    for (size_t i = 0; i < trace_files_.size(); ++i) {
 137  E :      if (!parser.OpenTraceFile(trace_files_[i])) {
 138  i :        LOG(ERROR) << "Unable to open trace file \'"
 139    :                   << trace_files_[i].value() << "'";
 140  i :        return 1;
 141    :      }
 142  E :    }
 143    :  
 144    :    // Open the output file. We do this early so as to fail before processing
 145    :    // the logs if the output is not able to be opened.
 146  E :    FILE* output = out();
 147  E :    file_util::ScopedFILE auto_close;
 148  E :    if (!output_file_.empty()) {
 149  E :      output = file_util::OpenFile(output_file_, "w");
 150  E :      if (output == NULL) {
 151  i :        LOG(ERROR) << "Unable to create output file \'"
 152    :                   << output_file_.value() << "'";
 153  i :        return 1;
 154    :      }
 155    :  
 156  E :      auto_close.reset(output);
 157    :    }
 158    :  
 159  E :    LOG(INFO) << "Parsing trace files.";
 160  E :    if (!parser.Consume()) {
 161  i :      LOG(ERROR) << "Error parsing trace files.";
 162  i :      return 1;
 163    :    }
 164    :  
 165  E :    LOG(INFO) << "Aggregating data.";
 166  E :    if (!grinder_->Grind()) {
 167  i :      LOG(ERROR) << "Failed to grind data.";
 168  i :      return 1;
 169    :    }
 170    :  
 171  E :    std::wstring output_name(L"stdout");
 172  E :    if (!output_file_.empty())
 173  E :      output_name = base::StringPrintf(L"\"%ls\"", output_file_.value().c_str());
 174  E :    LOG(INFO) << "Writing output to " << output_name << ".";
 175  E :    DCHECK(output != NULL);
 176  E :    if (!grinder_->OutputData(output)) {
 177  i :      LOG(ERROR) << "Failed to output data.";
 178  i :      return 1;
 179    :    }
 180    :  
 181  E :    return 0;
 182  E :  }
 183    :  
 184  E :  void GrinderApp::TearDown() {
 185    :    // Release the grinder so it has a chance to clean up before COM goes away.
 186  E :    grinder_.reset();
 187  E :  }
 188    :  
 189    :  }  // namespace grinder

Coverage information generated Thu Jul 04 09:34:53 2013.