package tests import ( "context" "io" "log" "os" "path/filepath" "testing" "Moonshark/routers" "Moonshark/runner" "Moonshark/utils/logger" ) // setupTestEnv initializes test components and returns cleanup function func setupTestEnv(b *testing.B) (*routers.LuaRouter, *runner.Runner, func()) { // Completely silence logging during benchmarks logger.InitGlobalLogger(false, false) // Redirect standard logger output to discard log.SetOutput(io.Discard) // Store original stderr to restore later originalStderr := os.Stderr devNull, _ := os.Open(os.DevNull) os.Stderr = devNull // Create temp directories tempDir, err := os.MkdirTemp("", "moonshark-bench") if err != nil { b.Fatalf("Failed to create temp dir: %v", err) } // Rest of the function remains the same... routesDir := filepath.Join(tempDir, "routes") staticDir := filepath.Join(tempDir, "static") libsDir := filepath.Join(tempDir, "libs") dataDir := filepath.Join(tempDir, "data") fsDir := filepath.Join(tempDir, "fs") os.MkdirAll(routesDir, 0755) os.MkdirAll(staticDir, 0755) os.MkdirAll(libsDir, 0755) os.MkdirAll(dataDir, 0755) os.MkdirAll(fsDir, 0755) // Create test routes createTestRoutes(routesDir) // Initialize router luaRouter, err := routers.NewLuaRouter(routesDir) if err != nil { b.Fatalf("Failed to create router: %v", err) } // Initialize runner luaRunner, err := runner.NewRunner( runner.WithPoolSize(4), runner.WithLibDirs(libsDir), runner.WithDataDir(dataDir), runner.WithFsDir(fsDir), ) if err != nil { b.Fatalf("Failed to create runner: %v", err) } // Return cleanup function that restores stderr cleanup := func() { luaRunner.Close() os.RemoveAll(tempDir) os.Stderr = originalStderr devNull.Close() } return luaRouter, luaRunner, cleanup } // createTestRoutes creates test Lua scripts for benchmarking func createTestRoutes(routesDir string) { // Simple GET endpoint getCode := []byte(`return "Hello, World!"`) os.WriteFile(filepath.Join(routesDir, "GET_hello.lua"), getCode, 0644) // POST endpoint with form handling postCode := []byte(` local data = ctx.form or {} return "Received: " .. (data.message or "no message") `) os.WriteFile(filepath.Join(routesDir, "POST_hello.lua"), postCode, 0644) // Computationally intensive endpoint complexCode := []byte(` local result = {} for i = 1, 1000 do table.insert(result, i * i) end return "Calculated " .. #result .. " squared numbers" `) os.WriteFile(filepath.Join(routesDir, "GET_complex.lua"), complexCode, 0644) } // BenchmarkRouterLookup tests route lookup performance func BenchmarkRouterLookup(b *testing.B) { luaRouter, _, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/hello" params := &routers.Params{} b.ResetTimer() for i := 0; i < b.N; i++ { _, _, _, _ = luaRouter.GetRouteInfo(method, path, params) } } // BenchmarkSimpleLuaExecution tests execution of a simple Lua script func BenchmarkSimpleLuaExecution(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/hello" params := &routers.Params{} bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) ctx := runner.NewContext() defer ctx.Release() b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = luaRunner.Run(bytecode, ctx, scriptPath) } } // BenchmarkComplexLuaExecution tests execution of a computation-heavy script func BenchmarkComplexLuaExecution(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/complex" params := &routers.Params{} bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) ctx := runner.NewContext() defer ctx.Release() b.ResetTimer() for i := 0; i < b.N; i++ { _, _ = luaRunner.Run(bytecode, ctx, scriptPath) } } // BenchmarkGetEndpoint tests end-to-end processing for GET endpoint func BenchmarkGetEndpoint(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/hello" params := &routers.Params{} b.ResetTimer() for i := 0; i < b.N; i++ { // Route lookup bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) // Context setup ctx := runner.NewContext() // Script execution _, _ = luaRunner.Run(bytecode, ctx, scriptPath) // Cleanup ctx.Release() } } // BenchmarkPostEndpoint tests end-to-end processing for POST endpoint func BenchmarkPostEndpoint(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "POST" path := "/hello" params := &routers.Params{} b.ResetTimer() for i := 0; i < b.N; i++ { // Route lookup bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) // Context setup with form data ctx := runner.NewContext() ctx.Set("form", map[string]any{ "message": "Hello from benchmark test", }) // Script execution _, _ = luaRunner.Run(bytecode, ctx, scriptPath) // Cleanup ctx.Release() } } // BenchmarkConcurrentExecution tests parallel execution performance func BenchmarkConcurrentExecution(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/hello" params := &routers.Params{} bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { ctx := runner.NewContext() _, _ = luaRunner.Run(bytecode, ctx, scriptPath) ctx.Release() } }) } // BenchmarkConcurrentComplexExecution tests parallel execution of intensive scripts func BenchmarkConcurrentComplexExecution(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/complex" params := &routers.Params{} bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { ctx := runner.NewContext() _, _ = luaRunner.Run(bytecode, ctx, scriptPath) ctx.Release() } }) } // BenchmarkRouteCompilation tests the performance of route compilation func BenchmarkRouteCompilation(b *testing.B) { tempDir, err := os.MkdirTemp("", "moonshark-compile") if err != nil { b.Fatalf("Failed to create temp dir: %v", err) } defer os.RemoveAll(tempDir) routesDir := filepath.Join(tempDir, "routes") os.MkdirAll(routesDir, 0755) b.ResetTimer() for i := 0; i < b.N; i++ { b.StopTimer() os.RemoveAll(routesDir) os.MkdirAll(routesDir, 0755) createTestRoutes(routesDir) b.StartTimer() // Creating router triggers compilation _, _ = routers.NewLuaRouter(routesDir) } } // BenchmarkContextCreation measures the cost of creating execution contexts func BenchmarkContextCreation(b *testing.B) { for i := 0; i < b.N; i++ { ctx := runner.NewContext() ctx.Release() } } // BenchmarkContextWithData measures context creation with realistic data func BenchmarkContextWithData(b *testing.B) { for i := 0; i < b.N; i++ { ctx := runner.NewContext() ctx.Set("method", "POST") ctx.Set("path", "/api/users") ctx.Set("host", "example.com") ctx.Set("params", map[string]any{"id": "123"}) ctx.Set("form", map[string]any{ "username": "testuser", "email": "user@example.com", "active": true, }) ctx.Release() } } // BenchmarkRunnerExecute tests the runner's Execute method with timeout func BenchmarkRunnerExecute(b *testing.B) { luaRouter, luaRunner, cleanup := setupTestEnv(b) defer cleanup() method := "GET" path := "/hello" params := &routers.Params{} bytecode, scriptPath, _, _ := luaRouter.GetRouteInfo(method, path, params) b.ResetTimer() for i := 0; i < b.N; i++ { ctx := runner.NewContext() _, _ = luaRunner.Execute(context.Background(), bytecode, ctx, scriptPath) ctx.Release() } }