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