Skip to content

Commit 304c28f

Browse files
committed
adding DisassembledInstruction unit tests
1 parent 1014235 commit 304c28f

File tree

4 files changed

+137
-7
lines changed

4 files changed

+137
-7
lines changed

lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments &args) const {
8282
}
8383

8484
DisassembledInstruction disassembled_inst;
85-
disassembled_inst.address = "0x" + llvm::utohexstr(inst_addr);
85+
disassembled_inst.address = inst_addr;
8686
disassembled_inst.instructionBytes =
8787
bytes.size() > 0 ? bytes.substr(0, bytes.size() - 1) : "";
8888

lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "Protocol/ProtocolTypes.h"
10+
#include "JSONUtils.h"
11+
#include "lldb/lldb-types.h"
12+
#include "llvm/ADT/StringExtras.h"
1013
#include "llvm/ADT/StringRef.h"
1114
#include "llvm/Support/ErrorHandling.h"
1215
#include "llvm/Support/JSON.h"
@@ -782,18 +785,69 @@ bool fromJSON(const llvm::json::Value &Params, InstructionBreakpoint &IB,
782785
O.mapOptional("mode", IB.mode);
783786
}
784787

788+
bool fromJSON(const llvm::json::Value &Params,
789+
DisassembledInstruction::PresentationHint &PH,
790+
llvm::json::Path P) {
791+
auto rawHint = Params.getAsString();
792+
if (!rawHint) {
793+
P.report("expected a string");
794+
return false;
795+
}
796+
std::optional<DisassembledInstruction::PresentationHint> hint =
797+
StringSwitch<std::optional<DisassembledInstruction::PresentationHint>>(
798+
*rawHint)
799+
.Case("normal", DisassembledInstruction::
800+
eDisassembledInstructionPresentationHintNormal)
801+
.Case("invalid", DisassembledInstruction::
802+
eDisassembledInstructionPresentationHintInvalid)
803+
.Default(std::nullopt);
804+
if (!hint) {
805+
P.report("unexpected value");
806+
return false;
807+
}
808+
PH = *hint;
809+
return true;
810+
}
811+
785812
llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &PH) {
786813
switch (PH) {
787-
case DisassembledInstruction::eSourcePresentationHintNormal:
814+
case DisassembledInstruction::eDisassembledInstructionPresentationHintNormal:
788815
return "normal";
789-
case DisassembledInstruction::eSourcePresentationHintInvalid:
816+
case DisassembledInstruction::eDisassembledInstructionPresentationHintInvalid:
790817
return "invalid";
791818
}
792819
llvm_unreachable("unhandled presentation hint.");
793820
}
794821

822+
bool fromJSON(const llvm::json::Value &Params, DisassembledInstruction &DI,
823+
llvm::json::Path P) {
824+
std::optional<llvm::StringRef> raw_address =
825+
Params.getAsObject()->getString("address");
826+
if (!raw_address) {
827+
P.report("missing `address` field");
828+
return false;
829+
}
830+
831+
std::optional<lldb::addr_t> address = DecodeMemoryReference(*raw_address);
832+
if (!address) {
833+
P.report("invalid `address`");
834+
return false;
835+
}
836+
837+
DI.address = *address;
838+
llvm::json::ObjectMapper O(Params, P);
839+
return O && O.map("instruction", DI.instruction) &&
840+
O.mapOptional("instructionBytes", DI.instructionBytes) &&
841+
O.mapOptional("symbol", DI.symbol) &&
842+
O.mapOptional("location", DI.location) &&
843+
O.mapOptional("line", DI.line) && O.mapOptional("column", DI.column) &&
844+
O.mapOptional("endLine", DI.endLine) &&
845+
O.mapOptional("endColumn", DI.endColumn) &&
846+
O.mapOptional("presentationHint", DI.presentationHint);
847+
}
848+
795849
llvm::json::Value toJSON(const DisassembledInstruction &DI) {
796-
llvm::json::Object result{{"address", DI.address},
850+
llvm::json::Object result{{"address", "0x" + llvm::utohexstr(DI.address)},
797851
{"instruction", DI.instruction}};
798852

799853
if (DI.instructionBytes)

lldb/tools/lldb-dap/Protocol/ProtocolTypes.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,13 +631,13 @@ bool fromJSON(const llvm::json::Value &, InstructionBreakpoint &,
631631
/// request.
632632
struct DisassembledInstruction {
633633
enum PresentationHint : unsigned {
634-
eSourcePresentationHintNormal,
635-
eSourcePresentationHintInvalid,
634+
eDisassembledInstructionPresentationHintNormal,
635+
eDisassembledInstructionPresentationHintInvalid,
636636
};
637637

638638
/// The address of the instruction. Treated as a hex value if prefixed with
639639
/// `0x`, or as a decimal value otherwise.
640-
std::string address;
640+
lldb::addr_t address;
641641

642642
/// Raw bytes representing the instruction and its operands, in an
643643
/// implementation-defined format.
@@ -678,7 +678,11 @@ struct DisassembledInstruction {
678678
/// Values: 'normal', 'invalid'
679679
std::optional<PresentationHint> presentationHint;
680680
};
681+
bool fromJSON(const llvm::json::Value &,
682+
DisassembledInstruction::PresentationHint &, llvm::json::Path);
681683
llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &);
684+
bool fromJSON(const llvm::json::Value &, DisassembledInstruction &,
685+
llvm::json::Path);
682686
llvm::json::Value toJSON(const DisassembledInstruction &);
683687

684688
} // namespace lldb_dap::protocol

lldb/unittests/DAP/ProtocolTypesTest.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,3 +530,75 @@ TEST(ProtocolTypesTest, ChecksumAlgorithm) {
530530
llvm::json::Path::Root root;
531531
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
532532
}
533+
534+
TEST(ProtocolTypesTest, DisassembledInstructionPresentationHint) {
535+
// Test all PresentationHint values.
536+
std::vector<
537+
std::pair<DisassembledInstruction::PresentationHint, llvm::StringRef>>
538+
test_cases = {{DisassembledInstruction::
539+
eDisassembledInstructionPresentationHintNormal,
540+
"normal"},
541+
{DisassembledInstruction::
542+
eDisassembledInstructionPresentationHintInvalid,
543+
"invalid"}};
544+
545+
for (const auto &test_case : test_cases) {
546+
// Serialize the PresentationHint to JSON.
547+
llvm::json::Value serialized = toJSON(test_case.first);
548+
ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
549+
EXPECT_EQ(serialized.getAsString(), test_case.second);
550+
551+
// Deserialize the JSON back to PresentationHint.
552+
DisassembledInstruction::PresentationHint deserialized;
553+
llvm::json::Path::Root root;
554+
ASSERT_TRUE(fromJSON(serialized, deserialized, root))
555+
<< llvm::toString(root.getError());
556+
EXPECT_EQ(deserialized, test_case.first);
557+
}
558+
559+
// Test invalid value.
560+
llvm::json::Value invalid_value = "invalid_hint";
561+
DisassembledInstruction::PresentationHint deserialized_invalid;
562+
llvm::json::Path::Root root;
563+
EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
564+
}
565+
566+
TEST(ProtocolTypesTest, DisassembledInstruction) {
567+
DisassembledInstruction instruction;
568+
instruction.address = 0x12345678;
569+
instruction.instructionBytes = "0F 1F 00";
570+
instruction.instruction = "mov eax, ebx";
571+
instruction.symbol = "main";
572+
instruction.location = Source{"test.cpp", "/path/to/test.cpp", 123,
573+
Source::eSourcePresentationHintNormal};
574+
instruction.line = 10;
575+
instruction.column = 5;
576+
instruction.endLine = 15;
577+
instruction.endColumn = 10;
578+
instruction.presentationHint =
579+
DisassembledInstruction::eDisassembledInstructionPresentationHintNormal;
580+
581+
llvm::Expected<DisassembledInstruction> deserialized_instruction =
582+
roundtrip(instruction);
583+
ASSERT_THAT_EXPECTED(deserialized_instruction, llvm::Succeeded());
584+
585+
EXPECT_EQ(instruction.address, deserialized_instruction->address);
586+
EXPECT_EQ(instruction.instructionBytes,
587+
deserialized_instruction->instructionBytes);
588+
EXPECT_EQ(instruction.instruction, deserialized_instruction->instruction);
589+
EXPECT_EQ(instruction.symbol, deserialized_instruction->symbol);
590+
EXPECT_EQ(instruction.location->name,
591+
deserialized_instruction->location->name);
592+
EXPECT_EQ(instruction.location->path,
593+
deserialized_instruction->location->path);
594+
EXPECT_EQ(instruction.location->sourceReference,
595+
deserialized_instruction->location->sourceReference);
596+
EXPECT_EQ(instruction.location->presentationHint,
597+
deserialized_instruction->location->presentationHint);
598+
EXPECT_EQ(instruction.line, deserialized_instruction->line);
599+
EXPECT_EQ(instruction.column, deserialized_instruction->column);
600+
EXPECT_EQ(instruction.endLine, deserialized_instruction->endLine);
601+
EXPECT_EQ(instruction.endColumn, deserialized_instruction->endColumn);
602+
EXPECT_EQ(instruction.presentationHint,
603+
deserialized_instruction->presentationHint);
604+
}

0 commit comments

Comments
 (0)