Author: Gongyu Deng Date: 2020-08-24T17:55:54+02:00 New Revision: 3cd8d7b1727f06a701f41764c1109e5d321284b3
URL: https://github.com/llvm/llvm-project/commit/3cd8d7b1727f06a701f41764c1109e5d321284b3 DIFF: https://github.com/llvm/llvm-project/commit/3cd8d7b1727f06a701f41764c1109e5d321284b3.diff LOG: [lldb] Remote disk file/directory completion for platform commands 1. Extended the gdb-remote communication related classes with disk file/directory completion functions; 2. Added two common completion functions RemoteDiskFiles and RemoteDiskDirectories based on the functions above; 3. Added completion for these commands: A. platform get-file <remote-file> <local-file>; B. platform put-file <local-file> <remote-file>; C. platform get-size <remote-file>; D. platform settings -w <remote-dir>; E. platform open file <remote-file>. 4. Added related tests for client and server; 5. Updated docs/lldb-platform-packets.txt. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D85284 Added: lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteDiskFileCompletion.py lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py Modified: lldb/docs/lldb-platform-packets.txt lldb/include/lldb/Interpreter/CommandCompletions.h lldb/include/lldb/Target/Platform.h lldb/include/lldb/Utility/StringExtractorGDBRemote.h lldb/source/Commands/CommandCompletions.cpp lldb/source/Commands/CommandObjectPlatform.cpp lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h lldb/source/Utility/StringExtractorGDBRemote.cpp lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py Removed: ################################################################################ diff --git a/lldb/docs/lldb-platform-packets.txt b/lldb/docs/lldb-platform-packets.txt index 23d1cacc5f7e..8d3fed7ab341 100644 --- a/lldb/docs/lldb-platform-packets.txt +++ b/lldb/docs/lldb-platform-packets.txt @@ -237,6 +237,27 @@ incompatible with the flags that gdb specifies. // Continues to return the results of the qfProcessInfo. Once all matches // have been sent, Exx is returned to indicate end of matches. +//---------------------------------------------------------------------- +// qPathComplete +// +// BRIEF +// Get a list of matched disk files/directories by passing a boolean flag +// and a partial path. +// +// EXAMPLE +// +// receive: qPathComplete:0,6d61696e +// send: M6d61696e2e637070 +// receive: qPathComplete:1,746573 +// send: M746573742f,74657374732f +// +// If the first argument is zero, the result should contain all +// files (including directories) starting with the given path. If the +// argument is one, the result should contain only directories. +// +// The result should be a comma-separated list of hex-encoded paths. +// Paths denoting a directory should end with a directory separator ('/' or '\'). + //---------------------------------------------------------------------- // vFile:size: // diff --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h index 0392eaed62c5..b90e81cb95a8 100644 --- a/lldb/include/lldb/Interpreter/CommandCompletions.h +++ b/lldb/include/lldb/Interpreter/CommandCompletions.h @@ -47,10 +47,12 @@ class CommandCompletions { eBreakpointNameCompletion = (1u << 19), eProcessIDCompletion = (1u << 20), eProcessNameCompletion = (1u << 21), + eRemoteDiskFileCompletion = (1u << 22), + eRemoteDiskDirectoryCompletion = (1u << 23), // This item serves two purposes. It is the last element in the enum, so // you can add custom enums starting from here in your Option class. Also // if you & in this bit the base code will not process the option. - eCustomCompletion = (1u << 22) + eCustomCompletion = (1u << 24) }; static bool InvokeCommonCompletionCallbacks( @@ -72,6 +74,14 @@ class CommandCompletions { StringList &matches, TildeExpressionResolver &Resolver); + static void RemoteDiskFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher); + + static void RemoteDiskDirectories(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher); + static void SourceFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 6234b8244b3f..9335f73b37df 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -523,6 +523,9 @@ class Platform : public PluginInterface { return UINT64_MAX; } + virtual void AutoCompleteDiskFileOrDirectory(CompletionRequest &request, + bool only_dir) {} + virtual uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error) { error.SetErrorStringWithFormat( diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index 715f3cb2541d..efb43767e739 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -76,6 +76,7 @@ class StringExtractorGDBRemote : public StringExtractor { eServerPacketType_QSetSTDERR, eServerPacketType_QSetWorkingDir, eServerPacketType_QStartNoAckMode, + eServerPacketType_qPathComplete, eServerPacketType_qPlatform_shell, eServerPacketType_qPlatform_mkdir, eServerPacketType_qPlatform_chmod, diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index 9e74d8ad26cd..9221830b6460 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -73,6 +73,8 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, {eProcessIDCompletion, CommandCompletions::ProcessIDs}, {eProcessNameCompletion, CommandCompletions::ProcessNames}, + {eRemoteDiskFileCompletion, CommandCompletions::RemoteDiskFiles}, + {eRemoteDiskDirectoryCompletion, CommandCompletions::RemoteDiskDirectories}, {eNoCompletion, nullptr} // This one has to be last in the list. }; @@ -486,6 +488,24 @@ void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); } +void CommandCompletions::RemoteDiskFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + lldb::PlatformSP platform_sp = + interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + if (platform_sp) + platform_sp->AutoCompleteDiskFileOrDirectory(request, false); +} + +void CommandCompletions::RemoteDiskDirectories(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + lldb::PlatformSP platform_sp = + interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); + if (platform_sp) + platform_sp->AutoCompleteDiskFileOrDirectory(request, true); +} + void CommandCompletions::Modules(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher) { diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index da113e5cb342..b5409e611f05 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -392,7 +392,8 @@ class CommandObjectPlatformSettings : public CommandObjectParsed { "or for a platform by name.", "platform settings", 0), m_options(), - m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0, + m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', + CommandCompletions::eRemoteDiskDirectoryCompletion, eArgTypePath, "The working directory for the platform.") { m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -485,6 +486,15 @@ class CommandObjectPlatformFOpen : public CommandObjectParsed { ~CommandObjectPlatformFOpen() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + if (request.GetCursorIndex() == 0) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), + CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + } + bool DoExecute(Args &args, CommandReturnObject &result) override { PlatformSP platform_sp( GetDebugger().GetPlatformList().GetSelectedPlatform()); @@ -817,6 +827,19 @@ class CommandObjectPlatformGetFile : public CommandObjectParsed { ~CommandObjectPlatformGetFile() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + if (request.GetCursorIndex() == 0) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), + CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + else if (request.GetCursorIndex() == 1) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + request, nullptr); + } + bool DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 2) { @@ -882,6 +905,17 @@ class CommandObjectPlatformGetSize : public CommandObjectParsed { ~CommandObjectPlatformGetSize() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + if (request.GetCursorIndex() != 0) + return; + + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion, + request, nullptr); + } + bool DoExecute(Args &args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 1) { @@ -927,6 +961,19 @@ class CommandObjectPlatformPutFile : public CommandObjectParsed { ~CommandObjectPlatformPutFile() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + if (request.GetCursorIndex() == 0) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, + request, nullptr); + else if (request.GetCursorIndex() == 1) + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), + CommandCompletions::eRemoteDiskFileCompletion, request, nullptr); + } + bool DoExecute(Args &args, CommandReturnObject &result) override { const char *src = args.GetArgumentAtIndex(0); const char *dst = args.GetArgumentAtIndex(1); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 21bf7f4ac46d..e1eb15c3e8c9 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -661,6 +661,11 @@ PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) { return m_gdb_client.GetFileSize(file_spec); } +void PlatformRemoteGDBServer::AutoCompleteDiskFileOrDirectory( + CompletionRequest &request, bool only_dir) { + m_gdb_client.AutoCompleteDiskFileOrDirectory(request, only_dir); +} + uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error) { diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 0602be1fa377..3562b2bb09df 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -127,6 +127,9 @@ class PlatformRemoteGDBServer : public Platform, private UserIDResolver { lldb::user_id_t GetFileSize(const FileSpec &file_spec) override; + void AutoCompleteDiskFileOrDirectory(CompletionRequest &request, + bool only_dir) override; + Status PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index cf0daccc2d0c..2e6d174e4674 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -2982,6 +2982,31 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( return UINT64_MAX; } +void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory( + CompletionRequest &request, bool only_dir) { + lldb_private::StreamString stream; + stream.PutCString("qPathComplete:"); + stream.PutHex32(only_dir ? 1 : 0); + stream.PutChar(','); + stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix()); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + PacketResult::Success) { + StreamString strm; + char ch = response.GetChar(); + if (ch != 'M') + return; + while (response.Peek()) { + strm.Clear(); + while ((ch = response.GetHexU8(0, false)) != '\0') + strm.PutChar(ch); + request.AddCompletion(strm.GetString()); + if (response.GetChar() != ',') + break; + } + } +} + Status GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 8df08cbde735..0159125a433b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -375,6 +375,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { lldb::user_id_t GetFileSize(const FileSpec &file_spec); + void AutoCompleteDiskFileOrDirectory(CompletionRequest &request, + bool only_dir); + Status GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index d14b79a03d17..7e94afb9ec68 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -26,12 +26,14 @@ #include "lldb/Host/FileAction.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Target/Platform.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/TildeExpressionResolver.h" #include "lldb/Utility/UriParser.h" #include "lldb/Utility/StringExtractorGDBRemote.h" @@ -68,6 +70,9 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qProcessInfo, &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qPathComplete, + &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); @@ -333,6 +338,38 @@ GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo( return SendPacketNoLock(response.GetString()); } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qPathComplete( + StringExtractorGDBRemote &packet) { + packet.SetFilePos(::strlen("qPathComplete:")); + const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1); + if (packet.GetChar() != ',') + return SendErrorResponse(85); + std::string path; + packet.GetHexByteString(path); + + StringList matches; + StandardTildeExpressionResolver resolver; + if (only_dir) + CommandCompletions::DiskDirectories(path, matches, resolver); + else + CommandCompletions::DiskFiles(path, matches, resolver); + + StreamString response; + response.PutChar('M'); + llvm::StringRef separator; + std::sort(matches.begin(), matches.end()); + for (const auto &match : matches) { + response << separator; + separator = ","; + // encode result strings into hex bytes to avoid unexpected error caused by + // special characters like '$'. + response.PutStringAsRawHex8(match.c_str()); + } + + return SendPacketNoLock(response.GetString()); +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir( StringExtractorGDBRemote &packet) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index a8cacea78835..8b3122d1423e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -81,6 +81,8 @@ class GDBRemoteCommunicationServerPlatform PacketResult Handle_qKillSpawnedProcess(StringExtractorGDBRemote &packet); + PacketResult Handle_qPathComplete(StringExtractorGDBRemote &packet); + PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index cfe7577e4863..2901500b29e3 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -233,6 +233,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_qPlatform_chmod; if (PACKET_MATCHES("qProcessInfo")) return eServerPacketType_qProcessInfo; + if (PACKET_STARTS_WITH("qPathComplete:")) + return eServerPacketType_qPathComplete; break; case 'Q': diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteDiskFileCompletion.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteDiskFileCompletion.py new file mode 100644 index 000000000000..90f830c4a278 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteDiskFileCompletion.py @@ -0,0 +1,29 @@ +from gdbclientutils import * + +class TestGDBRemoteDiskFileCompletion(GDBRemoteTestBase): + + def test_autocomplete_request(self): + """Test remote disk completion on remote-gdb-server plugin""" + + class Responder(MockGDBServerResponder): + def qPathComplete(self): + return "M{},{}".format( + "test".encode().hex(), + "123".encode().hex() + ) + + self.server.responder = Responder() + + try: + self.runCmd("platform select remote-gdb-server") + self.runCmd("platform connect connect://localhost:%d" % + self.server.port) + self.assertTrue(self.dbg.GetSelectedPlatform().IsConnected()) + + self.complete_from_to('platform get-size ', ['test', '123']) + self.complete_from_to('platform get-file ', ['test', '123']) + self.complete_from_to('platform put-file foo ', ['test', '123']) + self.complete_from_to('platform file open ', ['test', '123']) + self.complete_from_to('platform settings -w ', ['test', '123']) + finally: + self.dbg.GetSelectedPlatform().DisconnectRemote() diff --git a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py index feda8873d872..eb789e861d9c 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py +++ b/lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py @@ -178,6 +178,8 @@ def respond(self, packet): return self.qsProcessInfo() if packet.startswith("qfProcessInfo"): return self.qfProcessInfo(packet) + if packet.startswith("qPathComplete:"): + return self.qPathComplete() return self.other(packet) @@ -282,6 +284,9 @@ def QListThreadsInStopReply(self): def qMemoryRegionInfo(self): return "" + def qPathComplete(self): + return "" + """ Raised when we receive a packet for which there is no default action. Override the responder class to implement behavior suitable for the test at diff --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py new file mode 100644 index 000000000000..94e628c811af --- /dev/null +++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteCompletion.py @@ -0,0 +1,63 @@ +import tempfile +import gdbremote_testcase +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbgdbserverutils import * + +class GdbRemoteCompletionTestCase(gdbremote_testcase.GdbRemoteTestCaseBase): + mydir = TestBase.compute_mydir(__file__) + + def init_lldb_server(self): + self.debug_monitor_exe = get_lldb_server_exe() + if not self.debug_monitor_exe: + self.skipTest("lldb-server exe not found") + port_file = tempfile.NamedTemporaryFile().name + commandline_args = [ + "platform", + "--listen", + "*:0", + "--socket-file", + port_file + ] + server = self.spawnSubprocess( + get_lldb_server_exe(), + commandline_args, + install_remote=False) + self.assertIsNotNone(server) + self.stub_hostname = "localhost" + self.port = int(lldbutil.wait_for_file_on_target(self, port_file)) + self.sock = self.create_socket() + + self.add_no_ack_remote_stream() + + def generate_hex_path(self, target): + return str(os.path.join(self.getBuildDir(), target)).encode().hex() + + @skipIfDarwinEmbedded # <rdar://problem/34539270> lldb-server tests not updated to work on ios etc yet + @llgs_test + def test_autocomplete_path(self): + self.build() + self.init_lldb_server() + + # Test file-included completion when flag is set to 0. + self.test_sequence.add_log_lines( + ["read packet: $qPathComplete:0,{}#00".format( + self.generate_hex_path("main")), + "send packet: $M{},{}#00".format( + self.generate_hex_path("main.d"), + self.generate_hex_path("main.o")) + ], + True) + + # Test directory-only completion when flag is set to 1. + os.makedirs(os.path.join(self.getBuildDir(), "test")) + self.test_sequence.add_log_lines( + ["read packet: $qPathComplete:1,{}#00".format( + self.generate_hex_path("tes")), + "send packet: $M{}{}#00".format( + self.generate_hex_path("test"), + os.path.sep.encode().hex()) # "test/" or "test\". + ], + True) + + self.expect_gdbremote_sequence() _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits