[M94 Dev][Tizen] Fix for errors for generating ninja files
[platform/framework/web/chromium-efl.git] / base / command_line_unittest.cc
1 // Copyright (c) 2012 The Chromium 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 "base/command_line.h"
6
7 #include <memory>
8 #include <string>
9 #include <vector>
10
11 #include "base/files/file_path.h"
12 #include "base/strings/strcat.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "build/build_config.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19
20 // To test Windows quoting behavior, we use a string that has some backslashes
21 // and quotes.
22 // Consider the command-line argument: q\"bs1\bs2\\bs3q\\\"
23 // Here it is with C-style escapes.
24 static const CommandLine::StringType kTrickyQuoted =
25     FILE_PATH_LITERAL("q\\\"bs1\\bs2\\\\bs3q\\\\\\\"");
26 // It should be parsed by Windows as: q"bs1\bs2\\bs3q\"
27 // Here that is with C-style escapes.
28 static const CommandLine::StringType kTricky =
29     FILE_PATH_LITERAL("q\"bs1\\bs2\\\\bs3q\\\"");
30
31 TEST(CommandLineTest, CommandLineConstructor) {
32   const CommandLine::CharType* argv[] = {
33       FILE_PATH_LITERAL("program"),
34       FILE_PATH_LITERAL("--foo="),
35       FILE_PATH_LITERAL("-bAr"),
36       FILE_PATH_LITERAL("-spaetzel=pierogi"),
37       FILE_PATH_LITERAL("-baz"),
38       FILE_PATH_LITERAL("flim"),
39       FILE_PATH_LITERAL("--other-switches=--dog=canine --cat=feline"),
40       FILE_PATH_LITERAL("-spaetzle=Crepe"),
41       FILE_PATH_LITERAL("-=loosevalue"),
42       FILE_PATH_LITERAL("-"),
43       FILE_PATH_LITERAL("FLAN"),
44       FILE_PATH_LITERAL("a"),
45       FILE_PATH_LITERAL("--input-translation=45--output-rotation"),
46       FILE_PATH_LITERAL("--"),
47       FILE_PATH_LITERAL("--"),
48       FILE_PATH_LITERAL("--not-a-switch"),
49       FILE_PATH_LITERAL("\"in the time of submarines...\""),
50       FILE_PATH_LITERAL("unquoted arg-with-space")};
51   CommandLine cl(size(argv), argv);
52
53   EXPECT_FALSE(cl.GetCommandLineString().empty());
54   EXPECT_FALSE(cl.HasSwitch("cruller"));
55   EXPECT_FALSE(cl.HasSwitch("flim"));
56   EXPECT_FALSE(cl.HasSwitch("program"));
57   EXPECT_FALSE(cl.HasSwitch("dog"));
58   EXPECT_FALSE(cl.HasSwitch("cat"));
59   EXPECT_FALSE(cl.HasSwitch("output-rotation"));
60   EXPECT_FALSE(cl.HasSwitch("not-a-switch"));
61   EXPECT_FALSE(cl.HasSwitch("--"));
62
63   EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")).value(),
64             cl.GetProgram().value());
65
66   EXPECT_TRUE(cl.HasSwitch("foo"));
67 #if defined(OS_WIN)
68   EXPECT_TRUE(cl.HasSwitch("bar"));
69 #else
70   EXPECT_FALSE(cl.HasSwitch("bar"));
71 #endif
72   EXPECT_TRUE(cl.HasSwitch("baz"));
73   EXPECT_TRUE(cl.HasSwitch("spaetzle"));
74   EXPECT_TRUE(cl.HasSwitch("other-switches"));
75   EXPECT_TRUE(cl.HasSwitch("input-translation"));
76
77   EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
78   EXPECT_EQ("", cl.GetSwitchValueASCII("foo"));
79   EXPECT_EQ("", cl.GetSwitchValueASCII("bar"));
80   EXPECT_EQ("", cl.GetSwitchValueASCII("cruller"));
81   EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
82       "other-switches"));
83   EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
84
85   const CommandLine::StringVector& args = cl.GetArgs();
86   ASSERT_EQ(8U, args.size());
87
88   auto iter = args.begin();
89   EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
90   ++iter;
91   EXPECT_EQ(FILE_PATH_LITERAL("-"), *iter);
92   ++iter;
93   EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
94   ++iter;
95   EXPECT_EQ(FILE_PATH_LITERAL("a"), *iter);
96   ++iter;
97   EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
98   ++iter;
99   EXPECT_EQ(FILE_PATH_LITERAL("--not-a-switch"), *iter);
100   ++iter;
101   EXPECT_EQ(FILE_PATH_LITERAL("\"in the time of submarines...\""), *iter);
102   ++iter;
103   EXPECT_EQ(FILE_PATH_LITERAL("unquoted arg-with-space"), *iter);
104   ++iter;
105   EXPECT_TRUE(iter == args.end());
106 }
107
108 TEST(CommandLineTest, CommandLineFromString) {
109 #if defined(OS_WIN)
110   CommandLine cl = CommandLine::FromString(
111       L"program --foo= -bAr  /Spaetzel=pierogi /Baz flim "
112       L"--other-switches=\"--dog=canine --cat=feline\" "
113       L"-spaetzle=Crepe   -=loosevalue  FLAN "
114       L"--input-translation=\"45\"--output-rotation "
115       L"--quotes=" +
116       kTrickyQuoted +
117       L" -- -- --not-a-switch \"in the time of submarines...\"");
118
119   EXPECT_FALSE(cl.GetCommandLineString().empty());
120   EXPECT_FALSE(cl.HasSwitch("cruller"));
121   EXPECT_FALSE(cl.HasSwitch("flim"));
122   EXPECT_FALSE(cl.HasSwitch("program"));
123   EXPECT_FALSE(cl.HasSwitch("dog"));
124   EXPECT_FALSE(cl.HasSwitch("cat"));
125   EXPECT_FALSE(cl.HasSwitch("output-rotation"));
126   EXPECT_FALSE(cl.HasSwitch("not-a-switch"));
127   EXPECT_FALSE(cl.HasSwitch("--"));
128
129   EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")).value(),
130             cl.GetProgram().value());
131
132   EXPECT_TRUE(cl.HasSwitch("foo"));
133   EXPECT_TRUE(cl.HasSwitch("bar"));
134   EXPECT_TRUE(cl.HasSwitch("baz"));
135   EXPECT_TRUE(cl.HasSwitch("spaetzle"));
136   EXPECT_TRUE(cl.HasSwitch("other-switches"));
137   EXPECT_TRUE(cl.HasSwitch("input-translation"));
138   EXPECT_TRUE(cl.HasSwitch("quotes"));
139
140   EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
141   EXPECT_EQ("", cl.GetSwitchValueASCII("foo"));
142   EXPECT_EQ("", cl.GetSwitchValueASCII("bar"));
143   EXPECT_EQ("", cl.GetSwitchValueASCII("cruller"));
144   EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
145       "other-switches"));
146   EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
147   EXPECT_EQ(kTricky, cl.GetSwitchValueNative("quotes"));
148
149   const CommandLine::StringVector& args = cl.GetArgs();
150   ASSERT_EQ(5U, args.size());
151
152   std::vector<CommandLine::StringType>::const_iterator iter = args.begin();
153   EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
154   ++iter;
155   EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
156   ++iter;
157   EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
158   ++iter;
159   EXPECT_EQ(FILE_PATH_LITERAL("--not-a-switch"), *iter);
160   ++iter;
161   EXPECT_EQ(FILE_PATH_LITERAL("in the time of submarines..."), *iter);
162   ++iter;
163   EXPECT_TRUE(iter == args.end());
164
165   // Check that a generated string produces an equivalent command line.
166   CommandLine cl_duplicate = CommandLine::FromString(cl.GetCommandLineString());
167   EXPECT_EQ(cl.GetCommandLineString(), cl_duplicate.GetCommandLineString());
168 #endif
169 }
170
171 // Tests behavior with an empty input string.
172 TEST(CommandLineTest, EmptyString) {
173 #if defined(OS_WIN)
174   CommandLine cl_from_string = CommandLine::FromString(std::wstring());
175   EXPECT_TRUE(cl_from_string.GetCommandLineString().empty());
176   EXPECT_TRUE(cl_from_string.GetProgram().empty());
177   EXPECT_EQ(1U, cl_from_string.argv().size());
178   EXPECT_TRUE(cl_from_string.GetArgs().empty());
179 #endif
180   CommandLine cl_from_argv(0, nullptr);
181   EXPECT_TRUE(cl_from_argv.GetCommandLineString().empty());
182   EXPECT_TRUE(cl_from_argv.GetProgram().empty());
183   EXPECT_EQ(1U, cl_from_argv.argv().size());
184   EXPECT_TRUE(cl_from_argv.GetArgs().empty());
185 }
186
187 TEST(CommandLineTest, GetArgumentsString) {
188   static const FilePath::CharType kPath1[] =
189       FILE_PATH_LITERAL("C:\\Some File\\With Spaces.ggg");
190   static const FilePath::CharType kPath2[] =
191       FILE_PATH_LITERAL("C:\\no\\spaces.ggg");
192
193   static const char kFirstArgName[] = "first-arg";
194   static const char kSecondArgName[] = "arg2";
195   static const char kThirdArgName[] = "arg with space";
196   static const char kFourthArgName[] = "nospace";
197
198   CommandLine cl(CommandLine::NO_PROGRAM);
199   cl.AppendSwitchPath(kFirstArgName, FilePath(kPath1));
200   cl.AppendSwitchPath(kSecondArgName, FilePath(kPath2));
201   cl.AppendArg(kThirdArgName);
202   cl.AppendArg(kFourthArgName);
203
204 #if defined(OS_WIN)
205   CommandLine::StringType expected_first_arg(UTF8ToWide(kFirstArgName));
206   CommandLine::StringType expected_second_arg(UTF8ToWide(kSecondArgName));
207   CommandLine::StringType expected_third_arg(UTF8ToWide(kThirdArgName));
208   CommandLine::StringType expected_fourth_arg(UTF8ToWide(kFourthArgName));
209 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
210   CommandLine::StringType expected_first_arg(kFirstArgName);
211   CommandLine::StringType expected_second_arg(kSecondArgName);
212   CommandLine::StringType expected_third_arg(kThirdArgName);
213   CommandLine::StringType expected_fourth_arg(kFourthArgName);
214 #endif
215
216 #if defined(OS_WIN)
217 #define QUOTE_ON_WIN FILE_PATH_LITERAL("\"")
218 #else
219 #define QUOTE_ON_WIN FILE_PATH_LITERAL("")
220 #endif  // OS_WIN
221
222   CommandLine::StringType expected_str;
223   expected_str.append(FILE_PATH_LITERAL("--"))
224       .append(expected_first_arg)
225       .append(FILE_PATH_LITERAL("="))
226       .append(QUOTE_ON_WIN)
227       .append(kPath1)
228       .append(QUOTE_ON_WIN)
229       .append(FILE_PATH_LITERAL(" "))
230       .append(FILE_PATH_LITERAL("--"))
231       .append(expected_second_arg)
232       .append(FILE_PATH_LITERAL("="))
233       .append(QUOTE_ON_WIN)
234       .append(kPath2)
235       .append(QUOTE_ON_WIN)
236       .append(FILE_PATH_LITERAL(" "))
237       .append(QUOTE_ON_WIN)
238       .append(expected_third_arg)
239       .append(QUOTE_ON_WIN)
240       .append(FILE_PATH_LITERAL(" "))
241       .append(expected_fourth_arg);
242   EXPECT_EQ(expected_str, cl.GetArgumentsString());
243 }
244
245 // Test methods for appending switches to a command line.
246 TEST(CommandLineTest, AppendSwitches) {
247   std::string switch1 = "switch1";
248   std::string switch2 = "switch2";
249   std::string value2 = "value";
250   std::string switch3 = "switch3";
251   std::string value3 = "a value with spaces";
252   std::string switch4 = "switch4";
253   std::string value4 = "\"a value with quotes\"";
254   std::string switch5 = "quotes";
255   CommandLine::StringType value5 = kTricky;
256
257   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
258
259   cl.AppendSwitch(switch1);
260   cl.AppendSwitchASCII(switch2, value2);
261   cl.AppendSwitchASCII(switch3, value3);
262   cl.AppendSwitchASCII(switch4, value4);
263   cl.AppendSwitchASCII(switch5, value4);
264   cl.AppendSwitchNative(switch5, value5);
265
266   EXPECT_TRUE(cl.HasSwitch(switch1));
267   EXPECT_TRUE(cl.HasSwitch(switch2));
268   EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
269   EXPECT_TRUE(cl.HasSwitch(switch3));
270   EXPECT_EQ(value3, cl.GetSwitchValueASCII(switch3));
271   EXPECT_TRUE(cl.HasSwitch(switch4));
272   EXPECT_EQ(value4, cl.GetSwitchValueASCII(switch4));
273   EXPECT_TRUE(cl.HasSwitch(switch5));
274   EXPECT_EQ(value5, cl.GetSwitchValueNative(switch5));
275
276 #if defined(OS_WIN)
277   EXPECT_EQ(
278       L"Program "
279       L"--switch1 "
280       L"--switch2=value "
281       L"--switch3=\"a value with spaces\" "
282       L"--switch4=\"\\\"a value with quotes\\\"\" "
283       // Even though the switches are unique, appending can add repeat
284       // switches to argv.
285       L"--quotes=\"\\\"a value with quotes\\\"\" "
286       L"--quotes=\"" +
287           kTrickyQuoted + L"\"",
288       cl.GetCommandLineString());
289 #endif
290 }
291
292 TEST(CommandLineTest, AppendSwitchesDashDash) {
293  const CommandLine::CharType* raw_argv[] = { FILE_PATH_LITERAL("prog"),
294                                              FILE_PATH_LITERAL("--"),
295                                              FILE_PATH_LITERAL("--arg1") };
296  CommandLine cl(size(raw_argv), raw_argv);
297
298  cl.AppendSwitch("switch1");
299  cl.AppendSwitchASCII("switch2", "foo");
300
301  cl.AppendArg("--arg2");
302
303  EXPECT_EQ(FILE_PATH_LITERAL("prog --switch1 --switch2=foo -- --arg1 --arg2"),
304            cl.GetCommandLineString());
305  CommandLine::StringVector cl_argv = cl.argv();
306  EXPECT_EQ(FILE_PATH_LITERAL("prog"), cl_argv[0]);
307  EXPECT_EQ(FILE_PATH_LITERAL("--switch1"), cl_argv[1]);
308  EXPECT_EQ(FILE_PATH_LITERAL("--switch2=foo"), cl_argv[2]);
309  EXPECT_EQ(FILE_PATH_LITERAL("--"), cl_argv[3]);
310  EXPECT_EQ(FILE_PATH_LITERAL("--arg1"), cl_argv[4]);
311  EXPECT_EQ(FILE_PATH_LITERAL("--arg2"), cl_argv[5]);
312 }
313
314 #if defined(OS_WIN)
315 TEST(CommandLineTest, GetCommandLineStringForShell) {
316   CommandLine cl = CommandLine::FromString(
317       FILE_PATH_LITERAL("program --switch /switch2 --"));
318   EXPECT_EQ(
319       cl.GetCommandLineStringForShell(),
320       FILE_PATH_LITERAL("program --switch /switch2 -- --single-argument %1"));
321 }
322
323 TEST(CommandLineTest, GetCommandLineStringWithUnsafeInsertSequences) {
324   CommandLine cl(FilePath(FILE_PATH_LITERAL("program")));
325   cl.AppendSwitchASCII("switch", "%1");
326   cl.AppendSwitch("%2");
327   cl.AppendArg("%3");
328   EXPECT_EQ(FILE_PATH_LITERAL("program --switch=%1 --%2 %3"),
329             cl.GetCommandLineStringWithUnsafeInsertSequences());
330 }
331 #endif  // defined(OS_WIN)
332
333 // Tests that when AppendArguments is called that the program is set correctly
334 // on the target CommandLine object and the switches from the source
335 // CommandLine are added to the target.
336 TEST(CommandLineTest, AppendArguments) {
337   CommandLine cl1(FilePath(FILE_PATH_LITERAL("Program")));
338   cl1.AppendSwitch("switch1");
339   cl1.AppendSwitchASCII("switch2", "foo");
340
341   CommandLine cl2(CommandLine::NO_PROGRAM);
342   cl2.AppendArguments(cl1, true);
343   EXPECT_EQ(cl1.GetProgram().value(), cl2.GetProgram().value());
344   EXPECT_EQ(cl1.GetCommandLineString(), cl2.GetCommandLineString());
345
346   CommandLine c1(FilePath(FILE_PATH_LITERAL("Program1")));
347   c1.AppendSwitch("switch1");
348   CommandLine c2(FilePath(FILE_PATH_LITERAL("Program2")));
349   c2.AppendSwitch("switch2");
350
351   c1.AppendArguments(c2, true);
352   EXPECT_EQ(c1.GetProgram().value(), c2.GetProgram().value());
353   EXPECT_TRUE(c1.HasSwitch("switch1"));
354   EXPECT_TRUE(c1.HasSwitch("switch2"));
355 }
356
357 #if defined(OS_WIN)
358 // Make sure that the command line string program paths are quoted as necessary.
359 // This only makes sense on Windows and the test is basically here to guard
360 // against regressions.
361 TEST(CommandLineTest, ProgramQuotes) {
362   // Check that quotes are not added for paths without spaces.
363   const FilePath kProgram(L"Program");
364   CommandLine cl_program(kProgram);
365   EXPECT_EQ(kProgram.value(), cl_program.GetProgram().value());
366   EXPECT_EQ(kProgram.value(), cl_program.GetCommandLineString());
367
368   const FilePath kProgramPath(L"Program Path");
369
370   // Check that quotes are not returned from GetProgram().
371   CommandLine cl_program_path(kProgramPath);
372   EXPECT_EQ(kProgramPath.value(), cl_program_path.GetProgram().value());
373
374   // Check that quotes are added to command line string paths containing spaces.
375   CommandLine::StringType cmd_string(cl_program_path.GetCommandLineString());
376   EXPECT_EQ(L"\"Program Path\"", cmd_string);
377 }
378 #endif
379
380 // Calling Init multiple times should not modify the previous CommandLine.
381 TEST(CommandLineTest, Init) {
382   // Call Init without checking output once so we know it's been called
383   // whether or not the test runner does so.
384   CommandLine::Init(0, nullptr);
385   CommandLine* initial = CommandLine::ForCurrentProcess();
386   EXPECT_FALSE(CommandLine::Init(0, nullptr));
387   CommandLine* current = CommandLine::ForCurrentProcess();
388   EXPECT_EQ(initial, current);
389 }
390
391 // Test that copies of CommandLine have a valid StringPiece map.
392 TEST(CommandLineTest, Copy) {
393   std::unique_ptr<CommandLine> initial(
394       new CommandLine(CommandLine::NO_PROGRAM));
395   initial->AppendSwitch("a");
396   initial->AppendSwitch("bbbbbbbbbbbbbbb");
397   initial->AppendSwitch("c");
398   CommandLine copy_constructed(*initial);
399   CommandLine assigned = *initial;
400   CommandLine::SwitchMap switch_map = initial->GetSwitches();
401   initial.reset();
402   for (const auto& pair : switch_map)
403     EXPECT_TRUE(copy_constructed.HasSwitch(pair.first));
404   for (const auto& pair : switch_map)
405     EXPECT_TRUE(assigned.HasSwitch(pair.first));
406 }
407
408 TEST(CommandLineTest, PrependSimpleWrapper) {
409   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
410   cl.AppendSwitch("a");
411   cl.AppendSwitch("b");
412   cl.PrependWrapper(FILE_PATH_LITERAL("wrapper --foo --bar"));
413
414   EXPECT_EQ(6u, cl.argv().size());
415   EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
416   EXPECT_EQ(FILE_PATH_LITERAL("--foo"), cl.argv()[1]);
417   EXPECT_EQ(FILE_PATH_LITERAL("--bar"), cl.argv()[2]);
418   EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
419   EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
420   EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
421 }
422
423 TEST(CommandLineTest, PrependComplexWrapper) {
424   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
425   cl.AppendSwitch("a");
426   cl.AppendSwitch("b");
427   cl.PrependWrapper(
428       FILE_PATH_LITERAL("wrapper --foo='hello world' --bar=\"let's go\""));
429
430   EXPECT_EQ(6u, cl.argv().size());
431   EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
432   EXPECT_EQ(FILE_PATH_LITERAL("--foo='hello world'"), cl.argv()[1]);
433   EXPECT_EQ(FILE_PATH_LITERAL("--bar=\"let's go\""), cl.argv()[2]);
434   EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
435   EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
436   EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
437 }
438
439 TEST(CommandLineTest, RemoveSwitch) {
440   const std::string switch1 = "switch1";
441   const std::string switch2 = "switch2";
442   const std::string value2 = "value";
443
444   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
445
446   cl.AppendSwitch(switch1);
447   cl.AppendSwitchASCII(switch2, value2);
448
449   EXPECT_TRUE(cl.HasSwitch(switch1));
450   EXPECT_TRUE(cl.HasSwitch(switch2));
451   EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
452   EXPECT_THAT(cl.argv(),
453               testing::ElementsAre(FILE_PATH_LITERAL("Program"),
454                                    FILE_PATH_LITERAL("--switch1"),
455                                    FILE_PATH_LITERAL("--switch2=value")));
456
457   cl.RemoveSwitch(switch1);
458
459   EXPECT_FALSE(cl.HasSwitch(switch1));
460   EXPECT_TRUE(cl.HasSwitch(switch2));
461   EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
462   EXPECT_THAT(cl.argv(),
463               testing::ElementsAre(FILE_PATH_LITERAL("Program"),
464                                    FILE_PATH_LITERAL("--switch2=value")));
465 }
466
467 TEST(CommandLineTest, RemoveSwitchWithValue) {
468   const std::string switch1 = "switch1";
469   const std::string switch2 = "switch2";
470   const std::string value2 = "value";
471
472   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
473
474   cl.AppendSwitch(switch1);
475   cl.AppendSwitchASCII(switch2, value2);
476
477   EXPECT_TRUE(cl.HasSwitch(switch1));
478   EXPECT_TRUE(cl.HasSwitch(switch2));
479   EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
480   EXPECT_THAT(cl.argv(),
481               testing::ElementsAre(FILE_PATH_LITERAL("Program"),
482                                    FILE_PATH_LITERAL("--switch1"),
483                                    FILE_PATH_LITERAL("--switch2=value")));
484
485   cl.RemoveSwitch(switch2);
486
487   EXPECT_TRUE(cl.HasSwitch(switch1));
488   EXPECT_FALSE(cl.HasSwitch(switch2));
489   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program"),
490                                               FILE_PATH_LITERAL("--switch1")));
491 }
492
493 TEST(CommandLineTest, RemoveSwitchDropsMultipleSameSwitches) {
494   const std::string switch1 = "switch1";
495   const std::string value2 = "value2";
496
497   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
498
499   cl.AppendSwitch(switch1);
500   cl.AppendSwitchASCII(switch1, value2);
501
502   EXPECT_TRUE(cl.HasSwitch(switch1));
503   EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch1));
504   EXPECT_THAT(cl.argv(),
505               testing::ElementsAre(FILE_PATH_LITERAL("Program"),
506                                    FILE_PATH_LITERAL("--switch1"),
507                                    FILE_PATH_LITERAL("--switch1=value2")));
508
509   cl.RemoveSwitch(switch1);
510
511   EXPECT_FALSE(cl.HasSwitch(switch1));
512   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program")));
513 }
514
515 TEST(CommandLineTest, AppendAndRemoveSwitchWithDefaultPrefix) {
516   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
517
518   cl.AppendSwitch("foo");
519   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program"),
520                                               FILE_PATH_LITERAL("--foo")));
521   EXPECT_EQ(0u, cl.GetArgs().size());
522
523   cl.RemoveSwitch("foo");
524   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program")));
525   EXPECT_EQ(0u, cl.GetArgs().size());
526 }
527
528 TEST(CommandLineTest, AppendAndRemoveSwitchWithAlternativePrefix) {
529   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
530
531   cl.AppendSwitch("-foo");
532   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program"),
533                                               FILE_PATH_LITERAL("-foo")));
534   EXPECT_EQ(0u, cl.GetArgs().size());
535
536   cl.RemoveSwitch("foo");
537   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program")));
538   EXPECT_EQ(0u, cl.GetArgs().size());
539 }
540
541 TEST(CommandLineTest, AppendAndRemoveSwitchPreservesOtherSwitchesAndArgs) {
542   CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
543
544   cl.AppendSwitch("foo");
545   cl.AppendSwitch("bar");
546   cl.AppendArg("arg");
547   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program"),
548                                               FILE_PATH_LITERAL("--foo"),
549                                               FILE_PATH_LITERAL("--bar"),
550                                               FILE_PATH_LITERAL("arg")));
551   EXPECT_THAT(cl.GetArgs(), testing::ElementsAre(FILE_PATH_LITERAL("arg")));
552
553   cl.RemoveSwitch("foo");
554   EXPECT_THAT(cl.argv(), testing::ElementsAre(FILE_PATH_LITERAL("Program"),
555                                               FILE_PATH_LITERAL("--bar"),
556                                               FILE_PATH_LITERAL("arg")));
557   EXPECT_THAT(cl.GetArgs(), testing::ElementsAre(FILE_PATH_LITERAL("arg")));
558 }
559
560 TEST(CommandLineTest, MultipleSameSwitch) {
561   const CommandLine::CharType* argv[] = {
562       FILE_PATH_LITERAL("program"),
563       FILE_PATH_LITERAL("--foo=one"),  // --foo first time
564       FILE_PATH_LITERAL("-baz"),
565       FILE_PATH_LITERAL("--foo=two")  // --foo second time
566   };
567   CommandLine cl(size(argv), argv);
568
569   EXPECT_TRUE(cl.HasSwitch("foo"));
570   EXPECT_TRUE(cl.HasSwitch("baz"));
571
572   EXPECT_EQ("two", cl.GetSwitchValueASCII("foo"));
573 }
574
575 #if defined(OS_WIN)
576 TEST(CommandLineTest, ParseAsSingleArgument) {
577   CommandLine cl = CommandLine::FromString(
578       FILE_PATH_LITERAL("program --switch_before arg_before "
579                         "--single-argument arg with spaces \"and quotes\" \""));
580
581   EXPECT_FALSE(cl.GetCommandLineString().empty());
582   EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")), cl.GetProgram());
583   EXPECT_TRUE(cl.HasSwitch("switch_before"));
584   EXPECT_EQ(cl.GetArgs(), CommandLine::StringVector({FILE_PATH_LITERAL(
585                               "arg with spaces \"and quotes\" \"")}));
586
587   CommandLine cl_without_arg =
588       CommandLine::FromString(FILE_PATH_LITERAL("program --single-argument "));
589
590   EXPECT_FALSE(cl_without_arg.GetCommandLineString().empty());
591   EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")),
592             cl_without_arg.GetProgram());
593   EXPECT_TRUE(cl_without_arg.GetArgs().empty());
594 }
595 #endif  // defined(OS_WIN)
596
597 } // namespace base