| """ | |
| Verify that `scripting extension list -j` emits a well-formed JSON array of | |
| scripted-extension records that can be round-tripped through SBStructuredData. | |
| """ | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| class TestScriptingExtensionListJSON(TestBase): | |
| NO_DEBUG_INFO_TESTCASE = True | |
| def run_command(self, command): | |
| result = lldb.SBCommandReturnObject() | |
| self.dbg.GetCommandInterpreter().HandleCommand(command, result) | |
| self.assertTrue(result.Succeeded(), result.GetError()) | |
| return result.GetOutput() | |
| def run_and_parse(self, command): | |
| data = lldb.SBStructuredData() | |
| self.assertSuccess(data.SetFromJSON(self.run_command(command))) | |
| return data | |
| @skipIfNoSBHeaders | |
| def test_json_output_shape(self): | |
| """Every entry has the expected top-level keys and array-valued | |
| `languages`, `api_usages`, `command_interpreter_usages`.""" | |
| data = self.run_and_parse("scripting extension list -j") | |
| self.assertEqual(data.GetType(), lldb.eStructuredDataTypeArray) | |
| self.assertGreater(data.GetSize(), 0) | |
| expected_keys = { | |
| "name", | |
| "description", | |
| "languages", | |
| "api_usages", | |
| "command_interpreter_usages", | |
| } | |
| for i in range(data.GetSize()): | |
| entry = data.GetItemAtIndex(i) | |
| self.assertEqual(entry.GetType(), lldb.eStructuredDataTypeDictionary) | |
| keys = lldb.SBStringList() | |
| entry.GetKeys(keys) | |
| got = {keys.GetStringAtIndex(k) for k in range(keys.GetSize())} | |
| self.assertEqual(got, expected_keys) | |
| self.assertEqual( | |
| entry.GetValueForKey("name").GetType(), | |
| lldb.eStructuredDataTypeString, | |
| ) | |
| self.assertEqual( | |
| entry.GetValueForKey("description").GetType(), | |
| lldb.eStructuredDataTypeString, | |
| ) | |
| for array_key in ("languages", "api_usages", "command_interpreter_usages"): | |
| self.assertEqual( | |
| entry.GetValueForKey(array_key).GetType(), | |
| lldb.eStructuredDataTypeArray, | |
| array_key, | |
| ) | |
| def test_json_includes_known_extension(self): | |
| """`ScriptedProcess` is registered unconditionally, so it must appear | |
| with `SBTarget.Launch` in its `api_usages`.""" | |
| data = self.run_and_parse("scripting extension list -j") | |
| names = set() | |
| scripted_process_entry = None | |
| for i in range(data.GetSize()): | |
| entry = data.GetItemAtIndex(i) | |
| name = entry.GetValueForKey("name").GetStringValue(256) | |
| names.add(name) | |
| if name == "ScriptedProcess": | |
| scripted_process_entry = entry | |
| self.assertIn("ScriptedProcess", names) | |
| api_usages = scripted_process_entry.GetValueForKey("api_usages") | |
| found_launch = False | |
| for i in range(api_usages.GetSize()): | |
| usage = api_usages.GetItemAtIndex(i).GetStringValue(256) | |
| if usage == "SBTarget.Launch": | |
| found_launch = True | |
| break | |
| self.assertTrue( | |
| found_launch, | |
| f"expected SBTarget.Launch in ScriptedProcess.api_usages", | |
| ) | |
| def test_json_name_filter(self): | |
| """`scripting extension list -j <name>` restricts output to that | |
| one extension.""" | |
| data = self.run_and_parse("scripting extension list -j ScriptedProcess") | |
| self.assertEqual(data.GetSize(), 1) | |
| entry = data.GetItemAtIndex(0) | |
| self.assertEqual( | |
| entry.GetValueForKey("name").GetStringValue(256), "ScriptedProcess" | |
| ) | |
| def test_json_lua_yields_empty_array(self): | |
| """No lua-registered extensions -> empty JSON array.""" | |
| data = self.run_and_parse("scripting extension list -j -l lua --") | |
| self.assertEqual(data.GetType(), lldb.eStructuredDataTypeArray) | |
| self.assertEqual(data.GetSize(), 0) |