Coverage for /Syzygy/application/application.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%51510.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    :  // Declares a generic command-line application framework.
  16    :  //
  17    :  // An application can be declared as follows in a library:
  18    :  //
  19    :  //     class MyApp : public application::AppImplBase {
  20    :  //      public:
  21    :  //       bool ParseCommandLine(const base::CommandLine* command_line);
  22    :  //       int Run();
  23    :  //      protected:
  24    :  //       bool InternalFunc();
  25    :  //     };
  26    :  //
  27    :  // The application class can then be unit-tested as appropriate. See the
  28    :  // declaration of application::AppImplBase for the entire interface expected
  29    :  // by the application framework. Note that derivation from AppImplBase
  30    :  // is optional, as the integration with the application framework is
  31    :  // by template expansion, not virtual function invocation; AppImplBase
  32    :  // is purely a convenience base class to allow you to elide defining
  33    :  // parts of the interface you don't need to specialize.
  34    :  //
  35    :  // The main() function for the executable can be reduced to:
  36    :  //
  37    :  //     int main(int argc, const char* const* argv) {
  38    :  //       base::AtExitManager at_exit_manager;
  39    :  //       base::CommandLine::Init(argc, argv);
  40    :  //       return application::Application<MyApp>().Run();
  41    :  //     }
  42    :  //
  43    :  // To test how your application implementation interacts with the
  44    :  // application framework. You can run the application directly from
  45    :  // a unittest as follows:
  46    :  //
  47    :  //     TEST(FixtureName, TestName) {
  48    :  //       using application::Application;
  49    :  //
  50    :  //       base::ScopedFILE in(base::OpenFile("NUL", "r"));
  51    :  //       base::ScopedFILE out(base::OpenFile("NUL", "w"));
  52    :  //       base::ScopedFILE err(base::OpenFile("NUL", "w"));
  53    :  //       ASSERT_TRUE(in.get() != NULL);
  54    :  //       ASSERT_TRUE(out.get() != NULL);
  55    :  //       ASSERT_TRUE(err.get() != NULL);
  56    :  //
  57    :  //       base::CommandLine cmd_line(base::FilePath(L"program"));
  58    :  //       Application<MyTestApp, LOG_INIT_NO> test_app(&cmd_line,
  59    :  //                                                    in.get(),
  60    :  //                                                    out.get(),
  61    :  //                                                    err.get());
  62    :  //
  63    :  //       ASSERT_TRUE(test_app.implementation().SomeFunc());
  64    :  //       ASSERT_EQ(0, test_app.Run());
  65    :  //     }
  66    :  //
  67    :  
  68    :  #ifndef SYZYGY_APPLICATION_APPLICATION_H_
  69    :  #define SYZYGY_APPLICATION_APPLICATION_H_
  70    :  
  71    :  #include <objbase.h>
  72    :  #include <vector>
  73    :  
  74    :  #include "base/at_exit.h"
  75    :  #include "base/command_line.h"
  76    :  #include "base/logging.h"
  77    :  #include "base/strings/string_number_conversions.h"
  78    :  #include "base/strings/string_util.h"
  79    :  #include "syzygy/common/com_utils.h"
  80    :  
  81    :  namespace application {
  82    :  
  83    :  // A convenience base class that describes the interface an application
  84    :  // implementation is expected to expose. This class provides empty default
  85    :  // method implementations.
  86    :  //
  87    :  // @note Each method is responsible for logging its own errors as it deems
  88    :  //     appropriate. No log messages are otherwise generated if one of the
  89    :  //     AppImplBase methods returns an error.
  90    :  class AppImplBase {
  91    :   public:
  92    :    // Initializes an application implementation with the standard IO streams.
  93    :    // Use the stream IO accessors to customize the IO streams.
  94    :    // @param name the name of the application.
  95    :    explicit AppImplBase(const base::StringPiece& name);
  96    :  
  97    :    // Parse the given command line in preparation for execution.
  98    :    bool ParseCommandLine(const base::CommandLine* command_line);
  99    :  
 100    :    // A hook called just before Run().
 101    :    bool SetUp();
 102    :  
 103    :    // The main logic for the application implementation.
 104    :    // @returns the exit status for the application.
 105    :    int Run();
 106    :  
 107    :    // A hook called just after Run().
 108    :    void TearDown();
 109    :  
 110    :    // Get the application name.
 111  E :    const std::string& name() const { return name_; }
 112    :  
 113    :    // @name IO Stream Accessors
 114    :    // @{
 115  E :    FILE* in() const { return in_; }
 116  E :    FILE* out() const { return out_; }
 117  E :    FILE* err() const { return err_; }
 118    :  
 119  E :    void set_in(FILE* f) {
 120  E :      DCHECK(f != NULL);
 121  E :      in_ = f;
 122  E :    }
 123    :  
 124  E :    void set_out(FILE* f) {
 125  E :      DCHECK(f != NULL);
 126  E :      out_ = f;
 127  E :    }
 128    :  
 129  E :    void set_err(FILE* f) {
 130  E :      DCHECK(f != NULL);
 131  E :      err_ = f;
 132  E :    }
 133    :    // @}
 134    :  
 135    :    // A helper function to return an absolute path (if possible) for the given
 136    :    // path. If the conversion to an absolute path fails, the original path is
 137    :    // returned.
 138    :    static base::FilePath AbsolutePath(const base::FilePath& path);
 139    :  
 140    :    // A helper function which appends the set of absolute file paths matching
 141    :    // the @p pattern (for example ..\foo\*.bin) to the end of @p matches.
 142    :    // @returns true if at least one matching file was found.
 143    :    static bool AppendMatchingPaths(const base::FilePath& pattern,
 144    :                                    std::vector<base::FilePath>* matches);
 145    :  
 146    :    // A helper function to get a command line parameter that has both a current
 147    :    // and a deprecated name.
 148    :    template <typename ValueType>
 149    :    static bool GetDeprecatedSwitch(
 150    :        const base::CommandLine* cmd_line,
 151    :        const std::string& current_switch_name,
 152    :        const std::string& deprecated_switch_name,
 153    :        ValueType (base::CommandLine::*getter)(const base::StringPiece&) const,
 154  E :        ValueType* value) {
 155  E :      DCHECK(cmd_line != NULL);
 156  E :      DCHECK(getter != NULL);
 157  E :      DCHECK(value != NULL);
 158  E :      if (cmd_line->HasSwitch(deprecated_switch_name)) {
 159  E :        if (cmd_line->HasSwitch(current_switch_name)) {
 160  E :          LOG(ERROR) << "Cannot specify both --" << current_switch_name
 161    :                     << " and --" << deprecated_switch_name << ".";
 162  E :          return false;
 163    :        }
 164  E :        LOG(WARNING)
 165    :            << "Using deprecated switch: --" << deprecated_switch_name << ".";
 166  E :        *value = (cmd_line->*getter)(deprecated_switch_name);
 167  E :      } else {
 168  E :        *value = (cmd_line->*getter)(current_switch_name);
 169    :      }
 170  E :      return true;
 171  E :    }
 172    :  
 173    :   protected:
 174    :    // The name of this application.
 175    :    std::string name_;
 176    :  
 177    :    // @name Standard file streams.
 178    :    // @{
 179    :    FILE* in_;
 180    :    FILE* out_;
 181    :    FILE* err_;
 182    :    // @}
 183    :  };
 184    :  
 185    :  // Flags controlling the initialization of the logging subsystem.
 186    :  enum AppLoggingFlag { INIT_LOGGING_NO, INIT_LOGGING_YES };
 187    :  
 188    :  // The Application template class.
 189    :  //
 190    :  // @tparam Implementation The class which implements the application logic.
 191    :  // @tparam kInitLogging Tracks whether or not the application should
 192    :  //     (re-)initialize the logging subsystem on startup. Under testing,
 193    :  //     for example, one might want to skip initializing the logging
 194    :  //     subsystem.
 195    :  template <typename Impl, AppLoggingFlag kInitLogging = INIT_LOGGING_YES>
 196    :  class Application {
 197    :   public:
 198    :    // The application implementation class.
 199    :    typedef typename Impl Implementation;
 200    :  
 201    :    // Initializes the application with the current processes command line and
 202    :    // the standard IO streams.
 203    :    //
 204    :    // @pre base::CommandLine::Init() has been called prior to the creation of the
 205    :    //     application object.
 206    :    Application();
 207    :  
 208    :    // Accessor for the underlying implementation.
 209  E :    Implementation& implementation() { return implementation_; }
 210    :  
 211    :    // @name Accessors for the command line.
 212    :    // @{
 213  E :    const base::CommandLine* command_line() const { return command_line_; }
 214    :  
 215  E :    void set_command_line(const base::CommandLine* command_line) {
 216  E :      DCHECK(command_line != NULL);
 217  E :      command_line_ = command_line;
 218  E :    }
 219    :    // @}
 220    :  
 221    :    // Get the application name.
 222  E :    const std::string& name() const { return implementation_.name(); }
 223    :  
 224    :    // The main skeleton for actually running an application.
 225    :    // @returns the exit status for the application.
 226    :    int Run();
 227    :  
 228    :    // @name IO Stream Accessors
 229    :    // @{
 230  E :    FILE* in() const { return implementation_.in(); }
 231  E :    FILE* out() const { return implementation_.out(); }
 232  E :    FILE* err() const { return implementation_.err(); }
 233    :  
 234  E :    void set_in(FILE* f) { implementation_.set_in(f); }
 235  E :    void set_out(FILE* f) { implementation_.set_out(f); }
 236  E :    void set_err(FILE* f) { implementation_.set_err(f); }
 237    :    // @}
 238    :  
 239    :   protected:
 240    :    // Initializes the logging subsystem for this application. This includes
 241    :    // checking the command line for the --verbose[=level] flag and handling
 242    :    // it appropriately.
 243    :    bool InitializeLogging();
 244    :  
 245    :    // The command line for this application. The referred instance must outlive
 246    :    // the application instance.
 247    :    const base::CommandLine* command_line_;
 248    :  
 249    :    // The implementation instance for this application. Execution will be
 250    :    // delegated to this object.
 251    :    Implementation implementation_;
 252    :  
 253    :   private:
 254    :    DISALLOW_COPY_AND_ASSIGN(Application);
 255    :  };
 256    :  
 257    :  // A helper class for timing an activity within a scope.
 258    :  class ScopedTimeLogger {
 259    :   public:
 260  E :    explicit ScopedTimeLogger(const char* label)
 261    :        : label_(label), start_(base::Time::Now()) {
 262  E :      DCHECK(label != NULL);
 263  E :      LOG(INFO) << label_ << ".";
 264  E :    }
 265    :  
 266  E :    ~ScopedTimeLogger() {
 267  E :      base::TimeDelta duration = base::Time::Now() - start_;
 268  E :      LOG(INFO) << label_ << " took " << duration.InSecondsF() << " seconds.";
 269  E :    }
 270    :  
 271    :   private:
 272    :    // A labeling phrase for the activity being timed.
 273    :    const char* const label_;
 274    :  
 275    :    // The time at which the activity began.
 276    :    const base::Time start_;
 277    :  };
 278    :  
 279    :  }  // namespace application
 280    :  
 281    :  #include "syzygy/application/application_impl.h"
 282    :  
 283    :  #endif  // SYZYGY_APPLICATION_APPLICATION_H_

Coverage information generated Thu Jan 14 17:40:38 2016.