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, ShiftArguments) { 35 std::string command = "a bad c"; 36 const unsigned cursor_pos = 3; 37 const int arg_index = 1; 38 const int arg_cursor_pos = 1; 39 StringList matches; 40 CompletionResult result; 41 42 CompletionRequest request(command, cursor_pos, result); 43 result.GetMatches(matches); 44 45 EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str()); 46 EXPECT_EQ(request.GetRawCursorPos(), cursor_pos); 47 EXPECT_EQ(request.GetCursorIndex(), arg_index); 48 EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos); 49 50 EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 2u); 51 EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(1), "b"); 52 53 // Shift away the 'a' argument. 54 request.ShiftArguments(); 55 56 // The raw line/cursor stays identical. 57 EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str()); 58 EXPECT_EQ(request.GetRawCursorPos(), cursor_pos); 59 60 // Relative cursor position in arg is identical. 61 EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos); 62 63 // Partially parsed line and cursor should be updated. 64 EXPECT_EQ(request.GetCursorIndex(), arg_index - 1U); 65 EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 1u); 66 EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(0), "b"); 67 } 68 69 TEST(CompletionRequest, DuplicateFiltering) { 70 std::string command = "a bad c"; 71 const unsigned cursor_pos = 3; 72 StringList matches; 73 74 CompletionResult result; 75 CompletionRequest request(command, cursor_pos, result); 76 result.GetMatches(matches); 77 78 EXPECT_EQ(0U, result.GetNumberOfResults()); 79 80 // Add foo twice 81 request.AddCompletion("foo"); 82 result.GetMatches(matches); 83 84 EXPECT_EQ(1U, result.GetNumberOfResults()); 85 EXPECT_EQ(1U, matches.GetSize()); 86 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 87 88 request.AddCompletion("foo"); 89 result.GetMatches(matches); 90 91 EXPECT_EQ(1U, result.GetNumberOfResults()); 92 EXPECT_EQ(1U, matches.GetSize()); 93 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 94 95 // Add bar twice 96 request.AddCompletion("bar"); 97 result.GetMatches(matches); 98 99 EXPECT_EQ(2U, result.GetNumberOfResults()); 100 EXPECT_EQ(2U, matches.GetSize()); 101 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 102 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 103 104 request.AddCompletion("bar"); 105 result.GetMatches(matches); 106 107 EXPECT_EQ(2U, result.GetNumberOfResults()); 108 EXPECT_EQ(2U, matches.GetSize()); 109 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 110 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 111 112 // Add foo again. 113 request.AddCompletion("foo"); 114 result.GetMatches(matches); 115 116 EXPECT_EQ(2U, result.GetNumberOfResults()); 117 EXPECT_EQ(2U, matches.GetSize()); 118 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 119 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 120 121 // Add something with an existing prefix 122 request.AddCompletion("foobar"); 123 result.GetMatches(matches); 124 125 EXPECT_EQ(3U, result.GetNumberOfResults()); 126 EXPECT_EQ(3U, matches.GetSize()); 127 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 128 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 129 EXPECT_STREQ("foobar", matches.GetStringAtIndex(2)); 130 } 131 132 TEST(CompletionRequest, DuplicateFilteringWithComments) { 133 std::string command = "a bad c"; 134 const unsigned cursor_pos = 3; 135 StringList matches, descriptions; 136 137 CompletionResult result; 138 CompletionRequest request(command, cursor_pos, result); 139 result.GetMatches(matches); 140 result.GetDescriptions(descriptions); 141 142 EXPECT_EQ(0U, result.GetNumberOfResults()); 143 144 // Add foo twice with same comment 145 request.AddCompletion("foo", "comment"); 146 result.GetMatches(matches); 147 result.GetDescriptions(descriptions); 148 149 EXPECT_EQ(1U, result.GetNumberOfResults()); 150 EXPECT_EQ(1U, matches.GetSize()); 151 EXPECT_EQ(1U, descriptions.GetSize()); 152 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 153 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 154 155 request.AddCompletion("foo", "comment"); 156 result.GetMatches(matches); 157 result.GetDescriptions(descriptions); 158 159 EXPECT_EQ(1U, result.GetNumberOfResults()); 160 EXPECT_EQ(1U, matches.GetSize()); 161 EXPECT_EQ(1U, descriptions.GetSize()); 162 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 163 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 164 165 // Add bar twice with different comments 166 request.AddCompletion("bar", "comment"); 167 result.GetMatches(matches); 168 result.GetDescriptions(descriptions); 169 170 EXPECT_EQ(2U, result.GetNumberOfResults()); 171 EXPECT_EQ(2U, matches.GetSize()); 172 EXPECT_EQ(2U, descriptions.GetSize()); 173 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 174 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 175 176 request.AddCompletion("bar", "another comment"); 177 result.GetMatches(matches); 178 result.GetDescriptions(descriptions); 179 180 EXPECT_EQ(3U, result.GetNumberOfResults()); 181 EXPECT_EQ(3U, matches.GetSize()); 182 EXPECT_EQ(3U, descriptions.GetSize()); 183 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 184 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 185 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 186 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1)); 187 EXPECT_STREQ("bar", matches.GetStringAtIndex(2)); 188 EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2)); 189 190 // Add foo again with no comment 191 request.AddCompletion("foo"); 192 result.GetMatches(matches); 193 result.GetDescriptions(descriptions); 194 195 EXPECT_EQ(4U, result.GetNumberOfResults()); 196 EXPECT_EQ(4U, matches.GetSize()); 197 EXPECT_EQ(4U, descriptions.GetSize()); 198 EXPECT_STREQ("foo", matches.GetStringAtIndex(0)); 199 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0)); 200 EXPECT_STREQ("bar", matches.GetStringAtIndex(1)); 201 EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1)); 202 EXPECT_STREQ("bar", matches.GetStringAtIndex(2)); 203 EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2)); 204 EXPECT_STREQ("foo", matches.GetStringAtIndex(3)); 205 EXPECT_STREQ("", descriptions.GetStringAtIndex(3)); 206 } 207 208 TEST(CompletionRequest, TestCompletionOwnership) { 209 std::string command = "a bad c"; 210 const unsigned cursor_pos = 3; 211 StringList matches; 212 213 CompletionResult result; 214 CompletionRequest request(command, cursor_pos, result); 215 216 std::string Temporary = "bar"; 217 request.AddCompletion(Temporary); 218 // Manipulate our completion. The request should have taken a copy, so that 219 // shouldn't influence anything. 220 Temporary[0] = 'f'; 221 222 result.GetMatches(matches); 223 EXPECT_EQ(1U, result.GetNumberOfResults()); 224 EXPECT_STREQ("bar", matches.GetStringAtIndex(0)); 225 } 226