352 lines
8.9 KiB
Go
352 lines
8.9 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
// TestLoad verifies we can successfully load configuration values from a Lua file.
|
|
func TestLoad(t *testing.T) {
|
|
// Create a temporary config file
|
|
content := `
|
|
-- Basic configuration values
|
|
host = "localhost"
|
|
port = 8080
|
|
debug = true
|
|
pi = 3.14159
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Verify values were loaded correctly
|
|
if host := cfg.GetString("host", ""); host != "localhost" {
|
|
t.Errorf("Expected host to be 'localhost', got '%s'", host)
|
|
}
|
|
|
|
if port := cfg.GetInt("port", 0); port != 8080 {
|
|
t.Errorf("Expected port to be 8080, got %d", port)
|
|
}
|
|
|
|
if debug := cfg.GetBool("debug", false); !debug {
|
|
t.Errorf("Expected debug to be true")
|
|
}
|
|
|
|
if pi := cfg.GetFloat("pi", 0); pi != 3.14159 {
|
|
t.Errorf("Expected pi to be 3.14159, got %f", pi)
|
|
}
|
|
}
|
|
|
|
// TestLoadErrors ensures the package properly handles loading errors.
|
|
func TestLoadErrors(t *testing.T) {
|
|
// Test with non-existent file
|
|
_, err := Load("nonexistent.lua")
|
|
if err == nil {
|
|
t.Error("Expected error when loading non-existent file, got nil")
|
|
}
|
|
|
|
// Test with invalid Lua
|
|
content := `
|
|
-- This is invalid Lua
|
|
host = "localhost
|
|
port = 8080)
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
_, err = Load(configFile)
|
|
if err == nil {
|
|
t.Error("Expected error when loading invalid Lua, got nil")
|
|
}
|
|
}
|
|
|
|
// TestLocalVsGlobal verifies only global variables are exported, not locals.
|
|
func TestLocalVsGlobal(t *testing.T) {
|
|
// Create a temporary config file with both local and global variables
|
|
content := `
|
|
-- Local variables should not be exported
|
|
local local_var = "hidden"
|
|
|
|
-- Global variables should be exported
|
|
global_var = "visible"
|
|
|
|
-- A function that uses both
|
|
function test_func()
|
|
return local_var .. " " .. global_var
|
|
end
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Check that global_var exists
|
|
if globalVar := cfg.GetString("global_var", ""); globalVar != "visible" {
|
|
t.Errorf("Expected global_var to be 'visible', got '%s'", globalVar)
|
|
}
|
|
|
|
// Check that local_var does not exist
|
|
if localVar := cfg.GetString("local_var", "default"); localVar != "default" {
|
|
t.Errorf("Expected local_var to use default, got '%s'", localVar)
|
|
}
|
|
|
|
// Check that functions are not exported
|
|
if val := cfg.Get("test_func"); val != nil {
|
|
t.Errorf("Expected function to not be exported, got %v", val)
|
|
}
|
|
}
|
|
|
|
// TestArrayHandling verifies correct handling of Lua arrays.
|
|
func TestArrayHandling(t *testing.T) {
|
|
// Create a temporary config file with arrays
|
|
content := `
|
|
-- Numeric array
|
|
numbers = {10, 20, 30, 40, 50}
|
|
|
|
-- String array
|
|
strings = {"apple", "banana", "cherry"}
|
|
|
|
-- Mixed array
|
|
mixed = {1, "two", true, 4.5}
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Test GetIntArray
|
|
intArray := cfg.GetIntArray("numbers")
|
|
expectedInts := []int{10, 20, 30, 40, 50}
|
|
if !reflect.DeepEqual(intArray, expectedInts) {
|
|
t.Errorf("Expected int array %v, got %v", expectedInts, intArray)
|
|
}
|
|
|
|
// Test GetStringArray
|
|
strArray := cfg.GetStringArray("strings")
|
|
expectedStrs := []string{"apple", "banana", "cherry"}
|
|
if !reflect.DeepEqual(strArray, expectedStrs) {
|
|
t.Errorf("Expected string array %v, got %v", expectedStrs, strArray)
|
|
}
|
|
|
|
// Test GetArray with mixed types
|
|
mixedArray := cfg.GetArray("mixed")
|
|
if len(mixedArray) != 4 {
|
|
t.Errorf("Expected mixed array length 4, got %d", len(mixedArray))
|
|
// Skip further tests if array is empty to avoid panic
|
|
return
|
|
}
|
|
|
|
// Check types - carefully to avoid panics
|
|
if len(mixedArray) > 0 {
|
|
if num, ok := mixedArray[0].(float64); !ok || num != 1 {
|
|
t.Errorf("Expected first element to be 1, got %v", mixedArray[0])
|
|
}
|
|
}
|
|
|
|
if len(mixedArray) > 1 {
|
|
if str, ok := mixedArray[1].(string); !ok || str != "two" {
|
|
t.Errorf("Expected second element to be 'two', got %v", mixedArray[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestComplexTable tests handling of complex nested tables.
|
|
func TestComplexTable(t *testing.T) {
|
|
// Create a temporary config file with complex tables
|
|
content := `
|
|
-- Nested table structure
|
|
server = {
|
|
host = "localhost",
|
|
port = 8080,
|
|
settings = {
|
|
timeout = 30,
|
|
retries = 3
|
|
}
|
|
}
|
|
|
|
-- Table with mixed array and map elements
|
|
mixed_table = {
|
|
list = {1, 2, 3},
|
|
mapping = {
|
|
a = "apple",
|
|
b = "banana"
|
|
}
|
|
}
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Test getting nested values
|
|
serverMap := cfg.GetMap("server")
|
|
if serverMap == nil {
|
|
t.Fatal("Expected server map to exist")
|
|
}
|
|
|
|
// Check first level values
|
|
if host, ok := serverMap["host"].(string); !ok || host != "localhost" {
|
|
t.Errorf("Expected server.host to be 'localhost', got %v", serverMap["host"])
|
|
}
|
|
|
|
if port, ok := serverMap["port"].(float64); !ok || port != 8080 {
|
|
t.Errorf("Expected server.port to be 8080, got %v", serverMap["port"])
|
|
}
|
|
|
|
// Check nested settings
|
|
settings, ok := serverMap["settings"].(map[string]any)
|
|
if !ok {
|
|
t.Fatal("Expected server.settings to be a map")
|
|
}
|
|
|
|
if timeout, ok := settings["timeout"].(float64); !ok || timeout != 30 {
|
|
t.Errorf("Expected server.settings.timeout to be 30, got %v", settings["timeout"])
|
|
}
|
|
}
|
|
|
|
// TestDefaultValues verifies default values work correctly when keys don't exist.
|
|
func TestDefaultValues(t *testing.T) {
|
|
// Create a temporary config file
|
|
content := `
|
|
-- Just one value
|
|
existing = "value"
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Test defaults for non-existent keys
|
|
if val := cfg.GetString("nonexistent", "default"); val != "default" {
|
|
t.Errorf("Expected default string, got '%s'", val)
|
|
}
|
|
|
|
if val := cfg.GetInt("nonexistent", 42); val != 42 {
|
|
t.Errorf("Expected default int 42, got %d", val)
|
|
}
|
|
|
|
if val := cfg.GetFloat("nonexistent", 3.14); val != 3.14 {
|
|
t.Errorf("Expected default float 3.14, got %f", val)
|
|
}
|
|
|
|
if val := cfg.GetBool("nonexistent", true); !val {
|
|
t.Errorf("Expected default bool true, got false")
|
|
}
|
|
}
|
|
|
|
// TestModifyConfig tests the ability to modify configuration values.
|
|
func TestModifyConfig(t *testing.T) {
|
|
// Create a config manually
|
|
cfg := New()
|
|
|
|
// Set some values
|
|
cfg.Set("host", "localhost")
|
|
cfg.Set("port", 8080)
|
|
|
|
// Verify the values were set
|
|
if host := cfg.GetString("host", ""); host != "localhost" {
|
|
t.Errorf("Expected host to be 'localhost', got '%s'", host)
|
|
}
|
|
|
|
if port := cfg.GetInt("port", 0); port != 8080 {
|
|
t.Errorf("Expected port to be 8080, got %d", port)
|
|
}
|
|
|
|
// Modify a value
|
|
cfg.Set("host", "127.0.0.1")
|
|
|
|
// Verify the change
|
|
if host := cfg.GetString("host", ""); host != "127.0.0.1" {
|
|
t.Errorf("Expected modified host to be '127.0.0.1', got '%s'", host)
|
|
}
|
|
}
|
|
|
|
// TestTypeConversion tests the type conversion in getter methods.
|
|
func TestTypeConversion(t *testing.T) {
|
|
// Create a temporary config file with values that need conversion
|
|
content := `
|
|
-- Numbers that can be integers
|
|
int_as_float = 42.0
|
|
|
|
-- Floats that should remain floats
|
|
float_val = 3.14159
|
|
`
|
|
configFile := createTempLuaFile(t, content)
|
|
defer os.Remove(configFile)
|
|
|
|
// Load the config
|
|
cfg, err := Load(configFile)
|
|
if err != nil {
|
|
t.Fatalf("Failed to load config: %v", err)
|
|
}
|
|
|
|
// Test GetInt with a float value
|
|
if val := cfg.GetInt("int_as_float", 0); val != 42 {
|
|
t.Errorf("Expected int 42, got %d", val)
|
|
}
|
|
|
|
// Test GetFloat with an int value
|
|
if val := cfg.GetFloat("int_as_float", 0); val != 42.0 {
|
|
t.Errorf("Expected float 42.0, got %f", val)
|
|
}
|
|
|
|
// Test incorrect type handling
|
|
cfg.Set("string_val", "not a number")
|
|
|
|
if val := cfg.GetInt("string_val", 99); val != 99 {
|
|
t.Errorf("Expected default int 99 for string value, got %d", val)
|
|
}
|
|
|
|
if val := cfg.GetFloat("string_val", 99.9); val != 99.9 {
|
|
t.Errorf("Expected default float 99.9 for string value, got %f", val)
|
|
}
|
|
|
|
if val := cfg.GetBool("float_val", false); val != false {
|
|
t.Errorf("Expected default false for non-bool value, got true")
|
|
}
|
|
}
|
|
|
|
// Helper function to create a temporary Lua file with content
|
|
func createTempLuaFile(t *testing.T, content string) string {
|
|
t.Helper()
|
|
|
|
tempFile, err := os.CreateTemp("", "config-test-*.lua")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
|
|
if _, err := tempFile.WriteString(content); err != nil {
|
|
os.Remove(tempFile.Name())
|
|
t.Fatalf("Failed to write to temp file: %v", err)
|
|
}
|
|
|
|
if err := tempFile.Close(); err != nil {
|
|
os.Remove(tempFile.Name())
|
|
t.Fatalf("Failed to close temp file: %v", err)
|
|
}
|
|
|
|
return tempFile.Name()
|
|
}
|