DroidMind

by hyperb1iss
Verified
"""Tests for the ADB wrapper module.""" import tempfile import unittest from unittest.mock import AsyncMock, patch import pytest import pytest_asyncio from droidmind.adb import ADBWrapper class TestADBWrapper(unittest.TestCase): """Test the ADB wrapper module.""" def setUp(self): """Set up test environment.""" # Create a temporary directory for test files self.temp_dir = tempfile.mkdtemp(prefix="droidmind_test_") # Mock subprocess for ADB commands self.subprocess_patcher = patch("asyncio.create_subprocess_exec") self.mock_subprocess = self.subprocess_patcher.start() # Set up mock process self.mock_process = AsyncMock() self.mock_process.communicate = AsyncMock(return_value=(b"stdout", b"stderr")) self.mock_process.returncode = 0 self.mock_subprocess.return_value = self.mock_process def tearDown(self): """Clean up test environment.""" self.subprocess_patcher.stop() # Remove temporary directory import shutil shutil.rmtree(self.temp_dir) def test_initialization(self): """Test ADBWrapper initialization.""" wrapper = ADBWrapper() # Verify defaults assert wrapper.connection_timeout == 10.0 assert wrapper.auth_timeout == 1.0 assert wrapper._devices_cache == [] @pytest.mark.asyncio class TestADBWrapperAsync: """Test the async methods of ADBWrapper.""" @pytest_asyncio.fixture async def wrapper(self, request): """Set up ADBWrapper for testing.""" # Create a temporary directory temp_dir = tempfile.mkdtemp(prefix="droidmind_test_") # Mock subprocess for ADB commands subprocess_patcher = patch("asyncio.create_subprocess_exec") mock_subprocess = subprocess_patcher.start() # Set up mock process mock_process = AsyncMock() mock_process.communicate = AsyncMock(return_value=(b"stdout", b"stderr")) mock_process.returncode = 0 mock_subprocess.return_value = mock_process # Create wrapper wrapper = ADBWrapper() # Mock the get_devices method to return a connected device wrapper.get_devices = AsyncMock( return_value=[{"serial": "device1", "model": "Pixel 4", "android_version": "11"}] ) # Add cleanup def cleanup(): subprocess_patcher.stop() import shutil shutil.rmtree(temp_dir) request.addfinalizer(cleanup) return wrapper async def test_connect_device_tcp(self, wrapper): """Test connecting to a device over TCP/IP.""" # Mock the ADB command output wrapper._run_adb_command = AsyncMock(return_value=("connected to 192.168.1.100:5555", "")) # Call the method result = await wrapper.connect_device_tcp("192.168.1.100", 5555) # Verify the result - the actual implementation returns just the serial assert result == "192.168.1.100:5555" wrapper._run_adb_command.assert_called_once_with( ["connect", "192.168.1.100:5555"], timeout_seconds=wrapper.connection_timeout ) async def test_connect_device_tcp_error(self, wrapper): """Test error handling when connecting to a device over TCP/IP.""" # Mock the ADB command output for an error wrapper._run_adb_command = AsyncMock(return_value=("failed to connect to 192.168.1.100:5555", "")) # Call the method - should raise RuntimeError with pytest.raises(RuntimeError) as excinfo: await wrapper.connect_device_tcp("192.168.1.100", 5555) # Verify the error message assert "Failed to connect" in str(excinfo.value) wrapper._run_adb_command.assert_called_once_with( ["connect", "192.168.1.100:5555"], timeout_seconds=wrapper.connection_timeout ) async def test_disconnect_device(self, wrapper): """Test disconnecting from a device.""" # Mock the ADB command output wrapper._run_adb_command = AsyncMock(return_value=("disconnected device1:5555", "")) # Call the method with a TCP device (has a colon in the serial) result = await wrapper.disconnect_device("device1:5555") # Verify the result assert result is True wrapper._run_adb_command.assert_called_once_with(["disconnect", "device1:5555"], check=False) async def test_disconnect_device_not_connected(self, wrapper): """Test disconnecting from a device that's not connected.""" # Call the method with a USB device (no colon in the serial) result = await wrapper.disconnect_device("device1") # Verify the result - should be False for USB devices assert result is False # No ADB command should be called for USB devices async def test_shell(self, wrapper): """Test running a shell command on a device.""" # Mock the ADB command output wrapper._run_adb_device_command = AsyncMock(return_value=("command output", "")) # Mock the _run_adb_command to make the device appear connected wrapper._run_adb_command = AsyncMock(return_value=("List of devices attached\ndevice1\tdevice", "")) # Clear the devices cache to force a check wrapper._devices_cache = [] # Call the method result = await wrapper.shell("device1", "ls -la") # Verify the result assert result == "command output" wrapper._run_adb_device_command.assert_called_once_with("device1", ["shell", "ls -la"]) async def test_shell_device_not_connected(self, wrapper): """Test running a shell command on a device that's not connected.""" # Override the get_devices mock to return no devices wrapper.get_devices = AsyncMock(return_value=[]) # Call the method and expect an exception with pytest.raises(ValueError) as excinfo: await wrapper.shell("nonexistent", "ls -la") # Verify the error message assert "Device nonexistent not connected" in str(excinfo.value) async def test_get_device_properties(self, wrapper): """Test getting device properties.""" # Mock the shell command output wrapper.shell = AsyncMock( return_value=( "[ro.build.version.release]: [11]\n[ro.build.version.sdk]: [30]\n[ro.product.model]: [Pixel 4]\n" ) ) # Call the method result = await wrapper.get_device_properties("device1") # Verify the result assert result == { "ro.build.version.release": "11", "ro.build.version.sdk": "30", "ro.product.model": "Pixel 4", } wrapper.shell.assert_called_once_with("device1", "getprop")
ID: p03zdsi6ol