1 //===-- CompletionRequestTest.cpp -------------------------------*- C++ -*-===// 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/CompletionRequest.h" 12 using namespace lldb_private; 13 14 TEST(CompletionRequest, Constructor) { 15 std::string command = "a bad c"; 16 const unsigned cursor_pos = 3; 17 const int arg_index = 1; 18 const int arg_cursor_pos = 1; 19 StringList matches; 20 CompletionResult result; 21 22 CompletionRequest request(command, cursor_pos, result); 23 result.GetMatches(matches); 24 25 EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str()); 26 EXPECT_EQ(request.GetRawCursorPos(), cursor_pos); 27 EXPECT_EQ(request.GetCursorIndex(), arg_index); 28 EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos); 29 30 EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 2u); 31 EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(1), "b"); 32 } 33 34 TEST(CompletionRequest, TryCompleteCurrentArgGood) { 35 std::string command = "a bad c"; 36 StringList matches, descriptions; 37 CompletionResult result; 38 39 CompletionRequest request(command, 3, result); 40 request.TryCompleteCurrentArg("boo", "car"); 41 result.GetMatches(matches); 42 result.GetDescriptions(descriptions); 43 44 EXPECT_EQ(1U, result.GetResults().size()); 45 EXPECT_STREQ("boo", matches.GetStringAtIndex(0U)); 46 EXPECT_EQ(1U, descriptions.GetSize()); 47 EXPECT_STREQ("car", descriptions.GetStringAtIndex(0U)); 48 } 49 50 TEST(CompletionRequest, TryCompleteCurrentArgBad) { 51 std::string command = "a bad c"; 52 CompletionResult result; 53 54 CompletionRequest request(command, 3, result); 55 request.TryCompleteCurrentArg("car", "card"); 56 57 EXPECT_EQ(0U, result.GetResults().size()); 58 } 59 60 TEST(CompletionRequest, TryCompleteCurrentArgMode) { 61 std::string command = "a bad c"; 62 CompletionResult result; 63 64 CompletionRequest request(command, 3, result); 65 request.TryCompleteCurrentArg<CompletionMode::Partial>("bar", "bard"); 66 67 EXPECT_EQ(1U, result.GetResults().size()); 68 EXPECT_EQ(CompletionMode::Partial, result.GetResults()[0].GetMode()); 69 } 70 71 TEST(CompletionRequest, ShiftArguments) { 72 std::string command = "a bad c"; 73 const unsigned cursor_pos = 3; 74 const int arg_index = 1; 75 const int arg_cursor_pos = 1; 76 StringList matches; 77 CompletionResult result; 78 79 CompletionRequest request(command, cursor_pos, result); 80 result.GetMatches(matches); 81 82 EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str()); 83 EXPECT_EQ(request.GetRawCursorPos(), cursor_pos); 84 EXPECT_EQ(request.GetCursorIndex(), arg_index); 85 EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos); 86 87 EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 2u); 88 EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(1), "b"); 89 90 // Shift away the 'a' argument. 91 request.ShiftArguments(); 92 93 // The raw line/cursor stays identical. 94 EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str()); 95 EXPECT_EQ(request.GetRawCursorPos(), cursor_pos); 96 97 // Relative cursor position in arg is identical. 98 EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos); 99 100 // Partially parsed line and cursor should be updated. 101 EXPECT_EQ(request.GetCursorIndex(), arg_index - 1U); 102 EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 1u); 103 EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(0), "b"); 104 } 105 106 TEST(CompletionRequest, DuplicateFiltering) { 107 std::string command = "a bad c"; 108 const unsigned cursor_pos = 3; 109 StringList matches; 110 111 CompletionResult result; 112 CompletionRequest request(command, cursor_pos, result); 113 result.GetMatches(matches); 114 115 EXPECT_EQ(0U, result.GetNumberOfResults()); 116 117 // Add foo twice 118 request.AddCompletion("foo"); 119 result.GetMatches(matches); 120 121 EXPECT_EQ(1U, result.GetNumberOfResults()); 122 EXPECT_EQ(1U, matches.GetSize()); 123 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 124 125 request.AddCompletion("foo"); 126 result.GetMatches(matches); 127 128 EXPECT_EQ(1U, result.GetNumberOfResults()); 129 EXPECT_EQ(1U, matches.GetSize()); 130 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 131 132 // Add bar twice 133 request.AddCompletion("bar"); 134 result.GetMatches(matches); 135 136 EXPECT_EQ(2U, result.GetNumberOfResults()); 137 EXPECT_EQ(2U, matches.GetSize()); 138 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 139 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 140 141 request.AddCompletion("bar"); 142 result.GetMatches(matches); 143 144 EXPECT_EQ(2U, result.GetNumberOfResults()); 145 EXPECT_EQ(2U, matches.GetSize()); 146 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 147 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 148 149 // Add foo again. 150 request.AddCompletion("foo"); 151 result.GetMatches(matches); 152 153 EXPECT_EQ(2U, result.GetNumberOfResults()); 154 EXPECT_EQ(2U, matches.GetSize()); 155 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 156 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 157 158 // Add something with an existing prefix 159 request.AddCompletion("foobar"); 160 result.GetMatches(matches); 161 162 EXPECT_EQ(3U, result.GetNumberOfResults()); 163 EXPECT_EQ(3U, matches.GetSize()); 164 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 165 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 166 EXPECT_STREQ("foobar", matches.GetStringAtIndex(2)); 167 } 168 169 TEST(CompletionRequest, DuplicateFilteringWithComments) { 170 std::string command = "a bad c"; 171 const unsigned cursor_pos = 3; 172 StringList matches, descriptions; 173 174 CompletionResult result; 175 CompletionRequest request(command, cursor_pos, result); 176 result.GetMatches(matches); 177 result.GetDescriptions(descriptions); 178 179 EXPECT_EQ(0U, result.GetNumberOfResults()); 180 181 // Add foo twice with same comment 182 request.AddCompletion("foo", "comment"); 183 result.GetMatches(matches); 184 result.GetDescriptions(descriptions); 185 186 EXPECT_EQ(1U, result.GetNumberOfResults()); 187 EXPECT_EQ(1U, matches.GetSize()); 188 EXPECT_EQ(1U, descriptions.GetSize()); 189 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 190 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 191 192 request.AddCompletion("foo", "comment"); 193 result.GetMatches(matches); 194 result.GetDescriptions(descriptions); 195 196 EXPECT_EQ(1U, result.GetNumberOfResults()); 197 EXPECT_EQ(1U, matches.GetSize()); 198 EXPECT_EQ(1U, descriptions.GetSize()); 199 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 200 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 201 202 // Add bar twice with different comments 203 request.AddCompletion("bar", "comment"); 204 result.GetMatches(matches); 205 result.GetDescriptions(descriptions); 206 207 EXPECT_EQ(2U, result.GetNumberOfResults()); 208 EXPECT_EQ(2U, matches.GetSize()); 209 EXPECT_EQ(2U, descriptions.GetSize()); 210 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 211 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 212 213 request.AddCompletion("bar", "another comment"); 214 result.GetMatches(matches); 215 result.GetDescriptions(descriptions); 216 217 EXPECT_EQ(3U, result.GetNumberOfResults()); 218 EXPECT_EQ(3U, matches.GetSize()); 219 EXPECT_EQ(3U, descriptions.GetSize()); 220 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 221 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 222 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 223 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1)); 224 EXPECT_STREQ("bar", matches.GetStringAtIndex(2)); 225 EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2)); 226 227 // Add foo again with no comment 228 request.AddCompletion("foo"); 229 result.GetMatches(matches); 230 result.GetDescriptions(descriptions); 231 232 EXPECT_EQ(4U, result.GetNumberOfResults()); 233 EXPECT_EQ(4U, matches.GetSize()); 234 EXPECT_EQ(4U, descriptions.GetSize()); 235 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 236 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 237 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 238 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1)); 239 EXPECT_STREQ("bar", matches.GetStringAtIndex(2)); 240 EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2)); 241 EXPECT_STREQ("foo", matches.GetStringAtIndex(3)); 242 EXPECT_STREQ("", descriptions.GetStringAtIndex(3)); 243 } 244 245 TEST(CompletionRequest, TestCompletionOwnership) { 246 std::string command = "a bad c"; 247 const unsigned cursor_pos = 3; 248 StringList matches; 249 250 CompletionResult result; 251 CompletionRequest request(command, cursor_pos, result); 252 253 std::string Temporary = "bar"; 254 request.AddCompletion(Temporary); 255 // Manipulate our completion. The request should have taken a copy, so that 256 // shouldn't influence anything. 257 Temporary[0] = 'f'; 258 259 result.GetMatches(matches); 260 EXPECT_EQ(1U, result.GetNumberOfResults()); 261 EXPECT_STREQ("bar", matches.GetStringAtIndex(0)); 262 } 263