Moonshark/core/routers/luarouter_test.go
2025-03-05 19:17:43 -06:00

257 lines
6.5 KiB
Go

package routers
import (
"os"
"path/filepath"
"testing"
)
func setupTestRoutes(t *testing.T) (string, func()) {
// Create a temporary directory for test routes
tempDir, err := os.MkdirTemp("", "fsrouter-test")
if err != nil {
t.Fatalf("Failed to create temp directory: %v", err)
}
// Create route structure with valid Lua code
routes := map[string]string{
"get.lua": "return { path = '/' }",
"post.lua": "return { path = '/' }",
"api/get.lua": "return { path = '/api' }",
"api/users/get.lua": "return { path = '/api/users' }",
"api/users/[id]/get.lua": "return { path = '/api/users/[id]' }",
"api/users/[id]/posts/get.lua": "return { path = '/api/users/[id]/posts' }",
"api/[version]/docs/get.lua": "return { path = '/api/[version]/docs' }",
}
for path, content := range routes {
routePath := filepath.Join(tempDir, path)
// Create directories
err := os.MkdirAll(filepath.Dir(routePath), 0755)
if err != nil {
t.Fatalf("Failed to create directory %s: %v", filepath.Dir(routePath), err)
}
// Create file
err = os.WriteFile(routePath, []byte(content), 0644)
if err != nil {
t.Fatalf("Failed to create file %s: %v", routePath, err)
}
}
// Return cleanup function
cleanup := func() {
os.RemoveAll(tempDir)
}
return tempDir, cleanup
}
func TestRouterInitialization(t *testing.T) {
routesDir, cleanup := setupTestRoutes(t)
defer cleanup()
router, err := NewLuaRouter(routesDir)
if err != nil {
t.Fatalf("Failed to create router: %v", err)
}
if router == nil {
t.Fatal("Router is nil")
}
}
func TestRouteMatching(t *testing.T) {
routesDir, cleanup := setupTestRoutes(t)
defer cleanup()
router, err := NewLuaRouter(routesDir)
if err != nil {
t.Fatalf("Failed to create router: %v", err)
}
tests := []struct {
method string
path string
wantFound bool
wantParams map[string]string
wantHandler string
}{
// Static routes
{"GET", "/", true, nil, filepath.Join(routesDir, "get.lua")},
{"POST", "/", true, nil, filepath.Join(routesDir, "post.lua")},
{"GET", "/api", true, nil, filepath.Join(routesDir, "api/get.lua")},
{"GET", "/api/users", true, nil, filepath.Join(routesDir, "api/users/get.lua")},
// Parameterized routes
{"GET", "/api/users/123", true, map[string]string{"id": "123"}, filepath.Join(routesDir, "api/users/[id]/get.lua")},
{"GET", "/api/users/456/posts", true, map[string]string{"id": "456"}, filepath.Join(routesDir, "api/users/[id]/posts/get.lua")},
{"GET", "/api/v1/docs", true, map[string]string{"version": "v1"}, filepath.Join(routesDir, "api/[version]/docs/get.lua")},
// Non-existent routes
{"PUT", "/", false, nil, ""},
{"GET", "/nonexistent", false, nil, ""},
{"GET", "/api/nonexistent", false, nil, ""},
}
for _, tt := range tests {
t.Run(tt.method+" "+tt.path, func(t *testing.T) {
var params Params
node, found := router.Match(tt.method, tt.path, &params)
if found != tt.wantFound {
t.Errorf("Match() found = %v, want %v", found, tt.wantFound)
}
if !found {
return
}
if node.handler != tt.wantHandler {
t.Errorf("Match() handler = %v, want %v", node.handler, tt.wantHandler)
}
// Verify bytecode was compiled
if len(node.bytecode) == 0 {
t.Errorf("No bytecode found for handler: %s", node.handler)
}
// Verify parameters
if tt.wantParams != nil {
for key, wantValue := range tt.wantParams {
gotValue := params.Get(key)
if gotValue != wantValue {
t.Errorf("Parameter %s = %s, want %s", key, gotValue, wantValue)
}
}
}
})
}
}
func TestParamExtraction(t *testing.T) {
routesDir, cleanup := setupTestRoutes(t)
defer cleanup()
router, err := NewLuaRouter(routesDir)
if err != nil {
t.Fatalf("Failed to create router: %v", err)
}
var params Params
_, found := router.Match("GET", "/api/v2/docs", &params)
if !found {
t.Fatalf("Route not found")
}
if params.Count != 1 {
t.Errorf("Expected 1 parameter, got %d", params.Count)
}
if params.Keys[0] != "version" {
t.Errorf("Expected parameter key 'version', got '%s'", params.Keys[0])
}
if params.Values[0] != "v2" {
t.Errorf("Expected parameter value 'v2', got '%s'", params.Values[0])
}
if params.Get("version") != "v2" {
t.Errorf("Get(\"version\") returned '%s', expected 'v2'", params.Get("version"))
}
}
func TestGetBytecode(t *testing.T) {
routesDir, cleanup := setupTestRoutes(t)
defer cleanup()
router, err := NewLuaRouter(routesDir)
if err != nil {
t.Fatalf("Failed to create router: %v", err)
}
var params Params
bytecode, found := router.GetBytecode("GET", "/api/users/123", &params)
if !found {
t.Fatalf("Route not found")
}
if len(bytecode) == 0 {
t.Errorf("Expected non-empty bytecode")
}
// Check parameters were extracted
if params.Get("id") != "123" {
t.Errorf("Expected id parameter '123', got '%s'", params.Get("id"))
}
}
func TestRefresh(t *testing.T) {
routesDir, cleanup := setupTestRoutes(t)
defer cleanup()
router, err := NewLuaRouter(routesDir)
if err != nil {
t.Fatalf("Failed to create router: %v", err)
}
// Add a new route file
newRoutePath := filepath.Join(routesDir, "new", "get.lua")
err = os.MkdirAll(filepath.Dir(newRoutePath), 0755)
if err != nil {
t.Fatalf("Failed to create directory: %v", err)
}
err = os.WriteFile(newRoutePath, []byte("return { path = '/new' }"), 0644)
if err != nil {
t.Fatalf("Failed to create file: %v", err)
}
// Before refresh, route should not be found
var params Params
_, found := router.GetBytecode("GET", "/new", &params)
if found {
t.Errorf("New route should not be found before refresh")
}
// Refresh router
err = router.Refresh()
if err != nil {
t.Fatalf("Failed to refresh router: %v", err)
}
// After refresh, route should be found
bytecode, found := router.GetBytecode("GET", "/new", &params)
if !found {
t.Errorf("New route should be found after refresh")
}
if len(bytecode) == 0 {
t.Errorf("Expected non-empty bytecode for new route")
}
}
func TestInvalidRoutesDir(t *testing.T) {
// Non-existent directory
_, err := NewLuaRouter("/non/existent/directory")
if err == nil {
t.Error("Expected error for non-existent directory, got nil")
}
// Create a file instead of a directory
tmpFile, err := os.CreateTemp("", "fsrouter-test-file")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
defer tmpFile.Close()
_, err = NewLuaRouter(tmpFile.Name())
if err == nil {
t.Error("Expected error for file as routes dir, got nil")
}
}