https://github.com/DavidSpickett updated 
https://github.com/llvm/llvm-project/pull/93158

>From 0c6fe37563d7e7ee338a308b32cbea01d1f3808c Mon Sep 17 00:00:00 2001
From: David Spickett <david.spick...@linaro.org>
Date: Wed, 1 May 2024 13:08:54 +0000
Subject: [PATCH 1/2] [lldb][Test] Add C++ tests for DumpValueObjectOptions and
 enums

DumpValueObjectOptions can only be created and modified from C++.
This means it's currently only testable from Python by calling some
command that happens to use one, and even so, you can't pick
which options get chosen.

So we have decent coverage for the major options that way, but I
want to add more niche options that will be harder to test from
Python (register field options).

So this change adds some "unit tests", though it's stretching the
definition to the point it's more "test written in C++". So
we can test future options in isolation.

Since I want to add options specific to enums, that's all it covers.
There is a test class that sets up the type system so it will be
easy to test other types in future (e.g. structs, which register
fields also use).
---
 lldb/unittests/CMakeLists.txt                 |   1 +
 lldb/unittests/ValueObject/CMakeLists.txt     |  10 ++
 .../DumpValueObjectOptionsTests.cpp           | 136 ++++++++++++++++++
 3 files changed, 147 insertions(+)
 create mode 100644 lldb/unittests/ValueObject/CMakeLists.txt
 create mode 100644 lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp

diff --git a/lldb/unittests/CMakeLists.txt b/lldb/unittests/CMakeLists.txt
index c084fa5cca92b..dc1d8b69f0036 100644
--- a/lldb/unittests/CMakeLists.txt
+++ b/lldb/unittests/CMakeLists.txt
@@ -73,6 +73,7 @@ add_subdirectory(tools)
 add_subdirectory(UnwindAssembly)
 add_subdirectory(Utility)
 add_subdirectory(Thread)
+add_subdirectory(ValueObject)
 
 if(LLDB_CAN_USE_DEBUGSERVER AND LLDB_TOOL_DEBUGSERVER_BUILD AND NOT 
LLDB_USE_SYSTEM_DEBUGSERVER)
   add_subdirectory(debugserver)
diff --git a/lldb/unittests/ValueObject/CMakeLists.txt 
b/lldb/unittests/ValueObject/CMakeLists.txt
new file mode 100644
index 0000000000000..fb31f76506286
--- /dev/null
+++ b/lldb/unittests/ValueObject/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_unittest(LLDBValueObjectTests
+  DumpValueObjectOptionsTests.cpp
+
+  LINK_LIBS
+    lldbPluginPlatformLinux
+    lldbPluginScriptInterpreterNone
+
+  LINK_COMPONENTS
+    Support
+  )
diff --git a/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp 
b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
new file mode 100644
index 0000000000000..e89ec4508f6d8
--- /dev/null
+++ b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
@@ -0,0 +1,136 @@
+//===-- DumpValueObjectOptionsTests.cpp 
-----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Platform/Linux/PlatformLinux.h"
+#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
+#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "TestingSupport/Symbol/ClangTestUtils.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+struct MockProcess : Process {
+  MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)
+      : Process(target_sp, listener_sp) {}
+
+  llvm::StringRef GetPluginName() override { return "mock process"; }
+
+  bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override 
{
+    return false;
+  };
+
+  Status DoDestroy() override { return {}; }
+
+  void RefreshStateAfterStop() override {}
+
+  bool DoUpdateThreadList(ThreadList &old_thread_list,
+                          ThreadList &new_thread_list) override {
+    return false;
+  };
+
+  size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+                      Status &error) override {
+    // No need to read memory in these tests.
+    return size;
+  }
+};
+
+class ValueObjectMockProcessTest : public ::testing::Test {
+public:
+  void SetUp() override {
+    ArchSpec arch("i386-pc-linux");
+    Platform::SetHostPlatform(
+        platform_linux::PlatformLinux::CreateInstance(true, &arch));
+    m_debugger_sp = Debugger::CreateInstance();
+    ASSERT_TRUE(m_debugger_sp);
+    m_debugger_sp->GetTargetList().CreateTarget(*m_debugger_sp, "", arch,
+                                                eLoadDependentsNo,
+                                                m_platform_sp, m_target_sp);
+    ASSERT_TRUE(m_target_sp);
+    ASSERT_TRUE(m_target_sp->GetArchitecture().IsValid());
+    ASSERT_TRUE(m_platform_sp);
+    m_listener_sp = Listener::MakeListener("dummy");
+    m_process_sp = std::make_shared<MockProcess>(m_target_sp, m_listener_sp);
+    ASSERT_TRUE(m_process_sp);
+    m_exe_ctx = ExecutionContext(m_process_sp);
+
+    m_holder = std::make_unique<clang_utils::TypeSystemClangHolder>("test");
+    m_type_system = m_holder->GetAST();
+  }
+
+  ExecutionContext m_exe_ctx;
+  TypeSystemClang *m_type_system;
+
+private:
+  SubsystemRAII<FileSystem, HostInfo, platform_linux::PlatformLinux,
+                ScriptInterpreterNone>
+      m_subsystems;
+
+  std::unique_ptr<clang_utils::TypeSystemClangHolder> m_holder;
+  lldb::DebuggerSP m_debugger_sp;
+  lldb::TargetSP m_target_sp;
+  lldb::PlatformSP m_platform_sp;
+  lldb::ListenerSP m_listener_sp;
+  lldb::ProcessSP m_process_sp;
+};
+
+TEST_F(ValueObjectMockProcessTest, Enum) {
+  CompilerType uint_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
+      lldb::eEncodingUint, 32);
+  CompilerType enum_type = m_type_system->CreateEnumerationType(
+      "test_enum", m_type_system->GetTranslationUnitDecl(),
+      OptionalClangModuleID(), Declaration(), uint_type, false);
+
+  m_type_system->StartTagDeclarationDefinition(enum_type);
+  Declaration decl;
+  // Each value sets one bit in the enum, to make this a "bitfield like enum".
+  m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, 
"test_2",
+                                                      2, 32);
+  m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, 
"test_4",
+                                                      4, 32);
+  m_type_system->CompleteTagDeclarationDefinition(enum_type);
+
+  std::vector<std::tuple<uint32_t, DumpValueObjectOptions, const char *>> 
enums{
+      {0, {}, "(test_enum) test_var =\n"},
+      {1, {}, "(test_enum) test_var = 0x1\n"},
+      {2, {}, "(test_enum) test_var = test_2\n"},
+      {4, {}, "(test_enum) test_var = test_4\n"},
+      {6, {}, "(test_enum) test_var = test_2 | test_4\n"},
+      {7, {}, "(test_enum) test_var = test_2 | test_4 | 0x1\n"},
+      {8, {}, "(test_enum) test_var = 0x8\n"},
+      {1, DumpValueObjectOptions().SetHideRootName(true), "(test_enum) 0x1\n"},
+      {1, DumpValueObjectOptions().SetHideRootType(true), "test_var = 0x1\n"},
+      {1, DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
+       "0x1\n"},
+      {1, DumpValueObjectOptions().SetHideName(true), "(test_enum) 0x1\n"},
+      {1, DumpValueObjectOptions().SetHideValue(true),
+       "(test_enum) test_var =\n"},
+      {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
+       "(test_enum) \n"},
+  };
+
+  StreamString strm;
+  ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
+  ConstString var_name("test_var");
+  ByteOrder endian = endian::InlHostByteOrder();
+  for (auto [value, options, expected] : enums) {
+    DataExtractor data_extractor{&value, sizeof(value), endian, 4};
+    ValueObjectConstResult::Create(exe_scope, enum_type, var_name,
+                                   data_extractor)
+        ->Dump(strm, options);
+    ASSERT_STREQ(strm.GetString().str().c_str(), expected);
+    strm.Clear();
+  }
+}

>From cf967ad89924534ecd84cd31c984134d87a5eee8 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spick...@linaro.org>
Date: Thu, 23 May 2024 09:41:24 +0000
Subject: [PATCH 2/2] non bitfield enum tests and refactoring

---
 .../DumpValueObjectOptionsTests.cpp           | 130 ++++++++++++------
 1 file changed, 85 insertions(+), 45 deletions(-)

diff --git a/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp 
b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
index e89ec4508f6d8..31068a04d8dfe 100644
--- a/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
+++ b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
@@ -70,6 +70,42 @@ class ValueObjectMockProcessTest : public ::testing::Test {
     m_type_system = m_holder->GetAST();
   }
 
+  CompilerType
+  MakeEnumType(const std::vector<std::pair<const char *, int>> enumerators) {
+    CompilerType uint_type = 
m_type_system->GetBuiltinTypeForEncodingAndBitSize(
+        lldb::eEncodingUint, 32);
+    CompilerType enum_type = m_type_system->CreateEnumerationType(
+        "TestEnum", m_type_system->GetTranslationUnitDecl(),
+        OptionalClangModuleID(), Declaration(), uint_type, false);
+
+    m_type_system->StartTagDeclarationDefinition(enum_type);
+    Declaration decl;
+    for (auto [name, value] : enumerators)
+      m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, 
name,
+                                                          value, 32);
+    m_type_system->CompleteTagDeclarationDefinition(enum_type);
+
+    return enum_type;
+  }
+
+  void TestDumpValueObject(
+      CompilerType enum_type,
+      const std::vector<
+          std::tuple<uint32_t, DumpValueObjectOptions, const char *>> &tests) {
+    StreamString strm;
+    ConstString var_name("test_var");
+    ByteOrder endian = endian::InlHostByteOrder();
+    ExecutionContextScope *exe_scope = 
m_exe_ctx.GetBestExecutionContextScope();
+    for (auto [value, options, expected] : tests) {
+      DataExtractor data_extractor{&value, sizeof(value), endian, 4};
+      ValueObjectConstResult::Create(exe_scope, enum_type, var_name,
+                                     data_extractor)
+          ->Dump(strm, options);
+      ASSERT_STREQ(strm.GetString().str().c_str(), expected);
+      strm.Clear();
+    }
+  }
+
   ExecutionContext m_exe_ctx;
   TypeSystemClang *m_type_system;
 
@@ -87,50 +123,54 @@ class ValueObjectMockProcessTest : public ::testing::Test {
 };
 
 TEST_F(ValueObjectMockProcessTest, Enum) {
-  CompilerType uint_type = m_type_system->GetBuiltinTypeForEncodingAndBitSize(
-      lldb::eEncodingUint, 32);
-  CompilerType enum_type = m_type_system->CreateEnumerationType(
-      "test_enum", m_type_system->GetTranslationUnitDecl(),
-      OptionalClangModuleID(), Declaration(), uint_type, false);
-
-  m_type_system->StartTagDeclarationDefinition(enum_type);
-  Declaration decl;
-  // Each value sets one bit in the enum, to make this a "bitfield like enum".
-  m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, 
"test_2",
-                                                      2, 32);
-  m_type_system->AddEnumerationValueToEnumerationType(enum_type, decl, 
"test_4",
-                                                      4, 32);
-  m_type_system->CompleteTagDeclarationDefinition(enum_type);
-
-  std::vector<std::tuple<uint32_t, DumpValueObjectOptions, const char *>> 
enums{
-      {0, {}, "(test_enum) test_var =\n"},
-      {1, {}, "(test_enum) test_var = 0x1\n"},
-      {2, {}, "(test_enum) test_var = test_2\n"},
-      {4, {}, "(test_enum) test_var = test_4\n"},
-      {6, {}, "(test_enum) test_var = test_2 | test_4\n"},
-      {7, {}, "(test_enum) test_var = test_2 | test_4 | 0x1\n"},
-      {8, {}, "(test_enum) test_var = 0x8\n"},
-      {1, DumpValueObjectOptions().SetHideRootName(true), "(test_enum) 0x1\n"},
-      {1, DumpValueObjectOptions().SetHideRootType(true), "test_var = 0x1\n"},
-      {1, DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
-       "0x1\n"},
-      {1, DumpValueObjectOptions().SetHideName(true), "(test_enum) 0x1\n"},
-      {1, DumpValueObjectOptions().SetHideValue(true),
-       "(test_enum) test_var =\n"},
-      {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
-       "(test_enum) \n"},
-  };
+  // This is not a bitfield-like enum, so values are printed as decimal by
+  // default. Also we only show the enumerator name if the value is an
+  // exact match.
+  TestDumpValueObject(
+      MakeEnumType({{"test_2", 2}, {"test_3", 3}}),
+      {{0, {}, "(TestEnum) test_var = 0\n"},
+       {1, {}, "(TestEnum) test_var = 1\n"},
+       {2, {}, "(TestEnum) test_var = test_2\n"},
+       {3, {}, "(TestEnum) test_var = test_3\n"},
+       {4, {}, "(TestEnum) test_var = 4\n"},
+       {5, {}, "(TestEnum) test_var = 5\n"},
+       {1, DumpValueObjectOptions().SetHideRootName(true), "(TestEnum) 1\n"},
+       {1, DumpValueObjectOptions().SetHideRootType(true), "test_var = 1\n"},
+       {1, 
DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
+        "1\n"},
+       {1, DumpValueObjectOptions().SetHideName(true), "(TestEnum) 1\n"},
+       {1, DumpValueObjectOptions().SetHideValue(true),
+        "(TestEnum) test_var =\n"},
+       {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
+        "(TestEnum) \n"}});
+}
 
-  StreamString strm;
-  ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
-  ConstString var_name("test_var");
-  ByteOrder endian = endian::InlHostByteOrder();
-  for (auto [value, options, expected] : enums) {
-    DataExtractor data_extractor{&value, sizeof(value), endian, 4};
-    ValueObjectConstResult::Create(exe_scope, enum_type, var_name,
-                                   data_extractor)
-        ->Dump(strm, options);
-    ASSERT_STREQ(strm.GetString().str().c_str(), expected);
-    strm.Clear();
-  }
+TEST_F(ValueObjectMockProcessTest, BitFieldLikeEnum) {
+  // These enumerators set individual bits in the value, as if it were a flag
+  // set. lldb treats this as a "bitfield like enum". This means we show values
+  // as hex, a value of 0 shows nothing, and values with no exact enumerator 
are
+  // shown as combinations of the other values.
+  TestDumpValueObject(
+      MakeEnumType({{"test_2", 2}, {"test_4", 4}}),
+      {
+          {0, {}, "(TestEnum) test_var =\n"},
+          {1, {}, "(TestEnum) test_var = 0x1\n"},
+          {2, {}, "(TestEnum) test_var = test_2\n"},
+          {4, {}, "(TestEnum) test_var = test_4\n"},
+          {6, {}, "(TestEnum) test_var = test_2 | test_4\n"},
+          {7, {}, "(TestEnum) test_var = test_2 | test_4 | 0x1\n"},
+          {8, {}, "(TestEnum) test_var = 0x8\n"},
+          {1, DumpValueObjectOptions().SetHideRootName(true),
+           "(TestEnum) 0x1\n"},
+          {1, DumpValueObjectOptions().SetHideRootType(true),
+           "test_var = 0x1\n"},
+          {1,
+           
DumpValueObjectOptions().SetHideRootName(true).SetHideRootType(true),
+           "0x1\n"},
+          {1, DumpValueObjectOptions().SetHideName(true), "(TestEnum) 0x1\n"},
+          {1, DumpValueObjectOptions().SetHideValue(true),
+           "(TestEnum) test_var =\n"},
+          {1, DumpValueObjectOptions().SetHideName(true).SetHideValue(true),
+           "(TestEnum) \n"},
+      });
 }

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to