[formatters] Add a libstdcpp formatter for multiset and unify tests across stdlibs
authorDanil Stefaniuc <danilashtefan@gmail.com>
Sat, 30 Oct 2021 21:48:26 +0000 (14:48 -0700)
committerWalter Erquinigo <wallace@fb.com>
Sat, 30 Oct 2021 22:07:23 +0000 (15:07 -0700)
This diff adds a data formatter for libstdcpp's multiset. Besides, it improves and unifies the tests for multiset for libcxx and libstdcpp for maintainability.

Reviewed By: wallace

Differential Revision: https://reviews.llvm.org/D112785

lldb/examples/synthetic/gnu_libstdcpp.py
lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/Makefile [moved from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile with 54% similarity]
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py [moved from lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py with 74% similarity]
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp [new file with mode: 0644]
lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp [deleted file]

index dd07195..30149d1 100644 (file)
@@ -324,10 +324,17 @@ class StdMapLikeSynthProvider:
         logger = lldb.formatters.Logger.Logger()
         self.valobj = valobj
         self.count = None
-        self.kind = "set" if "set" in valobj.GetTypeName() else "map"
+        self.kind = self.get_object_kind(valobj)
         logger >> "Providing synthetic children for a " + self.kind + " named " + \
             str(valobj.GetName())
 
+    def get_object_kind(self, valobj):
+        type_name = valobj.GetTypeName()
+        for kind in ["multiset", "multimap", "set", "map"]:
+           if kind in type_name:
+              return kind
+        return type_name
+
     # we need this function as a temporary workaround for rdar://problem/10801549
     # which prevents us from extracting the std::pair<K,V> SBType out of the template
     # arguments for _Rep_Type _M_t in the object itself - because we have to make up the
index 7b64faa..e4d9813 100644 (file)
@@ -914,6 +914,11 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
           stl_deref_flags,
           "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
   cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
+      RegularExpression("^std::multiset<.+> >(( )?&)?$"),
+      SyntheticChildrenSP(new ScriptedSyntheticChildren(
+          stl_deref_flags,
+          "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
+  cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(
       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
       SyntheticChildrenSP(new ScriptedSyntheticChildren(
           stl_synth_flags,
@@ -941,6 +946,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
       TypeSummaryImplSP(
           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
   cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
+      RegularExpression("^std::multiset<.+> >(( )?&)?$"),
+      TypeSummaryImplSP(
+          new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+  cpp_category_sp->GetRegexTypeSummariesContainer()->Add(
       RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$"),
       TypeSummaryImplSP(
           new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
@@ -9,8 +9,10 @@ from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 
+USE_LIBSTDCPP = "USE_LIBSTDCPP"
+USE_LIBCPP = "USE_LIBCPP"
 
-class LibcxxMultiSetDataFormatterTestCase(TestBase):
+class GenericMultiSetDataFormatterTestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
@@ -18,34 +20,28 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
         TestBase.setUp(self)
         self.namespace = 'std'
 
-    def getVariableType(self, name):
+    def findVariable(self, name):
         var = self.frame().FindVariable(name)
         self.assertTrue(var.IsValid())
+        return var
+
+    def getVariableType(self, name):
+        var = self.findVariable(name)
         return var.GetType().GetDisplayTypeName()
 
-    def check_ii(self, var_name):
-        """ This checks the value of the bitset stored in ii at the call to by_ref_and_ptr.
-            We use this to make sure we get the same values for ii when we look at the object
-            directly, and when we look at a reference to the object. """
-        self.expect(
-            "frame variable " + var_name,
-            substrs=["size=7",
-                     "[2] = 2",
-                     "[3] = 3",
-                     "[6] = 6"])
-        self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"])
-        self.expect(
-            "p " + var_name,
-            substrs=[
-                "size=7",
-                "[2] = 2",
-                "[3] = 3",
-                "[6] = 6"])
 
-    @add_test_categories(["libc++"])
-    def test_with_run_command(self):
+    def check(self, var_name, size):
+        var = self.findVariable(var_name)
+        self.assertEqual(var.GetNumChildren(), size)
+        children = []
+        for i in range(size):
+            child = var.GetChildAtIndex(i)
+            children.append(ValueCheck(value=child.GetValue()))
+        self.expect_var_path(var_name, type=self.getVariableType(var_name), children=children)
+
+    def do_test_with_run_command(self, stdlib_type):
         """Test that that file and class static variables display correctly."""
-        self.build()
+        self.build(dictionary={stdlib_type: "1"})
         (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False))
 
@@ -81,16 +77,18 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
                 "[5] = 5"])
         lldbutil.continue_to_breakpoint(process, bkpt)
 
-        self.check_ii("ii")
+        self.check("ii", 7)
 
         lldbutil.continue_to_breakpoint(process, bkpt)
         self.expect("frame variable ii", substrs=["size=0", "{}"])
+        self.check("ii", 0)
         lldbutil.continue_to_breakpoint(process, bkpt)
         self.expect("frame variable ii", substrs=["size=0", "{}"])
         ss_type = self.getVariableType("ss")
         self.assertTrue(ss_type.startswith(self.namespace + "::multiset"),
                         "Type: " + ss_type)
         self.expect("frame variable ss", substrs=["size=0", "{}"])
+        self.check("ss", 0)
         lldbutil.continue_to_breakpoint(process, bkpt)
         self.expect(
             "frame variable ss",
@@ -98,6 +96,7 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
                 "size=2",
                 '[0] = "a"',
                 '[1] = "a very long string is right here"'])
+        self.check("ss", 2)
         lldbutil.continue_to_breakpoint(process, bkpt)
         self.expect(
             "frame variable ss",
@@ -108,6 +107,7 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
                 '[2] = "b"',
                 '[3] = "c"',
             ])
+        self.check("ss", 4)
         self.expect(
             "p ss",
             substrs=[
@@ -127,17 +127,32 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
                 '[1] = "a very long string is right here"',
                 '[2] = "c"'])
 
-    @add_test_categories(["libc++"])
-    def test_ref_and_ptr(self):
+    def do_test_ref_and_ptr(self, stdlib_type):
         """Test that the data formatters work on ref and ptr."""
-        self.build()
+        self.build(dictionary={stdlib_type: "1"})
         (self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
             self, "Stop here to check by ref and ptr.",
             lldb.SBFileSpec("main.cpp", False))
         # The reference should print just like the value:
-        self.check_ii("ref")
+        self.check("ref", 7)
 
         self.expect("frame variable ptr",
                     substrs=["ptr =", "size=7"])
         self.expect("expr ptr",
                     substrs=["size=7"])
+    
+    @add_test_categories(["libstdcxx"])
+    def test_with_run_command_libstdcpp(self):
+        self.do_test_with_run_command(USE_LIBSTDCPP)
+
+    @add_test_categories(["libc++"])
+    def test_with_run_command_libcpp(self):
+        self.do_test_with_run_command(USE_LIBCPP)
+    
+    @add_test_categories(["libstdcxx"])
+    def test_ref_and_ptr_libstdcpp(self):
+        self.do_test_ref_and_ptr(USE_LIBSTDCPP)
+
+    @add_test_categories(["libc++"])
+    def test_ref_and_ptr_libcpp(self):
+        self.do_test_ref_and_ptr(USE_LIBCPP)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/main.cpp
new file mode 100644 (file)
index 0000000..c44e556
--- /dev/null
@@ -0,0 +1,55 @@
+#include <set>
+#include <string>
+
+int g_the_foo = 0;
+
+int thefoo_rw(int arg = 1) {
+  if (arg < 0)
+    arg = 0;
+  if (!arg)
+    arg = 1;
+  g_the_foo += arg;
+  return g_the_foo;
+}
+
+void by_ref_and_ptr(std::multiset<int> &ref, std::multiset<int> *ptr) {
+  // Stop here to check by ref and ptr
+  return;
+}
+
+int main() {
+  std::multiset<int> ii;
+  thefoo_rw(1); // Set break point at this line.
+
+  ii.insert(0);
+  ii.insert(1);
+  ii.insert(2);
+  ii.insert(3);
+  ii.insert(4);
+  ii.insert(5);
+  thefoo_rw(1); // Set break point at this line.
+
+  ii.insert(6);
+  thefoo_rw(1); // Set break point at this line.
+
+  by_ref_and_ptr(ii, &ii);
+
+  ii.clear();
+  thefoo_rw(1); // Set break point at this line.
+
+  std::multiset<std::string> ss;
+  thefoo_rw(1); // Set break point at this line.
+
+  ss.insert("a");
+  ss.insert("a very long string is right here");
+  thefoo_rw(1); // Set break point at this line.
+
+  ss.insert("b");
+  ss.insert("c");
+  thefoo_rw(1); // Set break point at this line.
+
+  ss.erase("b");
+  thefoo_rw(1); // Set break point at this line.
+
+  return 0;
+}
index 2e03049..5c8cabc 100644 (file)
@@ -12,7 +12,7 @@ from lldbsuite.test import lldbutil
 USE_LIBSTDCPP = "USE_LIBSTDCPP"
 USE_LIBCPP = "USE_LIBCPP"
 
-class LibcxxSetDataFormatterTestCase(TestBase):
+class GenericSetDataFormatterTestCase(TestBase):
 
     mydir = TestBase.compute_mydir(__file__)
 
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp
deleted file mode 100644 (file)
index 6813b6e..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <string>
-#include <set>
-
-int g_the_foo = 0;
-
-int thefoo_rw(int arg = 1)
-{
-       if (arg < 0)
-               arg = 0;
-       if (!arg)
-               arg = 1;
-       g_the_foo += arg;
-       return g_the_foo;
-}
-
-void by_ref_and_ptr(std::multiset<int> &ref, std::multiset<int> *ptr)
-{
-    // Stop here to check by ref and ptr
-    return;
-} 
-
-int main()
-{
-    std::multiset<int> ii;
-    thefoo_rw(1);  // Set break point at this line.
-       
-       ii.insert(0);
-       ii.insert(1);
-       ii.insert(2);
-       ii.insert(3);
-       ii.insert(4);
-       ii.insert(5);
-    thefoo_rw(1);  // Set break point at this line.
-
-       ii.insert(6);
-       thefoo_rw(1);  // Set break point at this line.
-
-        by_ref_and_ptr(ii, &ii);
-
-       ii.clear();
-       thefoo_rw(1);  // Set break point at this line.
-
-       std::multiset<std::string> ss;
-       thefoo_rw(1);  // Set break point at this line.
-
-       ss.insert("a");
-       ss.insert("a very long string is right here");
-       thefoo_rw(1);  // Set break point at this line.
-
-       ss.insert("b");
-       ss.insert("c");
-       thefoo_rw(1);  // Set break point at this line.
-       
-       ss.erase("b");
-       thefoo_rw(1);  // Set break point at this line.
-
-    return 0;
-}