import pytest import os import tempfile from unittest.mock import patch, MagicMock class TestUserVideoAPI: """사용자 비디오 스트리밍 관련 API 테스트""" def test_stream_video_success(self, client): """비디오 스트리밍 성공 테스트""" # 임시 파일 생성 with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file: tmp_file.write(b"fake video content") tmp_filename = os.path.basename(tmp_file.name) # uploads 디렉토리 mock with patch('os.path.exists', return_value=True): with patch('os.path.join', return_value=tmp_file.name): # 테스트 실행 response = client.get(f"/api/v1/user/video/{tmp_filename}") # 검증 assert response.status_code == 200 assert response.headers["content-type"] == "video/mp4" # 임시 파일 삭제 os.unlink(tmp_file.name) def test_stream_video_not_found(self, client): """존재하지 않는 비디오 스트리밍 테스트""" # 파일이 존재하지 않도록 설정 with patch('os.path.exists', return_value=False): # 테스트 실행 response = client.get("/api/v1/user/video/non_existent_video.mp4") # 검증 assert response.status_code == 404 assert response.json()["detail"] == "Video not found" def test_stream_video_with_encoded_filename(self, client): """URL 인코딩된 파일명으로 비디오 스트리밍 테스트""" # URL 인코딩된 파일명 encoded_filename = "test%20video%20file.mp4" decoded_filename = "test video file.mp4" # 임시 파일 생성 with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file: tmp_file.write(b"fake video content") # Mock 설정 with patch('os.path.basename', return_value=decoded_filename): with patch('os.path.exists', return_value=True): with patch('os.path.join', return_value=tmp_file.name): # 테스트 실행 response = client.get(f"/api/v1/user/video/{encoded_filename}") # 검증 assert response.status_code == 200 assert response.headers["content-type"] == "video/mp4" # 임시 파일 삭제 os.unlink(tmp_file.name) def test_stream_video_with_special_characters(self, client): """특수문자가 포함된 파일명 테스트""" # 특수문자가 포함된 파일명 filename = "video@2024#test!.mp4" # 임시 파일 생성 with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file: tmp_file.write(b"fake video content") # Mock 설정 with patch('os.path.basename', return_value=filename): with patch('os.path.exists', return_value=True): with patch('os.path.join', return_value=tmp_file.name): # 테스트 실행 response = client.get(f"/api/v1/user/video/{filename}") # 검증 assert response.status_code == 200 # 임시 파일 삭제 os.unlink(tmp_file.name) def test_stream_video_path_traversal_protection(self, client): """경로 탐색 공격 방지 테스트""" # 경로 탐색 시도 malicious_filename = "../../../etc/passwd" safe_filename = "passwd" # basename이 경로를 제거하고 파일명만 반환 with patch('os.path.basename', return_value=safe_filename): with patch('os.path.exists', return_value=False): # 테스트 실행 response = client.get(f"/api/v1/user/video/{malicious_filename}") # 검증 - 파일을 찾을 수 없음 assert response.status_code == 404 def test_stream_video_empty_filename(self, client): """빈 파일명으로 요청 테스트""" # 테스트 실행 response = client.get("/api/v1/user/video/") # 검증 - 404 (라우트를 찾을 수 없음) assert response.status_code == 404 def test_stream_video_large_file(self, client): """대용량 파일 스트리밍 테스트""" # 10MB 크기의 임시 파일 생성 with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_file: # 10MB 더미 데이터 작성 tmp_file.write(b"0" * (10 * 1024 * 1024)) tmp_filename = os.path.basename(tmp_file.name) # uploads 디렉토리 mock with patch('os.path.exists', return_value=True): with patch('os.path.join', return_value=tmp_file.name): # 테스트 실행 response = client.get(f"/api/v1/user/video/{tmp_filename}") # 검증 assert response.status_code == 200 assert response.headers["content-type"] == "video/mp4" # 임시 파일 삭제 os.unlink(tmp_file.name) def test_stream_video_different_extensions(self, client): """다양한 비디오 확장자 테스트""" extensions = [".mp4", ".avi", ".mov", ".mkv", ".webm"] for ext in extensions: # 임시 파일 생성 with tempfile.NamedTemporaryFile(delete=False, suffix=ext) as tmp_file: tmp_file.write(b"fake video content") tmp_filename = os.path.basename(tmp_file.name) # uploads 디렉토리 mock with patch('os.path.exists', return_value=True): with patch('os.path.join', return_value=tmp_file.name): # 테스트 실행 response = client.get(f"/api/v1/user/video/{tmp_filename}") # 검증 - 모든 확장자가 video/mp4로 반환됨 assert response.status_code == 200 assert response.headers["content-type"] == "video/mp4" # 임시 파일 삭제 os.unlink(tmp_file.name)