1 //===-- ArgsTest.cpp ------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "gtest/gtest.h"
11 #include "lldb/Utility/Args.h"
12 #include "lldb/Utility/FileSpec.h"
13 #include "lldb/Utility/StringList.h"
18 using namespace lldb_private
;
20 TEST(ArgsTest
, TestSingleArg
) {
22 args
.SetCommandString("arg");
23 EXPECT_EQ(1u, args
.GetArgumentCount());
24 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg");
27 TEST(ArgsTest
, TestSingleQuotedArgWithSpace
) {
29 args
.SetCommandString("\"arg with space\"");
30 EXPECT_EQ(1u, args
.GetArgumentCount());
31 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg with space");
34 TEST(ArgsTest
, TestSingleArgWithQuotedSpace
) {
36 args
.SetCommandString("arg\\ with\\ space");
37 EXPECT_EQ(1u, args
.GetArgumentCount());
38 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg with space");
41 TEST(ArgsTest
, TestTrailingBackslash
) {
43 args
.SetCommandString("arg\\");
44 EXPECT_EQ(1u, args
.GetArgumentCount());
45 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg\\");
48 TEST(ArgsTest
, TestQuotedTrailingBackslash
) {
50 args
.SetCommandString("\"arg\\");
51 EXPECT_EQ(1u, args
.GetArgumentCount());
52 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg\\");
55 TEST(ArgsTest
, TestUnknownEscape
) {
57 args
.SetCommandString("arg\\y");
58 EXPECT_EQ(1u, args
.GetArgumentCount());
59 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg\\y");
62 TEST(ArgsTest
, TestQuotedUnknownEscape
) {
64 args
.SetCommandString("\"arg\\y");
65 EXPECT_EQ(1u, args
.GetArgumentCount());
66 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg\\y");
69 TEST(ArgsTest
, TestMultipleArgs
) {
71 args
.SetCommandString("this has multiple args");
72 EXPECT_EQ(4u, args
.GetArgumentCount());
73 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "this");
74 EXPECT_STREQ(args
.GetArgumentAtIndex(1), "has");
75 EXPECT_STREQ(args
.GetArgumentAtIndex(2), "multiple");
76 EXPECT_STREQ(args
.GetArgumentAtIndex(3), "args");
79 TEST(ArgsTest
, TestOverwriteArgs
) {
81 args
.SetCommandString("this has multiple args");
82 EXPECT_EQ(4u, args
.GetArgumentCount());
83 args
.SetCommandString("arg");
84 EXPECT_EQ(1u, args
.GetArgumentCount());
85 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "arg");
88 TEST(ArgsTest
, TestAppendArg
) {
90 args
.SetCommandString("first_arg");
91 EXPECT_EQ(1u, args
.GetArgumentCount());
92 args
.AppendArgument(llvm::StringRef("second_arg"));
93 EXPECT_EQ(2u, args
.GetArgumentCount());
94 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "first_arg");
95 EXPECT_STREQ(args
.GetArgumentAtIndex(1), "second_arg");
98 TEST(ArgsTest
, TestInsertArg
) {
100 args
.AppendArgument("1");
101 args
.AppendArgument("2");
102 args
.AppendArgument("3");
103 args
.InsertArgumentAtIndex(1, "1.5");
104 args
.InsertArgumentAtIndex(4, "3.5");
106 ASSERT_EQ(5u, args
.GetArgumentCount());
107 EXPECT_STREQ("1", args
.GetArgumentAtIndex(0));
108 EXPECT_STREQ("1.5", args
.GetArgumentAtIndex(1));
109 EXPECT_STREQ("2", args
.GetArgumentAtIndex(2));
110 EXPECT_STREQ("3", args
.GetArgumentAtIndex(3));
111 EXPECT_STREQ("3.5", args
.GetArgumentAtIndex(4));
114 TEST(ArgsTest
, TestArgv
) {
116 EXPECT_EQ(nullptr, args
.GetArgumentVector());
118 args
.AppendArgument("1");
119 EXPECT_NE(nullptr, args
.GetArgumentVector()[0]);
120 EXPECT_EQ(nullptr, args
.GetArgumentVector()[1]);
122 args
.AppendArgument("2");
123 EXPECT_NE(nullptr, args
.GetArgumentVector()[0]);
124 EXPECT_NE(nullptr, args
.GetArgumentVector()[1]);
125 EXPECT_EQ(nullptr, args
.GetArgumentVector()[2]);
127 args
.AppendArgument("3");
128 EXPECT_NE(nullptr, args
.GetArgumentVector()[0]);
129 EXPECT_NE(nullptr, args
.GetArgumentVector()[1]);
130 EXPECT_NE(nullptr, args
.GetArgumentVector()[2]);
131 EXPECT_EQ(nullptr, args
.GetArgumentVector()[3]);
133 args
.InsertArgumentAtIndex(1, "1.5");
134 EXPECT_NE(nullptr, args
.GetArgumentVector()[0]);
135 EXPECT_NE(nullptr, args
.GetArgumentVector()[1]);
136 EXPECT_NE(nullptr, args
.GetArgumentVector()[2]);
137 EXPECT_NE(nullptr, args
.GetArgumentVector()[3]);
138 EXPECT_EQ(nullptr, args
.GetArgumentVector()[4]);
140 args
.InsertArgumentAtIndex(4, "3.5");
141 EXPECT_NE(nullptr, args
.GetArgumentVector()[0]);
142 EXPECT_NE(nullptr, args
.GetArgumentVector()[1]);
143 EXPECT_NE(nullptr, args
.GetArgumentVector()[2]);
144 EXPECT_NE(nullptr, args
.GetArgumentVector()[3]);
145 EXPECT_NE(nullptr, args
.GetArgumentVector()[4]);
146 EXPECT_EQ(nullptr, args
.GetArgumentVector()[5]);
149 TEST(ArgsTest
, StringListConstructor
) {
155 ASSERT_EQ(3u, args
.GetArgumentCount());
156 EXPECT_EQ("foo", args
[0].ref());
157 EXPECT_EQ("bar", args
[1].ref());
158 EXPECT_EQ("baz", args
[2].ref());
161 TEST(ArgsTest
, GetQuotedCommandString
) {
163 const char *str
= "process launch -o stdout.txt -- \"a b c\"";
164 args
.SetCommandString(str
);
167 ASSERT_TRUE(args
.GetQuotedCommandString(stdstr
));
168 EXPECT_EQ(str
, stdstr
);
171 TEST(ArgsTest
, BareSingleQuote
) {
173 args
.SetCommandString("a\\'b");
174 EXPECT_EQ(1u, args
.GetArgumentCount());
176 EXPECT_STREQ("a'b", args
.GetArgumentAtIndex(0));
179 TEST(ArgsTest
, DoubleQuotedItem
) {
181 args
.SetCommandString("\"a b c\"");
182 EXPECT_EQ(1u, args
.GetArgumentCount());
184 EXPECT_STREQ("a b c", args
.GetArgumentAtIndex(0));
187 TEST(ArgsTest
, AppendArguments
) {
189 const char *argv
[] = {"1", "2", nullptr};
190 const char *argv2
[] = {"3", "4", nullptr};
192 args
.AppendArguments(argv
);
193 ASSERT_EQ(2u, args
.GetArgumentCount());
194 EXPECT_STREQ("1", args
.GetArgumentVector()[0]);
195 EXPECT_STREQ("2", args
.GetArgumentVector()[1]);
196 EXPECT_EQ(nullptr, args
.GetArgumentVector()[2]);
197 EXPECT_STREQ("1", args
.GetArgumentAtIndex(0));
198 EXPECT_STREQ("2", args
.GetArgumentAtIndex(1));
200 args
.AppendArguments(argv2
);
201 ASSERT_EQ(4u, args
.GetArgumentCount());
202 EXPECT_STREQ("1", args
.GetArgumentVector()[0]);
203 EXPECT_STREQ("2", args
.GetArgumentVector()[1]);
204 EXPECT_STREQ("3", args
.GetArgumentVector()[2]);
205 EXPECT_STREQ("4", args
.GetArgumentVector()[3]);
206 EXPECT_EQ(nullptr, args
.GetArgumentVector()[4]);
207 EXPECT_STREQ("1", args
.GetArgumentAtIndex(0));
208 EXPECT_STREQ("2", args
.GetArgumentAtIndex(1));
209 EXPECT_STREQ("3", args
.GetArgumentAtIndex(2));
210 EXPECT_STREQ("4", args
.GetArgumentAtIndex(3));
213 TEST(ArgsTest
, GetArgumentArrayRef
) {
214 Args
args("foo bar");
215 auto ref
= args
.GetArgumentArrayRef();
216 ASSERT_EQ(2u, ref
.size());
217 EXPECT_STREQ("foo", ref
[0]);
218 EXPECT_STREQ("bar", ref
[1]);
221 TEST(ArgsTest
, EscapeLLDBCommandArgument
) {
222 const std::string foo
= "foo'";
223 EXPECT_EQ("foo\\'", Args::EscapeLLDBCommandArgument(foo
, '\0'));
224 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo
, '\''));
225 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo
, '`'));
226 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo
, '"'));
228 const std::string bar
= "bar\"";
229 EXPECT_EQ("bar\\\"", Args::EscapeLLDBCommandArgument(bar
, '\0'));
230 EXPECT_EQ("bar\"", Args::EscapeLLDBCommandArgument(bar
, '\''));
231 EXPECT_EQ("bar\"", Args::EscapeLLDBCommandArgument(bar
, '`'));
232 EXPECT_EQ("bar\\\"", Args::EscapeLLDBCommandArgument(bar
, '"'));
234 const std::string baz
= "baz`";
235 EXPECT_EQ("baz\\`", Args::EscapeLLDBCommandArgument(baz
, '\0'));
236 EXPECT_EQ("baz`", Args::EscapeLLDBCommandArgument(baz
, '\''));
237 EXPECT_EQ("baz`", Args::EscapeLLDBCommandArgument(baz
, '`'));
238 EXPECT_EQ("baz\\`", Args::EscapeLLDBCommandArgument(baz
, '"'));
240 const std::string quux
= "quux\t";
241 EXPECT_EQ("quux\\\t", Args::EscapeLLDBCommandArgument(quux
, '\0'));
242 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux
, '\''));
243 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux
, '`'));
244 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux
, '"'));
247 TEST(ArgsTest
, ReplaceArgumentAtIndexShort
) {
249 args
.SetCommandString("foo ba b");
250 args
.ReplaceArgumentAtIndex(0, "f");
251 EXPECT_EQ(3u, args
.GetArgumentCount());
252 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "f");
255 TEST(ArgsTest
, ReplaceArgumentAtIndexEqual
) {
257 args
.SetCommandString("foo ba b");
258 args
.ReplaceArgumentAtIndex(0, "bar");
259 EXPECT_EQ(3u, args
.GetArgumentCount());
260 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "bar");
263 TEST(ArgsTest
, ReplaceArgumentAtIndexLonger
) {
265 args
.SetCommandString("foo ba b");
266 args
.ReplaceArgumentAtIndex(0, "baar");
267 EXPECT_EQ(3u, args
.GetArgumentCount());
268 EXPECT_STREQ(args
.GetArgumentAtIndex(0), "baar");
271 TEST(ArgsTest
, ReplaceArgumentAtIndexOutOfRange
) {
273 args
.SetCommandString("foo ba b");
274 args
.ReplaceArgumentAtIndex(3, "baar");
275 EXPECT_EQ(3u, args
.GetArgumentCount());
276 EXPECT_STREQ(args
.GetArgumentAtIndex(2), "b");
279 TEST(ArgsTest
, ReplaceArgumentAtIndexFarOutOfRange
) {
281 args
.SetCommandString("foo ba b");
282 args
.ReplaceArgumentAtIndex(4, "baar");
283 EXPECT_EQ(3u, args
.GetArgumentCount());
284 EXPECT_STREQ(args
.GetArgumentAtIndex(2), "b");
287 TEST(ArgsTest
, GetShellSafeArgument
) {
288 // Try escaping with bash at start/middle/end of the argument.
289 FileSpec
bash("/bin/bash", FileSpec::Style::posix
);
290 EXPECT_EQ(Args::GetShellSafeArgument(bash
, "\"b"), "\\\"b");
291 EXPECT_EQ(Args::GetShellSafeArgument(bash
, "a\""), "a\\\"");
292 EXPECT_EQ(Args::GetShellSafeArgument(bash
, "a\"b"), "a\\\"b");
294 FileSpec
zsh("/bin/zsh", FileSpec::Style::posix
);
295 EXPECT_EQ(Args::GetShellSafeArgument(zsh
, R
"('";()<>&|\
)"),
296 R"(\'\"\
;\
(\
)\
<\
>\
&\
|\\)");
297 // Normal characters and expressions that shouldn't be escaped.
298 EXPECT_EQ(Args::GetShellSafeArgument(zsh, "aA$
1*"), "aA$
1*");
300 // Test escaping bash special characters.
301 EXPECT_EQ(Args::GetShellSafeArgument(bash, R"( '"<>()&;)"),
302 R"(\ \'\"\<\>\(\)\&\;)");
303 // Normal characters and globbing expressions that shouldn't be escaped
.
304 EXPECT_EQ(Args::GetShellSafeArgument(bash
, "aA$1*"), "aA$1*");
306 // Test escaping tcsh special characters.
307 FileSpec
tcsh("/bin/tcsh", FileSpec::Style::posix
);
308 EXPECT_EQ(Args::GetShellSafeArgument(tcsh
, R
"( '"<>()&;)"),
309 R"(\
\'\"\
<\
>\
(\
)\
&\
;)");
310 // Normal characters and globbing expressions that shouldn't be escaped.
311 EXPECT_EQ(Args::GetShellSafeArgument(tcsh, "aA1
*"), "aA1
*");
313 // Test escaping sh special characters.
314 FileSpec sh("/bin
/sh
", FileSpec::Style::posix);
315 EXPECT_EQ(Args::GetShellSafeArgument(sh, R"( '"<>()&;)"),
316 R"(\ \'\"\<\>\(\)\&\;)");
317 // Normal characters and globbing expressions that shouldn't be escaped
.
318 EXPECT_EQ(Args::GetShellSafeArgument(sh
, "aA$1*"), "aA$1*");
320 // Test escaping fish special characters.
321 FileSpec
fish("/bin/fish", FileSpec::Style::posix
);
322 EXPECT_EQ(Args::GetShellSafeArgument(fish
, R
"( '"<>()&\
|;)"),
323 R"(\
\'\"\
<\
>\
(\
)\
&\\\
|\
;)");
324 // Normal characters and expressions that shouldn't be escaped.
325 EXPECT_EQ(Args::GetShellSafeArgument(fish, "aA$
1*"), "aA$
1*");
327 // Try escaping with an unknown shell.
328 FileSpec unknown_shell("/bin
/unknown_shell
", FileSpec::Style::posix);
329 EXPECT_EQ(Args::GetShellSafeArgument(unknown_shell, "a
'b"), "a\\'b
");
330 EXPECT_EQ(Args::GetShellSafeArgument(unknown_shell, "a
\"b
"), "a
\\\"b
");