Files
android-assistant/tests/core/test_file_transfer.py

235 lines
9.3 KiB
Python

"""Tests for file transfer module."""
import pytest
import unittest.mock as mock
import os
from unittest.mock import patch, MagicMock
from src.core.file_transfer import ADBFileTransfer
class TestADBFileTransfer:
"""Test ADB file transfer functionality."""
def test_init(self):
"""Test ADBFileTransfer initialization."""
transfer = ADBFileTransfer()
assert transfer.progress_callback is None
assert transfer.current_process is None
def test_validate_windows_root_path_valid(self):
"""Test Windows root path validation with valid path."""
transfer = ADBFileTransfer()
# Should not raise exception
transfer._validate_windows_root_path("C:/Users/test", "push")
def test_validate_windows_root_path_invalid_push(self):
"""Test Windows root path validation with invalid path for push."""
transfer = ADBFileTransfer()
with pytest.raises(ValueError, match="Cannot push to Windows root"):
transfer._validate_windows_root_path("C:", "push")
def test_validate_windows_root_path_invalid_pull(self):
"""Test Windows root path validation with invalid path for pull."""
transfer = ADBFileTransfer()
with pytest.raises(ValueError, match="Cannot pull from Windows root"):
transfer._validate_windows_root_path("C:", "pull")
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_pull_file_success(self, mock_exists, mock_command_runner):
"""Test successful file pull operation."""
mock_exists.return_value = False # Remote file doesn't exist locally
mock_runner = MagicMock()
mock_runner.run_adb_command.return_value = ("", "", 0)
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.pull_file("/sdcard/test.txt", "/local/test.txt")
assert result is True
# sanitize_local_path converts to absolute path, so we need to match that
expected_local_path = os.path.abspath(os.path.normpath("/local/test.txt"))
mock_runner.run_adb_command.assert_called_with(
["pull", "/sdcard/test.txt", expected_local_path]
)
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_pull_file_already_exists(self, mock_exists, mock_command_runner):
"""Test file pull when local file already exists."""
mock_exists.return_value = True
mock_runner = MagicMock()
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.pull_file("/sdcard/test.txt", "/local/test.txt")
assert result is False
mock_runner.run_adb_command.assert_not_called()
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_pull_file_command_failure(self, mock_exists, mock_command_runner):
"""Test file pull with ADB command failure."""
mock_exists.return_value = False
mock_runner = MagicMock()
mock_runner.run_adb_command.return_value = ("", "Error", 1)
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.pull_file("/sdcard/test.txt", "/local/test.txt")
assert result is False
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
@patch("os.path.isfile")
def test_push_file_success(self, mock_isfile, mock_exists, mock_command_runner):
"""Test successful file push operation."""
mock_exists.return_value = True # Local file exists
mock_isfile.return_value = True
mock_runner = MagicMock()
mock_runner.run_adb_command.return_value = ("", "", 0)
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.push_file("/local/test.txt", "/sdcard/test.txt")
assert result is True
# sanitize_local_path converts to absolute path
expected_local_path = os.path.abspath(os.path.normpath("/local/test.txt"))
mock_runner.run_adb_command.assert_called_with(
["push", expected_local_path, "/sdcard/test.txt"]
)
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_push_file_not_exists(self, mock_exists, mock_command_runner):
"""Test file push when local file doesn't exist."""
mock_exists.return_value = False
mock_runner = MagicMock()
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.push_file("/local/test.txt", "/sdcard/test.txt")
assert result is False
mock_runner.run_adb_command.assert_not_called()
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
@patch("os.path.isfile")
def test_push_file_not_a_file(self, mock_isfile, mock_exists, mock_command_runner):
"""Test file push when local path is not a file."""
mock_exists.return_value = True
mock_isfile.return_value = False # It's a directory, not a file
mock_runner = MagicMock()
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.push_file("/local/test", "/sdcard/test.txt")
assert result is False
mock_runner.run_adb_command.assert_not_called()
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
@patch("os.path.isdir")
def test_pull_folder_success(self, mock_isdir, mock_exists, mock_command_runner):
"""Test successful folder pull operation."""
mock_exists.return_value = False # Local folder doesn't exist
mock_isdir.return_value = True
mock_runner = MagicMock()
mock_runner.run_adb_command.return_value = ("", "", 0)
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.pull_folder("/sdcard/Documents", "/local/Documents")
assert result is True
# sanitize_local_path converts to absolute path
expected_local_path = os.path.abspath(os.path.normpath("/local/Documents"))
mock_runner.run_adb_command.assert_called_with(
["pull", "/sdcard/Documents", expected_local_path]
)
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_pull_folder_already_exists(self, mock_exists, mock_command_runner):
"""Test folder pull when local folder already exists."""
mock_exists.return_value = True
mock_runner = MagicMock()
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.pull_folder("/sdcard/Documents", "/local/Documents")
assert result is False
mock_runner.run_adb_command.assert_not_called()
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
@patch("os.path.isdir")
def test_push_folder_success(self, mock_isdir, mock_exists, mock_command_runner):
"""Test successful folder push operation."""
mock_exists.return_value = True # Local folder exists
mock_isdir.return_value = True
mock_runner = MagicMock()
mock_runner.run_adb_command.return_value = ("", "", 0)
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.push_folder("/local/Documents", "/sdcard/Documents")
assert result is True
# sanitize_local_path converts to absolute path
expected_local_path = os.path.abspath(os.path.normpath("/local/Documents"))
mock_runner.run_adb_command.assert_called_with(
["push", expected_local_path, "/sdcard/Documents"]
)
@patch("src.core.file_transfer.ADBCommandRunner")
@patch("os.path.exists")
def test_push_folder_not_exists(self, mock_exists, mock_command_runner):
"""Test folder push when local folder doesn't exist."""
mock_exists.return_value = False
mock_runner = MagicMock()
mock_command_runner.return_value = mock_runner
transfer = ADBFileTransfer()
result = transfer.push_folder("/local/Documents", "/sdcard/Documents")
assert result is False
mock_runner.run_adb_command.assert_not_called()
def test_cancel_transfer_no_process(self):
"""Test canceling transfer with no current process."""
transfer = ADBFileTransfer()
result = transfer.cancel_transfer()
assert result is False
def test_cancel_transfer_with_process(self):
"""Test canceling transfer with active process."""
transfer = ADBFileTransfer()
mock_process = MagicMock()
mock_process.poll.return_value = None # Process is running
transfer.current_process = mock_process
result = transfer.cancel_transfer()
assert result is True
mock_process.terminate.assert_called_once()
def test_cancel_transfer_finished_process(self):
"""Test canceling transfer with finished process."""
transfer = ADBFileTransfer()
mock_process = MagicMock()
mock_process.poll.return_value = 0 # Process finished
transfer.current_process = mock_process
result = transfer.cancel_transfer()
assert result is False
mock_process.terminate.assert_not_called()