180814287SRaphael Isemann //===-- CompletionRequestTest.cpp -----------------------------------------===//
22443bbd4SRaphael Isemann //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62443bbd4SRaphael Isemann //
72443bbd4SRaphael Isemann //===----------------------------------------------------------------------===//
82443bbd4SRaphael Isemann
92443bbd4SRaphael Isemann #include "gtest/gtest.h"
102443bbd4SRaphael Isemann
112443bbd4SRaphael Isemann #include "lldb/Utility/CompletionRequest.h"
122443bbd4SRaphael Isemann using namespace lldb_private;
132443bbd4SRaphael Isemann
TEST(CompletionRequest,Constructor)142443bbd4SRaphael Isemann TEST(CompletionRequest, Constructor) {
15a2e76c0bSRaphael Isemann std::string command = "a bad c";
16a2e76c0bSRaphael Isemann const unsigned cursor_pos = 3;
1714f6465cSRaphael Isemann const size_t arg_index = 1;
182443bbd4SRaphael Isemann StringList matches;
197f88829cSRaphael Isemann CompletionResult result;
20a2e76c0bSRaphael Isemann
21b22860daSJonas Devlieghere CompletionRequest request(command, cursor_pos, result);
227f88829cSRaphael Isemann result.GetMatches(matches);
232443bbd4SRaphael Isemann
24*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLine(), "a b");
25*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLineWithUnusedSuffix(), command);
262443bbd4SRaphael Isemann EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
272443bbd4SRaphael Isemann EXPECT_EQ(request.GetCursorIndex(), arg_index);
28a2e76c0bSRaphael Isemann
29ef06dd43SRaphael Isemann EXPECT_EQ(request.GetParsedLine().GetArgumentCount(), 2u);
30823fd950SRaphael Isemann EXPECT_EQ(request.GetCursorArgumentPrefix().str(), "b");
311a6d7ab5SRaphael Isemann }
32a2e76c0bSRaphael Isemann
TEST(CompletionRequest,FakeLastArg)3314f6465cSRaphael Isemann TEST(CompletionRequest, FakeLastArg) {
3414f6465cSRaphael Isemann // We insert an empty fake argument into the argument list when the
3514f6465cSRaphael Isemann // cursor is after a space.
3614f6465cSRaphael Isemann std::string command = "a bad c ";
3714f6465cSRaphael Isemann const unsigned cursor_pos = command.size();
3814f6465cSRaphael Isemann CompletionResult result;
3914f6465cSRaphael Isemann
4014f6465cSRaphael Isemann CompletionRequest request(command, cursor_pos, result);
4114f6465cSRaphael Isemann
42*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLine(), command);
43*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLineWithUnusedSuffix(), command);
4414f6465cSRaphael Isemann EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
4514f6465cSRaphael Isemann EXPECT_EQ(request.GetCursorIndex(), 3U);
4614f6465cSRaphael Isemann
47ef06dd43SRaphael Isemann EXPECT_EQ(request.GetParsedLine().GetArgumentCount(), 4U);
48823fd950SRaphael Isemann EXPECT_EQ(request.GetCursorArgumentPrefix().str(), "");
4914f6465cSRaphael Isemann }
5014f6465cSRaphael Isemann
TEST(CompletionRequest,TryCompleteCurrentArgGood)5193ca36d7SRaphael Isemann TEST(CompletionRequest, TryCompleteCurrentArgGood) {
5293ca36d7SRaphael Isemann std::string command = "a bad c";
5393ca36d7SRaphael Isemann StringList matches, descriptions;
5493ca36d7SRaphael Isemann CompletionResult result;
5593ca36d7SRaphael Isemann
5693ca36d7SRaphael Isemann CompletionRequest request(command, 3, result);
5793ca36d7SRaphael Isemann request.TryCompleteCurrentArg("boo", "car");
5893ca36d7SRaphael Isemann result.GetMatches(matches);
5993ca36d7SRaphael Isemann result.GetDescriptions(descriptions);
6093ca36d7SRaphael Isemann
6193ca36d7SRaphael Isemann EXPECT_EQ(1U, result.GetResults().size());
6293ca36d7SRaphael Isemann EXPECT_STREQ("boo", matches.GetStringAtIndex(0U));
6393ca36d7SRaphael Isemann EXPECT_EQ(1U, descriptions.GetSize());
6493ca36d7SRaphael Isemann EXPECT_STREQ("car", descriptions.GetStringAtIndex(0U));
6593ca36d7SRaphael Isemann }
6693ca36d7SRaphael Isemann
TEST(CompletionRequest,TryCompleteCurrentArgBad)6793ca36d7SRaphael Isemann TEST(CompletionRequest, TryCompleteCurrentArgBad) {
6893ca36d7SRaphael Isemann std::string command = "a bad c";
6993ca36d7SRaphael Isemann CompletionResult result;
7093ca36d7SRaphael Isemann
7193ca36d7SRaphael Isemann CompletionRequest request(command, 3, result);
7293ca36d7SRaphael Isemann request.TryCompleteCurrentArg("car", "card");
7393ca36d7SRaphael Isemann
7493ca36d7SRaphael Isemann EXPECT_EQ(0U, result.GetResults().size());
7593ca36d7SRaphael Isemann }
7693ca36d7SRaphael Isemann
TEST(CompletionRequest,TryCompleteCurrentArgMode)7793ca36d7SRaphael Isemann TEST(CompletionRequest, TryCompleteCurrentArgMode) {
7893ca36d7SRaphael Isemann std::string command = "a bad c";
7993ca36d7SRaphael Isemann CompletionResult result;
8093ca36d7SRaphael Isemann
8193ca36d7SRaphael Isemann CompletionRequest request(command, 3, result);
8293ca36d7SRaphael Isemann request.TryCompleteCurrentArg<CompletionMode::Partial>("bar", "bard");
8393ca36d7SRaphael Isemann
8493ca36d7SRaphael Isemann EXPECT_EQ(1U, result.GetResults().size());
8593ca36d7SRaphael Isemann EXPECT_EQ(CompletionMode::Partial, result.GetResults()[0].GetMode());
8693ca36d7SRaphael Isemann }
8793ca36d7SRaphael Isemann
TEST(CompletionRequest,ShiftArguments)88f8e733f1SRaphael Isemann TEST(CompletionRequest, ShiftArguments) {
89f8e733f1SRaphael Isemann std::string command = "a bad c";
90f8e733f1SRaphael Isemann const unsigned cursor_pos = 3;
9114f6465cSRaphael Isemann const size_t arg_index = 1;
92f8e733f1SRaphael Isemann StringList matches;
93f8e733f1SRaphael Isemann CompletionResult result;
94f8e733f1SRaphael Isemann
95f8e733f1SRaphael Isemann CompletionRequest request(command, cursor_pos, result);
96f8e733f1SRaphael Isemann result.GetMatches(matches);
97f8e733f1SRaphael Isemann
98*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLine(), "a b");
99*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLineWithUnusedSuffix(), command);
100f8e733f1SRaphael Isemann EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
101f8e733f1SRaphael Isemann EXPECT_EQ(request.GetCursorIndex(), arg_index);
102f8e733f1SRaphael Isemann
103ef06dd43SRaphael Isemann EXPECT_EQ(request.GetParsedLine().GetArgumentCount(), 2u);
104ef06dd43SRaphael Isemann EXPECT_STREQ(request.GetParsedLine().GetArgumentAtIndex(1), "b");
105f8e733f1SRaphael Isemann
106f8e733f1SRaphael Isemann // Shift away the 'a' argument.
107f8e733f1SRaphael Isemann request.ShiftArguments();
108f8e733f1SRaphael Isemann
109f8e733f1SRaphael Isemann // The raw line/cursor stays identical.
110*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLine(), "a b");
111*243f52b5SRaphael Isemann EXPECT_EQ(request.GetRawLineWithUnusedSuffix(), command);
112f8e733f1SRaphael Isemann EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
113f8e733f1SRaphael Isemann
114f8e733f1SRaphael Isemann // Partially parsed line and cursor should be updated.
115f8e733f1SRaphael Isemann EXPECT_EQ(request.GetCursorIndex(), arg_index - 1U);
116ef06dd43SRaphael Isemann EXPECT_EQ(request.GetParsedLine().GetArgumentCount(), 1u);
117823fd950SRaphael Isemann EXPECT_EQ(request.GetCursorArgumentPrefix().str(), "b");
118f8e733f1SRaphael Isemann }
119f8e733f1SRaphael Isemann
TEST(CompletionRequest,DuplicateFiltering)1201a6d7ab5SRaphael Isemann TEST(CompletionRequest, DuplicateFiltering) {
1211a6d7ab5SRaphael Isemann std::string command = "a bad c";
1221a6d7ab5SRaphael Isemann const unsigned cursor_pos = 3;
1231a6d7ab5SRaphael Isemann StringList matches;
1241a6d7ab5SRaphael Isemann
1257f88829cSRaphael Isemann CompletionResult result;
126b22860daSJonas Devlieghere CompletionRequest request(command, cursor_pos, result);
1277f88829cSRaphael Isemann result.GetMatches(matches);
1281a6d7ab5SRaphael Isemann
1296632ad58SRaphael Isemann EXPECT_EQ(0U, result.GetNumberOfResults());
1301a6d7ab5SRaphael Isemann
1311a6d7ab5SRaphael Isemann // Add foo twice
1321a6d7ab5SRaphael Isemann request.AddCompletion("foo");
1337f88829cSRaphael Isemann result.GetMatches(matches);
1347f88829cSRaphael Isemann
1356632ad58SRaphael Isemann EXPECT_EQ(1U, result.GetNumberOfResults());
1361a6d7ab5SRaphael Isemann EXPECT_EQ(1U, matches.GetSize());
1371a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1381a6d7ab5SRaphael Isemann
1391a6d7ab5SRaphael Isemann request.AddCompletion("foo");
1407f88829cSRaphael Isemann result.GetMatches(matches);
1417f88829cSRaphael Isemann
1426632ad58SRaphael Isemann EXPECT_EQ(1U, result.GetNumberOfResults());
1431a6d7ab5SRaphael Isemann EXPECT_EQ(1U, matches.GetSize());
1441a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1451a6d7ab5SRaphael Isemann
1461a6d7ab5SRaphael Isemann // Add bar twice
1471a6d7ab5SRaphael Isemann request.AddCompletion("bar");
1487f88829cSRaphael Isemann result.GetMatches(matches);
1497f88829cSRaphael Isemann
1506632ad58SRaphael Isemann EXPECT_EQ(2U, result.GetNumberOfResults());
1511a6d7ab5SRaphael Isemann EXPECT_EQ(2U, matches.GetSize());
1521a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1531a6d7ab5SRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
1541a6d7ab5SRaphael Isemann
1551a6d7ab5SRaphael Isemann request.AddCompletion("bar");
1567f88829cSRaphael Isemann result.GetMatches(matches);
1577f88829cSRaphael Isemann
1586632ad58SRaphael Isemann EXPECT_EQ(2U, result.GetNumberOfResults());
1591a6d7ab5SRaphael Isemann EXPECT_EQ(2U, matches.GetSize());
1601a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1611a6d7ab5SRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
1621a6d7ab5SRaphael Isemann
1631a6d7ab5SRaphael Isemann // Add foo again.
1641a6d7ab5SRaphael Isemann request.AddCompletion("foo");
1657f88829cSRaphael Isemann result.GetMatches(matches);
1667f88829cSRaphael Isemann
1676632ad58SRaphael Isemann EXPECT_EQ(2U, result.GetNumberOfResults());
1681a6d7ab5SRaphael Isemann EXPECT_EQ(2U, matches.GetSize());
1691a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1701a6d7ab5SRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
1711a6d7ab5SRaphael Isemann
1721a6d7ab5SRaphael Isemann // Add something with an existing prefix
1731a6d7ab5SRaphael Isemann request.AddCompletion("foobar");
1747f88829cSRaphael Isemann result.GetMatches(matches);
1757f88829cSRaphael Isemann
1766632ad58SRaphael Isemann EXPECT_EQ(3U, result.GetNumberOfResults());
1771a6d7ab5SRaphael Isemann EXPECT_EQ(3U, matches.GetSize());
1781a6d7ab5SRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
1791a6d7ab5SRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
1801a6d7ab5SRaphael Isemann EXPECT_STREQ("foobar", matches.GetStringAtIndex(2));
1811a6d7ab5SRaphael Isemann }
1821a6d7ab5SRaphael Isemann
TEST(CompletionRequest,DuplicateFilteringWithComments)1837f88829cSRaphael Isemann TEST(CompletionRequest, DuplicateFilteringWithComments) {
1847f88829cSRaphael Isemann std::string command = "a bad c";
1857f88829cSRaphael Isemann const unsigned cursor_pos = 3;
1867f88829cSRaphael Isemann StringList matches, descriptions;
1877f88829cSRaphael Isemann
1887f88829cSRaphael Isemann CompletionResult result;
189b22860daSJonas Devlieghere CompletionRequest request(command, cursor_pos, result);
1907f88829cSRaphael Isemann result.GetMatches(matches);
1917f88829cSRaphael Isemann result.GetDescriptions(descriptions);
1927f88829cSRaphael Isemann
1936632ad58SRaphael Isemann EXPECT_EQ(0U, result.GetNumberOfResults());
1947f88829cSRaphael Isemann
1957f88829cSRaphael Isemann // Add foo twice with same comment
1967f88829cSRaphael Isemann request.AddCompletion("foo", "comment");
1977f88829cSRaphael Isemann result.GetMatches(matches);
1987f88829cSRaphael Isemann result.GetDescriptions(descriptions);
1997f88829cSRaphael Isemann
2006632ad58SRaphael Isemann EXPECT_EQ(1U, result.GetNumberOfResults());
2017f88829cSRaphael Isemann EXPECT_EQ(1U, matches.GetSize());
2027f88829cSRaphael Isemann EXPECT_EQ(1U, descriptions.GetSize());
2037f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
2047f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
2057f88829cSRaphael Isemann
2067f88829cSRaphael Isemann request.AddCompletion("foo", "comment");
2077f88829cSRaphael Isemann result.GetMatches(matches);
2087f88829cSRaphael Isemann result.GetDescriptions(descriptions);
2097f88829cSRaphael Isemann
2106632ad58SRaphael Isemann EXPECT_EQ(1U, result.GetNumberOfResults());
2117f88829cSRaphael Isemann EXPECT_EQ(1U, matches.GetSize());
2127f88829cSRaphael Isemann EXPECT_EQ(1U, descriptions.GetSize());
2137f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
2147f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
2157f88829cSRaphael Isemann
2167f88829cSRaphael Isemann // Add bar twice with different comments
2177f88829cSRaphael Isemann request.AddCompletion("bar", "comment");
2187f88829cSRaphael Isemann result.GetMatches(matches);
2197f88829cSRaphael Isemann result.GetDescriptions(descriptions);
2207f88829cSRaphael Isemann
2216632ad58SRaphael Isemann EXPECT_EQ(2U, result.GetNumberOfResults());
2227f88829cSRaphael Isemann EXPECT_EQ(2U, matches.GetSize());
2237f88829cSRaphael Isemann EXPECT_EQ(2U, descriptions.GetSize());
2247f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
2257f88829cSRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
2267f88829cSRaphael Isemann
2277f88829cSRaphael Isemann request.AddCompletion("bar", "another comment");
2287f88829cSRaphael Isemann result.GetMatches(matches);
2297f88829cSRaphael Isemann result.GetDescriptions(descriptions);
2307f88829cSRaphael Isemann
2316632ad58SRaphael Isemann EXPECT_EQ(3U, result.GetNumberOfResults());
2327f88829cSRaphael Isemann EXPECT_EQ(3U, matches.GetSize());
2337f88829cSRaphael Isemann EXPECT_EQ(3U, descriptions.GetSize());
2347f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
2357f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
2367f88829cSRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
2377f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1));
2387f88829cSRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(2));
2397f88829cSRaphael Isemann EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2));
2407f88829cSRaphael Isemann
2417f88829cSRaphael Isemann // Add foo again with no comment
2427f88829cSRaphael Isemann request.AddCompletion("foo");
2437f88829cSRaphael Isemann result.GetMatches(matches);
2447f88829cSRaphael Isemann result.GetDescriptions(descriptions);
2457f88829cSRaphael Isemann
2466632ad58SRaphael Isemann EXPECT_EQ(4U, result.GetNumberOfResults());
2477f88829cSRaphael Isemann EXPECT_EQ(4U, matches.GetSize());
2487f88829cSRaphael Isemann EXPECT_EQ(4U, descriptions.GetSize());
2497f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
2507f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
2517f88829cSRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
2527f88829cSRaphael Isemann EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1));
2537f88829cSRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(2));
2547f88829cSRaphael Isemann EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2));
2557f88829cSRaphael Isemann EXPECT_STREQ("foo", matches.GetStringAtIndex(3));
2567f88829cSRaphael Isemann EXPECT_STREQ("", descriptions.GetStringAtIndex(3));
2577f88829cSRaphael Isemann }
2587f88829cSRaphael Isemann
TEST(CompletionRequest,TestCompletionOwnership)2591a6d7ab5SRaphael Isemann TEST(CompletionRequest, TestCompletionOwnership) {
2601a6d7ab5SRaphael Isemann std::string command = "a bad c";
2611a6d7ab5SRaphael Isemann const unsigned cursor_pos = 3;
2621a6d7ab5SRaphael Isemann StringList matches;
2631a6d7ab5SRaphael Isemann
2647f88829cSRaphael Isemann CompletionResult result;
265b22860daSJonas Devlieghere CompletionRequest request(command, cursor_pos, result);
2661a6d7ab5SRaphael Isemann
2671a6d7ab5SRaphael Isemann std::string Temporary = "bar";
2681a6d7ab5SRaphael Isemann request.AddCompletion(Temporary);
2691a6d7ab5SRaphael Isemann // Manipulate our completion. The request should have taken a copy, so that
2701a6d7ab5SRaphael Isemann // shouldn't influence anything.
2711a6d7ab5SRaphael Isemann Temporary[0] = 'f';
2721a6d7ab5SRaphael Isemann
2737f88829cSRaphael Isemann result.GetMatches(matches);
2746632ad58SRaphael Isemann EXPECT_EQ(1U, result.GetNumberOfResults());
2751a6d7ab5SRaphael Isemann EXPECT_STREQ("bar", matches.GetStringAtIndex(0));
2762443bbd4SRaphael Isemann }
277