Files
v-hono/test_comprehensive_suite.v
T

542 lines
12 KiB
V

import hono
import os
import time
import strings
// 测试统计
struct TestStats {
mut:
total_tests int
passed_tests int
failed_tests int
start_time time.Time
}
fn (mut stats TestStats) start_test(test_name string) {
stats.total_tests++
println('🧪 运行测试: ${test_name}')
}
fn (mut stats TestStats) pass_test(test_name string) {
stats.passed_tests++
println('✅ 测试通过: ${test_name}')
}
fn (mut stats TestStats) fail_test(test_name string, error string) {
stats.failed_tests++
println('❌ 测试失败: ${test_name} - ${error}')
}
fn (stats TestStats) print_summary() {
duration := time.since(stats.start_time)
println('\n=== 测试总结 ===')
println('总测试数: ${stats.total_tests}')
println('通过: ${stats.passed_tests}')
println('失败: ${stats.failed_tests}')
println('成功率: ${(stats.passed_tests * 100 / stats.total_tests)}%')
println('耗时: ${duration.milliseconds()}ms')
if stats.failed_tests == 0 {
println('🎉 所有测试通过!')
} else {
println('⚠️ 有 ${stats.failed_tests} 个测试失败')
}
}
// 1. 测试缓存系统
fn test_cache_system(mut stats TestStats) {
stats.start_test('缓存系统')
// 创建缓存
mut cache := hono.new_context_lru_cache(3)
// 测试基本操作
cache.put('key1', 'value1')
cache.put('key2', 'value2')
cache.put('key3', 'value3')
// 验证获取
if val := cache.get('key1') {
if val != 'value1' {
stats.fail_test('缓存系统', '获取值不匹配')
return
}
} else {
stats.fail_test('缓存系统', '无法获取缓存值')
return
}
// 测试LRU淘汰
cache.put('key4', 'value4') // 应该淘汰key2
if cache.get('key2') or { '' } != '' {
stats.fail_test('缓存系统', 'LRU淘汰机制失效')
return
}
// 测试健康检查
if !cache.is_healthy() {
stats.fail_test('缓存系统', '缓存健康检查失败')
return
}
stats.pass_test('缓存系统')
}
// 2. 测试安全验证
fn test_security_validation(mut stats TestStats) {
stats.start_test('安全验证')
// 测试路径验证
dangerous_paths := [
'../../../etc/passwd',
'..\\..\\windows\\system32',
'/etc/passwd',
'C:\\Windows\\System32',
'file<script>',
'file|rm -rf',
'CON.txt',
'PRN.log'
]
for path in dangerous_paths {
if hono.validate_file_path(path, hono.PathValidationOptions{}) {
stats.fail_test('安全验证', '危险路径未被拒绝: ${path}')
return
}
}
// 测试安全路径
safe_paths := [
'documents/file.txt',
'images/photo.jpg',
'data/report.pdf'
]
for path in safe_paths {
if !hono.validate_file_path(path, hono.PathValidationOptions{}) {
stats.fail_test('安全验证', '安全路径被错误拒绝: ${path}')
return
}
}
// 测试哈希验证
invalid_hashes := [
'invalid_hash',
'12345',
'abcdefghijklmnopqrstuvwxyz123456789',
'hash with spaces'
]
for hash in invalid_hashes {
if hono.validate_file_hash(hash) {
stats.fail_test('安全验证', '无效哈希未被拒绝: ${hash}')
return
}
}
// 测试有效哈希
valid_hash := 'a1b2c3d4e5f6789012345678901234567'
if !hono.validate_file_hash(valid_hash) {
stats.fail_test('安全验证', '有效哈希被错误拒绝')
return
}
stats.pass_test('安全验证')
}
// 3. 测试错误处理
fn test_error_handling(mut stats TestStats) {
stats.start_test('错误处理')
// 测试各种错误类型
error_tests := [
{
'type': 'bad_request'
'expected_code': '400'
},
{
'type': 'unauthorized'
'expected_code': '401'
},
{
'type': 'forbidden'
'expected_code': '403'
},
{
'type': 'not_found'
'expected_code': '404'
},
{
'type': 'internal_error'
'expected_code': '500'
}
]
for test in error_tests {
mut response := match test['type'] {
'bad_request' { hono.bad_request('测试错误', '/test') }
'unauthorized' { hono.unauthorized('未授权', '/test') }
'forbidden' { hono.forbidden('禁止访问', '/test') }
'not_found' { hono.not_found('未找到', '/test') }
'internal_error' { hono.internal_error('内部错误', '/test') }
else { hono.bad_request('默认错误', '/test') }
}
if !response.contains('"code":"${test['expected_code']}"') {
stats.fail_test('错误处理', '错误代码不匹配: ${test['type']}')
return
}
if !response.contains('"timestamp"') {
stats.fail_test('错误处理', '缺少时间戳: ${test['type']}')
return
}
}
stats.pass_test('错误处理')
}
// 4. 测试路由系统
fn test_router_system(mut stats TestStats) {
stats.start_test('路由系统')
mut router := hono.new_router()
// 添加路由
router.add_route('GET', '/users', 'get_users')
router.add_route('POST', '/users', 'create_user')
router.add_route('GET', '/users/:id', 'get_user')
router.add_route('PUT', '/users/:id', 'update_user')
// 测试路由匹配
route_tests := [
{
'method': 'GET'
'path': '/users'
'expected': 'get_users'
},
{
'method': 'POST'
'path': '/users'
'expected': 'create_user'
},
{
'method': 'GET'
'path': '/users/123'
'expected': 'get_user'
},
{
'method': 'PUT'
'path': '/users/456'
'expected': 'update_user'
}
]
for test in route_tests {
if route := router.match_route(test['method'], test['path']) {
if route.handler != test['expected'] {
stats.fail_test('路由系统', '路由处理器不匹配: ${test['path']}')
return
}
} else {
stats.fail_test('路由系统', '路由匹配失败: ${test['path']}')
return
}
}
// 测试不存在的路由
if router.match_route('DELETE', '/nonexistent') != none {
stats.fail_test('路由系统', '不应该匹配不存在的路由')
return
}
stats.pass_test('路由系统')
}
// 5. 测试配置管理
fn test_config_management(mut stats TestStats) {
stats.start_test('配置管理')
// 测试默认配置
config := hono.default_config()
if config.server.host != '127.0.0.1' {
stats.fail_test('配置管理', '默认主机地址不正确')
return
}
if config.server.port != 8080 {
stats.fail_test('配置管理', '默认端口不正确')
return
}
// 测试配置验证
mut invalid_config := config
invalid_config.server.port = 0
hono.validate_config(invalid_config) or {
// 应该验证失败
stats.pass_test('配置管理')
return
}
stats.fail_test('配置管理', '无效配置未被拒绝')
}
// 6. 测试日志系统
fn test_logging_system(mut stats TestStats) {
stats.start_test('日志系统')
// 创建测试日志器
config := hono.LoggerConfig{
level: hono.LogLevel.debug
output: hono.LogOutput.console
enable_colors: false
}
mut logger := hono.new_logger(config)
// 测试日志级别
if !logger.should_log(hono.LogLevel.info) {
stats.fail_test('日志系统', '日志级别检查失败')
return
}
if logger.should_log(hono.LogLevel.debug) && config.level != hono.LogLevel.debug {
stats.fail_test('日志系统', '日志级别过滤失败')
return
}
// 测试日志级别转换
if hono.parse_log_level('info') != hono.LogLevel.info {
stats.fail_test('日志系统', '日志级别解析失败')
return
}
if hono.log_level_to_string(hono.LogLevel.error) != 'ERROR' {
stats.fail_test('日志系统', '日志级别转字符串失败')
return
}
stats.pass_test('日志系统')
}
// 7. 测试文件上传
fn test_file_upload(mut stats TestStats) {
stats.start_test('文件上传')
// 创建上传配置
config := hono.ChunkUploadConfig{
upload_dir: './test_uploads'
max_file_size: 1024 * 1024 // 1MB
max_chunk_size: 1024 // 1KB
merge_buffer_size: 512 // 512B
}
mut uploader := hono.new_chunk_uploader(config)
// 清理测试目录
if os.exists(config.upload_dir) {
os.rmdir_all(config.upload_dir) or {}
}
// 创建测试分片
test_hash := 'test123456789012345678901234567890'
chunk_data := 'Hello, World! This is test chunk data.'
// 上传分片
uploader.upload_chunk(test_hash, 0, chunk_data.bytes()) or {
stats.fail_test('文件上传', '分片上传失败: ${err}')
return
}
// 检查分片是否存在
if !uploader.chunk_exists(test_hash, 0) {
stats.fail_test('文件上传', '分片检查失败')
return
}
// 测试合并(单个分片)
uploader.merge_chunks(test_hash, 1) or {
stats.fail_test('文件上传', '分片合并失败: ${err}')
return
}
// 验证合并后的文件
merged_file := '${config.upload_dir}/${test_hash}'
if !os.exists(merged_file) {
stats.fail_test('文件上传', '合并后文件不存在')
return
}
content := os.read_file(merged_file) or {
stats.fail_test('文件上传', '无法读取合并文件')
return
}
if content != chunk_data {
stats.fail_test('文件上传', '合并文件内容不匹配')
return
}
// 清理测试文件
os.rmdir_all(config.upload_dir) or {}
stats.pass_test('文件上传')
}
// 8. 测试性能
fn test_performance(mut stats TestStats) {
stats.start_test('性能测试')
// 测试字符串构建性能
start_time := time.now()
mut builder := strings.new_builder(1000)
for i in 0 .. 100 {
builder.write_string('test string ${i} ')
}
result := builder.str()
duration := time.since(start_time)
if result.len == 0 {
stats.fail_test('性能测试', '字符串构建失败')
return
}
if duration.milliseconds() > 100 { // 应该在100ms内完成
stats.fail_test('性能测试', '字符串构建性能不达标: ${duration.milliseconds()}ms')
return
}
// 测试缓存性能
start_time2 := time.now()
mut cache := hono.new_context_lru_cache(1000)
for i in 0 .. 1000 {
cache.put('key${i}', 'value${i}')
}
for i in 0 .. 1000 {
cache.get('key${i}') or { '' }
}
duration2 := time.since(start_time2)
if duration2.milliseconds() > 500 { // 应该在500ms内完成
stats.fail_test('性能测试', '缓存性能不达标: ${duration2.milliseconds()}ms')
return
}
stats.pass_test('性能测试')
}
// 9. 测试内存管理
fn test_memory_management(mut stats TestStats) {
stats.start_test('内存管理')
// 测试缓存清理
mut cache := hono.new_context_lru_cache(5)
// 填充缓存
for i in 0 .. 10 {
cache.put('key${i}', 'value${i}')
}
// 验证大小限制
if cache.size() > 5 {
stats.fail_test('内存管理', '缓存大小超出限制')
return
}
// 清理缓存
cache.clear()
if cache.size() != 0 {
stats.fail_test('内存管理', '缓存清理失败')
return
}
// 验证健康状态
if !cache.is_healthy() {
stats.fail_test('内存管理', '缓存清理后健康检查失败')
return
}
stats.pass_test('内存管理')
}
// 10. 集成测试
fn test_integration(mut stats TestStats) {
stats.start_test('集成测试')
// 创建完整的应用配置
app_config := hono.default_config()
// 创建日志器
log_config := hono.LoggerConfig{
level: hono.LogLevel.info
output: hono.LogOutput.console
enable_colors: false
}
mut logger := hono.new_logger(log_config)
// 创建路由器
mut router := hono.new_router()
router.add_route('GET', '/health', 'health_check')
// 创建缓存
mut cache := hono.new_context_lru_cache(100)
cache.put('app_status', 'running')
// 验证组件协作
if route := router.match_route('GET', '/health') {
if route.handler != 'health_check' {
stats.fail_test('集成测试', '路由匹配失败')
return
}
} else {
stats.fail_test('集成测试', '路由不存在')
return
}
if status := cache.get('app_status') {
if status != 'running' {
stats.fail_test('集成测试', '缓存状态不正确')
return
}
} else {
stats.fail_test('集成测试', '缓存获取失败')
return
}
// 记录集成测试日志
logger.info_with_module('集成测试完成', 'TEST')
stats.pass_test('集成测试')
}
fn main() {
println('🚀 开始V-Hono综合测试套件...\n')
mut stats := TestStats{
start_time: time.now()
}
// 运行所有测试
test_cache_system(mut stats)
test_security_validation(mut stats)
test_error_handling(mut stats)
test_router_system(mut stats)
test_config_management(mut stats)
test_logging_system(mut stats)
test_file_upload(mut stats)
test_performance(mut stats)
test_memory_management(mut stats)
test_integration(mut stats)
// 打印测试总结
stats.print_summary()
}