DroidMind

by hyperb1iss
Verified
"""Tests for app management functionality in DroidMind.""" from unittest.mock import AsyncMock, patch import pytest from droidmind.devices import Device, DeviceManager from droidmind.tools.app_management import ( clear_app_data, get_app_manifest, list_packages, start_app, stop_app, uninstall_app, ) from droidmind.tools.logs import app_logs @pytest.fixture def mock_device(): """Create a mock device for testing.""" device = AsyncMock(spec=Device) device.serial = "test_device" # Set up method responses device.uninstall_app.return_value = "Success" device.start_app.return_value = "Started package com.example.app" device.stop_app.return_value = "Stopped package com.example.app" device.clear_app_data.return_value = "Successfully cleared data for package com.example.app" device.get_app_list.return_value = [{"package": "com.example.app", "path": "/data/app/com.example.app.apk"}] device.get_app_info.return_value = { "version": "1.0", "install_path": "/data/app/com.example.app", "first_install": "2023-01-01", "user_id": "10001", "permissions": ["android.permission.INTERNET", "android.permission.CAMERA"], } # Run shell returns for various commands async def mock_run_shell(cmd, max_lines=None): if "pm path" in cmd: return "package:/data/app/com.example.app.apk" if "aapt" in cmd or "aapt2" in cmd: return "Mock AndroidManifest content" if "ls" in cmd and "shared_prefs" in cmd: return "-rw------- 1 u0_a123 u0_a123 1234 2023-01-01 12:00 prefs.xml" if "cat" in cmd and "shared_prefs" in cmd: return '<map><string name="key">value</string></map>' if "logcat" in cmd: return "01-01 12:00:00.000 1234 5678 I App: This is a log message" if "ps -A | grep" in cmd: return "u0_a123 1234 123 1234567 123456 0 0 S com.example.app" if "which su" in cmd: return "/system/bin/su" if "su -c" in cmd: return "Mock root command output" if "dumpsys package" in cmd: return """ Package [com.example.app] userId=10001 versionCode=1 versionName=1.0 """ return "Generic command output" device.run_shell.side_effect = mock_run_shell return device @pytest.fixture def mock_device_manager(mock_device): """Create a mock device manager for testing.""" manager = AsyncMock(spec=DeviceManager) manager.get_device.return_value = mock_device return manager @pytest.fixture def mock_context(): """Create a mock MCP context.""" context = AsyncMock() context.info = AsyncMock() return context @pytest.mark.asyncio async def test_uninstall_app(mock_device_manager, mock_context): """Test the uninstall_app tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await uninstall_app("test_device", "com.example.app", mock_context) assert "Successfully uninstalled" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.uninstall_app.assert_called_once_with("com.example.app", False) @pytest.mark.asyncio async def test_start_app(mock_device_manager, mock_context): """Test the start_app tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await start_app("test_device", "com.example.app", mock_context) assert "Started package" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.start_app.assert_called_once_with("com.example.app", "") @pytest.mark.asyncio async def test_stop_app(mock_device_manager, mock_context): """Test the stop_app tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await stop_app("test_device", "com.example.app", mock_context) assert "Stopped package" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.stop_app.assert_called_once_with("com.example.app") @pytest.mark.asyncio async def test_clear_app_data(mock_device_manager, mock_context): """Test the clear_app_data tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await clear_app_data("test_device", "com.example.app", mock_context) assert "Successfully" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.clear_app_data.assert_called_once_with("com.example.app") @pytest.mark.asyncio async def test_list_packages(mock_device_manager, mock_context): """Test the list_packages tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await list_packages("test_device", mock_context) assert "Installed Packages" in result assert "com.example.app" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.get_app_list.assert_called_once_with(False) @pytest.mark.asyncio async def test_get_app_manifest(mock_device_manager, mock_context): """Test the get_app_manifest tool.""" with patch("droidmind.tools.app_management.get_device_manager", return_value=mock_device_manager): result = await get_app_manifest("test_device", "com.example.app", mock_context) assert "App Manifest for" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.run_shell.assert_any_call("dumpsys package com.example.app", max_lines=None) @pytest.mark.asyncio async def test_app_logs_tool(mock_device_manager, mock_context): """Test the app_logs tool.""" with patch("droidmind.tools.logs.get_device_manager", return_value=mock_device_manager): result = await app_logs("test_device", "com.example.app", mock_context) assert "Logs for App" in result assert "This is a log message" in result mock_device_manager.get_device.assert_called_once_with("test_device") mock_device = mock_device_manager.get_device.return_value mock_device.run_shell.assert_any_call("ps -A | grep com.example.app")
ID: p03zdsi6ol