247 lines
6.0 KiB
Go
247 lines
6.0 KiB
Go
package luajit_test
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
|
)
|
|
|
|
func TestGetTableLength(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Create a table with numeric indices
|
|
if err := state.DoString("t = {10, 20, 30, 40, 50}"); err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
// Get the table
|
|
state.GetGlobal("t")
|
|
length := state.GetTableLength(-1)
|
|
if length != 5 {
|
|
t.Fatalf("Expected length 5, got %d", length)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Create a table with string keys
|
|
if err := state.DoString("t2 = {a=1, b=2, c=3}"); err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
// Get the table
|
|
state.GetGlobal("t2")
|
|
length = state.GetTableLength(-1)
|
|
if length != 0 {
|
|
t.Fatalf("Expected length 0 for string-keyed table, got %d", length)
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
|
|
func TestPushTable(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Create a test table
|
|
testTable := map[string]any{
|
|
"int": 42,
|
|
"float": 3.14,
|
|
"string": "hello",
|
|
"boolean": true,
|
|
"nil": nil,
|
|
}
|
|
|
|
// Push the table onto the stack
|
|
if err := state.PushTable(testTable); err != nil {
|
|
t.Fatalf("Failed to push table: %v", err)
|
|
}
|
|
|
|
// Execute Lua code to test the table contents
|
|
if err := state.DoString(`
|
|
function validate_table(t)
|
|
return t.int == 42 and
|
|
math.abs(t.float - 3.14) < 0.0001 and
|
|
t.string == "hello" and
|
|
t.boolean == true and
|
|
t["nil"] == nil
|
|
end
|
|
`); err != nil {
|
|
t.Fatalf("Failed to create validation function: %v", err)
|
|
}
|
|
|
|
// Call the validation function
|
|
state.GetGlobal("validate_table")
|
|
state.PushCopy(-2) // Copy the table to the top
|
|
if err := state.Call(1, 1); err != nil {
|
|
t.Fatalf("Failed to call validation function: %v", err)
|
|
}
|
|
|
|
if !state.ToBoolean(-1) {
|
|
t.Fatalf("Table validation failed")
|
|
}
|
|
state.Pop(2) // Pop the result and the table
|
|
}
|
|
|
|
func TestToTable(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Test regular table conversion
|
|
if err := state.DoString(`t = {a=1, b=2.5, c="test", d=true, e=nil}`); err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
state.GetGlobal("t")
|
|
table, err := state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert table: %v", err)
|
|
}
|
|
state.Pop(1)
|
|
|
|
expected := map[string]any{
|
|
"a": float64(1),
|
|
"b": 2.5,
|
|
"c": "test",
|
|
"d": true,
|
|
}
|
|
|
|
for k, v := range expected {
|
|
if table[k] != v {
|
|
t.Fatalf("Expected table[%s] = %v, got %v", k, v, table[k])
|
|
}
|
|
}
|
|
|
|
// Test array-like table conversion
|
|
if err := state.DoString(`arr = {10, 20, 30, 40, 50}`); err != nil {
|
|
t.Fatalf("Failed to create test array: %v", err)
|
|
}
|
|
|
|
state.GetGlobal("arr")
|
|
table, err = state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert array table: %v", err)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// For array tables, we should get a special format with an empty key
|
|
// and the array as the value
|
|
expectedArray := []float64{10, 20, 30, 40, 50}
|
|
if arr, ok := table[""].([]float64); !ok {
|
|
t.Fatalf("Expected array table to be converted with empty key, got: %v", table)
|
|
} else if !reflect.DeepEqual(arr, expectedArray) {
|
|
t.Fatalf("Expected %v, got %v", expectedArray, arr)
|
|
}
|
|
|
|
// Test invalid table index
|
|
_, err = state.ToTable(100)
|
|
if err == nil {
|
|
t.Fatalf("Expected error for invalid table index, got nil")
|
|
}
|
|
|
|
// Test non-table value
|
|
state.PushNumber(123)
|
|
_, err = state.ToTable(-1)
|
|
if err == nil {
|
|
t.Fatalf("Expected error for non-table value, got nil")
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Test mixed array with non-numeric values
|
|
if err := state.DoString(`mixed = {10, 20, key="value", 30}`); err != nil {
|
|
t.Fatalf("Failed to create mixed table: %v", err)
|
|
}
|
|
|
|
state.GetGlobal("mixed")
|
|
table, err = state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert mixed table: %v", err)
|
|
}
|
|
|
|
// Let's print the table for debugging
|
|
t.Logf("Table contents: %v", table)
|
|
|
|
state.Pop(1)
|
|
|
|
// Check if the array part is detected and stored with empty key
|
|
if arr, ok := table[""]; !ok {
|
|
t.Fatalf("Expected array-like part to be detected, got: %v", table)
|
|
} else {
|
|
// Verify the array contains the expected values
|
|
expectedArr := []float64{10, 20, 30}
|
|
actualArr := arr.([]float64)
|
|
if len(actualArr) != len(expectedArr) {
|
|
t.Fatalf("Expected array length %d, got %d", len(expectedArr), len(actualArr))
|
|
}
|
|
|
|
for i, v := range expectedArr {
|
|
if actualArr[i] != v {
|
|
t.Fatalf("Expected array[%d] = %v, got %v", i, v, actualArr[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
// Based on the implementation, we need to create a separate test for string keys
|
|
if err := state.DoString(`dict = {foo="bar", baz="qux"}`); err != nil {
|
|
t.Fatalf("Failed to create dict table: %v", err)
|
|
}
|
|
|
|
state.GetGlobal("dict")
|
|
dictTable, err := state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert dict table: %v", err)
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Check the string keys
|
|
if val, ok := dictTable["foo"]; !ok || val != "bar" {
|
|
t.Fatalf("Expected dictTable[\"foo\"] = \"bar\", got: %v", val)
|
|
}
|
|
if val, ok := dictTable["baz"]; !ok || val != "qux" {
|
|
t.Fatalf("Expected dictTable[\"baz\"] = \"qux\", got: %v", val)
|
|
}
|
|
}
|
|
|
|
func TestTablePooling(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Create a Lua table and push it onto the stack
|
|
if err := state.DoString(`t = {a=1, b=2}`); err != nil {
|
|
t.Fatalf("Failed to create test table: %v", err)
|
|
}
|
|
|
|
state.GetGlobal("t")
|
|
|
|
// First conversion - should get a table from the pool
|
|
table1, err := state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert table (1): %v", err)
|
|
}
|
|
|
|
// Second conversion - should get another table from the pool
|
|
table2, err := state.ToTable(-1)
|
|
if err != nil {
|
|
t.Fatalf("Failed to convert table (2): %v", err)
|
|
}
|
|
|
|
// Both tables should have the same content
|
|
if !reflect.DeepEqual(table1, table2) {
|
|
t.Fatalf("Tables should have the same content: %v vs %v", table1, table2)
|
|
}
|
|
|
|
// Clean up
|
|
state.Pop(1)
|
|
}
|