Added gdb-remote expedited register dupe check.
authorTodd Fiala <todd.fiala@gmail.com>
Sat, 14 Jun 2014 03:03:23 +0000 (03:03 +0000)
committerTodd Fiala <todd.fiala@gmail.com>
Sat, 14 Jun 2014 03:03:23 +0000 (03:03 +0000)
The llgs branch had a bug where register sets were not terminated with
LLDB_INVALID_REGNUM so the expedite register loop was issuing duplicate
registers.  This test was added to catch the problem.

Enhanced the key-val collection method to optionally (and by default)
support capturing duplicate values for a given key.  When that happens
and if permitted, it promotes a single key to a list and appends values
to it.

llvm-svn: 210963

lldb/test/tools/lldb-gdbserver/TestGdbRemoteExpeditedRegisters.py
lldb/test/tools/lldb-gdbserver/gdbremote_testcase.py

index 7fb46dd..f4b6fa0 100644 (file)
@@ -32,6 +32,8 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
     def stop_notification_contains_generic_register(self, generic_register_name):
         # Generate a stop reply, parse out expedited registers from stop notification.
         expedited_registers = self.gather_expedited_registers()
+        self.assertIsNotNone(expedited_registers)
+        self.assertTrue(len(expedited_registers) > 0)
 
         # Gather target register infos.
         reg_infos = self.gather_register_infos()
@@ -67,6 +69,31 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
         self.set_inferior_startup_launch()
         self.stop_notification_contains_any_registers()
 
+    def stop_notification_contains_no_duplicate_registers(self):
+        # Generate a stop reply, parse out expedited registers from stop notification.
+        expedited_registers = self.gather_expedited_registers()
+        # Verify no expedited register was specified multiple times.
+        for (reg_num, value) in expedited_registers.items():
+            if (type(value) == list) and (len(value) > 0):
+                self.fail("expedited register number {} specified more than once ({} times)".format(reg_num, len(value)))
+
+    @debugserver_test
+    @dsym_test
+    def test_stop_notification_contains_no_duplicate_registers_debugserver_dsym(self):
+        self.init_debugserver_test()
+        self.buildDsym()
+        self.set_inferior_startup_launch()
+        self.stop_notification_contains_no_duplicate_registers()
+
+    @llgs_test
+    @dwarf_test
+    @unittest2.expectedFailure()
+    def test_stop_notification_contains_no_duplicate_registers_llgs_dwarf(self):
+        self.init_llgs_test()
+        self.buildDwarf()
+        self.set_inferior_startup_launch()
+        self.stop_notification_contains_no_duplicate_registers()
+
     def stop_notification_contains_pc_register(self):
         self.stop_notification_contains_generic_register("pc")
 
index b082869..3f2dc7c 100644 (file)
@@ -345,11 +345,23 @@ class GdbRemoteTestCaseBase(TestBase):
              {"direction":"send", "regex":r"^\$(.+)#[0-9a-fA-F]{2}$", "capture":{1:"memory_region_response"} }],
             True)
 
-    def parse_key_val_dict(self, key_val_text):
+    def parse_key_val_dict(self, key_val_text, allow_dupes=True):
         self.assertIsNotNone(key_val_text)
         kv_dict = {}
         for match in re.finditer(r";?([^:]+):([^;]+)", key_val_text):
-            kv_dict[match.group(1)] = match.group(2)
+            key = match.group(1)
+            val = match.group(2)
+            if key in kv_dict:
+                if allow_dupes:
+                    if type(kv_dict[key]) == list:
+                        kv_dict[key].append(val)
+                    else:
+                        # Promote to list
+                        kv_dict[key] = [kv_dict[key], val]
+                else:
+                    self.fail("key '{}' already present when attempting to add value '{}' (text='{}', dict={})".format(key, val, key_val_text, kv_dict))
+            else:
+                kv_dict[key] = val
         return kv_dict
 
     def parse_memory_region_packet(self, context):