xref: /llvm-project/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp (revision b852fb1ec5fa15f0b913cc4988cbd09239b19904)
17cdd53daSDavid Spickett //===-- DumpValueObjectOptionsTests.cpp -----------------------------------===//
27cdd53daSDavid Spickett //
37cdd53daSDavid Spickett // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47cdd53daSDavid Spickett // See https://llvm.org/LICENSE.txt for license information.
57cdd53daSDavid Spickett // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67cdd53daSDavid Spickett //
77cdd53daSDavid Spickett //===----------------------------------------------------------------------===//
87cdd53daSDavid Spickett 
97cdd53daSDavid Spickett #include "Plugins/Platform/Linux/PlatformLinux.h"
107cdd53daSDavid Spickett #include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
117cdd53daSDavid Spickett #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
127cdd53daSDavid Spickett #include "TestingSupport/SubsystemRAII.h"
137cdd53daSDavid Spickett #include "TestingSupport/Symbol/ClangTestUtils.h"
147cdd53daSDavid Spickett #include "lldb/Core/Debugger.h"
157cdd53daSDavid Spickett #include "lldb/DataFormatters/DumpValueObjectOptions.h"
16*b852fb1eSJonas Devlieghere #include "lldb/ValueObject/ValueObject.h"
17*b852fb1eSJonas Devlieghere #include "lldb/ValueObject/ValueObjectConstResult.h"
187cdd53daSDavid Spickett 
197cdd53daSDavid Spickett #include "gtest/gtest.h"
207cdd53daSDavid Spickett 
21328d9f62SDavid Spickett #include <type_traits>
22328d9f62SDavid Spickett 
237cdd53daSDavid Spickett using namespace lldb;
247cdd53daSDavid Spickett using namespace lldb_private;
257cdd53daSDavid Spickett 
267cdd53daSDavid Spickett struct MockProcess : Process {
277cdd53daSDavid Spickett   MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
287cdd53daSDavid Spickett       : Process(target_sp, listener_sp) {}
297cdd53daSDavid Spickett 
307cdd53daSDavid Spickett   llvm::StringRef GetPluginName() override { return "mock process"; }
317cdd53daSDavid Spickett 
327cdd53daSDavid Spickett   bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {
337cdd53daSDavid Spickett     return false;
347cdd53daSDavid Spickett   };
357cdd53daSDavid Spickett 
367cdd53daSDavid Spickett   Status DoDestroy() override { return {}; }
377cdd53daSDavid Spickett 
387cdd53daSDavid Spickett   void RefreshStateAfterStop() override {}
397cdd53daSDavid Spickett 
407cdd53daSDavid Spickett   bool DoUpdateThreadList(ThreadList &old_thread_list,
417cdd53daSDavid Spickett                           ThreadList &new_thread_list) override {
427cdd53daSDavid Spickett     return false;
437cdd53daSDavid Spickett   };
447cdd53daSDavid Spickett 
457cdd53daSDavid Spickett   size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
467cdd53daSDavid Spickett                       Status &error) override {
477cdd53daSDavid Spickett     // No need to read memory in these tests.
487cdd53daSDavid Spickett     return size;
497cdd53daSDavid Spickett   }
507cdd53daSDavid Spickett };
517cdd53daSDavid Spickett 
527cdd53daSDavid Spickett class ValueObjectMockProcessTest : public ::testing::Test {
537cdd53daSDavid Spickett public:
547cdd53daSDavid Spickett   void SetUp() override {
557cdd53daSDavid Spickett     ArchSpec arch("i386-pc-linux");
567cdd53daSDavid Spickett     Platform::SetHostPlatform(
577cdd53daSDavid Spickett         platform_linux::PlatformLinux::CreateInstance(true, &arch));
587cdd53daSDavid Spickett     m_debugger_sp = Debugger::CreateInstance();
597cdd53daSDavid Spickett     ASSERT_TRUE(m_debugger_sp);
607cdd53daSDavid Spickett     m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
617cdd53daSDavid Spickett                                                 eLoadDependentsNo,
627cdd53daSDavid Spickett                                                 m_platform_sp, m_target_sp);
637cdd53daSDavid Spickett     ASSERT_TRUE(m_target_sp);
647cdd53daSDavid Spickett     ASSERT_TRUE(m_target_sp->GetArchitecture().IsValid());
657cdd53daSDavid Spickett     ASSERT_TRUE(m_platform_sp);
667cdd53daSDavid Spickett     m_listener_sp = Listener::MakeListener("dummy");
677cdd53daSDavid Spickett     m_process_sp = std::make_shared<MockProcess>(m_target_sp, m_listener_sp);
687cdd53daSDavid Spickett     ASSERT_TRUE(m_process_sp);
697cdd53daSDavid Spickett     m_exe_ctx = ExecutionContext(m_process_sp);
707cdd53daSDavid Spickett 
717cdd53daSDavid Spickett     m_holder = std::make_unique<clang_utils::TypeSystemClangHolder>("test");
727cdd53daSDavid Spickett     m_type_system = m_holder->GetAST();
737cdd53daSDavid Spickett   }
747cdd53daSDavid Spickett 
75328d9f62SDavid Spickett   template <typename UnderlyingType>
76328d9f62SDavid Spickett   void TestDumpEnum(
77328d9f62SDavid Spickett       const std::vector<std::pair<const char *, UnderlyingType>> enumerators,
78328d9f62SDavid Spickett       const std::vector<std::tuple<UnderlyingType, DumpValueObjectOptions,
79328d9f62SDavid Spickett                                    const char *>> &tests) {
80328d9f62SDavid Spickett     CompilerType enum_type = MakeEnumType(enumerators);
817cdd53daSDavid Spickett     StreamString strm;
827cdd53daSDavid Spickett     ConstString var_name("test_var");
837cdd53daSDavid Spickett     ByteOrder endian = endian::InlHostByteOrder();
847cdd53daSDavid Spickett     ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
857cdd53daSDavid Spickett     for (auto [value, options, expected] : tests) {
867cdd53daSDavid Spickett       DataExtractor data_extractor{&value, sizeof(value), endian, 4};
87d1bc75c0SAdrian Prantl       auto valobj_sp = ValueObjectConstResult::Create(exe_scope, enum_type,
88d1bc75c0SAdrian Prantl                                                       var_name, data_extractor);
89d1bc75c0SAdrian Prantl       if (llvm::Error error = valobj_sp->Dump(strm, options))
90d1bc75c0SAdrian Prantl         llvm::consumeError(std::move(error));
917cdd53daSDavid Spickett       ASSERT_STREQ(strm.GetString().str().c_str(), expected);
927cdd53daSDavid Spickett       strm.Clear();
937cdd53daSDavid Spickett     }
947cdd53daSDavid Spickett   }
957cdd53daSDavid Spickett 
96328d9f62SDavid Spickett   template <typename UnderlyingType>
97328d9f62SDavid Spickett   CompilerType MakeEnumType(
98328d9f62SDavid Spickett       const std::vector<std::pair<const char *, UnderlyingType>> enumerators) {
99328d9f62SDavid Spickett     CompilerType int_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
100328d9f62SDavid Spickett         std::is_same<UnderlyingType, int>::value ? lldb::eEncodingSint
101328d9f62SDavid Spickett                                                  : lldb::eEncodingUint,
102328d9f62SDavid Spickett         32);
103328d9f62SDavid Spickett     CompilerType enum_type = m_type_system->CreateEnumerationType(
104328d9f62SDavid Spickett         "TestEnum", m_type_system->GetTranslationUnitDecl(),
105328d9f62SDavid Spickett         OptionalClangModuleID(), Declaration(), int_type, false);
106328d9f62SDavid Spickett 
107328d9f62SDavid Spickett     m_type_system->StartTagDeclarationDefinition(enum_type);
108328d9f62SDavid Spickett     Declaration decl;
109328d9f62SDavid Spickett     for (auto [name, value] : enumerators)
110328d9f62SDavid Spickett       m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, name,
111328d9f62SDavid Spickett                                                           value, 32);
112328d9f62SDavid Spickett     m_type_system->CompleteTagDeclarationDefinition(enum_type);
113328d9f62SDavid Spickett 
114328d9f62SDavid Spickett     return enum_type;
115328d9f62SDavid Spickett   }
116328d9f62SDavid Spickett 
1177cdd53daSDavid Spickett   ExecutionContext m_exe_ctx;
1187cdd53daSDavid Spickett   TypeSystemClang *m_type_system;
1197cdd53daSDavid Spickett 
1207cdd53daSDavid Spickett private:
1217cdd53daSDavid Spickett   SubsystemRAII<FileSystem, HostInfo, platform_linux::PlatformLinux,
1227cdd53daSDavid Spickett                 ScriptInterpreterNone>
1237cdd53daSDavid Spickett       m_subsystems;
1247cdd53daSDavid Spickett 
1257cdd53daSDavid Spickett   std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
1267cdd53daSDavid Spickett   lldb::DebuggerSP m_debugger_sp;
1277cdd53daSDavid Spickett   lldb::TargetSP m_target_sp;
1287cdd53daSDavid Spickett   lldb::PlatformSP m_platform_sp;
1297cdd53daSDavid Spickett   lldb::ListenerSP m_listener_sp;
1307cdd53daSDavid Spickett   lldb::ProcessSP m_process_sp;
1317cdd53daSDavid Spickett };
1327cdd53daSDavid Spickett 
133328d9f62SDavid Spickett TEST_F(ValueObjectMockProcessTest, EmptyEnum) {
134328d9f62SDavid Spickett   // All values of an empty enum should be shown as plain numbers.
135328d9f62SDavid Spickett   TestDumpEnum<unsigned>({}, {{0, {}, "(TestEnum) test_var = 0\n"},
136328d9f62SDavid Spickett                               {1, {}, "(TestEnum) test_var = 1\n"},
137328d9f62SDavid Spickett                               {2, {}, "(TestEnum) test_var = 2\n"}});
138328d9f62SDavid Spickett 
139328d9f62SDavid Spickett   TestDumpEnum<int>({}, {{-2, {}, "(TestEnum) test_var = -2\n"},
140328d9f62SDavid Spickett                          {-1, {}, "(TestEnum) test_var = -1\n"},
141328d9f62SDavid Spickett                          {0, {}, "(TestEnum) test_var = 0\n"},
142328d9f62SDavid Spickett                          {1, {}, "(TestEnum) test_var = 1\n"},
143328d9f62SDavid Spickett                          {2, {}, "(TestEnum) test_var = 2\n"}});
144328d9f62SDavid Spickett }
145328d9f62SDavid Spickett 
1467cdd53daSDavid Spickett TEST_F(ValueObjectMockProcessTest, Enum) {
1477cdd53daSDavid Spickett   // This is not a bitfield-like enum, so values are printed as decimal by
1487cdd53daSDavid Spickett   // default. Also we only show the enumerator name if the value is an
1497cdd53daSDavid Spickett   // exact match.
150328d9f62SDavid Spickett   TestDumpEnum<unsigned>(
151328d9f62SDavid Spickett       {{"test_2", 2}, {"test_3", 3}},
1527cdd53daSDavid Spickett       {{0, {}, "(TestEnum) test_var = 0\n"},
1537cdd53daSDavid Spickett        {1, {}, "(TestEnum) test_var = 1\n"},
1547cdd53daSDavid Spickett        {2, {}, "(TestEnum) test_var = test_2\n"},
1557cdd53daSDavid Spickett        {3, {}, "(TestEnum) test_var = test_3\n"},
1567cdd53daSDavid Spickett        {4, {}, "(TestEnum) test_var = 4\n"},
1577cdd53daSDavid Spickett        {5, {}, "(TestEnum) test_var = 5\n"},
1587cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideRootName(true), "(TestEnum) 1\n"},
1597cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideRootType(true), "test_var = 1\n"},
1607cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
1617cdd53daSDavid Spickett         "1\n"},
1627cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideName(true), "(TestEnum) 1\n"},
1637cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideValue(true),
1647cdd53daSDavid Spickett         "(TestEnum) test_var =\n"},
1657cdd53daSDavid Spickett        {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
1667cdd53daSDavid Spickett         "(TestEnum) \n"}});
1677cdd53daSDavid Spickett }
1687cdd53daSDavid Spickett 
1697cdd53daSDavid Spickett TEST_F(ValueObjectMockProcessTest, BitFieldLikeEnum) {
1707cdd53daSDavid Spickett   // These enumerators set individual bits in the value, as if it were a flag
1717cdd53daSDavid Spickett   // set. lldb treats this as a "bitfield like enum". This means we show values
17231015240SDavid Spickett   // as hex, and values without exact matches are shown as a combination of
17331015240SDavid Spickett   // enumerators and any remaining value left over.
174328d9f62SDavid Spickett   TestDumpEnum<unsigned>(
175328d9f62SDavid Spickett       {{"test_2", 2}, {"test_4", 4}},
1767cdd53daSDavid Spickett       {
17731015240SDavid Spickett           {0, {}, "(TestEnum) test_var = 0x0\n"},
1787cdd53daSDavid Spickett           {1, {}, "(TestEnum) test_var = 0x1\n"},
1797cdd53daSDavid Spickett           {2, {}, "(TestEnum) test_var = test_2\n"},
1807cdd53daSDavid Spickett           {4, {}, "(TestEnum) test_var = test_4\n"},
1817cdd53daSDavid Spickett           {6, {}, "(TestEnum) test_var = test_2 | test_4\n"},
1827cdd53daSDavid Spickett           {7, {}, "(TestEnum) test_var = test_2 | test_4 | 0x1\n"},
1837cdd53daSDavid Spickett           {8, {}, "(TestEnum) test_var = 0x8\n"},
1847cdd53daSDavid Spickett           {1, DumpValueObjectOptions().SetHideRootName(true),
1857cdd53daSDavid Spickett            "(TestEnum) 0x1\n"},
1867cdd53daSDavid Spickett           {1, DumpValueObjectOptions().SetHideRootType(true),
1877cdd53daSDavid Spickett            "test_var = 0x1\n"},
1887cdd53daSDavid Spickett           {1,
1897cdd53daSDavid Spickett            DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
1907cdd53daSDavid Spickett            "0x1\n"},
1917cdd53daSDavid Spickett           {1, DumpValueObjectOptions().SetHideName(true), "(TestEnum) 0x1\n"},
1927cdd53daSDavid Spickett           {1, DumpValueObjectOptions().SetHideValue(true),
1937cdd53daSDavid Spickett            "(TestEnum) test_var =\n"},
1947cdd53daSDavid Spickett           {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
1957cdd53daSDavid Spickett            "(TestEnum) \n"},
1967cdd53daSDavid Spickett       });
1977cdd53daSDavid Spickett }
198