Skip to main content
Glama

CTS MCP Server

by EricA1019
tree_sitter.test.ts7.68 kB
/** * Tree-Sitter WASM Utilities Tests * * Performance benchmarks and accuracy validation */ import { describe, test, expect, beforeAll, afterEach } from '@jest/globals'; import { initTreeSitter, parseGDScript, parseGDScriptFile, findSignalDefinitions, findClassDefinitions, findFunctionDefinitions, clearCache, getMetrics, resetMetrics, } from '../tree_sitter.js'; describe('Tree-Sitter WASM Utilities', () => { beforeAll(async () => { // Initialize once for all tests await initTreeSitter(); }); afterEach(() => { clearCache(); resetMetrics(); }); describe('Initialization', () => { test('should initialize WASM runtime within 500ms', async () => { resetMetrics(); await initTreeSitter(); const metrics = getMetrics(); expect(metrics.initTime).toBeLessThan(500); }, 10000); // Allow 10s for WASM load test('should handle multiple init calls gracefully', async () => { await initTreeSitter(); await initTreeSitter(); await initTreeSitter(); // Should not throw expect(true).toBe(true); }); }); describe('Signal Detection', () => { test('should detect simple signal definitions', async () => { const code = ` extends Node signal player_died signal health_changed(new_health: int) signal item_collected(item_name: String, quantity: int) `; const tree = await parseGDScript(code); const signals = findSignalDefinitions(tree); expect(signals.length).toBe(3); expect(signals[0].name).toBe('player_died'); expect(signals[1].name).toBe('health_changed'); expect(signals[2].name).toBe('item_collected'); }); test('should extract signal parameters', async () => { const code = ` signal item_collected(item_name: String, quantity: int) `; const tree = await parseGDScript(code); const signals = findSignalDefinitions(tree); expect(signals.length).toBe(1); expect(signals[0].params).toContain('item_name'); expect(signals[0].params).toContain('quantity'); expect(signals[0].paramTypes['item_name']).toBe('String'); expect(signals[0].paramTypes['quantity']).toBe('int'); }); test('should achieve 100% signal detection accuracy', async () => { const code = ` extends Node # Test comment signal signal1 signal signal2() signal signal3(arg1) signal signal4(arg1: int) signal signal5(arg1: int, arg2: String) func _ready(): pass `; const tree = await parseGDScript(code); const signals = findSignalDefinitions(tree); // Should find exactly 5 signals (manual count) expect(signals.length).toBe(5); expect(signals.map(s => s.name)).toEqual([ 'signal1', 'signal2', 'signal3', 'signal4', 'signal5', ]); }); }); describe('Performance', () => { test('should parse 500-line file in <50ms', async () => { // Generate a 500-line GDScript file const lines: string[] = []; lines.push('extends Node\n'); for (let i = 0; i < 498; i++) { lines.push(`signal test_signal_${i}\n`); } const code = lines.join(''); resetMetrics(); const startTime = Date.now(); await parseGDScript(code, 'test_file.gd'); const parseTime = Date.now() - startTime; expect(parseTime).toBeLessThan(50); }); test('should cache parsed trees', async () => { const code = 'signal test'; // First parse (cache miss) await parseGDScript(code, 'cached_file.gd'); const metrics1 = getMetrics(); expect(metrics1.cacheMisses).toBe(1); expect(metrics1.cacheHits).toBe(0); // Second parse (cache hit) await parseGDScript(code, 'cached_file.gd'); const metrics2 = getMetrics(); expect(metrics2.cacheHits).toBe(1); }); test('should serve cached parse in <1ms', async () => { const code = 'signal test'; // Warm up cache await parseGDScript(code, 'fast_cached.gd'); // Measure cached parse const startTime = Date.now(); await parseGDScript(code, 'fast_cached.gd'); const cachedTime = Date.now() - startTime; expect(cachedTime).toBeLessThan(1); }); test('should handle 100 files without excessive memory', async () => { const files: string[] = []; for (let i = 0; i < 100; i++) { const code = ` extends Node signal test_signal_${i} func test_function_${i}(): pass `; files.push(code); } // Parse all files for (let i = 0; i < files.length; i++) { await parseGDScript(files[i], `file_${i}.gd`); } const metrics = getMetrics(); expect(metrics.filesProcessed).toBe(100); // Memory check (rough estimate) const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; expect(memoryUsage).toBeLessThan(100); // <100MB }); }); describe('Class and Function Detection', () => { test('should detect class definitions', async () => { const code = ` class_name PlayerController extends CharacterBody2D class InnerClass: pass `; const tree = await parseGDScript(code); const classes = findClassDefinitions(tree); expect(classes.length).toBeGreaterThan(0); // Note: tree-sitter grammar may parse class_name differently // Adjust expectations based on actual grammar }); test('should detect function definitions', async () => { const code = ` extends Node func _ready() -> void: pass func process_input(delta: float): pass func calculate_damage(base: int, multiplier: float) -> int: return int(base * multiplier) `; const tree = await parseGDScript(code); const functions = findFunctionDefinitions(tree); expect(functions.length).toBe(3); expect(functions[0].name).toBe('_ready'); expect(functions[1].name).toBe('process_input'); expect(functions[2].name).toBe('calculate_damage'); }); }); describe('Error Handling', () => { test('should handle malformed GDScript gracefully', async () => { const code = ` signal incomplete(param1 # Missing closing parenthesis `; // Should not throw const tree = await parseGDScript(code); expect(tree).toBeDefined(); // Tree-sitter is fault-tolerant, so it may still find some signals const signals = findSignalDefinitions(tree); expect(Array.isArray(signals)).toBe(true); }); test('should handle empty code', async () => { const code = ''; const tree = await parseGDScript(code); const signals = findSignalDefinitions(tree); expect(signals.length).toBe(0); }); }); describe('Cache Management', () => { test('should clear cache correctly', async () => { const code = 'signal test'; // Parse and cache await parseGDScript(code, 'cache_test.gd'); let metrics = getMetrics(); expect(metrics.cacheMisses).toBe(1); // Clear cache clearCache(); // Parse again (should be cache miss) await parseGDScript(code, 'cache_test.gd'); metrics = getMetrics(); expect(metrics.cacheMisses).toBe(2); }); test('should provide accurate metrics', async () => { resetMetrics(); await parseGDScript('signal a', 'file1.gd'); await parseGDScript('signal b', 'file2.gd'); await parseGDScript('signal a', 'file1.gd'); // Cache hit const metrics = getMetrics(); expect(metrics.filesProcessed).toBe(2); expect(metrics.cacheMisses).toBe(2); expect(metrics.cacheHits).toBe(1); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EricA1019/CTS_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server