diff --git a/TESTING.md b/TESTING.md index 6c812d8..12d3c25 100644 --- a/TESTING.md +++ b/TESTING.md @@ -81,6 +81,9 @@ The test script will: - Required fields in responses - Proper initialization of the MCP session - Ability to call tools and receive responses +- Mutating operations (tested by changing and reverting): + - Function renaming + - Comment addition/removal ## Troubleshooting diff --git a/test_mcp_client.py b/test_mcp_client.py index 4af1099..43ea318 100644 --- a/test_mcp_client.py +++ b/test_mcp_client.py @@ -59,6 +59,120 @@ async def test_bridge(): ) logger.info(f"List functions result: {list_functions_result}") + # Test mutating operations by changing and reverting + logger.info("Testing mutating operations...") + + try: + # Get a known function to test with from list_functions result + list_funcs = await session.call_tool( + "list_functions", + arguments={"port": 8192, "offset": 0, "limit": 5} + ) + + if not hasattr(list_funcs, "result") or not hasattr(list_funcs.result, "content") or not list_funcs.result.content: + logger.warning("No functions found - skipping mutating tests") + return + + # The list_functions result contains a JSON string in the text field + func_json = list_funcs.result.content[0].get("text", "") + if not func_json: + logger.warning("No function data found - skipping mutating tests") + return + + try: + # Parse the JSON to get the function list + func_data = json.loads(func_json) + func_list = func_data.get("result", "").split("\n") + if not func_list: + logger.warning("No functions in result - skipping mutating tests") + return + + # Extract first function name (format: "name @ address") + func_name = func_list[0].split("@")[0].strip() + except (json.JSONDecodeError, AttributeError) as e: + logger.warning(f"Error parsing function data: {e} - skipping mutating tests") + return + if not func_name: + logger.warning("Could not parse function name - skipping mutating tests") + return + + # Get full function details + func_details = await session.call_tool( + "get_function", + arguments={"port": 8192, "name": func_name} + ) + + if not hasattr(func_details, "result") or not hasattr(func_details.result, "content") or not func_details.result.content: + logger.warning("Could not get function details - skipping mutating tests") + return + + func_content = func_details.result.content[0] + func_name = func_content.get("text", "").split("\n")[0] + func_address = func_content.get("address", "") + + if not func_name or not func_address: + logger.warning("Could not get valid function name/address - skipping mutating tests") + return + + # Test function renaming + original_name = func_name + test_name = f"{func_name}_test" + + # Rename to test name + rename_result = await session.call_tool( + "update_function", + arguments={"port": 8192, "name": original_name, "new_name": test_name} + ) + logger.info(f"Rename result: {rename_result}") + + # Verify rename + renamed_func = await session.call_tool( + "get_function", + arguments={"port": 8192, "name": test_name} + ) + logger.info(f"Renamed function result: {renamed_func}") + + # Rename back to original + revert_result = await session.call_tool( + "update_function", + arguments={"port": 8192, "name": test_name, "new_name": original_name} + ) + logger.info(f"Revert rename result: {revert_result}") + + # Verify revert + original_func = await session.call_tool( + "get_function", + arguments={"port": 8192, "name": original_name} + ) + logger.info(f"Original function result: {original_func}") + + # Test adding/removing comment + test_comment = "Test comment from MCP client" + comment_result = await session.call_tool( + "set_decompiler_comment", + arguments={ + "port": 8192, + "address": func_address, + "comment": test_comment + } + ) + logger.info(f"Add comment result: {comment_result}") + + # Remove comment + remove_comment_result = await session.call_tool( + "set_decompiler_comment", + arguments={ + "port": 8192, + "address": func_address, + "comment": "" + } + ) + logger.info(f"Remove comment result: {remove_comment_result}") + + except Exception as e: + logger.error(f"Error testing mutating operations: {e}") + raise + def main(): """Main entry point""" try: