1 //===-- ArgsTest.cpp ------------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gtest/gtest.h" 10 11 #include "lldb/Utility/Args.h" 12 #include "lldb/Utility/StringList.h" 13 14 #include <limits> 15 #include <sstream> 16 17 using namespace lldb_private; 18 19 TEST(ArgsTest, TestSingleArg) { 20 Args args; 21 args.SetCommandString("arg"); 22 EXPECT_EQ(1u, args.GetArgumentCount()); 23 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg"); 24 } 25 26 TEST(ArgsTest, TestSingleQuotedArgWithSpace) { 27 Args args; 28 args.SetCommandString("\"arg with space\""); 29 EXPECT_EQ(1u, args.GetArgumentCount()); 30 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg with space"); 31 } 32 33 TEST(ArgsTest, TestSingleArgWithQuotedSpace) { 34 Args args; 35 args.SetCommandString("arg\\ with\\ space"); 36 EXPECT_EQ(1u, args.GetArgumentCount()); 37 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg with space"); 38 } 39 40 TEST(ArgsTest, TestTrailingBackslash) { 41 Args args; 42 args.SetCommandString("arg\\"); 43 EXPECT_EQ(1u, args.GetArgumentCount()); 44 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg\\"); 45 } 46 47 TEST(ArgsTest, TestQuotedTrailingBackslash) { 48 Args args; 49 args.SetCommandString("\"arg\\"); 50 EXPECT_EQ(1u, args.GetArgumentCount()); 51 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg\\"); 52 } 53 54 TEST(ArgsTest, TestUnknownEscape) { 55 Args args; 56 args.SetCommandString("arg\\y"); 57 EXPECT_EQ(1u, args.GetArgumentCount()); 58 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg\\y"); 59 } 60 61 TEST(ArgsTest, TestQuotedUnknownEscape) { 62 Args args; 63 args.SetCommandString("\"arg\\y"); 64 EXPECT_EQ(1u, args.GetArgumentCount()); 65 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg\\y"); 66 } 67 68 TEST(ArgsTest, TestMultipleArgs) { 69 Args args; 70 args.SetCommandString("this has multiple args"); 71 EXPECT_EQ(4u, args.GetArgumentCount()); 72 EXPECT_STREQ(args.GetArgumentAtIndex(0), "this"); 73 EXPECT_STREQ(args.GetArgumentAtIndex(1), "has"); 74 EXPECT_STREQ(args.GetArgumentAtIndex(2), "multiple"); 75 EXPECT_STREQ(args.GetArgumentAtIndex(3), "args"); 76 } 77 78 TEST(ArgsTest, TestOverwriteArgs) { 79 Args args; 80 args.SetCommandString("this has multiple args"); 81 EXPECT_EQ(4u, args.GetArgumentCount()); 82 args.SetCommandString("arg"); 83 EXPECT_EQ(1u, args.GetArgumentCount()); 84 EXPECT_STREQ(args.GetArgumentAtIndex(0), "arg"); 85 } 86 87 TEST(ArgsTest, TestAppendArg) { 88 Args args; 89 args.SetCommandString("first_arg"); 90 EXPECT_EQ(1u, args.GetArgumentCount()); 91 args.AppendArgument(llvm::StringRef("second_arg")); 92 EXPECT_EQ(2u, args.GetArgumentCount()); 93 EXPECT_STREQ(args.GetArgumentAtIndex(0), "first_arg"); 94 EXPECT_STREQ(args.GetArgumentAtIndex(1), "second_arg"); 95 } 96 97 TEST(ArgsTest, TestInsertArg) { 98 Args args; 99 args.AppendArgument("1"); 100 args.AppendArgument("2"); 101 args.AppendArgument("3"); 102 args.InsertArgumentAtIndex(1, "1.5"); 103 args.InsertArgumentAtIndex(4, "3.5"); 104 105 ASSERT_EQ(5u, args.GetArgumentCount()); 106 EXPECT_STREQ("1", args.GetArgumentAtIndex(0)); 107 EXPECT_STREQ("1.5", args.GetArgumentAtIndex(1)); 108 EXPECT_STREQ("2", args.GetArgumentAtIndex(2)); 109 EXPECT_STREQ("3", args.GetArgumentAtIndex(3)); 110 EXPECT_STREQ("3.5", args.GetArgumentAtIndex(4)); 111 } 112 113 TEST(ArgsTest, TestArgv) { 114 Args args; 115 EXPECT_EQ(nullptr, args.GetArgumentVector()); 116 117 args.AppendArgument("1"); 118 EXPECT_NE(nullptr, args.GetArgumentVector()[0]); 119 EXPECT_EQ(nullptr, args.GetArgumentVector()[1]); 120 121 args.AppendArgument("2"); 122 EXPECT_NE(nullptr, args.GetArgumentVector()[0]); 123 EXPECT_NE(nullptr, args.GetArgumentVector()[1]); 124 EXPECT_EQ(nullptr, args.GetArgumentVector()[2]); 125 126 args.AppendArgument("3"); 127 EXPECT_NE(nullptr, args.GetArgumentVector()[0]); 128 EXPECT_NE(nullptr, args.GetArgumentVector()[1]); 129 EXPECT_NE(nullptr, args.GetArgumentVector()[2]); 130 EXPECT_EQ(nullptr, args.GetArgumentVector()[3]); 131 132 args.InsertArgumentAtIndex(1, "1.5"); 133 EXPECT_NE(nullptr, args.GetArgumentVector()[0]); 134 EXPECT_NE(nullptr, args.GetArgumentVector()[1]); 135 EXPECT_NE(nullptr, args.GetArgumentVector()[2]); 136 EXPECT_NE(nullptr, args.GetArgumentVector()[3]); 137 EXPECT_EQ(nullptr, args.GetArgumentVector()[4]); 138 139 args.InsertArgumentAtIndex(4, "3.5"); 140 EXPECT_NE(nullptr, args.GetArgumentVector()[0]); 141 EXPECT_NE(nullptr, args.GetArgumentVector()[1]); 142 EXPECT_NE(nullptr, args.GetArgumentVector()[2]); 143 EXPECT_NE(nullptr, args.GetArgumentVector()[3]); 144 EXPECT_NE(nullptr, args.GetArgumentVector()[4]); 145 EXPECT_EQ(nullptr, args.GetArgumentVector()[5]); 146 } 147 148 TEST(ArgsTest, StringListConstructor) { 149 StringList list; 150 list << "foo" 151 << "bar" 152 << "baz"; 153 Args args(list); 154 ASSERT_EQ(3u, args.GetArgumentCount()); 155 EXPECT_EQ("foo", args[0].ref()); 156 EXPECT_EQ("bar", args[1].ref()); 157 EXPECT_EQ("baz", args[2].ref()); 158 } 159 160 TEST(ArgsTest, GetQuotedCommandString) { 161 Args args; 162 const char *str = "process launch -o stdout.txt -- \"a b c\""; 163 args.SetCommandString(str); 164 165 std::string stdstr; 166 ASSERT_TRUE(args.GetQuotedCommandString(stdstr)); 167 EXPECT_EQ(str, stdstr); 168 } 169 170 TEST(ArgsTest, BareSingleQuote) { 171 Args args; 172 args.SetCommandString("a\\'b"); 173 EXPECT_EQ(1u, args.GetArgumentCount()); 174 175 EXPECT_STREQ("a'b", args.GetArgumentAtIndex(0)); 176 } 177 178 TEST(ArgsTest, DoubleQuotedItem) { 179 Args args; 180 args.SetCommandString("\"a b c\""); 181 EXPECT_EQ(1u, args.GetArgumentCount()); 182 183 EXPECT_STREQ("a b c", args.GetArgumentAtIndex(0)); 184 } 185 186 TEST(ArgsTest, AppendArguments) { 187 Args args; 188 const char *argv[] = {"1", "2", nullptr}; 189 const char *argv2[] = {"3", "4", nullptr}; 190 191 args.AppendArguments(argv); 192 ASSERT_EQ(2u, args.GetArgumentCount()); 193 EXPECT_STREQ("1", args.GetArgumentVector()[0]); 194 EXPECT_STREQ("2", args.GetArgumentVector()[1]); 195 EXPECT_EQ(nullptr, args.GetArgumentVector()[2]); 196 EXPECT_STREQ("1", args.GetArgumentAtIndex(0)); 197 EXPECT_STREQ("2", args.GetArgumentAtIndex(1)); 198 199 args.AppendArguments(argv2); 200 ASSERT_EQ(4u, args.GetArgumentCount()); 201 EXPECT_STREQ("1", args.GetArgumentVector()[0]); 202 EXPECT_STREQ("2", args.GetArgumentVector()[1]); 203 EXPECT_STREQ("3", args.GetArgumentVector()[2]); 204 EXPECT_STREQ("4", args.GetArgumentVector()[3]); 205 EXPECT_EQ(nullptr, args.GetArgumentVector()[4]); 206 EXPECT_STREQ("1", args.GetArgumentAtIndex(0)); 207 EXPECT_STREQ("2", args.GetArgumentAtIndex(1)); 208 EXPECT_STREQ("3", args.GetArgumentAtIndex(2)); 209 EXPECT_STREQ("4", args.GetArgumentAtIndex(3)); 210 } 211 212 TEST(ArgsTest, GetArgumentArrayRef) { 213 Args args("foo bar"); 214 auto ref = args.GetArgumentArrayRef(); 215 ASSERT_EQ(2u, ref.size()); 216 EXPECT_STREQ("foo", ref[0]); 217 EXPECT_STREQ("bar", ref[1]); 218 } 219 220 TEST(ArgsTest, EscapeLLDBCommandArgument) { 221 const std::string foo = "foo'"; 222 EXPECT_EQ("foo\\'", Args::EscapeLLDBCommandArgument(foo, '\0')); 223 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo, '\'')); 224 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo, '`')); 225 EXPECT_EQ("foo'", Args::EscapeLLDBCommandArgument(foo, '"')); 226 227 const std::string bar = "bar\""; 228 EXPECT_EQ("bar\\\"", Args::EscapeLLDBCommandArgument(bar, '\0')); 229 EXPECT_EQ("bar\"", Args::EscapeLLDBCommandArgument(bar, '\'')); 230 EXPECT_EQ("bar\"", Args::EscapeLLDBCommandArgument(bar, '`')); 231 EXPECT_EQ("bar\\\"", Args::EscapeLLDBCommandArgument(bar, '"')); 232 233 const std::string baz = "baz`"; 234 EXPECT_EQ("baz\\`", Args::EscapeLLDBCommandArgument(baz, '\0')); 235 EXPECT_EQ("baz`", Args::EscapeLLDBCommandArgument(baz, '\'')); 236 EXPECT_EQ("baz`", Args::EscapeLLDBCommandArgument(baz, '`')); 237 EXPECT_EQ("baz\\`", Args::EscapeLLDBCommandArgument(baz, '"')); 238 239 const std::string quux = "quux\t"; 240 EXPECT_EQ("quux\\\t", Args::EscapeLLDBCommandArgument(quux, '\0')); 241 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux, '\'')); 242 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux, '`')); 243 EXPECT_EQ("quux\t", Args::EscapeLLDBCommandArgument(quux, '"')); 244 } 245 246 TEST(ArgsTest, ReplaceArgumentAtIndexShort) { 247 Args args; 248 args.SetCommandString("foo ba b"); 249 args.ReplaceArgumentAtIndex(0, "f"); 250 EXPECT_EQ(3u, args.GetArgumentCount()); 251 EXPECT_STREQ(args.GetArgumentAtIndex(0), "f"); 252 } 253 254 TEST(ArgsTest, ReplaceArgumentAtIndexEqual) { 255 Args args; 256 args.SetCommandString("foo ba b"); 257 args.ReplaceArgumentAtIndex(0, "bar"); 258 EXPECT_EQ(3u, args.GetArgumentCount()); 259 EXPECT_STREQ(args.GetArgumentAtIndex(0), "bar"); 260 } 261 262 TEST(ArgsTest, ReplaceArgumentAtIndexLonger) { 263 Args args; 264 args.SetCommandString("foo ba b"); 265 args.ReplaceArgumentAtIndex(0, "baar"); 266 EXPECT_EQ(3u, args.GetArgumentCount()); 267 EXPECT_STREQ(args.GetArgumentAtIndex(0), "baar"); 268 } 269 270 TEST(ArgsTest, ReplaceArgumentAtIndexOutOfRange) { 271 Args args; 272 args.SetCommandString("foo ba b"); 273 args.ReplaceArgumentAtIndex(3, "baar"); 274 EXPECT_EQ(3u, args.GetArgumentCount()); 275 EXPECT_STREQ(args.GetArgumentAtIndex(2), "b"); 276 } 277 278 TEST(ArgsTest, ReplaceArgumentAtIndexFarOutOfRange) { 279 Args args; 280 args.SetCommandString("foo ba b"); 281 args.ReplaceArgumentAtIndex(4, "baar"); 282 EXPECT_EQ(3u, args.GetArgumentCount()); 283 EXPECT_STREQ(args.GetArgumentAtIndex(2), "b"); 284 } 285