Files
life-echo/api/tests/test_memoir_image_storage.py
2026-03-11 11:27:32 +08:00

136 lines
4.8 KiB
Python

import os
import unittest
from unittest.mock import Mock, patch
from api.services.memoir_images.storage import (
TencentCosStorageService,
normalize_cos_url,
resolve_image_storage_key,
)
class MemoirImageStorageTest(unittest.TestCase):
@patch.dict(
os.environ,
{
"TENCENT_COS_SECRET_ID": "id",
"TENCENT_COS_SECRET_KEY": "key",
"TENCENT_COS_REGION": "ap-shanghai",
"TENCENT_COS_BUCKET": "memoir-1250000000",
"TENCENT_COS_BASE_URL": "https://memoir-1250000000.cos.ap-shanghai.myqcloud.com",
},
clear=False,
)
@patch("api.services.memoir_images.storage.CosS3Client")
def test_from_env_reuses_singleton_for_same_config(self, client_cls):
TencentCosStorageService._instance = None
TencentCosStorageService._instance_config = None
client_cls.return_value = Mock()
first = TencentCosStorageService.from_env()
second = TencentCosStorageService.from_env()
self.assertIs(first, second)
client_cls.assert_called_once()
@patch("api.services.memoir_images.storage.CosS3Client")
def test_upload_bytes_returns_persistent_cos_url(self, client_cls):
client = Mock()
client_cls.return_value = client
storage = TencentCosStorageService(
secret_id="id",
secret_key="key",
region="ap-shanghai",
bucket="memoir-1250000000",
base_url="https://memoir-1250000000.cos.ap-shanghai.myqcloud.com",
)
url = storage.upload_bytes(
image_bytes=b"png-bytes",
key="memoirs/u1/c1/0-demo.png",
content_type="image/png",
)
self.assertEqual(
url,
"https://memoir-1250000000.cos.ap-shanghai.myqcloud.com/memoirs/u1/c1/0-demo.png",
)
client.put_object.assert_called_once()
@patch("api.services.memoir_images.storage.CosS3Client")
def test_upload_bytes_normalizes_duplicate_appid_suffix_in_base_url(self, client_cls):
client = Mock()
client_cls.return_value = client
storage = TencentCosStorageService(
secret_id="id",
secret_key="key",
region="ap-shanghai",
bucket="life-echo-dev-1319381411",
base_url="https://life-echo-dev-1319381411-appid.cos.ap-shanghai.myqcloud.com",
)
url = storage.upload_bytes(
image_bytes=b"png-bytes",
key="memoirs/u1/c1/0-demo.png",
content_type="image/png",
)
self.assertEqual(
url,
"https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com/memoirs/u1/c1/0-demo.png",
)
client.put_object.assert_called_once()
def test_normalize_cos_url_repairs_existing_duplicate_appid_host(self):
normalized = normalize_cos_url(
"https://life-echo-dev-1319381411-appid.cos.ap-shanghai.myqcloud.com/memoirs/u1/c1/0-demo.png",
bucket="life-echo-dev-1319381411",
region="ap-shanghai",
)
self.assertEqual(
normalized,
"https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com/memoirs/u1/c1/0-demo.png",
)
@patch("api.services.memoir_images.storage.CosS3Client")
def test_get_download_url_returns_presigned_download_url(self, client_cls):
client = Mock()
client.get_presigned_download_url.return_value = "https://cos.example.com/0.png?q-sign-algorithm=sha1"
client_cls.return_value = client
storage = TencentCosStorageService(
secret_id="id",
secret_key="key",
region="ap-shanghai",
bucket="life-echo-dev-1319381411",
base_url="https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com",
)
url = storage.get_download_url("memoirs/u1/c1/0-demo.png", expires=1800)
self.assertEqual(url, "https://cos.example.com/0.png?q-sign-algorithm=sha1")
client.get_presigned_download_url.assert_called_once_with(
Bucket="life-echo-dev-1319381411",
Key="memoirs/u1/c1/0-demo.png",
Expired=1800,
)
def test_resolve_image_storage_key_prefers_explicit_storage_key(self):
key = resolve_image_storage_key(
{
"storage_key": "memoirs/u1/c1/0-demo.png",
"url": "https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com/other.png",
}
)
self.assertEqual(key, "memoirs/u1/c1/0-demo.png")
def test_resolve_image_storage_key_derives_key_from_existing_url(self):
key = resolve_image_storage_key(
{
"url": "https://life-echo-dev-1319381411.cos.ap-shanghai.myqcloud.com/memoirs/u1/c1/0-demo.png?q-sign-algorithm=sha1"
}
)
self.assertEqual(key, "memoirs/u1/c1/0-demo.png")