import unittest from unittest.mock import AsyncMock, MagicMock, patch import os import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "opax-mcp")) import gitea_handler def make_stream_context(response): context = MagicMock() context.__aenter__ = AsyncMock(return_value=response) context.__aexit__ = AsyncMock(return_value=False) return context class TestGiteaHelpers(unittest.IsolatedAsyncioTestCase): def test_validate_branch_name_valid(self): self.assertEqual(gitea_handler._validate_branch_name("main"), "main") self.assertEqual(gitea_handler._validate_branch_name("feat/opax-domain-decouple"), "feat/opax-domain-decouple") def test_validate_branch_name_invalid(self): with self.assertRaises(ValueError): gitea_handler._validate_branch_name("../../etc/passwd") with self.assertRaises(ValueError): gitea_handler._validate_branch_name("main@{bad}") with self.assertRaises(ValueError): gitea_handler._validate_branch_name("feat//bad") def test_validate_commit_sha_valid(self): self.assertEqual(gitea_handler._validate_commit_sha("395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9"), "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9") def test_validate_commit_sha_invalid(self): with self.assertRaises(ValueError): gitea_handler._validate_commit_sha("main") with self.assertRaises(ValueError): gitea_handler._validate_commit_sha("395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c") # 39 chars def test_validate_gitea_url_https_required(self): with self.assertRaises(ValueError): gitea_handler._validate_gitea_url("http://example.com") @patch("gitea_handler.httpx.AsyncClient") async def test_resolve_branch_to_commit_sha(self, mock_client): mock_response = unittest.mock.Mock() mock_response.status_code = 200 mock_response.json.return_value = {"commit": {"id": "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9"}} mock_client.return_value.__aenter__.return_value.get.return_value = mock_response sha = await gitea_handler.resolve_branch_to_commit_sha("main", "chris/OSVauco", "https://gitea.example.com") self.assertEqual(sha, "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9") @patch("gitea_handler.httpx.AsyncClient") async def test_download_repo_archive_uses_sha(self, mock_client): response = MagicMock() response.headers = {} response.raise_for_status = MagicMock() async def aiter_bytes(): yield b"archive-data" response.aiter_bytes = aiter_bytes stream_context = make_stream_context(response) client = mock_client.return_value.__aenter__.return_value client.stream = MagicMock(return_value=stream_context) archive = await gitea_handler.download_repo_archive( "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9", "chris/OSVauco", "https://gitea.example.com", ) self.assertEqual(archive, b"archive-data") client.stream.assert_called_once_with( "GET", ( "https://gitea.example.com/api/v1/repos/" "chris/OSVauco/archive/" "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9.tar.gz" ), headers=unittest.mock.ANY, ) @patch("gitea_handler.httpx.AsyncClient") async def test_download_repo_archive_size_limit(self, mock_client): response = MagicMock() response.headers = { "content-length": str( gitea_handler.MAX_SOURCE_ARCHIVE_BYTES + 1 ) } response.raise_for_status = MagicMock() stream_context = make_stream_context(response) client = mock_client.return_value.__aenter__.return_value client.stream = MagicMock(return_value=stream_context) with self.assertRaisesRegex( ValueError, "Source archive exceeds allowed size", ): await gitea_handler.download_repo_archive( "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9", "chris/OSVauco", "https://gitea.example.com", ) @patch("gitea_handler.httpx.AsyncClient") async def test_download_repo_archive_no_redirects(self, mock_client): response = MagicMock() response.headers = {} response.raise_for_status = MagicMock() async def aiter_bytes(): yield b"" response.aiter_bytes = aiter_bytes stream_context = make_stream_context(response) client = mock_client.return_value.__aenter__.return_value client.stream = MagicMock(return_value=stream_context) await gitea_handler.download_repo_archive( "395aad5d70d1d30ccd4c3f84e3dfb56e38a2c2c9", "chris/OSVauco", "https://gitea.example.com", ) self.assertFalse( mock_client.call_args.kwargs["follow_redirects"] ) if __name__ == "__main__": unittest.main()