137 lines
5.0 KiB
Python
137 lines
5.0 KiB
Python
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() |