import 'dart:convert'; import 'dart:io'; import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/core/performance_parser.dart'; import 'package:swagger_generator_flutter/core/smart_cache.dart'; import 'package:swagger_generator_flutter/generators/performance_generator.dart'; import 'package:test/test.dart'; void main() { group('Performance Tests', () { group('PerformanceParser', () { late PerformanceParser parser; setUp(() { parser = PerformanceParser( config: ParseConfig( enableParallelParsing: true, enableStreamParsing: false, enablePerformanceStats: true, maxConcurrency: 4, ), ); }); test('parses document with performance tracking', () async { final jsonString = jsonEncode({ 'openapi': '3.0.3', 'info': { 'title': 'Test API', 'version': '1.0.0', }, 'paths': { '/users': { 'get': { 'summary': 'Get users', 'responses': { '200': { 'description': 'Success', }, }, }, }, }, }); final document = await parser.parseDocument(jsonString); expect(document.title, equals('Test API')); expect(document.version, equals('1.0.0')); expect(document.paths, hasLength(1)); final stats = parser.lastStats; expect(stats, isNotNull); expect(stats!.totalTime.inMicroseconds, greaterThan(0)); expect(stats.documentSize, equals(jsonString.length)); expect(stats.pathCount, equals(1)); }); test('handles large documents efficiently', () async { // 创建大型文档 final paths = {}; for (int i = 0; i < 100; i++) { paths['/api/v1/resource$i'] = { 'get': { 'summary': 'Get resource $i', 'responses': { '200': {'description': 'Success'}, }, }, 'post': { 'summary': 'Create resource $i', 'responses': { '201': {'description': 'Created'}, }, }, }; } final largeDoc = { 'openapi': '3.0.3', 'info': { 'title': 'Large API', 'version': '1.0.0', }, 'paths': paths, }; final jsonString = jsonEncode(largeDoc); final stopwatch = Stopwatch()..start(); final document = await parser.parseDocument(jsonString); stopwatch.stop(); expect(document.paths.length, greaterThan(50)); // 应该解析出多个路径 expect(stopwatch.elapsedMilliseconds, lessThan(5000)); // 应该在5秒内完成 final stats = parser.lastStats; expect(stats, isNotNull); expect(stats!.pathsPerSecond, greaterThan(10)); // 每秒至少处理10个路径 }); test('parallel parsing improves performance', () async { final sequentialParser = PerformanceParser( config: ParseConfig( enableParallelParsing: false, enablePerformanceStats: true, ), ); final parallelParser = PerformanceParser( config: ParseConfig( enableParallelParsing: true, enablePerformanceStats: true, maxConcurrency: 4, ), ); // 创建中等大小的文档 final paths = {}; for (int i = 0; i < 50; i++) { paths['/api/v1/resource$i'] = { 'get': { 'summary': 'Get resource $i', 'responses': { '200': {'description': 'Success'} }, }, }; } final doc = { 'openapi': '3.0.3', 'info': {'title': 'Test API', 'version': '1.0.0'}, 'paths': paths, }; final jsonString = jsonEncode(doc); // 顺序解析 await sequentialParser.parseDocument(jsonString); final sequentialTime = sequentialParser.lastStats!.totalTime; // 并行解析 await parallelParser.parseDocument(jsonString); final parallelTime = parallelParser.lastStats!.totalTime; // 并行解析应该更快(在有足够任务的情况下) print('Sequential: ${sequentialTime.inMilliseconds}ms'); print('Parallel: ${parallelTime.inMilliseconds}ms'); // 注意:在小型文档上,并行可能不会更快,因为开销 expect(parallelTime.inMilliseconds, lessThan(sequentialTime.inMilliseconds * 2)); }); }); group('SmartCache', () { late SmartCache cache; setUp(() { cache = SmartCache( maxSize: 10, strategy: CacheStrategy.smart, defaultTtl: Duration(seconds: 1), ); }); test('basic cache operations work correctly', () { cache.put('key1', 'value1'); expect(cache.get('key1'), equals('value1')); expect(cache.containsKey('key1'), isTrue); cache.remove('key1'); expect(cache.get('key1'), isNull); expect(cache.containsKey('key1'), isFalse); }); test('cache eviction works when full', () { // 填满缓存 for (int i = 0; i < 10; i++) { cache.put('key$i', 'value$i'); } expect(cache.getStats().size, equals(10)); // 添加新项应该触发驱逐 cache.put('key10', 'value10'); expect(cache.getStats().size, equals(10)); expect(cache.getStats().evictions, greaterThan(0)); }); test('TTL expiration works', () async { cache.put('key1', 'value1', ttl: Duration(milliseconds: 100)); expect(cache.get('key1'), equals('value1')); await Future.delayed(Duration(milliseconds: 150)); expect(cache.get('key1'), isNull); }); test('cache statistics are accurate', () { cache.put('key1', 'value1'); cache.get('key1'); // hit cache.get('key2'); // miss final stats = cache.getStats(); expect(stats.totalRequests, equals(2)); expect(stats.hits, equals(1)); expect(stats.misses, equals(1)); expect(stats.hitRate, equals(0.5)); }); test('smart eviction strategy works', () { // 添加一些项并模拟不同的访问模式 cache.put('frequent', 'value1'); cache.put('recent', 'value2'); cache.put('old', 'value3'); // 频繁访问第一个 for (int i = 0; i < 5; i++) { cache.get('frequent'); } // 最近访问第二个 cache.get('recent'); // 第三个很久没访问 // 填满缓存以触发驱逐 for (int i = 0; i < 8; i++) { cache.put('filler$i', 'value$i'); } // 频繁访问的项应该还在 expect(cache.get('frequent'), equals('value1')); // 旧的项可能被驱逐了 // expect(cache.get('old'), isNull); }); }); group('PerformanceGenerator', () { late PerformanceGenerator generator; late SwaggerDocument testDocument; setUp(() { generator = PerformanceGenerator( maxConcurrency: 4, enableCaching: true, enableIncremental: true, enableParallel: true, ); testDocument = SwaggerDocument( title: 'Performance Test API', version: '1.0.0', description: 'API for performance testing', servers: [ApiServer(url: 'https://api.example.com')], components: ApiComponents(schemas: {}, securitySchemes: {}), paths: { '/users': ApiPath( path: '/users', method: HttpMethod.get, summary: 'Get users', description: 'Get all users', operationId: 'getUsers', tags: ['users'], parameters: [], responses: { '200': ApiResponse( code: '200', description: 'Success', ), }, ), '/posts': ApiPath( path: '/posts', method: HttpMethod.get, summary: 'Get posts', description: 'Get all posts', operationId: 'getPosts', tags: ['posts'], parameters: [], responses: { '200': ApiResponse( code: '200', description: 'Success', ), }, ), }, models: { 'User': ApiModel( name: 'User', description: 'User model', properties: { 'id': ApiProperty( name: 'id', type: PropertyType.integer, description: 'User ID', required: true, ), 'name': ApiProperty( name: 'name', type: PropertyType.string, description: 'User name', required: true, ), }, required: ['id', 'name'], ), }, controllers: {}, security: [], ); }); test('generates code with performance tracking', () async { final result = await generator.generateFromDocument(testDocument); expect(result, isNotEmpty); expect(result, contains('Performance Test API')); expect(result, contains('class User')); expect(result, contains('UsersApi')); expect(result, contains('PostsApi')); final stats = generator.getStats(); expect(stats.totalTasks, greaterThan(0)); expect(stats.completedTasks, greaterThan(0)); expect(stats.successRate, equals(1.0)); }); test('caching improves performance on repeated generation', () async { // 第一次生成 final stopwatch1 = Stopwatch()..start(); await generator.generateFromDocument(testDocument); stopwatch1.stop(); final firstTime = stopwatch1.elapsedMicroseconds; // 第二次生成(应该使用缓存) final stopwatch2 = Stopwatch()..start(); await generator.generateFromDocument(testDocument); stopwatch2.stop(); final secondTime = stopwatch2.elapsedMicroseconds; print('First generation: ${firstTime}μs'); print('Second generation: ${secondTime}μs'); // 第二次应该更快(由于缓存) expect(secondTime, lessThan(firstTime)); final cacheStats = generator.getCacheStats(); expect(cacheStats.hits, greaterThan(0)); }); test('parallel generation works with multiple modules', () async { // 创建有多个模块的大型文档 final largePaths = {}; final modules = ['users', 'posts', 'comments', 'tags', 'categories']; for (final module in modules) { for (int i = 0; i < 5; i++) { final path = '/api/v1/$module/$i'; largePaths[path] = ApiPath( path: path, method: HttpMethod.get, summary: 'Get $module $i', description: 'Get $module item $i', operationId: 'get${module.toUpperCase()}$i', tags: [module], parameters: [], responses: { '200': ApiResponse(code: '200', description: 'Success'), }, ); } } final largeDocument = SwaggerDocument( title: 'Large API', version: '1.0.0', description: 'Large API for testing', servers: [ApiServer(url: 'https://api.example.com')], components: ApiComponents(schemas: {}, securitySchemes: {}), paths: largePaths, models: {}, controllers: {}, security: [], ); final result = await generator.generateFromDocument(largeDocument); expect(result, isNotEmpty); expect(result, contains('Large API')); // 应该包含所有模块的 API for (final module in modules) { final className = '${module[0].toUpperCase()}${module.substring(1)}Api'; expect(result, contains(className)); } final stats = generator.getStats(); expect(stats.totalTasks, greaterThan(modules.length)); expect(stats.parallelEfficiency, greaterThan(0.5)); }); test('incremental generation detects no changes', () async { // 第一次生成 await generator.generateFromDocument(testDocument); final firstStats = generator.getStats(); // 第二次生成相同文档(应该检测到无变更) await generator.generateFromDocument(testDocument); final secondStats = generator.getStats(); // 第二次生成的任务数应该更少(由于增量生成) expect( secondStats.totalTasks, lessThanOrEqualTo(firstStats.totalTasks)); }); }); group('Real Project Performance', () { test('handles real swagger.json efficiently', () async { final file = File('swagger.json'); if (!file.existsSync()) { print( 'swagger.json not found, skipping real project performance test'); return; } final jsonString = await file.readAsString(); // 解析性能测试 final parser = PerformanceParser( config: ParseConfig( enableParallelParsing: true, enablePerformanceStats: true, maxConcurrency: 4, ), ); final parseStopwatch = Stopwatch()..start(); final document = await parser.parseDocument(jsonString); parseStopwatch.stop(); print('Parse Performance:'); print(' Time: ${parseStopwatch.elapsedMilliseconds}ms'); print( ' Document size: ${(jsonString.length / 1024).toStringAsFixed(2)}KB'); print(' Paths: ${document.paths.length}'); print(' Models: ${document.models.length}'); final parseStats = parser.lastStats!; print(parseStats.toString()); expect( parseStopwatch.elapsedMilliseconds, lessThan(10000)); // 应该在10秒内完成 expect(parseStats.pathsPerSecond, greaterThan(1)); // 每秒至少处理1个路径 // 生成性能测试 final generator = PerformanceGenerator( maxConcurrency: 4, enableCaching: true, enableParallel: true, ); final genStopwatch = Stopwatch()..start(); final result = await generator.generateFromDocument(document); genStopwatch.stop(); print('\nGeneration Performance:'); print(' Time: ${genStopwatch.elapsedMilliseconds}ms'); print( ' Generated size: ${(result.length / 1024).toStringAsFixed(2)}KB'); print(' Lines: ${result.split('\n').length}'); final genStats = generator.getStats(); print(genStats.toString()); expect(genStopwatch.elapsedMilliseconds, lessThan(15000)); // 应该在15秒内完成 expect(result.length, greaterThan(1000)); // 应该生成足够的代码 expect(genStats.successRate, greaterThan(0.8)); // 至少80%的任务成功 }); }); }); }