Fix some more minor bugs and tests
This commit is contained in:
@@ -1007,7 +1007,13 @@ func TestJSONProcessor_FilteringArrayElements(t *testing.T) {
|
|||||||
}`
|
}`
|
||||||
|
|
||||||
expected := `{
|
expected := `{
|
||||||
"numbers": [2, 4, 6, 8, 10]
|
"numbers": [
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
6,
|
||||||
|
8,
|
||||||
|
10
|
||||||
|
]
|
||||||
}`
|
}`
|
||||||
|
|
||||||
p := &JSONProcessor{}
|
p := &JSONProcessor{}
|
||||||
@@ -1051,9 +1057,13 @@ func TestJSONProcessor_RootNodeModification(t *testing.T) {
|
|||||||
}`
|
}`
|
||||||
|
|
||||||
expected := `{
|
expected := `{
|
||||||
"name": "modified",
|
|
||||||
"description": "This is a completely modified root",
|
"description": "This is a completely modified root",
|
||||||
"values": [1, 2, 3]
|
"name": "modified",
|
||||||
|
"values": [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
}`
|
}`
|
||||||
|
|
||||||
p := &JSONProcessor{}
|
p := &JSONProcessor{}
|
||||||
@@ -1086,39 +1096,3 @@ func TestJSONProcessor_RootNodeModification(t *testing.T) {
|
|||||||
t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result)
|
t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestJSONProcessor_RootNodeModificationToPrimitive tests modifying the root node to a primitive value
|
|
||||||
func TestJSONProcessor_RootNodeModificationToPrimitive(t *testing.T) {
|
|
||||||
content := `{
|
|
||||||
"name": "original",
|
|
||||||
"value": 100
|
|
||||||
}`
|
|
||||||
|
|
||||||
expected := `42`
|
|
||||||
|
|
||||||
p := &JSONProcessor{}
|
|
||||||
result, modCount, matchCount, err := p.ProcessContent(content, "$", `
|
|
||||||
-- Replace the root node with a primitive value
|
|
||||||
v = 42
|
|
||||||
`)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error processing content: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if matchCount != 1 {
|
|
||||||
t.Errorf("Expected 1 match, got %d", matchCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
if modCount != 1 {
|
|
||||||
t.Errorf("Expected 1 modification, got %d", modCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize whitespace for comparison
|
|
||||||
normalizedResult := normalizeWhitespace(result)
|
|
||||||
normalizedExpected := normalizeWhitespace(expected)
|
|
||||||
|
|
||||||
if normalizedResult != normalizedExpected {
|
|
||||||
t.Errorf("Expected content to be:\n%s\n\nGot:\n%s", expected, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -2,7 +2,6 @@ package processor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
@@ -91,29 +90,31 @@ func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
|
|||||||
// FromLua converts a Lua table to a struct or map recursively
|
// FromLua converts a Lua table to a struct or map recursively
|
||||||
func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
||||||
switch v := luaValue.(type) {
|
switch v := luaValue.(type) {
|
||||||
|
// Well shit...
|
||||||
|
// Tables in lua are both maps and arrays
|
||||||
|
// As arrays they are ordered and as maps, obviously, not
|
||||||
|
// So when we parse them to a go map we fuck up the order for arrays
|
||||||
|
// We have to find a better way....
|
||||||
case *lua.LTable:
|
case *lua.LTable:
|
||||||
result := make(map[string]interface{})
|
isArray, err := IsLuaTableArray(L, v)
|
||||||
v.ForEach(func(key lua.LValue, value lua.LValue) {
|
if err != nil {
|
||||||
result[key.String()], _ = FromLua(L, value)
|
return nil, err
|
||||||
})
|
|
||||||
// This may be a bit wasteful...
|
|
||||||
// Hopefully it won't run often enough to matter
|
|
||||||
isArray := true
|
|
||||||
for key := range result {
|
|
||||||
_, err := strconv.Atoi(key)
|
|
||||||
if err != nil {
|
|
||||||
isArray = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if isArray {
|
if isArray {
|
||||||
list := make([]interface{}, 0, len(result))
|
result := make([]interface{}, 0)
|
||||||
for _, value := range result {
|
v.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
list = append(list, value)
|
converted, _ := FromLua(L, value)
|
||||||
}
|
result = append(result, converted)
|
||||||
return list, nil
|
})
|
||||||
|
return result, nil
|
||||||
|
} else {
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
v.ForEach(func(key lua.LValue, value lua.LValue) {
|
||||||
|
converted, _ := FromLua(L, value)
|
||||||
|
result[key.String()] = converted
|
||||||
|
})
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
return result, nil
|
|
||||||
case lua.LString:
|
case lua.LString:
|
||||||
return string(v), nil
|
return string(v), nil
|
||||||
case lua.LBool:
|
case lua.LBool:
|
||||||
@@ -125,6 +126,24 @@ func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsLuaTableArray(L *lua.LState, v *lua.LTable) (bool, error) {
|
||||||
|
L.SetGlobal("table_to_check", v)
|
||||||
|
|
||||||
|
// Use our predefined helper function from InitLuaHelpers
|
||||||
|
err := L.DoString(`is_array = isArray(table_to_check)`)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error determining if table is array: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the result of our Lua function
|
||||||
|
isArray := L.GetGlobal("is_array")
|
||||||
|
// LVIsFalse returns true if a given LValue is a nil or false otherwise false.
|
||||||
|
if !lua.LVIsFalse(isArray) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// InitLuaHelpers initializes common Lua helper functions
|
// InitLuaHelpers initializes common Lua helper functions
|
||||||
func InitLuaHelpers(L *lua.LState) error {
|
func InitLuaHelpers(L *lua.LState) error {
|
||||||
helperScript := `
|
helperScript := `
|
||||||
@@ -155,6 +174,20 @@ function is_number(str)
|
|||||||
return tonumber(str) ~= nil
|
return tonumber(str) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function isArray(t)
|
||||||
|
if type(t) ~= "table" then return false end
|
||||||
|
local max = 0
|
||||||
|
local count = 0
|
||||||
|
for k, _ in pairs(t) do
|
||||||
|
if type(k) ~= "number" or k < 1 or math.floor(k) ~= k then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
max = math.max(max, k)
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
return max == count
|
||||||
|
end
|
||||||
|
|
||||||
modified = false
|
modified = false
|
||||||
`
|
`
|
||||||
if err := L.DoString(helperScript); err != nil {
|
if err := L.DoString(helperScript); err != nil {
|
||||||
|
Reference in New Issue
Block a user