Squashed 'paste-framework/' content from commit 34e8684

git-subtree-dir: paste-framework
git-subtree-split: 34e8684c4bc3cebbe177509f42ab4ef5b5425a7a
This commit is contained in:
zwf
2026-06-02 19:09:22 +08:00
commit 4729698049
107 changed files with 21484 additions and 0 deletions
View File
+60
View File
@@ -0,0 +1,60 @@
"""
测试配置读取功能。
使用 mock 配置文件,不依赖真实 config.json。
"""
from unittest.mock import patch
import pytest
from paste.core import config
class TestConfiguration:
"""配置管理测试"""
def test_load_config_with_mock_file(self, temp_config_file):
"""使用临时配置文件测试加载"""
with patch.object(config, 'load_config', wraps=config.load_config):
# 模拟配置文件路径
with patch('paste.core.config.os.path.abspath') as mock_abspath:
mock_abspath.return_value = str(temp_config_file)
cfg = config.load_config()
assert isinstance(cfg, dict)
assert 'db_engine' in cfg
def test_get_config_by_path_existing(self, mock_config_dict):
"""测试读取存在的配置项"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
result = config.get_config_by_path('db_engine.engine')
assert result == "sqlite+pysqlite:///:memory:"
def test_get_config_by_path_nested(self, mock_config_dict):
"""测试读取深层嵌套配置"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
result = config.get_config_by_path('redis.connection.url')
assert result == "redis://localhost:6379/15"
def test_get_config_by_path_with_default(self, mock_config_dict):
"""测试带默认值的配置读取"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
result = config.get_config_by_path('nonexistent.key', default='fallback')
assert result == 'fallback'
def test_get_config_by_path_missing_without_default(self, mock_config_dict):
"""测试缺失配置项且无默认值时抛出异常"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
with pytest.raises(AssertionError):
config.get_config_by_path('nonexistent.key')
def test_get_config_shortcut(self, mock_config_dict):
"""测试 get_config 快捷方法"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
result = config.get_config('tornado.demo.port')
assert result == 9000
def test_get_config_default_none(self, mock_config_dict):
"""测试 get_config 默认值 None 的情况"""
with patch('paste.core.config.GLOBAL_CONFIG', mock_config_dict):
with pytest.raises(AssertionError):
config.get_config('completely.nonexistent')
+75
View File
@@ -0,0 +1,75 @@
"""
测试 JWT 令牌编解码功能。
使用 mock 配置,不依赖真实密钥文件。
"""
import time
import pytest
from paste.security.token import encode_token, decode_token
class TestJwtToken:
"""JWT 令牌测试"""
def test_encode_decode_basic(self):
"""基础编解码测试"""
payload = {
'user_id': 123,
'username': 'test_user',
'role': 'admin',
}
token = encode_token(**payload)
assert token is not None
assert isinstance(token, str)
assert len(token) > 0
decoded = decode_token(token)
assert decoded is not None
assert decoded.get('params', {}).get('user_id') == 123
def test_token_contains_expected_fields(self):
"""验证 token 包含必要字段"""
payload = {'user_id': 456, 'username': 'demo'}
token = encode_token(**payload)
decoded = decode_token(token)
# 标准 JWT 字段
assert 'iss' in decoded, "Token should have issuer"
assert 'iat' in decoded, "Token should have issued-at time"
assert 'exp' in decoded, "Token should have expiration time"
# 自定义字段
params = decoded.get('params', {})
assert params.get('user_id') == 456
assert params.get('username') == 'demo'
def test_token_expiration(self):
"""验证 token 过期机制"""
payload = {
'user_id': 789,
'username': 'expired_user',
'exp': int(time.time()) - 3600, # 1小时前过期
}
token = encode_token(**payload)
with pytest.raises(Exception):
decode_token(token)
def test_token_tampering(self):
"""验证 token 防篡改"""
payload = {'user_id': 999, 'username': 'hacker'}
token = encode_token(**payload)
# 篡改 token
tampered_token = token[:-5] + 'XXXXX'
with pytest.raises(Exception):
decode_token(tampered_token)
def test_empty_payload(self):
"""空 payload 处理"""
token = encode_token()
decoded = decode_token(token)
assert decoded is not None
+119
View File
@@ -0,0 +1,119 @@
"""
测试分页逻辑。
无外部依赖,可离线运行。
"""
from paste.util.pagination import Pagination
class TestPagination:
"""分页功能测试"""
def test_pages_calculation_exact(self):
"""精确整除的分页计算"""
p = Pagination(row_count=100)
pages = p.pages(page_size=20)
assert pages == 5
def test_pages_calculation_remainder(self):
"""有余数的分页计算"""
p = Pagination(row_count=101)
pages = p.pages(page_size=20)
assert pages == 6
def test_pages_calculation_zero_rows(self):
"""零行数据的处理"""
p = Pagination(row_count=0)
pages = p.pages(page_size=20)
assert pages == 1
def test_page_number_valid(self):
"""页码有效性检测"""
p = Pagination(row_count=50)
p.pages(page_size=20)
assert p.number(1) == 1
assert p.number(3) == 3 # 超出范围应返回最大页
def test_page_number_negative(self):
"""负页码处理"""
p = Pagination(row_count=50)
p.pages(page_size=20)
assert p.number(-1) == 1
def test_offset_calculation(self):
"""偏移量计算"""
p = Pagination(row_count=100)
p.pages(page_size=20)
assert p.offset(1) == 0
assert p.offset(2) == 20
assert p.offset(3) == 40
def test_paging_chain(self):
"""链式调用分页"""
p = Pagination(row_count=123).paging(page_number=2, page_size=20)
assert p.page_count == 7
assert p.page_number == 2
assert p.offset_size == 20
def test_page_size_bounds(self):
"""页大小边界: 最小1,最大1000"""
p = Pagination(row_count=2000)
assert p.pages(page_size=0) > 0
assert p.pages(page_size=2000) <= 1000
def test_large_dataset(self):
"""大数据集分页"""
p = Pagination(row_count=1000000)
pages = p.pages(page_size=100)
assert pages == 10000
def test_single_row(self):
"""单行数据"""
p = Pagination(row_count=1)
assert p.pages(page_size=10) == 1
p.paging(page_number=1, page_size=10)
assert p.page_number == 1
assert p.offset_size == 0
def test_page_number_upper_bound(self):
"""页码上限处理"""
p = Pagination(row_count=30).paging(page_number=100, page_size=10)
assert p.page_number == 3 # 最大只能到3页
# ============================================================
# 以下是从 test_db.py 迁移过来的分页测试
# 原函数 test_pagination() 改为标准的 pytest 测试
# ============================================================
class TestPaginationFromDb:
"""从 test_db.py 迁移的分页测试"""
def test_pagination_basic(self):
"""基础分页计算"""
from paste.util.pagination import Pagination
p = Pagination(row_count=123).paging(page_number=2, page_size=20)
assert p.page_count == 7
assert p.page_number == 2
assert p.offset_size == 20
def test_pagination_first_page(self):
"""第一页"""
from paste.util.pagination import Pagination
p = Pagination(row_count=50).paging(page_number=1, page_size=10)
assert p.page_number == 1
assert p.offset_size == 0
def test_pagination_last_page(self):
"""最后一页"""
from paste.util.pagination import Pagination
p = Pagination(row_count=55).paging(page_number=6, page_size=10)
assert p.page_number == 6
assert p.offset_size == 50
def test_pagination_out_of_range(self):
"""超出范围时自动修正"""
from paste.util.pagination import Pagination
p = Pagination(row_count=30).paging(page_number=100, page_size=10)
assert p.page_number == 3 # 只有3页,自动修正
+26
View File
@@ -0,0 +1,26 @@
"""
测试 paste 包的基本导入和版本信息。
无外部依赖,可离线运行。
"""
import paste
class TestPasteImport:
"""测试 paste 包基础功能"""
def test_paste_imports(self):
"""确保 paste 包能正确导入"""
assert paste is not None
def test_paste_version(self):
"""检查 paste 包是否有 __version__"""
assert hasattr(paste, "__version__"), "paste package should have __version__"
assert isinstance(paste.__version__, str), "__version__ should be a string"
def test_paste_version_value(self):
"""验证版本号格式符合语义化版本规范"""
import re
version = paste.__version__
assert re.match(r'^\d+\.\d+\.\d+', version), \
f"Version {version} should follow semver format"
+46
View File
@@ -0,0 +1,46 @@
"""
测试雪花 ID 生成器。
无外部依赖,可离线运行。
"""
from paste.util.snow_id import IdWorker
class TestSnowflakeId:
"""雪花 ID 生成器测试"""
def test_snow_id_generates_string(self):
"""测试 Snowflake ID 是否生成字符串"""
id_worker = IdWorker.get_id_worker()
sid = f'{id_worker.get_id()}'
assert isinstance(sid, str), "雪花 ID 必须是字符串"
assert len(sid) > 0, "雪花 ID 必须包含内容"
def test_snow_id_is_unique(self):
"""测试生成的 ID 是否唯一(简单验证)"""
id_worker = IdWorker.get_id_worker()
ids = [id_worker.get_id() for _ in range(50)]
assert len(set(ids)) == len(ids), "All generated IDs should be unique"
def test_snow_id_monotonic_increase(self):
"""测试雪花 ID 单调递增"""
id_worker = IdWorker.get_id_worker()
ids = [id_worker.get_id() for _ in range(100)]
for i in range(1, len(ids)):
assert ids[i] > ids[i - 1], \
f"ID at position {i} should be greater than previous"
def test_snow_id_worker_isolation(self):
"""测试不同 worker 生成的 ID 不冲突"""
worker1 = IdWorker.get_id_worker(datacenter_id=1, worker_id=1)
worker2 = IdWorker.get_id_worker(datacenter_id=2, worker_id=2)
ids = [worker1.get_id() for _ in range(50)] + \
[worker2.get_id() for _ in range(50)]
assert len(set(ids)) == len(ids), \
"IDs from different workers should be unique"
def test_snow_id_high_throughput(self):
"""测试短时间高并发生成"""
id_worker = IdWorker.get_id_worker()
ids = [id_worker.get_id() for _ in range(1000)]
assert len(set(ids)) == 1000
+45
View File
@@ -0,0 +1,45 @@
"""
测试字典工具。
无外部依赖,可离线运行。
"""
from paste.util import udict
class TestUdict:
"""字典工具测试"""
def test_get_by_path_simple(self):
"""简单路径读取"""
data = {"a": 1, "b": 2}
assert udict.get_by_path(data, "a") == 1
def test_get_by_path_nested(self):
"""嵌套路径读取"""
data = {"a": {"b": {"c": 123}}}
assert udict.get_by_path(data, "a.b.c") == 123
def test_get_by_path_missing(self):
"""缺失路径处理"""
data = {"a": 1}
assert udict.get_by_path(data, "b.c.d", "default") == "default"
def test_get_by_path_none_default(self):
"""缺失路径无默认值"""
data = {"a": 1}
assert udict.get_by_path(data, "b") is None
def test_get_with_default_existing(self):
"""存在的键读取"""
data = {"key": "value"}
assert udict.get_with_default(data, "key", "fallback") == "value"
def test_get_with_default_missing(self):
"""缺失键使用默认值"""
data = {"key": "value"}
assert udict.get_with_default(data, "missing", "fallback") == "fallback"
def test_get_with_default_none_value(self):
"""值为 None 时使用默认值"""
data = {"key": None}
assert udict.get_with_default(data, "key", "fallback") == "fallback"
+44
View File
@@ -0,0 +1,44 @@
"""
测试字符串工具。
无外部依赖,可离线运行。
"""
import datetime
from paste.util import ustr
class TestUstr:
"""字符串工具测试"""
def test_str_q_count_all_cn(self):
"""全中文统计"""
assert ustr.str_q_count("中国汉字") == 4
def test_str_q_count_mixed(self):
"""中英文混合统计"""
count = ustr.str_q_count("Hello中国")
assert count == 2 # 只有中文字符算
def test_str_q_count_empty(self):
"""空字符串统计"""
assert ustr.str_q_count("") == 0
def test_str_q_count_no_cn(self):
"""纯英文统计"""
assert ustr.str_q_count("HelloWorld") == 0
def test_to_datetime_standard(self):
"""标准格式解析"""
result = ustr.to_datetime("2024-01-15 10:30:00", ["%Y-%m-%d %H:%M:%S"])
assert result is not None
assert isinstance(result, datetime.datetime)
def test_to_datetime_invalid(self):
"""无效格式解析"""
result = ustr.to_datetime("not-a-date", ["%Y-%m-%d"])
assert result is None
def test_to_datetime_empty(self):
"""空字符串解析"""
result = ustr.to_datetime("", ["%Y-%m-%d"])
assert result is None