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