import os
import pytest
from unittest.mock import patch, mock_open, MagicMock, call
mock_LINE_RULES = {
"test_package": {
"test_file.py": ["mock_content"],
"remove_file.py": ["REMOVE"],
"line_rule_file.py": [
''' line1
- line2
+ replaced_line2
line3'''
]
}
}
mock_GENERAL_RULES = []
mock_SHELL_RULES = []
mock_FILE_RULES = [["test", "mocked"]]
mock_SPECIAL_RULES = {
"test_package": {
"test_file.py": [
("pattern", "replacement"),
("", "appended_content")
]
}
}
try:
import sys
from unittest.mock import MagicMock
sys.modules['rules'] = MagicMock()
sys.modules['rules.line_rules'] = MagicMock(
LINE_RULES=mock_LINE_RULES,
GENERAL_RULES=mock_GENERAL_RULES,
SHELL_RULES=mock_SHELL_RULES,
FILE_RULES=mock_FILE_RULES,
SPECIAL_RULES=mock_SPECIAL_RULES
)
from tools.transfer import (
getfiles,
convert_general_rules,
convert_special_rules,
convert_special_rules_by_line,
convert_package
)
transfer_available = True
except Exception as e:
print(f"Warning: Failed to import transfer module: {e}")
transfer_available = False
def getfiles(path):
pass
def convert_general_rules(origin_path, save_path):
pass
def convert_special_rules(origin_path, save_path, package):
pass
def convert_special_rules_by_line(origin_path, save_path, package):
pass
def convert_package(origin_path, save_path, package):
pass
"""Test the functionality in transfer.py module - Using simple direct mocking to avoid file system operations"""
@pytest.fixture
def test_dir():
"""
Feature: Provide test directory path fixture
Description: Return a test origin directory path for use in test functions
Expectation: Returns '/test_origin' string
"""
return '/test_origin'
@pytest.fixture
def save_dir():
return '/test_save'
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
@patch('os.walk')
@patch('os.path.isfile', return_value=True)
@patch('os.path.join')
def test_getfiles(mock_join, mock_isfile, mock_walk):
"""
Feature: Test getfiles function functionality
Description: Mock file system operations to test if getfiles correctly walks through directories and collects files
Expectation: Returns a list of files and correctly calls os.walk function with the provided path
"""
mock_walk.return_value = [('test_dir', ['subdir'], ['file1.py', 'file2.py'])]
mock_join.return_value = 'test_dir/file1.py'
result = getfiles('test_dir')
mock_walk.assert_called_once_with('test_dir')
assert isinstance(result, list)
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
def test_convert_general_rules():
"""
Feature: Test convert_general_rules function functionality
Description: Mock file system operations and rules to test if convert_general_rules correctly processes files and applies general rules
Expectation: Correctly calls getfiles, processes only Python files (skips pyc), and applies FILE_RULES to the content
"""
with patch('tools.transfer.getfiles', return_value=['test_origin/file1.py', 'test_origin/file2.pyc']) as mock_getfiles, \
patch('builtins.open', mock_open(read_data='test content')) as mock_open_file, \
patch('os.path.exists', return_value=True), \
patch('os.makedirs') as mock_makedirs, \
patch('tools.transfer.FILE_RULES', [['test', 'mocked']]):
convert_general_rules('test_origin', 'test_save')
mock_getfiles.assert_called_once_with('test_origin')
assert mock_open_file.call_count == 2
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
@patch('builtins.open', new_callable=mock_open, read_data='pattern\ncontent\n')
@patch('os.path.exists', return_value=True)
@patch('os.makedirs')
@patch('tools.transfer.SPECIAL_RULES', mock_SPECIAL_RULES)
def test_convert_special_rules(mock_makedirs, mock_exists, mock_file, test_dir, save_dir):
"""
Feature: Test convert_special_rules function functionality
Description: Mock file system operations and SPECIAL_RULES to test if convert_special_rules correctly processes files and applies special rules
Expectation: Correctly opens, reads, writes files, creates directories if needed, and applies SPECIAL_RULES to the content
"""
convert_special_rules(test_dir, save_dir, 'test_package')
assert mock_file.called
handle = mock_file()
handle.write.assert_called()
mock_makedirs.assert_called()
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
def test_convert_special_rules_by_line():
"""
Feature: Test convert_special_rules_by_line function functionality
Description: Mock file system operations and LINE_RULES to test if convert_special_rules_by_line correctly processes files and applies line-by-line rules
Expectation: Correctly opens source and destination files, creates directories if needed, and applies line-by-line replacement rules
"""
from unittest.mock import mock_open
with patch('builtins.open', mock_open(read_data='line1\nline2\nline3')) as mock_open_file, \
patch('os.path.exists', return_value=True), \
patch('os.makedirs') as mock_makedirs, \
patch('tools.transfer.LINE_RULES', {
'test_package': {
'test_file.py': ['''line1\n-line2\n+replaced_line2\nline3''']
}
}):
convert_special_rules_by_line('test_origin', 'test_save', 'test_package')
mock_open_file.assert_any_call('test_origin/test_file.py', 'r', encoding='UTF-8')
mock_open_file.assert_any_call('test_save/test_file.py', 'w', encoding='UTF-8')
mock_makedirs.assert_called_once()
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
def test_convert_special_rules_by_line_remove():
"""
Feature: Test convert_special_rules_by_line function with file removal
Description: Mock file system operations and LINE_RULES with 'REMOVE' directive to test if convert_special_rules_by_line correctly removes files
Expectation: Correctly identifies files marked for removal in LINE_RULES and calls os.remove on the source file
"""
with patch('os.path.exists', return_value=True), \
patch('os.remove') as mock_remove, \
patch('tools.transfer.LINE_RULES', {
'test_package': {
'test_file.py': ['REMOVE']
}
}):
convert_special_rules_by_line('test_origin', 'test_save', 'test_package')
mock_remove.assert_called_once_with('test_origin/test_file.py')
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
@patch('os.makedirs')
@patch('os.path.exists', return_value=True)
@patch('tools.transfer.convert_special_rules_by_line')
@patch('rules.line_rules.LINE_RULES', {'MindSpeed-LLM': {}})
def test_convert_package_mind_speed_llm(mock_convert_special, mock_exists, mock_makedirs):
"""
Feature: Test convert_package function for MindSpeed-LLM package
Description: Mock file system operations and convert_special_rules_by_line function to test if convert_package correctly handles the MindSpeed-LLM package
Expectation: Correctly calls convert_special_rules_by_line with the appropriate parameters for the MindSpeed-LLM package
"""
test_path = os.path.join('some', 'path', 'mind_speed_llm')
save_path = os.path.join('save', 'path')
convert_package(test_path, save_path, package_name='MindSpeed-LLM')
mock_convert_special.assert_called_once_with(test_path, save_path, package_name='MindSpeed-LLM')
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
@patch('os.makedirs')
@patch('os.path.exists', return_value=True)
@patch('tools.transfer.convert_special_rules')
@patch('tools.transfer.convert_special_rules_by_line')
@patch('rules.line_rules.LINE_RULES', {'other_package': {}})
@patch('rules.line_rules.SPECIAL_RULES', {'other_package': {}})
def test_convert_package_other(mock_convert_special_line, mock_convert_special, mock_exists, mock_makedirs):
"""
Feature: Test convert_package function for other packages
Description: Mock file system operations, convert_special_rules, and convert_special_rules_by_line functions to test if convert_package correctly handles other packages (non-MindSpeed-LLM)
Expectation: Correctly calls both convert_special_rules and convert_special_rules_by_line with the appropriate parameters for the other package
"""
test_path = os.path.join('some', 'path', 'other_package')
save_path = os.path.join('save', 'path')
convert_package(test_path, save_path, package_name='other_package')
mock_convert_special_line.assert_called_once_with(test_path, save_path, package_name='other_package')
mock_convert_special.assert_called_once_with(test_path, save_path, package_name='other_package')
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
def test_convert_general_rules_mkdir():
"""
Feature: Test convert_general_rules function directory operations
Description: Mock file system operations and FILE_RULES to test if convert_general_rules handles existing directories correctly
Expectation: Correctly processes files without calling os.makedirs when the directory already exists
"""
with patch('tools.transfer.getfiles', return_value=[]) as mock_getfiles, \
patch('os.path.exists', return_value=True), \
patch('os.makedirs') as mock_makedirs, \
patch('tools.transfer.FILE_RULES', []):
convert_general_rules('test_origin', 'test_save')
mock_makedirs.assert_not_called()
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
def test_convert_special_rules_by_line_create_new():
"""
Feature: Test convert_special_rules_by_line function with new file creation
Description: Mock file system operations and LINE_RULES to test if convert_special_rules_by_line correctly creates new files
Expectation: Correctly creates directories if needed and writes new content to a new file
"""
with patch('builtins.open', mock_open()) as mock_open_file, \
patch('os.path.exists', return_value=False), \
patch('os.makedirs') as mock_makedirs, \
patch('tools.transfer.LINE_RULES', {
'test_package': {
'new_file.py': ['new content']
}
}):
convert_special_rules_by_line('test_origin', 'test_save', 'test_package')
mock_open_file.assert_called_once_with('test_save/new_file.py', 'w', encoding='UTF-8')
mock_open_file().write.assert_called_once_with('new content')
mock_makedirs.assert_called_once()
@pytest.mark.skipif(not transfer_available, reason="Transfer module not available")
@patch('logging.warning')
@patch('logging.info')
def test_convert_special_rules_by_line_replace_fail(mock_info, mock_warning):
"""
Feature: Test convert_special_rules_by_line function with replacement failure
Description: Mock file system operations and LINE_RULES with a pattern that doesn't match existing content to test if convert_special_rules_by_line handles replacement failures correctly
Expectation: Correctly logs a warning when line replacement fails and writes the original content without modification
"""
with patch('builtins.open', mock_open(read_data='existing content')) as mock_open_file, \
patch('os.path.exists', return_value=True), \
patch('os.makedirs') as mock_makedirs, \
patch('tools.transfer.LINE_RULES', {
'test_package': {
'test_file.py': [
'''pattern_to_replace\nthat_does_not_exist'''
]
}
}):
convert_special_rules_by_line('test_origin', 'test_save', 'test_package')
mock_warning.assert_called_once()
mock_info.assert_called_once()
mock_open_file().write.assert_called_once()