| 1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "flutter/fml/command_line.h" |
| 6 | |
| 7 | #include <string_view> |
| 8 | #include <utility> |
| 9 | |
| 10 | #include "flutter/fml/macros.h" |
| 11 | #include "flutter/fml/size.h" |
| 12 | #include "gtest/gtest.h" |
| 13 | |
| 14 | namespace fml { |
| 15 | namespace { |
| 16 | |
| 17 | TEST(CommandLineTest, Basic) { |
| 18 | // Making this const verifies that the methods called are const. |
| 19 | const auto cl = CommandLineFromInitializerList( |
| 20 | argv: {"my_program" , "--flag1" , "--flag2=value2" , "arg1" , "arg2" , "arg3" }); |
| 21 | |
| 22 | EXPECT_TRUE(cl.has_argv0()); |
| 23 | EXPECT_EQ("my_program" , cl.argv0()); |
| 24 | |
| 25 | EXPECT_EQ(2u, cl.options().size()); |
| 26 | EXPECT_EQ("flag1" , cl.options()[0].name); |
| 27 | EXPECT_EQ(std::string(), cl.options()[0].value); |
| 28 | EXPECT_EQ("flag2" , cl.options()[1].name); |
| 29 | EXPECT_EQ("value2" , cl.options()[1].value); |
| 30 | |
| 31 | EXPECT_EQ(3u, cl.positional_args().size()); |
| 32 | EXPECT_EQ("arg1" , cl.positional_args()[0]); |
| 33 | EXPECT_EQ("arg2" , cl.positional_args()[1]); |
| 34 | EXPECT_EQ("arg3" , cl.positional_args()[2]); |
| 35 | |
| 36 | EXPECT_TRUE(cl.HasOption("flag1" )); |
| 37 | EXPECT_TRUE(cl.HasOption("flag1" , nullptr)); |
| 38 | size_t index = static_cast<size_t>(-1); |
| 39 | EXPECT_TRUE(cl.HasOption("flag2" , &index)); |
| 40 | EXPECT_EQ(1u, index); |
| 41 | EXPECT_FALSE(cl.HasOption("flag3" )); |
| 42 | EXPECT_FALSE(cl.HasOption("flag3" , nullptr)); |
| 43 | |
| 44 | std::string value = "nonempty" ; |
| 45 | EXPECT_TRUE(cl.GetOptionValue("flag1" , &value)); |
| 46 | EXPECT_EQ(std::string(), value); |
| 47 | EXPECT_TRUE(cl.GetOptionValue("flag2" , &value)); |
| 48 | EXPECT_EQ("value2" , value); |
| 49 | EXPECT_FALSE(cl.GetOptionValue("flag3" , &value)); |
| 50 | |
| 51 | EXPECT_EQ(std::string(), cl.GetOptionValueWithDefault("flag1" , "nope" )); |
| 52 | EXPECT_EQ("value2" , cl.GetOptionValueWithDefault("flag2" , "nope" )); |
| 53 | EXPECT_EQ("nope" , cl.GetOptionValueWithDefault("flag3" , "nope" )); |
| 54 | } |
| 55 | |
| 56 | TEST(CommandLineTest, DefaultConstructor) { |
| 57 | CommandLine cl; |
| 58 | EXPECT_FALSE(cl.has_argv0()); |
| 59 | EXPECT_EQ(std::string(), cl.argv0()); |
| 60 | EXPECT_EQ(std::vector<CommandLine::Option>(), cl.options()); |
| 61 | EXPECT_EQ(std::vector<std::string>(), cl.positional_args()); |
| 62 | } |
| 63 | |
| 64 | TEST(CommandLineTest, ComponentConstructor) { |
| 65 | const std::string argv0 = "my_program" ; |
| 66 | const std::vector<CommandLine::Option> options = { |
| 67 | CommandLine::Option("flag" , "value" )}; |
| 68 | const std::vector<std::string> positional_args = {"arg" }; |
| 69 | |
| 70 | CommandLine cl(argv0, options, positional_args); |
| 71 | EXPECT_TRUE(cl.has_argv0()); |
| 72 | EXPECT_EQ(argv0, cl.argv0()); |
| 73 | EXPECT_EQ(options, cl.options()); |
| 74 | EXPECT_EQ(positional_args, cl.positional_args()); |
| 75 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 76 | } |
| 77 | |
| 78 | TEST(CommandLineTest, CommandLineFromIteratorsFindFirstPositionalArg) { |
| 79 | // This shows how one might process subcommands. |
| 80 | { |
| 81 | static std::vector<std::string> argv = {"my_program" , "--flag1" , |
| 82 | "--flag2" , "subcommand" , |
| 83 | "--subflag" , "subarg" }; |
| 84 | auto first = argv.cbegin(); |
| 85 | auto last = argv.cend(); |
| 86 | std::vector<std::string>::const_iterator sub_first; |
| 87 | auto cl = |
| 88 | CommandLineFromIteratorsFindFirstPositionalArg(first, last, first_positional_arg: &sub_first); |
| 89 | EXPECT_TRUE(cl.has_argv0()); |
| 90 | EXPECT_EQ(argv[0], cl.argv0()); |
| 91 | std::vector<CommandLine::Option> expected_options = { |
| 92 | CommandLine::Option("flag1" ), CommandLine::Option("flag2" )}; |
| 93 | EXPECT_EQ(expected_options, cl.options()); |
| 94 | std::vector<std::string> expected_positional_args = {argv[3], argv[4], |
| 95 | argv[5]}; |
| 96 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 97 | EXPECT_TRUE(cl.HasOption("flag1" , nullptr)); |
| 98 | EXPECT_TRUE(cl.HasOption("flag2" , nullptr)); |
| 99 | EXPECT_FALSE(cl.HasOption("subflag" , nullptr)); |
| 100 | |
| 101 | EXPECT_EQ(first + 3, sub_first); |
| 102 | auto sub_cl = CommandLineFromIterators(first: sub_first, last); |
| 103 | EXPECT_TRUE(sub_cl.has_argv0()); |
| 104 | EXPECT_EQ(argv[3], sub_cl.argv0()); |
| 105 | std::vector<CommandLine::Option> expected_sub_options = { |
| 106 | CommandLine::Option("subflag" )}; |
| 107 | EXPECT_EQ(expected_sub_options, sub_cl.options()); |
| 108 | std::vector<std::string> expected_sub_positional_args = {argv[5]}; |
| 109 | EXPECT_EQ(expected_sub_positional_args, sub_cl.positional_args()); |
| 110 | EXPECT_FALSE(sub_cl.HasOption("flag1" , nullptr)); |
| 111 | EXPECT_FALSE(sub_cl.HasOption("flag2" , nullptr)); |
| 112 | EXPECT_TRUE(sub_cl.HasOption("subflag" , nullptr)); |
| 113 | } |
| 114 | |
| 115 | // No positional argument. |
| 116 | { |
| 117 | static std::vector<std::string> argv = {"my_program" , "--flag" }; |
| 118 | std::vector<std::string>::const_iterator sub_first; |
| 119 | auto cl = CommandLineFromIteratorsFindFirstPositionalArg( |
| 120 | first: argv.cbegin(), last: argv.cend(), first_positional_arg: &sub_first); |
| 121 | EXPECT_EQ(argv.cend(), sub_first); |
| 122 | } |
| 123 | |
| 124 | // Multiple positional arguments. |
| 125 | { |
| 126 | static std::vector<std::string> argv = {"my_program" , "arg1" , "arg2" }; |
| 127 | std::vector<std::string>::const_iterator sub_first; |
| 128 | auto cl = CommandLineFromIteratorsFindFirstPositionalArg( |
| 129 | first: argv.cbegin(), last: argv.cend(), first_positional_arg: &sub_first); |
| 130 | EXPECT_EQ(argv.cbegin() + 1, sub_first); |
| 131 | } |
| 132 | |
| 133 | // "--". |
| 134 | { |
| 135 | static std::vector<std::string> argv = {"my_program" , "--" , "--arg" }; |
| 136 | std::vector<std::string>::const_iterator sub_first; |
| 137 | auto cl = CommandLineFromIteratorsFindFirstPositionalArg( |
| 138 | first: argv.cbegin(), last: argv.cend(), first_positional_arg: &sub_first); |
| 139 | EXPECT_EQ(argv.cbegin() + 2, sub_first); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | TEST(CommandLineTest, CommmandLineFromIterators) { |
| 144 | { |
| 145 | // Note (here and below): The |const| ensures that the factory method can |
| 146 | // accept const iterators. |
| 147 | const std::vector<std::string> argv = {"my_program" , "--flag=value" , "arg" }; |
| 148 | |
| 149 | auto cl = CommandLineFromIterators(first: argv.begin(), last: argv.end()); |
| 150 | EXPECT_TRUE(cl.has_argv0()); |
| 151 | EXPECT_EQ(argv[0], cl.argv0()); |
| 152 | std::vector<CommandLine::Option> expected_options = { |
| 153 | CommandLine::Option("flag" , "value" )}; |
| 154 | EXPECT_EQ(expected_options, cl.options()); |
| 155 | std::vector<std::string> expected_positional_args = {argv[2]}; |
| 156 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 157 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 158 | } |
| 159 | |
| 160 | // Can handle empty argv. |
| 161 | { |
| 162 | const std::vector<std::string> argv; |
| 163 | |
| 164 | auto cl = CommandLineFromIterators(first: argv.begin(), last: argv.end()); |
| 165 | EXPECT_FALSE(cl.has_argv0()); |
| 166 | EXPECT_EQ(std::string(), cl.argv0()); |
| 167 | EXPECT_EQ(std::vector<CommandLine::Option>(), cl.options()); |
| 168 | EXPECT_EQ(std::vector<std::string>(), cl.positional_args()); |
| 169 | } |
| 170 | |
| 171 | // Can handle empty |argv[0]|. |
| 172 | { |
| 173 | const std::vector<std::string> argv = {"" }; |
| 174 | |
| 175 | auto cl = CommandLineFromIterators(first: argv.begin(), last: argv.end()); |
| 176 | EXPECT_TRUE(cl.has_argv0()); |
| 177 | EXPECT_EQ(std::string(), cl.argv0()); |
| 178 | EXPECT_EQ(std::vector<CommandLine::Option>(), cl.options()); |
| 179 | EXPECT_EQ(std::vector<std::string>(), cl.positional_args()); |
| 180 | } |
| 181 | |
| 182 | // Can also take a vector of |const char*|s. |
| 183 | { |
| 184 | const std::vector<const char*> argv = {"my_program" , "--flag=value" , "arg" }; |
| 185 | |
| 186 | auto cl = CommandLineFromIterators(first: argv.begin(), last: argv.end()); |
| 187 | EXPECT_TRUE(cl.has_argv0()); |
| 188 | EXPECT_EQ(argv[0], cl.argv0()); |
| 189 | std::vector<CommandLine::Option> expected_options = { |
| 190 | CommandLine::Option("flag" , "value" )}; |
| 191 | EXPECT_EQ(expected_options, cl.options()); |
| 192 | std::vector<std::string> expected_positional_args = {argv[2]}; |
| 193 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 194 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 195 | } |
| 196 | |
| 197 | // Or a plain old array. |
| 198 | { |
| 199 | static const char* const argv[] = {"my_program" , "--flag=value" , "arg" }; |
| 200 | |
| 201 | auto cl = CommandLineFromIterators(first: argv, last: argv + fml::size(array: argv)); |
| 202 | EXPECT_TRUE(cl.has_argv0()); |
| 203 | EXPECT_EQ(argv[0], cl.argv0()); |
| 204 | std::vector<CommandLine::Option> expected_options = { |
| 205 | CommandLine::Option("flag" , "value" )}; |
| 206 | EXPECT_EQ(expected_options, cl.options()); |
| 207 | std::vector<std::string> expected_positional_args = {argv[2]}; |
| 208 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 209 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | TEST(CommandLineTest, CommandLineFromArgcArgv) { |
| 214 | static const char* const argv[] = {"my_program" , "--flag=value" , "arg" }; |
| 215 | const int argc = static_cast<int>(fml::size(array: argv)); |
| 216 | |
| 217 | auto cl = CommandLineFromArgcArgv(argc, argv); |
| 218 | EXPECT_TRUE(cl.has_argv0()); |
| 219 | EXPECT_EQ(argv[0], cl.argv0()); |
| 220 | std::vector<CommandLine::Option> expected_options = { |
| 221 | CommandLine::Option("flag" , "value" )}; |
| 222 | EXPECT_EQ(expected_options, cl.options()); |
| 223 | std::vector<std::string> expected_positional_args = {argv[2]}; |
| 224 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 225 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 226 | } |
| 227 | |
| 228 | TEST(CommandLineTest, CommandLineFromInitializerList) { |
| 229 | { |
| 230 | std::initializer_list<const char*> il = {"my_program" , "--flag=value" , |
| 231 | "arg" }; |
| 232 | auto cl = CommandLineFromInitializerList(argv: il); |
| 233 | EXPECT_TRUE(cl.has_argv0()); |
| 234 | EXPECT_EQ("my_program" , cl.argv0()); |
| 235 | std::vector<CommandLine::Option> expected_options = { |
| 236 | CommandLine::Option("flag" , "value" )}; |
| 237 | EXPECT_EQ(expected_options, cl.options()); |
| 238 | std::vector<std::string> expected_positional_args = {"arg" }; |
| 239 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 240 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 241 | } |
| 242 | |
| 243 | { |
| 244 | std::initializer_list<std::string> il = {"my_program" , "--flag=value" , |
| 245 | "arg" }; |
| 246 | auto cl = CommandLineFromInitializerList(argv: il); |
| 247 | EXPECT_TRUE(cl.has_argv0()); |
| 248 | EXPECT_EQ("my_program" , cl.argv0()); |
| 249 | std::vector<CommandLine::Option> expected_options = { |
| 250 | CommandLine::Option("flag" , "value" )}; |
| 251 | EXPECT_EQ(expected_options, cl.options()); |
| 252 | std::vector<std::string> expected_positional_args = {"arg" }; |
| 253 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 254 | EXPECT_EQ("value" , cl.GetOptionValueWithDefault("flag" , "nope" )); |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | TEST(CommandLineTest, OddArguments) { |
| 259 | { |
| 260 | // Except for "arg", these are all options. |
| 261 | auto cl = CommandLineFromInitializerList( |
| 262 | argv: {"my_program" , "--=" , "--=foo" , "--bar=" , "--==" , "--===" , "--==x" , |
| 263 | "arg" }); |
| 264 | EXPECT_TRUE(cl.has_argv0()); |
| 265 | EXPECT_EQ("my_program" , cl.argv0()); |
| 266 | std::vector<CommandLine::Option> expected_options = { |
| 267 | CommandLine::Option("=" ), CommandLine::Option("=foo" ), |
| 268 | CommandLine::Option("bar" ), CommandLine::Option("=" ), |
| 269 | CommandLine::Option("=" , "=" ), CommandLine::Option("=" , "x" )}; |
| 270 | EXPECT_EQ(expected_options, cl.options()); |
| 271 | std::vector<std::string> expected_positional_args = {"arg" }; |
| 272 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 273 | } |
| 274 | |
| 275 | // "-x" is an argument, not an options. |
| 276 | { |
| 277 | auto cl = CommandLineFromInitializerList(argv: {"" , "-x" }); |
| 278 | EXPECT_TRUE(cl.has_argv0()); |
| 279 | EXPECT_EQ(std::string(), cl.argv0()); |
| 280 | EXPECT_EQ(std::vector<CommandLine::Option>(), cl.options()); |
| 281 | std::vector<std::string> expected_positional_args = {"-x" }; |
| 282 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 283 | } |
| 284 | |
| 285 | // Ditto for "-". |
| 286 | { |
| 287 | auto cl = CommandLineFromInitializerList(argv: {"" , "-" }); |
| 288 | EXPECT_TRUE(cl.has_argv0()); |
| 289 | EXPECT_EQ(std::string(), cl.argv0()); |
| 290 | EXPECT_EQ(std::vector<CommandLine::Option>(), cl.options()); |
| 291 | std::vector<std::string> expected_positional_args = {"-" }; |
| 292 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 293 | } |
| 294 | |
| 295 | // "--" terminates option processing, but isn't an argument in the first |
| 296 | // occurrence. |
| 297 | { |
| 298 | auto cl = CommandLineFromInitializerList( |
| 299 | argv: {"" , "--flag=value" , "--" , "--not-a-flag" , "arg" , "--" }); |
| 300 | EXPECT_TRUE(cl.has_argv0()); |
| 301 | EXPECT_EQ(std::string(), cl.argv0()); |
| 302 | std::vector<CommandLine::Option> expected_options = { |
| 303 | CommandLine::Option("flag" , "value" )}; |
| 304 | std::vector<std::string> expected_positional_args = {"--not-a-flag" , "arg" , |
| 305 | "--" }; |
| 306 | EXPECT_EQ(expected_positional_args, cl.positional_args()); |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | TEST(CommandLineTest, MultipleOccurrencesOfOption) { |
| 311 | auto cl = CommandLineFromInitializerList( |
| 312 | argv: {"my_program" , "--flag1=value1" , "--flag2=value2" , "--flag1=value3" }); |
| 313 | std::vector<CommandLine::Option> expected_options = { |
| 314 | CommandLine::Option("flag1" , "value1" ), |
| 315 | CommandLine::Option("flag2" , "value2" ), |
| 316 | CommandLine::Option("flag1" , "value3" )}; |
| 317 | EXPECT_EQ("value3" , cl.GetOptionValueWithDefault("flag1" , "nope" )); |
| 318 | EXPECT_EQ("value2" , cl.GetOptionValueWithDefault("flag2" , "nope" )); |
| 319 | std::vector<std::string_view> values = cl.GetOptionValues(name: "flag1" ); |
| 320 | ASSERT_EQ(2u, values.size()); |
| 321 | EXPECT_EQ("value1" , values[0]); |
| 322 | EXPECT_EQ("value3" , values[1]); |
| 323 | } |
| 324 | |
| 325 | // |cl1| and |cl2| should be not equal. |
| 326 | void ExpectNotEqual(const char* message, |
| 327 | std::initializer_list<std::string> c1, |
| 328 | std::initializer_list<std::string> c2) { |
| 329 | SCOPED_TRACE(message); |
| 330 | |
| 331 | const auto cl1 = CommandLineFromInitializerList(argv: c1); |
| 332 | const auto cl2 = CommandLineFromInitializerList(argv: c2); |
| 333 | |
| 334 | // These are tautological. |
| 335 | EXPECT_TRUE(cl1 == cl1); |
| 336 | EXPECT_FALSE(cl1 != cl1); |
| 337 | EXPECT_TRUE(cl2 == cl2); |
| 338 | EXPECT_FALSE(cl2 != cl2); |
| 339 | |
| 340 | // These rely on |cl1| not being equal to |cl2|. |
| 341 | EXPECT_FALSE(cl1 == cl2); |
| 342 | EXPECT_TRUE(cl1 != cl2); |
| 343 | EXPECT_FALSE(cl2 == cl1); |
| 344 | EXPECT_TRUE(cl2 != cl1); |
| 345 | } |
| 346 | |
| 347 | void ExpectEqual(const char* message, |
| 348 | std::initializer_list<std::string> c1, |
| 349 | std::initializer_list<std::string> c2) { |
| 350 | SCOPED_TRACE(message); |
| 351 | |
| 352 | const auto cl1 = CommandLineFromInitializerList(argv: c1); |
| 353 | const auto cl2 = CommandLineFromInitializerList(argv: c2); |
| 354 | |
| 355 | // These are tautological. |
| 356 | EXPECT_TRUE(cl1 == cl1); |
| 357 | EXPECT_FALSE(cl1 != cl1); |
| 358 | EXPECT_TRUE(cl2 == cl2); |
| 359 | EXPECT_FALSE(cl2 != cl2); |
| 360 | |
| 361 | // These rely on |cl1| being equal to |cl2|. |
| 362 | EXPECT_TRUE(cl1 == cl2); |
| 363 | EXPECT_FALSE(cl1 != cl2); |
| 364 | EXPECT_TRUE(cl2 == cl1); |
| 365 | EXPECT_FALSE(cl2 != cl1); |
| 366 | } |
| 367 | |
| 368 | TEST(CommandLineTest, ComparisonOperators) { |
| 369 | ExpectNotEqual(message: "1" , c1: {}, c2: {"" }); |
| 370 | ExpectNotEqual(message: "2" , c1: {"abc" }, c2: {"def" }); |
| 371 | ExpectNotEqual(message: "3" , c1: {"abc" , "--flag" }, c2: {"abc" }); |
| 372 | ExpectNotEqual(message: "4" , c1: {"abc" , "--flag1" }, c2: {"abc" , "--flag2" }); |
| 373 | ExpectNotEqual(message: "5" , c1: {"abc" , "--flag1" , "--flag2" }, c2: {"abc" , "--flag1" }); |
| 374 | ExpectNotEqual(message: "6" , c1: {"abc" , "arg" }, c2: {"abc" }); |
| 375 | ExpectNotEqual(message: "7" , c1: {"abc" , "arg1" }, c2: {"abc" , "arg2" }); |
| 376 | ExpectNotEqual(message: "8" , c1: {"abc" , "arg1" , "arg2" }, c2: {"abc" , "arg1" }); |
| 377 | ExpectNotEqual(message: "9" , c1: {"abc" , "--flag" , "arg1" }, c2: {"abc" , "--flag" , "arg2" }); |
| 378 | |
| 379 | // However, the presence of an unnecessary "--" shouldn't affect what's |
| 380 | // constructed. |
| 381 | ExpectEqual(message: "10" , c1: {"abc" , "--flag" , "arg" }, c2: {"abc" , "--flag" , "--" , "arg" }); |
| 382 | } |
| 383 | |
| 384 | TEST(CommandLineTest, MoveAndCopy) { |
| 385 | const auto cl = CommandLineFromInitializerList( |
| 386 | argv: {"my_program" , "--flag1=value1" , "--flag2" , "arg" }); |
| 387 | |
| 388 | // Copy constructor. |
| 389 | CommandLine cl2(cl); |
| 390 | EXPECT_EQ(cl, cl2); |
| 391 | // Check that |option_index_| gets copied too. |
| 392 | EXPECT_EQ("value1" , cl2.GetOptionValueWithDefault("flag1" , "nope" )); |
| 393 | |
| 394 | // Move constructor. |
| 395 | CommandLine cl3(std::move(cl2)); |
| 396 | EXPECT_EQ(cl, cl3); |
| 397 | EXPECT_EQ("value1" , cl3.GetOptionValueWithDefault("flag1" , "nope" )); |
| 398 | |
| 399 | // Copy assignment. |
| 400 | CommandLine cl4; |
| 401 | EXPECT_NE(cl, cl4); |
| 402 | cl4 = cl; |
| 403 | EXPECT_EQ(cl, cl4); |
| 404 | EXPECT_EQ("value1" , cl4.GetOptionValueWithDefault("flag1" , "nope" )); |
| 405 | |
| 406 | // Move assignment. |
| 407 | CommandLine cl5; |
| 408 | EXPECT_NE(cl, cl5); |
| 409 | cl5 = std::move(cl4); |
| 410 | EXPECT_EQ(cl, cl5); |
| 411 | EXPECT_EQ("value1" , cl5.GetOptionValueWithDefault("flag1" , "nope" )); |
| 412 | } |
| 413 | |
| 414 | void ToArgvHelper(const char* message, std::initializer_list<std::string> c) { |
| 415 | SCOPED_TRACE(message); |
| 416 | std::vector<std::string> argv = c; |
| 417 | auto cl = CommandLineFromInitializerList(argv: c); |
| 418 | EXPECT_EQ(argv, CommandLineToArgv(cl)); |
| 419 | } |
| 420 | |
| 421 | TEST(CommandLineTest, CommandLineToArgv) { |
| 422 | ToArgvHelper(message: "1" , c: {}); |
| 423 | ToArgvHelper(message: "2" , c: {"" }); |
| 424 | ToArgvHelper(message: "3" , c: {"my_program" }); |
| 425 | ToArgvHelper(message: "4" , c: {"my_program" , "--flag" }); |
| 426 | ToArgvHelper(message: "5" , c: {"my_program" , "--flag1" , "--flag2=value" }); |
| 427 | ToArgvHelper(message: "6" , c: {"my_program" , "arg" }); |
| 428 | ToArgvHelper(message: "7" , c: {"my_program" , "arg1" , "arg2" }); |
| 429 | ToArgvHelper(message: "8" , c: {"my_program" , "--flag1" , "--flag2=value" , "arg1" , "arg2" }); |
| 430 | ToArgvHelper(message: "9" , c: {"my_program" , "--flag" , "--" , "--not-a-flag" }); |
| 431 | ToArgvHelper(message: "10" , c: {"my_program" , "--flag" , "arg" , "--" }); |
| 432 | |
| 433 | // However, |CommandLineToArgv()| will "strip" an unneeded "--". |
| 434 | { |
| 435 | auto cl = CommandLineFromInitializerList(argv: {"my_program" , "--" }); |
| 436 | std::vector<std::string> argv = {"my_program" }; |
| 437 | EXPECT_EQ(argv, CommandLineToArgv(cl)); |
| 438 | } |
| 439 | { |
| 440 | auto cl = |
| 441 | CommandLineFromInitializerList(argv: {"my_program" , "--flag" , "--" , "arg" }); |
| 442 | std::vector<std::string> argv = {"my_program" , "--flag" , "arg" }; |
| 443 | EXPECT_EQ(argv, CommandLineToArgv(cl)); |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | } // namespace |
| 448 | } // namespace fml |
| 449 | |