• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
InputOk(const std::string & value) const35   bool InputOk(const std::string& value) const {
36     return value.length() > 0;
37   }
38 };
39 
InputBuilder(const std::string & title,const InputValidator * input_validator,const OverrideRegistry & override_registry)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 
~InputBuilder()47 InputBuilder::~InputBuilder() {
48   delete input_validator_;
49 }
50 
AskForInput() const51 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 
ActuallyAskUser() const61 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 
WithInputSource(FILE * input_source)87 InputBuilder& InputBuilder::WithInputSource(FILE* input_source) {
88   input_source_ = input_source;
89   return *this;
90 }
91 
WithInputValidator(const InputValidator * input_validator)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 
WithDefault(const std::string & default_value)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 
WithAdditionalInfo(const std::string & info)107 InputBuilder& InputBuilder::WithAdditionalInfo(const std::string& info) {
108   additional_info_ = info;
109   return *this;
110 }
111 
GetOverride() const112 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 
OverrideRegistry(const std::string & overrides)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 
HasOverrideFor(const std::string & title) const137 bool OverrideRegistry::HasOverrideFor(const std::string& title) const {
138   return overrides_.find(title) != overrides_.end();
139 }
140 
GetOverrideFor(const std::string & title) const141 const std::string& OverrideRegistry::GetOverrideFor(
142     const std::string& title) const {
143   assert(HasOverrideFor(title));
144   return (*overrides_.find(title)).second;
145 }
146 
TypedInput(const std::string & title)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 
Split(const std::string & to_split,const std::string & delimiter)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