Files
ewoooc/tests/test_file_upload.py
ogt 1b4f3a7bbe
Some checks failed
CD Pipeline / deploy (push) Failing after 59s
feat: EwoooC 初始化 — 完整專案推版至 Gitea
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml)
- 部署模式: rsync Python 檔案至 188 → docker restart (volume mount)
- Dockerfile/requirements 變動時自動重建 Docker image
- 部署通知: Telegram (開始/成功/失敗)
- 健康檢查: https://mo.wooo.work/health (最多 5 次重試)
- 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 01:21:13 +08:00

180 lines
5.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
檔案上傳驗證測試腳本
測試 app.py 中的檔案上傳驗證函數
"""
import sys
import os
from io import BytesIO
# 確保可以導入專案模組
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from app import allowed_file, validate_upload_file
from werkzeug.datastructures import FileStorage
def test_allowed_file():
"""測試檔案副檔名驗證"""
print("="*60)
print("測試 1: 檔案副檔名驗證 (allowed_file)")
print("="*60)
test_cases = [
# (檔案名, 是否應該通過, 描述)
('report.xlsx', True, 'Excel 2007+ 格式'),
('data.xls', True, 'Excel 97-2003 格式'),
('export.csv', True, 'CSV 格式'),
('REPORT.XLSX', True, '大寫副檔名'),
('file.XLS', True, '混合大小寫'),
('malware.exe', False, '執行檔'),
('script.php', False, 'PHP 腳本'),
('shell.sh', False, 'Shell 腳本'),
('image.jpg', False, '圖片檔'),
('document.pdf', False, 'PDF 檔案'),
('archive.zip', False, '壓縮檔'),
('file', False, '無副檔名'),
('', False, '空檔名'),
('.xlsx', False, '只有副檔名'),
('../../etc/passwd.csv', True, '路徑遍歷但副檔名正確'),
('file.csv.exe', False, '雙副檔名攻擊'),
]
passed = 0
failed = 0
for filename, should_pass, description in test_cases:
result = allowed_file(filename)
if result == should_pass:
print(f"✅ 通過: {description} | 檔名: '{filename}' | 結果: {result}")
passed += 1
else:
print(f"❌ 失敗: {description} | 檔名: '{filename}' | 期望: {should_pass} | 實際: {result}")
failed += 1
return passed, failed
def test_validate_upload_file():
"""測試完整的檔案上傳驗證"""
print("\n" + "="*60)
print("測試 2: 完整檔案上傳驗證 (validate_upload_file)")
print("="*60)
test_cases = [
# (檔名, 是否應該通過, 描述)
('即時業績(全月).xlsx', True, '正常中文檔名'),
('sales_report.csv', True, '正常英文檔名'),
('data 2024.xls', True, '包含空格的檔名'),
('../../../etc/passwd.csv', False, '路徑遍歷攻擊'),
('../../config.py.xlsx', False, '路徑遍歷攻擊'),
('malware.exe', False, '不允許的副檔名'),
('', False, '空檔名'),
('<script>alert(1)</script>.xlsx', True, 'XSS 嘗試(會被清理)'),
('file|pipe.csv', True, '特殊字元(會被清理)'),
('file\x00null.xlsx', True, 'Null 字元(會被清理)'),
]
passed = 0
failed = 0
for filename, should_pass, description in test_cases:
# 建立模擬的 FileStorage 物件
fake_file = FileStorage(
stream=BytesIO(b"test data"),
filename=filename,
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
is_valid, error_msg, safe_name = validate_upload_file(fake_file)
if is_valid == should_pass:
print(f"✅ 通過: {description}")
print(f" 原始檔名: '{filename}'")
if is_valid:
print(f" 安全檔名: '{safe_name}'")
else:
print(f" 拒絕原因: {error_msg}")
passed += 1
else:
print(f"❌ 失敗: {description}")
print(f" 原始檔名: '{filename}'")
print(f" 期望: {'通過' if should_pass else '拒絕'}")
print(f" 實際: {'通過' if is_valid else '拒絕'}")
if not is_valid:
print(f" 錯誤訊息: {error_msg}")
failed += 1
print()
return passed, failed
def test_secure_filename_cleaning():
"""測試 secure_filename 的清理效果"""
print("="*60)
print("測試 3: 檔案名稱清理效果")
print("="*60)
from werkzeug.utils import secure_filename
test_cases = [
('即時業績(全月).xlsx', '中文與括號'),
('../../../etc/passwd.csv', '路徑遍歷'),
('file|pipe<>:*.csv', '特殊字元'),
(' spaces .xlsx', '空格'),
('file\x00null.csv', 'Null 字元'),
('<script>alert(1)</script>.xlsx', 'HTML 標籤'),
]
print("\n檔案名稱清理範例:")
print("-"*60)
for original, description in test_cases:
cleaned = secure_filename(original)
print(f"描述: {description}")
print(f" 原始: '{original}'")
print(f" 清理後: '{cleaned}'")
print()
return 0, 0 # 這個測試只是展示,不計入通過/失敗
def main():
"""主測試函數"""
print("="*60)
print("MOMO 監控系統 - 檔案上傳驗證測試")
print("="*60)
print()
total_passed = 0
total_failed = 0
# 執行所有測試
passed, failed = test_allowed_file()
total_passed += passed
total_failed += failed
passed, failed = test_validate_upload_file()
total_passed += passed
total_failed += failed
# 展示清理效果(不計入結果)
test_secure_filename_cleaning()
# 顯示總結
print("="*60)
print("測試結果摘要")
print("="*60)
print(f"✅ 通過: {total_passed}")
print(f"❌ 失敗: {total_failed}")
print(f"總計: {total_passed + total_failed}")
if total_failed == 0:
print("\n🎉 所有檔案上傳驗證測試通過!")
return 0
else:
print(f"\n⚠️ 有 {total_failed} 個測試失敗,請檢查!")
return 1
if __name__ == "__main__":
sys.exit(main())