Commit 30c2e327d1b2ba67eefd3019d5f9bc660685a316
Committed by
Henry Schreiner
1 parent
3a2c5112
Add single string parsing (#186)
* add Tests and ability to handle program file inclusion in the single string. add the ability to deal with a single string in the parse command and handle quoted string appropriately * Add extra test cases for full coverage, clear up escape quote sequencing and handling of extra spaces
Showing
7 changed files
with
306 additions
and
30 deletions
include/CLI/App.hpp
| @@ -1167,6 +1167,58 @@ class App { | @@ -1167,6 +1167,58 @@ class App { | ||
| 1167 | parse(args); | 1167 | parse(args); |
| 1168 | } | 1168 | } |
| 1169 | 1169 | ||
| 1170 | + /// parse a single string as if it contained command line arguments | ||
| 1171 | + /// this function splits the string into arguments then calls parse(std::vector<std::string> &) | ||
| 1172 | + /// the function takes an optional boolean argument specifying if the programName is included in the string to | ||
| 1173 | + /// process | ||
| 1174 | + void parse(std::string commandline, bool ProgramNameIncluded = false) { | ||
| 1175 | + detail::trim(commandline); | ||
| 1176 | + if(ProgramNameIncluded) { | ||
| 1177 | + // try to determine the programName | ||
| 1178 | + auto esp = commandline.find_first_of(' ', 1); | ||
| 1179 | + while(!ExistingFile(commandline.substr(0, esp)).empty()) { | ||
| 1180 | + esp = commandline.find_first_of(' ', esp + 1); | ||
| 1181 | + if(esp == std::string::npos) { | ||
| 1182 | + // if we have reached the end and haven't found a valid file just assume the first argument is the | ||
| 1183 | + // program name | ||
| 1184 | + esp = commandline.find_first_of(' ', 1); | ||
| 1185 | + break; | ||
| 1186 | + } | ||
| 1187 | + } | ||
| 1188 | + if(name_.empty()) { | ||
| 1189 | + name_ = commandline.substr(0, esp); | ||
| 1190 | + detail::rtrim(name_); | ||
| 1191 | + } | ||
| 1192 | + // strip the program name | ||
| 1193 | + commandline = commandline.substr(esp + 1); | ||
| 1194 | + } | ||
| 1195 | + // the first section of code is to deal with quoted arguments after and '=' | ||
| 1196 | + if(!commandline.empty()) { | ||
| 1197 | + size_t offset = commandline.length() - 1; | ||
| 1198 | + auto qeq = commandline.find_last_of('=', offset); | ||
| 1199 | + while(qeq != std::string::npos) { | ||
| 1200 | + if((commandline[qeq + 1] == '\"') || (commandline[qeq + 1] == '\'') || (commandline[qeq + 1] == '`')) { | ||
| 1201 | + auto astart = commandline.find_last_of("- \"\'`", qeq - 1); | ||
| 1202 | + if(astart != std::string::npos) { | ||
| 1203 | + if(commandline[astart] == '-') { | ||
| 1204 | + commandline[qeq] = ' '; // interpret this a space so the split_up works properly | ||
| 1205 | + offset = (astart == 0) ? 0 : (astart - 1); | ||
| 1206 | + } | ||
| 1207 | + } | ||
| 1208 | + } | ||
| 1209 | + offset = qeq - 1; | ||
| 1210 | + qeq = commandline.find_last_of('=', offset); | ||
| 1211 | + } | ||
| 1212 | + } | ||
| 1213 | + | ||
| 1214 | + auto args = detail::split_up(std::move(commandline)); | ||
| 1215 | + // remove all empty strings | ||
| 1216 | + args.erase(std::remove(args.begin(), args.end(), std::string()), args.end()); | ||
| 1217 | + std::reverse(args.begin(), args.end()); | ||
| 1218 | + | ||
| 1219 | + parse(args); | ||
| 1220 | + } | ||
| 1221 | + | ||
| 1170 | /// The real work is done here. Expects a reversed vector. | 1222 | /// The real work is done here. Expects a reversed vector. |
| 1171 | /// Changes the vector to the remaining options. | 1223 | /// Changes the vector to the remaining options. |
| 1172 | void parse(std::vector<std::string> &args) { | 1224 | void parse(std::vector<std::string> &args) { |
include/CLI/StringTools.hpp
| @@ -148,27 +148,38 @@ inline std::string remove_underscore(std::string str) { | @@ -148,27 +148,38 @@ inline std::string remove_underscore(std::string str) { | ||
| 148 | return str; | 148 | return str; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | +/// Find and replace a substring with another substring | ||
| 152 | +inline std::string find_and_replace(std::string str, std::string from, std::string to) { | ||
| 153 | + | ||
| 154 | + size_t start_pos = 0; | ||
| 155 | + | ||
| 156 | + while((start_pos = str.find(from, start_pos)) != std::string::npos) { | ||
| 157 | + str.replace(start_pos, from.length(), to); | ||
| 158 | + start_pos += to.length(); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + return str; | ||
| 162 | +} | ||
| 163 | + | ||
| 151 | /// Split a string '"one two" "three"' into 'one two', 'three' | 164 | /// Split a string '"one two" "three"' into 'one two', 'three' |
| 165 | +/// Quote characters can be ` ' or " | ||
| 152 | inline std::vector<std::string> split_up(std::string str) { | 166 | inline std::vector<std::string> split_up(std::string str) { |
| 153 | 167 | ||
| 154 | - std::vector<char> delims = {'\'', '\"'}; | 168 | + const std::string delims("\'\"`"); |
| 155 | auto find_ws = [](char ch) { return std::isspace<char>(ch, std::locale()); }; | 169 | auto find_ws = [](char ch) { return std::isspace<char>(ch, std::locale()); }; |
| 156 | trim(str); | 170 | trim(str); |
| 157 | 171 | ||
| 158 | std::vector<std::string> output; | 172 | std::vector<std::string> output; |
| 159 | - | 173 | + bool embeddedQuote = false; |
| 174 | + char keyChar = ' '; | ||
| 160 | while(!str.empty()) { | 175 | while(!str.empty()) { |
| 161 | - if(str[0] == '\'') { | ||
| 162 | - auto end = str.find('\'', 1); | ||
| 163 | - if(end != std::string::npos) { | ||
| 164 | - output.push_back(str.substr(1, end - 1)); | ||
| 165 | - str = str.substr(end + 1); | ||
| 166 | - } else { | ||
| 167 | - output.push_back(str.substr(1)); | ||
| 168 | - str = ""; | 176 | + if(delims.find_first_of(str[0]) != std::string::npos) { |
| 177 | + keyChar = str[0]; | ||
| 178 | + auto end = str.find_first_of(keyChar, 1); | ||
| 179 | + while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes | ||
| 180 | + end = str.find_first_of(keyChar, end + 1); | ||
| 181 | + embeddedQuote = true; | ||
| 169 | } | 182 | } |
| 170 | - } else if(str[0] == '\"') { | ||
| 171 | - auto end = str.find('\"', 1); | ||
| 172 | if(end != std::string::npos) { | 183 | if(end != std::string::npos) { |
| 173 | output.push_back(str.substr(1, end - 1)); | 184 | output.push_back(str.substr(1, end - 1)); |
| 174 | str = str.substr(end + 1); | 185 | str = str.substr(end + 1); |
| @@ -176,7 +187,6 @@ inline std::vector<std::string> split_up(std::string str) { | @@ -176,7 +187,6 @@ inline std::vector<std::string> split_up(std::string str) { | ||
| 176 | output.push_back(str.substr(1)); | 187 | output.push_back(str.substr(1)); |
| 177 | str = ""; | 188 | str = ""; |
| 178 | } | 189 | } |
| 179 | - | ||
| 180 | } else { | 190 | } else { |
| 181 | auto it = std::find_if(std::begin(str), std::end(str), find_ws); | 191 | auto it = std::find_if(std::begin(str), std::end(str), find_ws); |
| 182 | if(it != std::end(str)) { | 192 | if(it != std::end(str)) { |
| @@ -188,9 +198,13 @@ inline std::vector<std::string> split_up(std::string str) { | @@ -188,9 +198,13 @@ inline std::vector<std::string> split_up(std::string str) { | ||
| 188 | str = ""; | 198 | str = ""; |
| 189 | } | 199 | } |
| 190 | } | 200 | } |
| 201 | + // transform any embedded quotes into the regular character | ||
| 202 | + if(embeddedQuote) { | ||
| 203 | + output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar)); | ||
| 204 | + embeddedQuote = false; | ||
| 205 | + } | ||
| 191 | trim(str); | 206 | trim(str); |
| 192 | } | 207 | } |
| 193 | - | ||
| 194 | return output; | 208 | return output; |
| 195 | } | 209 | } |
| 196 | 210 | ||
| @@ -210,18 +224,5 @@ inline std::string fix_newlines(std::string leader, std::string input) { | @@ -210,18 +224,5 @@ inline std::string fix_newlines(std::string leader, std::string input) { | ||
| 210 | return input; | 224 | return input; |
| 211 | } | 225 | } |
| 212 | 226 | ||
| 213 | -/// Find and replace a subtring with another substring | ||
| 214 | -inline std::string find_and_replace(std::string str, std::string from, std::string to) { | ||
| 215 | - | ||
| 216 | - size_t start_pos = 0; | ||
| 217 | - | ||
| 218 | - while((start_pos = str.find(from, start_pos)) != std::string::npos) { | ||
| 219 | - str.replace(start_pos, from.length(), to); | ||
| 220 | - start_pos += to.length(); | ||
| 221 | - } | ||
| 222 | - | ||
| 223 | - return str; | ||
| 224 | -} | ||
| 225 | - | ||
| 226 | } // namespace detail | 227 | } // namespace detail |
| 227 | } // namespace CLI | 228 | } // namespace CLI |
tests/AppTest.cpp
| @@ -38,6 +38,18 @@ TEST_F(TApp, DashedOptions) { | @@ -38,6 +38,18 @@ TEST_F(TApp, DashedOptions) { | ||
| 38 | EXPECT_EQ((size_t)2, app.count("--that")); | 38 | EXPECT_EQ((size_t)2, app.count("--that")); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | +TEST_F(TApp, DashedOptionsSingleString) { | ||
| 42 | + app.add_flag("-c"); | ||
| 43 | + app.add_flag("--q"); | ||
| 44 | + app.add_flag("--this,--that"); | ||
| 45 | + | ||
| 46 | + app.parse("-c --q --this --that"); | ||
| 47 | + EXPECT_EQ((size_t)1, app.count("-c")); | ||
| 48 | + EXPECT_EQ((size_t)1, app.count("--q")); | ||
| 49 | + EXPECT_EQ((size_t)2, app.count("--this")); | ||
| 50 | + EXPECT_EQ((size_t)2, app.count("--that")); | ||
| 51 | +} | ||
| 52 | + | ||
| 41 | TEST_F(TApp, OneFlagRef) { | 53 | TEST_F(TApp, OneFlagRef) { |
| 42 | int ref; | 54 | int ref; |
| 43 | app.add_flag("-c,--count", ref); | 55 | app.add_flag("-c,--count", ref); |
| @@ -58,6 +70,16 @@ TEST_F(TApp, OneString) { | @@ -58,6 +70,16 @@ TEST_F(TApp, OneString) { | ||
| 58 | EXPECT_EQ(str, "mystring"); | 70 | EXPECT_EQ(str, "mystring"); |
| 59 | } | 71 | } |
| 60 | 72 | ||
| 73 | +TEST_F(TApp, OneStringSingleStringInput) { | ||
| 74 | + std::string str; | ||
| 75 | + app.add_option("-s,--string", str); | ||
| 76 | + | ||
| 77 | + app.parse("--string mystring"); | ||
| 78 | + EXPECT_EQ((size_t)1, app.count("-s")); | ||
| 79 | + EXPECT_EQ((size_t)1, app.count("--string")); | ||
| 80 | + EXPECT_EQ(str, "mystring"); | ||
| 81 | +} | ||
| 82 | + | ||
| 61 | TEST_F(TApp, OneStringEqualVersion) { | 83 | TEST_F(TApp, OneStringEqualVersion) { |
| 62 | std::string str; | 84 | std::string str; |
| 63 | app.add_option("-s,--string", str); | 85 | app.add_option("-s,--string", str); |
| @@ -68,6 +90,84 @@ TEST_F(TApp, OneStringEqualVersion) { | @@ -68,6 +90,84 @@ TEST_F(TApp, OneStringEqualVersion) { | ||
| 68 | EXPECT_EQ(str, "mystring"); | 90 | EXPECT_EQ(str, "mystring"); |
| 69 | } | 91 | } |
| 70 | 92 | ||
| 93 | +TEST_F(TApp, OneStringEqualVersionSingleString) { | ||
| 94 | + std::string str; | ||
| 95 | + app.add_option("-s,--string", str); | ||
| 96 | + app.parse("--string=mystring"); | ||
| 97 | + EXPECT_EQ((size_t)1, app.count("-s")); | ||
| 98 | + EXPECT_EQ((size_t)1, app.count("--string")); | ||
| 99 | + EXPECT_EQ(str, "mystring"); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuoted) { | ||
| 103 | + std::string str; | ||
| 104 | + app.add_option("-s,--string", str); | ||
| 105 | + app.parse("--string=\"this is my quoted string\""); | ||
| 106 | + EXPECT_EQ((size_t)1, app.count("-s")); | ||
| 107 | + EXPECT_EQ((size_t)1, app.count("--string")); | ||
| 108 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuotedMultiple) { | ||
| 112 | + std::string str, str2, str3; | ||
| 113 | + app.add_option("-s,--string", str); | ||
| 114 | + app.add_option("-t,--tstr", str2); | ||
| 115 | + app.add_option("-m,--mstr", str3); | ||
| 116 | + app.parse("--string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"`"); | ||
| 117 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 118 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 119 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 120 | +} | ||
| 121 | + | ||
| 122 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuotedMultipleInMiddle) { | ||
| 123 | + std::string str, str2, str3; | ||
| 124 | + app.add_option("-s,--string", str); | ||
| 125 | + app.add_option("-t,--tstr", str2); | ||
| 126 | + app.add_option("-m,--mstr", str3); | ||
| 127 | + app.parse(R"raw(--string="this is my quoted string" -t "qst\"ring 2" -m=`"quoted string"`")raw"); | ||
| 128 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 129 | + EXPECT_EQ(str2, "qst\"ring 2"); | ||
| 130 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuotedEscapedCharacters) { | ||
| 134 | + std::string str, str2, str3; | ||
| 135 | + app.add_option("-s,--string", str); | ||
| 136 | + app.add_option("-t,--tstr", str2); | ||
| 137 | + app.add_option("-m,--mstr", str3); | ||
| 138 | + app.parse(R"raw(--string="this is my \"quoted\" string" -t 'qst\'ring 2' -m=`"quoted\` string"`")raw"); | ||
| 139 | + EXPECT_EQ(str, "this is my \"quoted\" string"); | ||
| 140 | + EXPECT_EQ(str2, "qst\'ring 2"); | ||
| 141 | + EXPECT_EQ(str3, "\"quoted` string\""); | ||
| 142 | +} | ||
| 143 | + | ||
| 144 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuotedMultipleWithEqual) { | ||
| 145 | + std::string str, str2, str3, str4; | ||
| 146 | + app.add_option("-s,--string", str); | ||
| 147 | + app.add_option("-t,--tstr", str2); | ||
| 148 | + app.add_option("-m,--mstr", str3); | ||
| 149 | + app.add_option("-j,--jstr", str4); | ||
| 150 | + app.parse("--string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"` --jstr=Unquoted"); | ||
| 151 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 152 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 153 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 154 | + EXPECT_EQ(str4, "Unquoted"); | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +TEST_F(TApp, OneStringEqualVersionSingleStringQuotedMultipleWithEqualAndProgram) { | ||
| 158 | + std::string str, str2, str3, str4; | ||
| 159 | + app.add_option("-s,--string", str); | ||
| 160 | + app.add_option("-t,--tstr", str2); | ||
| 161 | + app.add_option("-m,--mstr", str3); | ||
| 162 | + app.add_option("-j,--jstr", str4); | ||
| 163 | + app.parse("program --string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"` --jstr=Unquoted", | ||
| 164 | + true); | ||
| 165 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 166 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 167 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 168 | + EXPECT_EQ(str4, "Unquoted"); | ||
| 169 | +} | ||
| 170 | + | ||
| 71 | TEST_F(TApp, TogetherInt) { | 171 | TEST_F(TApp, TogetherInt) { |
| 72 | int i; | 172 | int i; |
| 73 | app.add_option("-i,--int", i); | 173 | app.add_option("-i,--int", i); |
| @@ -107,6 +207,15 @@ TEST_F(TApp, DefaultStringAgain) { | @@ -107,6 +207,15 @@ TEST_F(TApp, DefaultStringAgain) { | ||
| 107 | EXPECT_EQ(str, "previous"); | 207 | EXPECT_EQ(str, "previous"); |
| 108 | } | 208 | } |
| 109 | 209 | ||
| 210 | +TEST_F(TApp, DefaultStringAgainEmpty) { | ||
| 211 | + std::string str = "previous"; | ||
| 212 | + app.add_option("-s,--string", str); | ||
| 213 | + app.parse(" "); | ||
| 214 | + EXPECT_EQ((size_t)0, app.count("-s")); | ||
| 215 | + EXPECT_EQ((size_t)0, app.count("--string")); | ||
| 216 | + EXPECT_EQ(str, "previous"); | ||
| 217 | +} | ||
| 218 | + | ||
| 110 | TEST_F(TApp, DualOptions) { | 219 | TEST_F(TApp, DualOptions) { |
| 111 | 220 | ||
| 112 | std::string str = "previous"; | 221 | std::string str = "previous"; |
| @@ -136,6 +245,30 @@ TEST_F(TApp, LotsOfFlags) { | @@ -136,6 +245,30 @@ TEST_F(TApp, LotsOfFlags) { | ||
| 136 | EXPECT_EQ((size_t)1, app.count("-A")); | 245 | EXPECT_EQ((size_t)1, app.count("-A")); |
| 137 | } | 246 | } |
| 138 | 247 | ||
| 248 | +TEST_F(TApp, LotsOfFlagsSingleString) { | ||
| 249 | + | ||
| 250 | + app.add_flag("-a"); | ||
| 251 | + app.add_flag("-A"); | ||
| 252 | + app.add_flag("-b"); | ||
| 253 | + | ||
| 254 | + app.parse("-a -b -aA"); | ||
| 255 | + EXPECT_EQ((size_t)2, app.count("-a")); | ||
| 256 | + EXPECT_EQ((size_t)1, app.count("-b")); | ||
| 257 | + EXPECT_EQ((size_t)1, app.count("-A")); | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +TEST_F(TApp, LotsOfFlagsSingleStringExtraSpace) { | ||
| 261 | + | ||
| 262 | + app.add_flag("-a"); | ||
| 263 | + app.add_flag("-A"); | ||
| 264 | + app.add_flag("-b"); | ||
| 265 | + | ||
| 266 | + app.parse(" -a -b -aA "); | ||
| 267 | + EXPECT_EQ((size_t)2, app.count("-a")); | ||
| 268 | + EXPECT_EQ((size_t)1, app.count("-b")); | ||
| 269 | + EXPECT_EQ((size_t)1, app.count("-A")); | ||
| 270 | +} | ||
| 271 | + | ||
| 139 | TEST_F(TApp, BoolAndIntFlags) { | 272 | TEST_F(TApp, BoolAndIntFlags) { |
| 140 | 273 | ||
| 141 | bool bflag; | 274 | bool bflag; |
| @@ -686,7 +819,7 @@ TEST_F(TApp, CallbackFlags) { | @@ -686,7 +819,7 @@ TEST_F(TApp, CallbackFlags) { | ||
| 686 | EXPECT_THROW(app.add_flag_function("hi", func), CLI::IncorrectConstruction); | 819 | EXPECT_THROW(app.add_flag_function("hi", func), CLI::IncorrectConstruction); |
| 687 | } | 820 | } |
| 688 | 821 | ||
| 689 | -#if __cplusplus >= 201402L | 822 | +#if __cplusplus >= 201402L || _MSC_VER >= 1900 |
| 690 | TEST_F(TApp, CallbackFlagsAuto) { | 823 | TEST_F(TApp, CallbackFlagsAuto) { |
| 691 | 824 | ||
| 692 | size_t value = 0; | 825 | size_t value = 0; |
| @@ -1381,7 +1514,7 @@ TEST_F(TApp, RangeDouble) { | @@ -1381,7 +1514,7 @@ TEST_F(TApp, RangeDouble) { | ||
| 1381 | run(); | 1514 | run(); |
| 1382 | } | 1515 | } |
| 1383 | 1516 | ||
| 1384 | -// Check to make sure progromatic access to left over is available | 1517 | +// Check to make sure programmatic access to left over is available |
| 1385 | TEST_F(TApp, AllowExtras) { | 1518 | TEST_F(TApp, AllowExtras) { |
| 1386 | 1519 | ||
| 1387 | app.allow_extras(); | 1520 | app.allow_extras(); |
tests/CMakeLists.txt
tests/HelpersTest.cpp
| @@ -356,6 +356,20 @@ TEST(SplitUp, Simple) { | @@ -356,6 +356,20 @@ TEST(SplitUp, Simple) { | ||
| 356 | EXPECT_EQ(oput, result); | 356 | EXPECT_EQ(oput, result); |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | +TEST(SplitUp, SimpleDifferentQuotes) { | ||
| 360 | + std::vector<std::string> oput = {"one", "two three"}; | ||
| 361 | + std::string orig{R"(one `two three`)"}; | ||
| 362 | + std::vector<std::string> result = CLI::detail::split_up(orig); | ||
| 363 | + EXPECT_EQ(oput, result); | ||
| 364 | +} | ||
| 365 | + | ||
| 366 | +TEST(SplitUp, SimpleDifferentQuotes2) { | ||
| 367 | + std::vector<std::string> oput = {"one", "two three"}; | ||
| 368 | + std::string orig{R"(one 'two three')"}; | ||
| 369 | + std::vector<std::string> result = CLI::detail::split_up(orig); | ||
| 370 | + EXPECT_EQ(oput, result); | ||
| 371 | +} | ||
| 372 | + | ||
| 359 | TEST(SplitUp, Layered) { | 373 | TEST(SplitUp, Layered) { |
| 360 | std::vector<std::string> output = {R"(one 'two three')"}; | 374 | std::vector<std::string> output = {R"(one 'two three')"}; |
| 361 | std::string orig{R"("one 'two three'")"}; | 375 | std::string orig{R"("one 'two three'")"}; |
tests/StringParseTest.cpp
0 → 100644
| 1 | +#include "app_helper.hpp" | ||
| 2 | + | ||
| 3 | +#include "gmock/gmock.h" | ||
| 4 | +#include <cstdio> | ||
| 5 | +#include <sstream> | ||
| 6 | + | ||
| 7 | +TEST_F(TApp, ExistingExeCheck) { | ||
| 8 | + | ||
| 9 | + TempFile tmpexe{"existingExe.out"}; | ||
| 10 | + | ||
| 11 | + std::string str, str2, str3; | ||
| 12 | + app.add_option("-s,--string", str); | ||
| 13 | + app.add_option("-t,--tstr", str2); | ||
| 14 | + app.add_option("-m,--mstr", str3); | ||
| 15 | + | ||
| 16 | + { | ||
| 17 | + std::ofstream out{tmpexe}; | ||
| 18 | + out << "useless string doesn't matter" << std::endl; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + app.parse(std::string("./") + std::string(tmpexe) + | ||
| 22 | + " --string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"`", | ||
| 23 | + true); | ||
| 24 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 25 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 26 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +TEST_F(TApp, ExistingExeCheckWithSpace) { | ||
| 30 | + | ||
| 31 | + TempFile tmpexe{"Space File.out"}; | ||
| 32 | + | ||
| 33 | + std::string str, str2, str3; | ||
| 34 | + app.add_option("-s,--string", str); | ||
| 35 | + app.add_option("-t,--tstr", str2); | ||
| 36 | + app.add_option("-m,--mstr", str3); | ||
| 37 | + | ||
| 38 | + { | ||
| 39 | + std::ofstream out{tmpexe}; | ||
| 40 | + out << "useless string doesn't matter" << std::endl; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + app.parse(std::string("./") + std::string(tmpexe) + | ||
| 44 | + " --string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"`", | ||
| 45 | + true); | ||
| 46 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 47 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 48 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 49 | + | ||
| 50 | + EXPECT_EQ(app.get_name(), std::string("./") + std::string(tmpexe)); | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +TEST_F(TApp, ExistingExeCheckWithLotsOfSpace) { | ||
| 54 | + | ||
| 55 | + TempFile tmpexe{"this is a weird file.exe"}; | ||
| 56 | + | ||
| 57 | + std::string str, str2, str3; | ||
| 58 | + app.add_option("-s,--string", str); | ||
| 59 | + app.add_option("-t,--tstr", str2); | ||
| 60 | + app.add_option("-m,--mstr", str3); | ||
| 61 | + | ||
| 62 | + { | ||
| 63 | + std::ofstream out{tmpexe}; | ||
| 64 | + out << "useless string doesn't matter" << std::endl; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + app.parse(std::string("./") + std::string(tmpexe) + | ||
| 68 | + " --string=\"this is my quoted string\" -t 'qstring 2' -m=`\"quoted string\"`", | ||
| 69 | + true); | ||
| 70 | + EXPECT_EQ(str, "this is my quoted string"); | ||
| 71 | + EXPECT_EQ(str2, "qstring 2"); | ||
| 72 | + EXPECT_EQ(str3, "\"quoted string\""); | ||
| 73 | + | ||
| 74 | + EXPECT_EQ(app.get_name(), std::string("./") + std::string(tmpexe)); | ||
| 75 | +} |