Skip to content

Commit

Permalink
Retry ""[lldb-vscode] Fix TestVSCode_module""
Browse files Browse the repository at this point in the history
Original commit c60216d.

The test can only run on Darwin because of how it was setup, so I'm
enforcing that.

Summary:

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:
  • Loading branch information
walter-erquinigo committed Jul 13, 2020
1 parent 32d35fb commit 77c9aaf
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
Expand Up @@ -113,6 +113,7 @@ def __init__(self, recv, send, init_commands):
self.initialize_body = None
self.thread_stop_reasons = {}
self.breakpoint_events = []
self.module_events = {}
self.sequence = 1
self.threads = None
self.recv_thread.start()
Expand All @@ -133,6 +134,9 @@ def validate_response(cls, command, response):
if command['seq'] != response['request_seq']:
raise ValueError('seq mismatch in response')

def get_active_modules(self):
return self.module_events

def get_output(self, category, timeout=0.0, clear=True):
self.output_condition.acquire()
output = None
Expand Down Expand Up @@ -218,6 +222,15 @@ def handle_recv_packet(self, packet):
self.breakpoint_events.append(packet)
# no need to add 'breakpoint' event packets to our packets list
return keepGoing
elif event == 'module':
reason = body['reason']
if (reason == 'new' or reason == 'changed'):
self.module_events[body['module']['name']] = body['module']
elif reason == 'removed':
if body['module']['name'] in self.module_events:
self.module_events.pop(body['module']['name'])
return keepGoing

elif packet_type == 'response':
if packet['command'] == 'disconnect':
keepGoing = False
Expand Down Expand Up @@ -747,6 +760,16 @@ def request_setFunctionBreakpoints(self, names, condition=None,
}
return self.send_recv(command_dict)

def request_getCompileUnits(self, moduleId):
args_dict = {'moduleId': moduleId}
command_dict = {
'command': 'getCompileUnits',
'type': 'request',
'arguments': args_dict
}
response = self.send_recv(command_dict)
return response

def request_completions(self, text):
args_dict = {
'text': text,
Expand Down
13 changes: 13 additions & 0 deletions lldb/test/API/tools/lldb-vscode/module/Makefile
@@ -0,0 +1,13 @@
DYLIB_NAME := foo
DYLIB_CXX_SOURCES := foo.cpp
CXX_SOURCES := main.cpp

all: a.out.stripped

include Makefile.rules

a.out.stripped: a.out.dSYM
strip -o a.out.stripped a.out
ifneq "$(CODESIGN)" ""
$(CODESIGN) -fs - a.out.stripped
endif
72 changes: 72 additions & 0 deletions lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py
@@ -0,0 +1,72 @@
"""
Test lldb-vscode setBreakpoints request
"""

from __future__ import print_function

import unittest2
import vscode
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import lldbvscode_testcase


class TestVSCode_module(lldbvscode_testcase.VSCodeTestCaseBase):

mydir = TestBase.compute_mydir(__file__)


@skipIfWindows
@skipUnlessDarwin
@skipIfRemote
def test_modules_event(self):
program_basename = "a.out.stripped"
program= self.getBuildArtifact(program_basename)
self.build_and_launch(program)
functions = ['foo']
breakpoint_ids = self.set_function_breakpoints(functions)
self.assertEquals(len(breakpoint_ids), len(functions),
'expect one breakpoint')
self.continue_to_breakpoints(breakpoint_ids)
active_modules = self.vscode.get_active_modules()
self.assertIn(program_basename, active_modules, '%s module is in active modules' % (program_basename))
program_module = active_modules[program_basename]
self.assertIn('name', program_module, 'make sure name is in module')
self.assertEqual(program_basename, program_module['name'])
self.assertIn('path', program_module, 'make sure path is in module')
self.assertEqual(program, program_module['path'])
self.assertTrue('symbolFilePath' not in program_module, 'Make sure a.out.stripped has no debug info')
self.assertEqual('Symbols not found.', program_module['symbolStatus'])
symbol_path = self.getBuildArtifact("a.out")
self.vscode.request_evaluate('`%s' % ('target symbols add -s "%s" "%s"' % (program, symbol_path)))
active_modules = self.vscode.get_active_modules()
program_module = active_modules[program_basename]
self.assertEqual(program_basename, program_module['name'])
self.assertEqual(program, program_module['path'])
self.assertEqual('Symbols loaded.', program_module['symbolStatus'])
self.assertIn('symbolFilePath', program_module)
self.assertEqual(symbol_path, program_module['symbolFilePath'])
self.assertIn('addressRange', program_module)

@skipIfWindows
@skipUnlessDarwin
@skipIfRemote
def test_compile_units(self):
program= self.getBuildArtifact("a.out")
self.build_and_launch(program)
source = "main.cpp"
main_source_path = self.getSourcePath(source)
breakpoint1_line = line_number(source, '// breakpoint 1')
lines = [breakpoint1_line]
breakpoint_ids = self.set_source_breakpoints(source, lines)
self.continue_to_breakpoints(breakpoint_ids)
moduleId = self.vscode.get_active_modules()['a.out']['id']
response = self.vscode.request_getCompileUnits(moduleId)
print(response['body'])
self.assertTrue(response['body'])
self.assertTrue(len(response['body']['compileUnits']) == 1,
'Only one source file should exist')
self.assertTrue(response['body']['compileUnits'][0]['compileUnitPath'] == main_source_path,
'Real path to main.cpp matches')

3 changes: 3 additions & 0 deletions lldb/test/API/tools/lldb-vscode/module/foo.cpp
@@ -0,0 +1,3 @@
int foo() {
return 12;
}
1 change: 1 addition & 0 deletions lldb/test/API/tools/lldb-vscode/module/foo.h
@@ -0,0 +1 @@
int foo();
6 changes: 6 additions & 0 deletions lldb/test/API/tools/lldb-vscode/module/main.cpp
@@ -0,0 +1,6 @@
#include "foo.h"

int main(int argc, char const *argv[]) {
foo();
return 0; // breakpoint 1
}
44 changes: 44 additions & 0 deletions lldb/tools/lldb-vscode/JSONUtils.cpp
Expand Up @@ -327,6 +327,41 @@ llvm::json::Value CreateBreakpoint(lldb::SBBreakpoint &bp,
return llvm::json::Value(std::move(object));
}

llvm::json::Value CreateModule(lldb::SBModule &module) {
llvm::json::Object object;
if (!module.IsValid())
return llvm::json::Value(std::move(object));
object.try_emplace("id", std::string(module.GetUUIDString()));
object.try_emplace("name", std::string(module.GetFileSpec().GetFilename()));
char module_path_arr[PATH_MAX];
module.GetFileSpec().GetPath(module_path_arr, sizeof(module_path_arr));
std::string module_path(module_path_arr);
object.try_emplace("path", module_path);
if (module.GetNumCompileUnits() > 0) {
object.try_emplace("symbolStatus", "Symbols loaded.");
char symbol_path_arr[PATH_MAX];
module.GetSymbolFileSpec().GetPath(symbol_path_arr, sizeof(symbol_path_arr));
std::string symbol_path(symbol_path_arr);
object.try_emplace("symbolFilePath", symbol_path);
} else {
object.try_emplace("symbolStatus", "Symbols not found.");
}
std::string loaded_addr = std::to_string(
module.GetObjectFileHeaderAddress().GetLoadAddress(g_vsc.target));
object.try_emplace("addressRange", loaded_addr);
std::string version_str;
uint32_t version_nums[3];
uint32_t num_versions = module.GetVersion(version_nums, sizeof(version_nums)/sizeof(uint32_t));
for (uint32_t i=0; i<num_versions; ++i) {
if (!version_str.empty())
version_str += ".";
version_str += std::to_string(version_nums[i]);
}
if (!version_str.empty())
object.try_emplace("version", version_str);
return llvm::json::Value(std::move(object));
}

void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints,
llvm::Optional<llvm::StringRef> request_path,
llvm::Optional<uint32_t> request_line) {
Expand Down Expand Up @@ -902,4 +937,13 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
return llvm::json::Value(std::move(object));
}

llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit) {
llvm::json::Object object;
char unit_path_arr[PATH_MAX];
unit.GetFileSpec().GetPath(unit_path_arr, sizeof(unit_path_arr));
std::string unit_path(unit_path_arr);
object.try_emplace("compileUnitPath", unit_path);
return llvm::json::Value(std::move(object));
}

} // namespace lldb_vscode
13 changes: 13 additions & 0 deletions lldb/tools/lldb-vscode/JSONUtils.h
Expand Up @@ -13,6 +13,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include "VSCodeForward.h"
#include "lldb/API/SBModule.h"

namespace lldb_vscode {

Expand Down Expand Up @@ -237,6 +238,16 @@ CreateBreakpoint(lldb::SBBreakpoint &bp,
llvm::Optional<llvm::StringRef> request_path = llvm::None,
llvm::Optional<uint32_t> request_line = llvm::None);

/// Converts a LLDB module to a VS Code DAP module for use in "modules" events.
///
/// \param[in] module
/// A LLDB module object to convert into a JSON value
///
/// \return
/// A "Module" JSON object with that follows the formal JSON
/// definition outlined by Microsoft.
llvm::json::Value CreateModule(lldb::SBModule &module);

/// Create a "Event" JSON object using \a event_name as the event name
///
/// \param[in] event_name
Expand Down Expand Up @@ -430,6 +441,8 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id);
llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
int64_t varID, bool format_hex);

llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit);

} // namespace lldb_vscode

#endif
5 changes: 5 additions & 0 deletions lldb/tools/lldb-vscode/VSCode.cpp
Expand Up @@ -358,6 +358,11 @@ void VSCode::SetTarget(const lldb::SBTarget target) {
lldb::SBTarget::eBroadcastBitBreakpointChanged);
listener.StartListeningForEvents(this->broadcaster,
eBroadcastBitStopEventThread);
listener.StartListeningForEvents(
this->target.GetBroadcaster(),
lldb::SBTarget::eBroadcastBitModulesLoaded |
lldb::SBTarget::eBroadcastBitModulesUnloaded |
lldb::SBTarget::eBroadcastBitSymbolsLoaded);
}
}

Expand Down
92 changes: 92 additions & 0 deletions lldb/tools/lldb-vscode/lldb-vscode.cpp
Expand Up @@ -39,6 +39,7 @@
#include <set>
#include <sstream>
#include <thread>
#include <vector>

#include "llvm/ADT/ArrayRef.h"
#include "llvm/Option/Arg.h"
Expand Down Expand Up @@ -434,6 +435,30 @@ void EventThreadFunction() {
g_vsc.SendJSON(llvm::json::Value(std::move(bp_event)));
}
}
} else if (lldb::SBTarget::EventIsTargetEvent(event)) {
if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded ||
event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded ||
event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded) {
int num_modules = lldb::SBTarget::GetNumModulesFromEvent(event);
for (int i = 0; i < num_modules; i++) {
auto module = lldb::SBTarget::GetModuleAtIndexFromEvent(i, event);
auto module_event = CreateEventObject("module");
llvm::json::Value module_value = CreateModule(module);
llvm::json::Object body;
if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded) {
body.try_emplace("reason", "new");
} else if (event_mask &
lldb::SBTarget::eBroadcastBitModulesUnloaded) {
body.try_emplace("reason", "removed");
} else if (event_mask &
lldb::SBTarget::eBroadcastBitSymbolsLoaded) {
body.try_emplace("reason", "changed");
}
body.try_emplace("module", module_value);
module_event.try_emplace("body", std::move(body));
g_vsc.SendJSON(llvm::json::Value(std::move(module_event)));
}
}
} else if (event.BroadcasterMatchesRef(g_vsc.broadcaster)) {
if (event_mask & eBroadcastBitStopEventThread) {
done = true;
Expand Down Expand Up @@ -1149,6 +1174,72 @@ void request_evaluate(const llvm::json::Object &request) {
g_vsc.SendJSON(llvm::json::Value(std::move(response)));
}

// "getCompileUnitsRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
// "description": "Compile Unit request; value of command field is
// 'getCompileUnits'.",
// "properties": {
// "command": {
// "type": "string",
// "enum": [ "getCompileUnits" ]
// },
// "arguments": {
// "$ref": "#/definitions/getCompileUnitRequestArguments"
// }
// },
// "required": [ "command", "arguments" ]
// }]
// },
// "getCompileUnitsRequestArguments": {
// "type": "object",
// "description": "Arguments for 'getCompileUnits' request.",
// "properties": {
// "moduleId": {
// "type": "string",
// "description": "The ID of the module."
// }
// },
// "required": [ "moduleId" ]
// },
// "getCompileUnitsResponse": {
// "allOf": [ { "$ref": "#/definitions/Response" }, {
// "type": "object",
// "description": "Response to 'getCompileUnits' request.",
// "properties": {
// "body": {
// "description": "Response to 'getCompileUnits' request. Array of
// paths of compile units."
// }
// }
// }]
// }

void request_getCompileUnits(const llvm::json::Object &request) {
llvm::json::Object response;
FillResponse(request, response);
lldb::SBProcess process = g_vsc.target.GetProcess();
llvm::json::Object body;
llvm::json::Array units;
auto arguments = request.getObject("arguments");
std::string module_id = std::string(GetString(arguments, "moduleId"));
int num_modules = g_vsc.target.GetNumModules();
for (int i = 0; i < num_modules; i++) {
auto curr_module = g_vsc.target.GetModuleAtIndex(i);
if (module_id == curr_module.GetUUIDString()) {
int num_units = curr_module.GetNumCompileUnits();
for (int j = 0; j < num_units; j++) {
auto curr_unit = curr_module.GetCompileUnitAtIndex(j);\
units.emplace_back(CreateCompileUnit(curr_unit));\
}
body.try_emplace("compileUnits", std::move(units));
break;
}
}
response.try_emplace("body", std::move(body));
g_vsc.SendJSON(llvm::json::Value(std::move(response)));
}

// "InitializeRequest": {
// "allOf": [ { "$ref": "#/definitions/Request" }, {
// "type": "object",
Expand Down Expand Up @@ -2734,6 +2825,7 @@ const std::map<std::string, RequestCallback> &GetRequestHandlers() {
REQUEST_CALLBACK(disconnect),
REQUEST_CALLBACK(evaluate),
REQUEST_CALLBACK(exceptionInfo),
REQUEST_CALLBACK(getCompileUnits),
REQUEST_CALLBACK(initialize),
REQUEST_CALLBACK(launch),
REQUEST_CALLBACK(next),
Expand Down

0 comments on commit 77c9aaf

Please sign in to comment.