367 lines
8.5 KiB
Go
367 lines
8.5 KiB
Go
package processor
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
lua "github.com/yuin/gopher-lua"
|
|
)
|
|
|
|
func TestSetVariables(t *testing.T) {
|
|
// Test with various variable types
|
|
vars := map[string]interface{}{
|
|
"multiplier": 2.5,
|
|
"prefix": "TEST_",
|
|
"enabled": true,
|
|
"count": 42,
|
|
}
|
|
|
|
SetVariables(vars)
|
|
|
|
// Create a new Lua state to verify variables are set
|
|
L, err := NewLuaState()
|
|
assert.NoError(t, err)
|
|
defer L.Close()
|
|
|
|
// Verify the variables are accessible
|
|
multiplier := L.GetGlobal("multiplier")
|
|
assert.Equal(t, lua.LTNumber, multiplier.Type())
|
|
assert.Equal(t, 2.5, float64(multiplier.(lua.LNumber)))
|
|
|
|
prefix := L.GetGlobal("prefix")
|
|
assert.Equal(t, lua.LTString, prefix.Type())
|
|
assert.Equal(t, "TEST_", string(prefix.(lua.LString)))
|
|
|
|
enabled := L.GetGlobal("enabled")
|
|
assert.Equal(t, lua.LTBool, enabled.Type())
|
|
assert.True(t, bool(enabled.(lua.LBool)))
|
|
|
|
count := L.GetGlobal("count")
|
|
assert.Equal(t, lua.LTNumber, count.Type())
|
|
assert.Equal(t, 42.0, float64(count.(lua.LNumber)))
|
|
}
|
|
|
|
func TestSetVariablesEmpty(t *testing.T) {
|
|
// Test with empty map
|
|
vars := map[string]interface{}{}
|
|
SetVariables(vars)
|
|
|
|
// Should not panic
|
|
L, err := NewLuaState()
|
|
assert.NoError(t, err)
|
|
defer L.Close()
|
|
}
|
|
|
|
func TestSetVariablesNil(t *testing.T) {
|
|
// Test with nil map
|
|
SetVariables(nil)
|
|
|
|
// Should not panic
|
|
L, err := NewLuaState()
|
|
assert.NoError(t, err)
|
|
defer L.Close()
|
|
}
|
|
|
|
func TestGetLuaFunctionsHelp(t *testing.T) {
|
|
help := GetLuaFunctionsHelp()
|
|
|
|
// Verify help is not empty
|
|
assert.NotEmpty(t, help)
|
|
|
|
// Verify it contains documentation for key functions
|
|
assert.Contains(t, help, "MATH FUNCTIONS")
|
|
assert.Contains(t, help, "STRING FUNCTIONS")
|
|
assert.Contains(t, help, "TABLE FUNCTIONS")
|
|
assert.Contains(t, help, "XML HELPER FUNCTIONS")
|
|
assert.Contains(t, help, "JSON HELPER FUNCTIONS")
|
|
assert.Contains(t, help, "HTTP FUNCTIONS")
|
|
assert.Contains(t, help, "REGEX FUNCTIONS")
|
|
assert.Contains(t, help, "UTILITY FUNCTIONS")
|
|
assert.Contains(t, help, "EXAMPLES")
|
|
|
|
// Verify specific functions are documented
|
|
assert.Contains(t, help, "min(a, b)")
|
|
assert.Contains(t, help, "max(a, b)")
|
|
assert.Contains(t, help, "round(x, n)")
|
|
assert.Contains(t, help, "fetch(url, options)")
|
|
assert.Contains(t, help, "findElements(root, tagName)")
|
|
assert.Contains(t, help, "visitJSON(data, callback)")
|
|
assert.Contains(t, help, "re(pattern, input)")
|
|
assert.Contains(t, help, "print(...)")
|
|
}
|
|
|
|
func TestFetchFunction(t *testing.T) {
|
|
L := lua.NewState()
|
|
defer L.Close()
|
|
|
|
// Register the fetch function
|
|
L.SetGlobal("fetch", L.NewFunction(fetch))
|
|
|
|
// Test 1: Missing URL should return nil and error
|
|
err := L.DoString(`
|
|
result, err = fetch("")
|
|
assert(result == nil, "Expected nil result for empty URL")
|
|
assert(err ~= nil, "Expected error for empty URL")
|
|
`)
|
|
assert.NoError(t, err)
|
|
|
|
// Test 2: Invalid URL should return error
|
|
err = L.DoString(`
|
|
result, err = fetch("not-a-valid-url")
|
|
assert(result == nil, "Expected nil result for invalid URL")
|
|
assert(err ~= nil, "Expected error for invalid URL")
|
|
`)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestFetchFunctionWithOptions(t *testing.T) {
|
|
L := lua.NewState()
|
|
defer L.Close()
|
|
|
|
// Register the fetch function
|
|
L.SetGlobal("fetch", L.NewFunction(fetch))
|
|
|
|
// Test with options (should fail gracefully with invalid URL)
|
|
err := L.DoString(`
|
|
local opts = {
|
|
method = "POST",
|
|
headers = {["Content-Type"] = "application/json"},
|
|
body = '{"test": "data"}'
|
|
}
|
|
result, err = fetch("http://invalid-domain-that-does-not-exist.local", opts)
|
|
-- Should get error due to invalid domain
|
|
assert(result == nil, "Expected nil result for invalid domain")
|
|
assert(err ~= nil, "Expected error for invalid domain")
|
|
`)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestPrependLuaAssignment(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Simple assignment",
|
|
input: "10",
|
|
expected: "v1 = 10",
|
|
},
|
|
{
|
|
name: "Expression",
|
|
input: "v1 * 2",
|
|
expected: "v1 = v1 * 2",
|
|
},
|
|
{
|
|
name: "Assignment with equal sign",
|
|
input: "= 5",
|
|
expected: "v1 = 5",
|
|
},
|
|
{
|
|
name: "Complex expression",
|
|
input: "math.floor(v1 / 2)",
|
|
expected: "v1 = math.floor(v1 / 2)",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := PrependLuaAssignment(tt.input)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
func TestBuildJSONLuaScript(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
contains []string
|
|
}{
|
|
{
|
|
name: "Simple JSON modification",
|
|
input: "data.value = data.value * 2; modified = true",
|
|
contains: []string{
|
|
"data.value = data.value * 2",
|
|
"modified = true",
|
|
},
|
|
},
|
|
{
|
|
name: "Complex JSON script",
|
|
input: "for i, item in ipairs(data.items) do item.price = item.price * 1.5 end; modified = true",
|
|
contains: []string{
|
|
"for i, item in ipairs(data.items)",
|
|
"modified = true",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := BuildJSONLuaScript(tt.input)
|
|
for _, substr := range tt.contains {
|
|
assert.Contains(t, result, substr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPrintToGo(t *testing.T) {
|
|
L := lua.NewState()
|
|
defer L.Close()
|
|
|
|
// Register the print function
|
|
L.SetGlobal("print", L.NewFunction(printToGo))
|
|
|
|
// Test printing various types
|
|
err := L.DoString(`
|
|
print("Hello, World!")
|
|
print(42)
|
|
print(true)
|
|
print(3.14)
|
|
`)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestEvalRegex(t *testing.T) {
|
|
L := lua.NewState()
|
|
defer L.Close()
|
|
|
|
// Register the regex function
|
|
L.SetGlobal("re", L.NewFunction(EvalRegex))
|
|
|
|
// Test 1: Simple match
|
|
err := L.DoString(`
|
|
matches = re("(\\d+)", "The answer is 42")
|
|
assert(matches ~= nil, "Expected matches")
|
|
assert(matches[1] == "42", "Expected full match to be 42")
|
|
assert(matches[2] == "42", "Expected capture group to be 42")
|
|
`)
|
|
assert.NoError(t, err)
|
|
|
|
// Test 2: No match
|
|
err = L.DoString(`
|
|
matches = re("(\\d+)", "No numbers here")
|
|
assert(matches == nil, "Expected nil for no match")
|
|
`)
|
|
assert.NoError(t, err)
|
|
|
|
// Test 3: Multiple capture groups
|
|
err = L.DoString(`
|
|
matches = re("(\\w+)\\s+(\\d+)", "item 123")
|
|
assert(matches ~= nil, "Expected matches")
|
|
assert(matches[1] == "item 123", "Expected full match")
|
|
assert(matches[2] == "item", "Expected first capture group")
|
|
assert(matches[3] == "123", "Expected second capture group")
|
|
`)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestEstimatePatternComplexity(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
pattern string
|
|
minExpected int
|
|
}{
|
|
{
|
|
name: "Simple literal",
|
|
pattern: "hello",
|
|
minExpected: 1,
|
|
},
|
|
{
|
|
name: "With capture group",
|
|
pattern: "(\\d+)",
|
|
minExpected: 2,
|
|
},
|
|
{
|
|
name: "Complex pattern",
|
|
pattern: "(?P<name>\\w+)\\s+(?P<value>\\d+\\.\\d+)",
|
|
minExpected: 3,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
complexity := estimatePatternComplexity(tt.pattern)
|
|
assert.GreaterOrEqual(t, complexity, tt.minExpected)
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
func TestParseNumeric(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected float64
|
|
shouldOk bool
|
|
}{
|
|
{"Integer", "42", 42.0, true},
|
|
{"Float", "3.14", 3.14, true},
|
|
{"Negative", "-10", -10.0, true},
|
|
{"Invalid", "not a number", 0, false},
|
|
{"Empty", "", 0, false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result, ok := parseNumeric(tt.input)
|
|
assert.Equal(t, tt.shouldOk, ok)
|
|
if tt.shouldOk {
|
|
assert.Equal(t, tt.expected, result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFormatNumeric(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input float64
|
|
expected string
|
|
}{
|
|
{"Integer value", 42.0, "42"},
|
|
{"Float value", 3.14, "3.14"},
|
|
{"Negative integer", -10.0, "-10"},
|
|
{"Negative float", -3.14, "-3.14"},
|
|
{"Zero", 0.0, "0"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := formatNumeric(tt.input)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLuaHelperFunctionsDocumentation(t *testing.T) {
|
|
help := GetLuaFunctionsHelp()
|
|
|
|
// All main function categories should be documented
|
|
expectedCategories := []string{
|
|
"MATH FUNCTIONS",
|
|
"STRING FUNCTIONS",
|
|
"XML HELPER FUNCTIONS",
|
|
"JSON HELPER FUNCTIONS",
|
|
}
|
|
|
|
for _, category := range expectedCategories {
|
|
assert.Contains(t, help, category, "Help should contain category: %s", category)
|
|
}
|
|
|
|
// Verify some key functions are mentioned
|
|
keyFunctions := []string{
|
|
"findElements",
|
|
"visitElements",
|
|
"visitJSON",
|
|
"round",
|
|
"fetch",
|
|
}
|
|
|
|
for _, fn := range keyFunctions {
|
|
assert.Contains(t, help, fn, "Help should mention function: %s", fn)
|
|
}
|
|
}
|