Files
realy/config/keyvalue/keyvalue_test.go

254 lines
6.7 KiB
Go

package keyvalue
import (
"bytes"
"reflect"
"sort"
"testing"
"time"
)
// TestStruct is a test struct with various field types and env tags
type TestStruct struct {
StringField string `env:"STRING_FIELD"`
IntField int `env:"INT_FIELD"`
BoolField bool `env:"BOOL_FIELD"`
DurationField time.Duration `env:"DURATION_FIELD"`
StringSlice []string `env:"STRING_SLICE"`
EmptySlice []string `env:"EMPTY_SLICE"`
NoTagField string // Field without env tag
EmbeddedStruct struct{} // Embedded struct
}
// EmbeddedTestStruct is a test struct with an embedded struct
type EmbeddedTestStruct struct {
TestStruct
AdditionalField string `env:"ADDITIONAL_FIELD"`
}
func TestEnvKV(t *testing.T) {
// Test case 1: Basic struct with various field types
testStruct := TestStruct{
StringField: "test-string",
IntField: 42,
BoolField: true,
DurationField: 5 * time.Second,
StringSlice: []string{"one", "two", "three"},
EmptySlice: []string{},
NoTagField: "no-tag",
}
kvs := EnvKV(testStruct)
// Expected key-value pairs
expected := KVSlice{
{Key: "STRING_FIELD", Value: "test-string"},
{Key: "INT_FIELD", Value: "42"},
{Key: "BOOL_FIELD", Value: "true"},
{Key: "DURATION_FIELD", Value: "5s"},
{Key: "STRING_SLICE", Value: "one,two,three"},
{Key: "EMPTY_SLICE", Value: ""},
}
// Check if the number of key-value pairs is correct
if len(kvs) != len(expected) {
t.Errorf("Expected %d key-value pairs, got %d", len(expected), len(kvs))
}
// Create a map for easier comparison
kvMap := make(map[string]string)
for _, kv := range kvs {
kvMap[kv.Key] = kv.Value
}
// Check if all expected key-value pairs are present
for _, kv := range expected {
if val, ok := kvMap[kv.Key]; !ok || val != kv.Value {
t.Errorf("Expected key %s with value %s, got %s", kv.Key, kv.Value, val)
}
}
// Test case 2: Struct with embedded struct
embeddedStruct := EmbeddedTestStruct{
TestStruct: TestStruct{
StringField: "embedded-string",
IntField: 100,
},
AdditionalField: "additional",
}
embeddedKVs := EnvKV(embeddedStruct)
// Check if the additional field is present
found := false
for _, kv := range embeddedKVs {
if kv.Key == "ADDITIONAL_FIELD" && kv.Value == "additional" {
found = true
break
}
}
if !found {
t.Errorf("Expected to find ADDITIONAL_FIELD with value 'additional' in embedded struct")
}
// Test case 3: Pointer to a struct
pointerStruct := &TestStruct{
StringField: "pointer-string",
IntField: 123,
BoolField: false,
DurationField: 10 * time.Second,
StringSlice: []string{"four", "five", "six"},
}
pointerKVs := EnvKV(pointerStruct)
// Expected key-value pairs for pointer struct
expectedPointer := KVSlice{
{Key: "STRING_FIELD", Value: "pointer-string"},
{Key: "INT_FIELD", Value: "123"},
{Key: "BOOL_FIELD", Value: "false"},
{Key: "DURATION_FIELD", Value: "10s"},
{Key: "STRING_SLICE", Value: "four,five,six"},
{Key: "EMPTY_SLICE", Value: ""},
}
// Check if the number of key-value pairs is correct
if len(pointerKVs) != len(expectedPointer) {
t.Errorf("Expected %d key-value pairs for pointer struct, got %d", len(expectedPointer), len(pointerKVs))
}
// Create a map for easier comparison
pointerKVMap := make(map[string]string)
for _, kv := range pointerKVs {
pointerKVMap[kv.Key] = kv.Value
}
// Check if all expected key-value pairs are present
for _, kv := range expectedPointer {
if val, ok := pointerKVMap[kv.Key]; !ok || val != kv.Value {
t.Errorf("Expected key %s with value %s for pointer struct, got %s", kv.Key, kv.Value, val)
}
}
// Test case 4: Nil pointer
var nilPointer *TestStruct = nil
nilKVs := EnvKV(nilPointer)
// Nil pointer should return empty slice
if len(nilKVs) != 0 {
t.Errorf("Expected empty slice for nil pointer, got %d items", len(nilKVs))
}
}
func TestPrintEnv(t *testing.T) {
// Test case 1: Regular struct
testStruct := TestStruct{
StringField: "test-string",
IntField: 42,
BoolField: true,
DurationField: 5 * time.Second,
StringSlice: []string{"one", "two", "three"},
}
// Create a buffer to capture the output
var buf bytes.Buffer
// Call PrintEnv
PrintEnv(testStruct, &buf)
// Get the output as a string
output := buf.String()
// Expected output (note: keys should be sorted)
expected := "#!/usr/bin/env bash\n" +
"export BOOL_FIELD=true\n" +
"export DURATION_FIELD=5s\n" +
"export EMPTY_SLICE=\n" +
"export INT_FIELD=42\n" +
"export STRING_FIELD=test-string\n" +
"export STRING_SLICE=one,two,three\n"
if output != expected {
t.Errorf("PrintEnv output does not match expected.\nExpected:\n%s\nGot:\n%s", expected, output)
}
// Test case 2: Pointer to struct
pointerStruct := &TestStruct{
StringField: "pointer-string",
IntField: 123,
BoolField: false,
DurationField: 10 * time.Second,
StringSlice: []string{"four", "five", "six"},
}
// Create a new buffer for the pointer test
var pointerBuf bytes.Buffer
// Call PrintEnv with a pointer
PrintEnv(pointerStruct, &pointerBuf)
// Get the output as a string
pointerOutput := pointerBuf.String()
// Expected output for pointer struct
expectedPointer := "#!/usr/bin/env bash\n" +
"export BOOL_FIELD=false\n" +
"export DURATION_FIELD=10s\n" +
"export EMPTY_SLICE=\n" +
"export INT_FIELD=123\n" +
"export STRING_FIELD=pointer-string\n" +
"export STRING_SLICE=four,five,six\n"
if pointerOutput != expectedPointer {
t.Errorf("PrintEnv output for pointer struct does not match expected.\nExpected:\n%s\nGot:\n%s",
expectedPointer, pointerOutput)
}
// Test case 3: Nil pointer
var nilPointer *TestStruct = nil
var nilBuf bytes.Buffer
// Call PrintEnv with a nil pointer
PrintEnv(nilPointer, &nilBuf)
// Get the output as a string
nilOutput := nilBuf.String()
// Expected output for nil pointer (just the shebang line)
expectedNil := "#!/usr/bin/env bash\n"
if nilOutput != expectedNil {
t.Errorf("PrintEnv output for nil pointer does not match expected.\nExpected:\n%s\nGot:\n%s",
expectedNil, nilOutput)
}
}
func TestKVSliceSorting(t *testing.T) {
// Create an unsorted KVSlice
kvs := KVSlice{
{Key: "C", Value: "3"},
{Key: "A", Value: "1"},
{Key: "B", Value: "2"},
}
// Expected sorted KVSlice
expected := KVSlice{
{Key: "A", Value: "1"},
{Key: "B", Value: "2"},
{Key: "C", Value: "3"},
}
// Sort the KVSlice
kvsCopy := make(KVSlice, len(kvs))
copy(kvsCopy, kvs)
reflect.DeepEqual(kvs, kvsCopy) // Verify the copy worked
// Sort the copy
sort.Sort(kvsCopy)
// Check if the sorted KVSlice matches the expected
if !reflect.DeepEqual(kvsCopy, expected) {
t.Errorf("KVSlice sorting failed. Expected %v, got %v", expected, kvsCopy)
}
}