gdb/testsuite: more testing of pretty printer 'array' display_hint

Message ID 20210325144603.1247726-1-andrew.burgess@embecosm.com
State New
Headers show
Series
  • gdb/testsuite: more testing of pretty printer 'array' display_hint
Related show

Commit Message

Andrew Burgess March 25, 2021, 2:46 p.m.
This commit adds a couple of tests to the python pretty printer
testing.

I've added a test for the 'array' display hint.  This display hint is
tested by gdb.python/py-mi.exp, however, the MI testing is done via
the varobj interface, and this code makes its own direct calls to the
Python pretty printers from gdb/varobj.c.  What this means is that the
interface to the pretty printers in gdb/python/py-prettyprint.c is not
tested for the 'array' display hint path.

I also added a test for what happens when the display_hint method
raises an exception.  There wasn't a bug that inspired this test, just
while adding the previous test I thought, I wonder what happens if...

The current behaviour of GDB seems reasonable, GDB displays the Python
exception, and then continues printing the value as if display_hint
had returned None.  I added a test to lock in this behaviour.

gdb/testsuite/ChangeLog:

	* gdb.python/py-prettyprint.c (struct container): Add 'is_array_p'
	member.
	(make_container): Initialise is_array_p.
	* gdb.python/py-prettyprint.exp: Add new tests.
	* gdb.python/py-prettyprint.py (ContainerPrinter.display_hint):
	Check is_array_p and possibly return 'array'.
---
 gdb/testsuite/ChangeLog                     |  9 +++++++
 gdb/testsuite/gdb.python/py-prettyprint.c   |  2 ++
 gdb/testsuite/gdb.python/py-prettyprint.exp | 29 +++++++++++++++++++++
 gdb/testsuite/gdb.python/py-prettyprint.py  |  5 ++++
 4 files changed, 45 insertions(+)

-- 
2.25.4

Comments

Keith Seitz via Gdb-patches March 25, 2021, 7:22 p.m. | #1
On 2021-03-25 10:46 a.m., Andrew Burgess wrote:
> This commit adds a couple of tests to the python pretty printer

> testing.

> 

> I've added a test for the 'array' display hint.  This display hint is

> tested by gdb.python/py-mi.exp, however, the MI testing is done via

> the varobj interface, and this code makes its own direct calls to the

> Python pretty printers from gdb/varobj.c.  What this means is that the

> interface to the pretty printers in gdb/python/py-prettyprint.c is not

> tested for the 'array' display hint path.

> 

> I also added a test for what happens when the display_hint method

> raises an exception.  There wasn't a bug that inspired this test, just

> while adding the previous test I thought, I wonder what happens if...

> 

> The current behaviour of GDB seems reasonable, GDB displays the Python

> exception, and then continues printing the value as if display_hint

> had returned None.  I added a test to lock in this behaviour.

> 

> gdb/testsuite/ChangeLog:

> 

> 	* gdb.python/py-prettyprint.c (struct container): Add 'is_array_p'

> 	member.

> 	(make_container): Initialise is_array_p.

> 	* gdb.python/py-prettyprint.exp: Add new tests.

> 	* gdb.python/py-prettyprint.py (ContainerPrinter.display_hint):

> 	Check is_array_p and possibly return 'array'.


This LGTM, thanks.

Simon

Patch

diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 2558e98f5c0..126537ff529 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -176,6 +176,7 @@  struct container
   int len;
   int *elements;
   int is_map_p;
+  int is_array_p;
 };
 
 typedef struct container zzz_type;
@@ -197,6 +198,7 @@  make_container (const char *s)
   result.len = 0;
   result.elements = 0;
   result.is_map_p = 0;
+  result.is_array_p = 0;
 
   return result;
 }
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 9f0b36a333c..6a3968fe054 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -112,7 +112,36 @@  proc run_lang_tests {exefile lang} {
     gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" \
 	"print c, pretty printing on, default display hint"
 
+    gdb_test_no_output "set variable c.is_array_p=1"
+    gdb_test "print c" " = container \"container\" with 2 elements = \\{23, 72\\}" \
+	"print c, pretty printing on, display hint is now array"
+
+    # Setting is_map_p while _is_array_p is also set will cause the
+    # display_hint method to raise an exception (see py-prettyprint.py).
     gdb_test_no_output "set variable c.is_map_p=1"
+
+    # This test checks what happens when the display hint throws an
+    # error.  GDB just treats this as though the display hint was
+    # None.
+    set py_exception \
+	[multi_line \
+	     "Traceback\[^\r\n\]+" \
+	     "\\s+File \"\[^\r\n\]+/py-prettyprint.py\", line \[0-9\]+, in display_hint" \
+	     "\\s+raise Exception \[^\r\n\]+" \
+	     "Exception: invalid object state found in display_hint"]
+    gdb_test "print c" \
+	[multi_line \
+	     " = ${py_exception}" \
+	     "container \"container\" with 2 elements = {" \
+	     "\\s+\\\[0\\\] = 23," \
+	     "\\s+\\\[1\\\] = 72" \
+	     "}"] \
+	"print c, pretty printing on, exception raised from display_hint"
+
+    # Unset is_array_p so that display_hint no longer raises an
+    # exception.
+    gdb_test_no_output "set variable c.is_array_p=0"
+
     gdb_test "print c" " = container \"container\" with 2 elements = \{$nl  \\\[23\\\] = 72$nl\}" \
 	"print c, pretty printing on, display hint is now map"
 
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index 5f09ea8944b..fab03a653b7 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -57,8 +57,13 @@  class ContainerPrinter (object):
         return _iterator(self.val['elements'], self.val['len'])
 
     def display_hint (self):
+        if (self.val['is_map_p'] and self.val['is_array_p']):
+            raise Exception ("invalid object state found in display_hint")
+
         if (self.val['is_map_p']):
             return 'map'
+        elif (self.val['is_array_p']):
+            return 'array'
         else:
             return None