Home | History | Annotate | Download | only in primitives
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/video_engine/test/auto_test/primitives/input_helpers.h"
     12 
     13 #include <assert.h>
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 
     17 #include <algorithm>
     18 
     19 #include "gflags/gflags.h"
     20 
     21 namespace webrtc {
     22 
     23 DEFINE_string(override, "",
     24     "Makes it possible to override choices or inputs. All choices and "
     25     "inputs will use their default values unless you override them in this "
     26     "flag's argument. There can be several comma-separated overrides specified:"
     27     " Overrides are specified as \"title=option text\" for choices and "
     28     "\"title=value\" for regular inputs. Note that the program will stop if "
     29     "you provide input not accepted by the input's validator through this flag."
     30     "\n\nExample: --override \"Enter destination IP=192.168.0.1, "
     31     "Select a codec=VP8\"");
     32 
     33 class AcceptAllNonEmptyValidator : public InputValidator {
     34  public:
     35   bool InputOk(const std::string& value) const {
     36     return value.length() > 0;
     37   }
     38 };
     39 
     40 InputBuilder::InputBuilder(const std::string& title,
     41                            const InputValidator* input_validator,
     42                            const OverrideRegistry& override_registry)
     43     : input_source_(stdin), input_validator_(input_validator),
     44       override_registry_(override_registry), default_value_(""), title_(title) {
     45 }
     46 
     47 InputBuilder::~InputBuilder() {
     48   delete input_validator_;
     49 }
     50 
     51 std::string InputBuilder::AskForInput() const {
     52   if (override_registry_.HasOverrideFor(title_))
     53     return GetOverride();
     54   if (!FLAGS_override.empty() && !default_value_.empty())
     55     return default_value_;
     56 
     57   // We don't know the answer already, so ask the user.
     58   return ActuallyAskUser();
     59 }
     60 
     61 std::string InputBuilder::ActuallyAskUser() const {
     62   printf("\n%s%s\n", title_.c_str(), additional_info_.c_str());
     63 
     64   if (!default_value_.empty())
     65     printf("Hit enter for default (%s):\n", default_value_.c_str());
     66 
     67   printf("# ");
     68   char raw_input[128];
     69   if (!fgets(raw_input, 128, input_source_)) {
     70     // If we get here the user probably hit CTRL+D.
     71     exit(1);
     72   }
     73 
     74   std::string input = raw_input;
     75   input = input.substr(0, input.size() - 1);  // Strip last \n.
     76 
     77   if (input.empty() && !default_value_.empty())
     78     return default_value_;
     79 
     80   if (!input_validator_->InputOk(input)) {
     81     printf("Invalid input. Please try again.\n");
     82     return ActuallyAskUser();
     83   }
     84   return input;
     85 }
     86 
     87 InputBuilder& InputBuilder::WithInputSource(FILE* input_source) {
     88   input_source_ = input_source;
     89   return *this;
     90 }
     91 
     92 InputBuilder& InputBuilder::WithInputValidator(
     93     const InputValidator* input_validator) {
     94   // If there's a default value, it must be accepted by the input validator.
     95   assert(default_value_.empty() || input_validator->InputOk(default_value_));
     96   delete input_validator_;
     97   input_validator_ = input_validator;
     98   return *this;
     99 }
    100 
    101 InputBuilder& InputBuilder::WithDefault(const std::string& default_value) {
    102   assert(input_validator_->InputOk(default_value));
    103   default_value_ = default_value;
    104   return *this;
    105 }
    106 
    107 InputBuilder& InputBuilder::WithAdditionalInfo(const std::string& info) {
    108   additional_info_ = info;
    109   return *this;
    110 }
    111 
    112 const std::string& InputBuilder::GetOverride() const {
    113   const std::string& override = override_registry_.GetOverrideFor(title_);
    114   if (!input_validator_->InputOk(override)) {
    115     printf("Fatal: Input validator for \"%s\" does not accept override %s.\n",
    116         title_.c_str(), override.c_str());
    117     exit(1);
    118   }
    119   return override;
    120 }
    121 
    122 OverrideRegistry::OverrideRegistry(const std::string& overrides) {
    123   std::vector<std::string> all_overrides = Split(overrides, ",");
    124   std::vector<std::string>::const_iterator override = all_overrides.begin();
    125   for (; override != all_overrides.end(); ++override) {
    126     std::vector<std::string> key_value = Split(*override, "=");
    127     if (key_value.size() != 2) {
    128       printf("Fatal: Override %s is malformed.", (*override).c_str());
    129       exit(1);
    130     }
    131     std::string key = key_value[0];
    132     std::string value = key_value[1];
    133     overrides_[key] = value;
    134   }
    135 }
    136 
    137 bool OverrideRegistry::HasOverrideFor(const std::string& title) const {
    138   return overrides_.find(title) != overrides_.end();
    139 }
    140 
    141 const std::string& OverrideRegistry::GetOverrideFor(
    142     const std::string& title) const {
    143   assert(HasOverrideFor(title));
    144   return (*overrides_.find(title)).second;
    145 }
    146 
    147 InputBuilder TypedInput(const std::string& title) {
    148   static OverrideRegistry override_registry_(FLAGS_override);
    149   return InputBuilder(
    150       title, new AcceptAllNonEmptyValidator(), override_registry_);
    151 }
    152 
    153 std::vector<std::string> Split(const std::string& to_split,
    154                                const std::string& delimiter) {
    155   std::vector<std::string> result;
    156   size_t current_pos = 0;
    157   size_t next_delimiter = 0;
    158   while ((next_delimiter = to_split.find(delimiter, current_pos)) !=
    159       std::string::npos) {
    160     std::string part = to_split.substr(
    161         current_pos, next_delimiter - current_pos);
    162     result.push_back(part);
    163     current_pos = next_delimiter + 1;
    164   }
    165   std::string last_part = to_split.substr(current_pos);
    166   if (!last_part.empty())
    167     result.push_back(last_part);
    168 
    169   return result;
    170 }
    171 
    172 }  // namespace webrtc
    173