将散落在项目根目录的测试文件统一整理到tests目录中,提高项目结构的清晰度和可维护性。 主要变更: 1. 移动测试文件:将根目录的test_*.py文件移动到tests/目录 2. 移动测试资源:将test_*.png图片文件移动到tests/目录 3. 移动测试输出:将test_output.dci文件移动到tests/目录 4. 清理环境:删除不需要的test_env虚拟环境目录 5. 更新文档:更新tests/README.md,详细记录所有测试文件分类 移动的文件包括: - test_advanced_compression.py - 高级压缩功能测试 - test_border_color.py - 边框颜色功能测试 - test_categories.py - 分类系统测试 - test_quality_feature.py - 图片质量功能测试 - test_transparent_preview.py - 透明预览测试 - test_pure_python_implementation.py - 纯Python实现测试 - test_pure_python_simple.py - 简单纯Python测试 - simple_quality_test.py - 简单质量测试脚本 - test_preview_*.png - 预览测试图片 - test_transparent_preview.png - 透明预览测试图片 这次整理确保了: - 项目根目录更加清洁,只保留核心配置文件 - 所有测试相关文件集中管理,便于维护和执行 - 测试文档完整记录了所有测试文件的用途和分类 - 符合标准的Python项目结构规范 refactor: Organize test file structure by moving all to tests directory Consolidated scattered test files from project root to tests directory to improve project structure clarity and maintainability. Key changes: 1. Move test files: Relocated test_*.py files from root to tests/ 2. Move test assets: Relocated test_*.png image files to tests/ 3. Move test output: Relocated test_output.dci file to tests/ 4. Clean environment: Removed unnecessary test_env virtual environment 5. Update documentation: Enhanced tests/README.md with detailed file classification Moved files include: - test_advanced_compression.py - Advanced compression feature tests - test_border_color.py - Border color functionality tests - test_categories.py - Category system tests - test_quality_feature.py - Image quality feature tests - test_transparent_preview.py - Transparent preview tests - test_pure_python_implementation.py - Pure Python implementation tests - test_pure_python_simple.py - Simple pure Python tests - simple_quality_test.py - Simple quality testing script - test_preview_*.png - Preview test images - test_transparent_preview.png - Transparent preview test image This reorganization ensures: - Cleaner project root with only core configuration files - Centralized test management for easier maintenance and execution - Complete test documentation with proper file categorization - Compliance with standard Python project structure conventions
258 lines
8.7 KiB
Python
258 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
简化的纯Python实现测试
|
|
直接测试ar功能,避免复杂的导入
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
|
|
def create_ar_archive_python(archive_path, files, working_dir):
|
|
"""创建ar归档的纯Python实现"""
|
|
try:
|
|
print("使用纯Python实现创建ar归档...")
|
|
|
|
with open(archive_path, 'wb') as ar_file:
|
|
# Write ar archive signature
|
|
ar_file.write(b"!<arch>\n")
|
|
|
|
for filename in files:
|
|
file_path = os.path.join(working_dir, filename)
|
|
|
|
if not os.path.exists(file_path):
|
|
print(f"警告:文件不存在: {file_path}")
|
|
continue
|
|
|
|
# Get file stats
|
|
stat = os.stat(file_path)
|
|
file_size = stat.st_size
|
|
|
|
# Read file content
|
|
with open(file_path, 'rb') as f:
|
|
file_content = f.read()
|
|
|
|
# Create ar header (60 bytes)
|
|
# Format: name(16) + date(12) + uid(6) + gid(6) + mode(8) + size(10) + end(2)
|
|
name_field = filename.ljust(16)[:16].encode('ascii')
|
|
date_field = str(int(stat.st_mtime)).ljust(12)[:12].encode('ascii')
|
|
uid_field = b"0 " # 6 bytes
|
|
gid_field = b"0 " # 6 bytes
|
|
mode_field = b"100644 " # 8 bytes
|
|
size_field = str(file_size).ljust(10)[:10].encode('ascii')
|
|
end_field = b"`\n" # 2 bytes
|
|
|
|
header = name_field + date_field + uid_field + gid_field + mode_field + size_field + end_field
|
|
|
|
# Write header and content
|
|
ar_file.write(header)
|
|
ar_file.write(file_content)
|
|
|
|
# Add padding if file size is odd
|
|
if file_size % 2 == 1:
|
|
ar_file.write(b"\n")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"错误:纯Python ar归档创建失败: {str(e)}")
|
|
return False
|
|
|
|
def extract_ar_archive_python(deb_file_path, extract_dir):
|
|
"""解析ar归档的纯Python实现"""
|
|
try:
|
|
print("使用纯Python实现解析ar归档...")
|
|
|
|
with open(deb_file_path, 'rb') as f:
|
|
# Read ar header
|
|
magic = f.read(8)
|
|
if magic != b'!<arch>\n':
|
|
print("错误:不是有效的ar归档文件")
|
|
return False
|
|
|
|
while True:
|
|
# Read file header (60 bytes)
|
|
header = f.read(60)
|
|
if len(header) < 60:
|
|
break
|
|
|
|
# Parse header
|
|
filename = header[0:16].decode('ascii').strip()
|
|
size_str = header[48:58].decode('ascii').strip()
|
|
|
|
if not size_str:
|
|
break
|
|
|
|
size = int(size_str)
|
|
|
|
# Read file content
|
|
content = f.read(size)
|
|
|
|
# Pad to even boundary
|
|
if size % 2 == 1:
|
|
f.read(1)
|
|
|
|
# Save file
|
|
if filename and not filename.startswith('/'):
|
|
output_path = os.path.join(extract_dir, filename)
|
|
with open(output_path, 'wb') as out_f:
|
|
out_f.write(content)
|
|
print(f" 提取文件: {filename} ({size} 字节)")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"Python ar解析失败: {str(e)}")
|
|
return False
|
|
|
|
def test_ar_functionality():
|
|
"""测试ar功能"""
|
|
print("=== 测试纯Python ar功能 ===")
|
|
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
print(f"测试目录: {temp_dir}")
|
|
|
|
# 1. 创建测试文件
|
|
test_files = []
|
|
for i in range(3):
|
|
filename = f"test_{i}.txt"
|
|
filepath = os.path.join(temp_dir, filename)
|
|
with open(filepath, 'w') as f:
|
|
f.write(f"Test content {i}\nThis is file number {i}")
|
|
test_files.append(filename)
|
|
print(f"创建测试文件: {filename}")
|
|
|
|
# 2. 创建ar归档
|
|
ar_path = os.path.join(temp_dir, "test.ar")
|
|
success = create_ar_archive_python(ar_path, test_files, temp_dir)
|
|
|
|
if not success:
|
|
print("❌ ar归档创建失败")
|
|
return False
|
|
|
|
ar_size = os.path.getsize(ar_path)
|
|
print(f"✓ ar归档创建成功: {ar_size} 字节")
|
|
|
|
# 3. 验证ar格式
|
|
with open(ar_path, 'rb') as f:
|
|
magic = f.read(8)
|
|
if magic != b'!<arch>\n':
|
|
print(f"❌ ar魔数不正确: {magic}")
|
|
return False
|
|
print("✓ ar格式验证通过")
|
|
|
|
# 4. 解析ar归档
|
|
extract_dir = os.path.join(temp_dir, "extract")
|
|
os.makedirs(extract_dir)
|
|
|
|
success = extract_ar_archive_python(ar_path, extract_dir)
|
|
if not success:
|
|
print("❌ ar归档解析失败")
|
|
return False
|
|
|
|
# 5. 验证提取的文件
|
|
for i, filename in enumerate(test_files):
|
|
extracted_file = os.path.join(extract_dir, filename)
|
|
if not os.path.exists(extracted_file):
|
|
print(f"❌ 文件未正确提取: {filename}")
|
|
return False
|
|
|
|
with open(extracted_file, 'r') as f:
|
|
content = f.read()
|
|
expected = f"Test content {i}\nThis is file number {i}"
|
|
if content != expected:
|
|
print(f"❌ 文件内容不正确: {filename}")
|
|
print(f"期望: {expected}")
|
|
print(f"实际: {content}")
|
|
return False
|
|
|
|
print(f" ✓ 文件验证成功: {filename}")
|
|
|
|
print("✓ 所有ar功能测试通过!")
|
|
return True
|
|
|
|
def test_cross_platform_compatibility():
|
|
"""测试跨平台兼容性"""
|
|
print("\n=== 测试跨平台兼容性 ===")
|
|
|
|
# 测试不同的文件名和内容(注意ar格式文件名限制为16字符)
|
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
# 创建包含特殊字符的文件(文件名不超过16字符)
|
|
test_cases = [
|
|
("simple.txt", "Simple content"),
|
|
("with-dash.txt", "Content with dash"),
|
|
("under_score.txt", "Content with underscore"),
|
|
("file123.txt", "Numeric content"),
|
|
]
|
|
|
|
files = []
|
|
for filename, content in test_cases:
|
|
if len(filename) > 16:
|
|
print(f"警告:文件名过长,将被截断: {filename}")
|
|
filepath = os.path.join(temp_dir, filename)
|
|
with open(filepath, 'w') as f:
|
|
f.write(content)
|
|
files.append(filename)
|
|
|
|
# 创建和解析ar归档
|
|
ar_path = os.path.join(temp_dir, "cross_platform.ar")
|
|
if not create_ar_archive_python(ar_path, files, temp_dir):
|
|
print("❌ 跨平台ar创建失败")
|
|
return False
|
|
|
|
extract_dir = os.path.join(temp_dir, "extract")
|
|
os.makedirs(extract_dir)
|
|
|
|
if not extract_ar_archive_python(ar_path, extract_dir):
|
|
print("❌ 跨平台ar解析失败")
|
|
return False
|
|
|
|
# 验证所有文件(考虑文件名可能被截断)
|
|
for filename, expected_content in test_cases:
|
|
# ar格式会截断超过16字符的文件名
|
|
truncated_filename = filename[:16].rstrip()
|
|
extracted_file = os.path.join(extract_dir, truncated_filename)
|
|
|
|
if not os.path.exists(extracted_file):
|
|
print(f"❌ 文件未找到: {truncated_filename} (原名: {filename})")
|
|
# 列出实际提取的文件
|
|
actual_files = os.listdir(extract_dir)
|
|
print(f"实际提取的文件: {actual_files}")
|
|
return False
|
|
|
|
with open(extracted_file, 'r') as f:
|
|
content = f.read()
|
|
if content != expected_content:
|
|
print(f"❌ 跨平台文件内容错误: {truncated_filename}")
|
|
return False
|
|
print(f" ✓ 文件验证成功: {truncated_filename}")
|
|
|
|
print("✓ 跨平台兼容性测试通过!")
|
|
return True
|
|
|
|
def main():
|
|
"""主测试函数"""
|
|
print("开始测试纯Python ar实现...")
|
|
|
|
# 基础功能测试
|
|
if not test_ar_functionality():
|
|
print("❌ 基础功能测试失败")
|
|
return False
|
|
|
|
# 跨平台兼容性测试
|
|
if not test_cross_platform_compatibility():
|
|
print("❌ 跨平台兼容性测试失败")
|
|
return False
|
|
|
|
print("\n🎉 所有测试通过!")
|
|
print("✓ 纯Python ar实现完全正常")
|
|
print("✓ 不依赖任何外部命令")
|
|
print("✓ 跨平台兼容性良好")
|
|
print("✓ ar格式完全兼容")
|
|
|
|
return True
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
sys.exit(0 if success else 1)
|