495 lines
9.3 KiB
Go
495 lines
9.3 KiB
Go
package yaml
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestAppendProcessor_ProcessMap(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input map[string]any
|
|
expected map[string]any
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "simple append to list",
|
|
input: map[string]any{
|
|
"values+": []any{"new-value"},
|
|
},
|
|
expected: map[string]any{
|
|
"values": []any{"new-value"},
|
|
},
|
|
},
|
|
{
|
|
name: "nested append",
|
|
input: map[string]any{
|
|
"config": map[string]any{
|
|
"items+": []any{"item1", "item2"},
|
|
},
|
|
},
|
|
expected: map[string]any{
|
|
"config": map[string]any{
|
|
"items": []any{"item1", "item2"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "mixed regular and append keys",
|
|
input: map[string]any{
|
|
"name": "test",
|
|
"values+": []any{"value1"},
|
|
"config": map[string]any{
|
|
"enabled": true,
|
|
"items+": []any{"item1"},
|
|
},
|
|
},
|
|
expected: map[string]any{
|
|
"name": "test",
|
|
"values": []any{"value1"},
|
|
"config": map[string]any{
|
|
"enabled": true,
|
|
"items": []any{"item1"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "non-list append value",
|
|
input: map[string]any{
|
|
"key+": "value",
|
|
},
|
|
expected: map[string]any{
|
|
"key": "value",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
processor := NewAppendProcessor()
|
|
result, err := processor.ProcessMap(tt.input)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAppendProcessor_MergeWithAppend(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dest map[string]any
|
|
src map[string]any
|
|
expected map[string]any
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "append to existing list",
|
|
dest: map[string]any{
|
|
"values": []any{"existing"},
|
|
},
|
|
src: map[string]any{
|
|
"values+": []any{"new"},
|
|
},
|
|
expected: map[string]any{
|
|
"values": []any{"existing", "new"},
|
|
},
|
|
},
|
|
{
|
|
name: "append to non-existent list",
|
|
dest: map[string]any{
|
|
"other": "value",
|
|
},
|
|
src: map[string]any{
|
|
"values+": []any{"new"},
|
|
},
|
|
expected: map[string]any{
|
|
"other": "value",
|
|
"values": []any{"new"},
|
|
},
|
|
},
|
|
{
|
|
name: "nested append",
|
|
dest: map[string]any{
|
|
"config": map[string]any{
|
|
"items": []any{"existing"},
|
|
},
|
|
},
|
|
src: map[string]any{
|
|
"config": map[string]any{
|
|
"items+": []any{"new"},
|
|
},
|
|
},
|
|
expected: map[string]any{
|
|
"config": map[string]any{
|
|
"items": []any{"existing", "new"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "scalar with key+ treated as regular key (replace)",
|
|
dest: map[string]any{
|
|
"replicas": 2,
|
|
},
|
|
src: map[string]any{
|
|
"replicas+": 1,
|
|
},
|
|
expected: map[string]any{
|
|
"replicas": 1,
|
|
},
|
|
},
|
|
{
|
|
name: "map with key+ treated as regular key (replace)",
|
|
dest: map[string]any{
|
|
"resources": map[string]any{
|
|
"limits": map[string]any{
|
|
"memory": "256Mi",
|
|
"cpu": "200m",
|
|
},
|
|
},
|
|
},
|
|
src: map[string]any{
|
|
"resources+": map[string]any{
|
|
"requests": map[string]any{
|
|
"memory": "128Mi",
|
|
"cpu": "100m",
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]any{
|
|
"resources": map[string]any{
|
|
"requests": map[string]any{
|
|
"memory": "128Mi",
|
|
"cpu": "100m",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "complex nested merge with key+ syntax for lists only",
|
|
dest: map[string]any{
|
|
"replicas": 2,
|
|
"resources": map[string]any{
|
|
"limits": map[string]any{
|
|
"memory": "256Mi",
|
|
"cpu": "200m",
|
|
},
|
|
"requests": map[string]any{
|
|
"memory": "128Mi",
|
|
"cpu": "100m",
|
|
},
|
|
},
|
|
"service": map[string]any{
|
|
"type": "ClusterIP",
|
|
"port": 80,
|
|
},
|
|
"kube-state-metrics": map[string]any{
|
|
"prometheus": map[string]any{
|
|
"metricsRelabel": []any{
|
|
map[string]any{"action": "drop"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
src: map[string]any{
|
|
"replicas+": 1,
|
|
"resources+": map[string]any{
|
|
"limits": map[string]any{
|
|
"memory": "512Mi",
|
|
"cpu": "500m",
|
|
},
|
|
"requests": map[string]any{
|
|
"memory": "256Mi",
|
|
"cpu": "250m",
|
|
},
|
|
},
|
|
"service+": map[string]any{
|
|
"type": "LoadBalancer",
|
|
"port": 443,
|
|
"annotations": map[string]any{
|
|
"service.beta.kubernetes.io/aws-load-balancer-type": "nlb",
|
|
},
|
|
},
|
|
"kube-state-metrics": map[string]any{
|
|
"prometheus": map[string]any{
|
|
"metricsRelabel+": []any{
|
|
map[string]any{"action": "keep"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expected: map[string]any{
|
|
"replicas": 1,
|
|
"resources": map[string]any{
|
|
"limits": map[string]any{
|
|
"memory": "512Mi",
|
|
"cpu": "500m",
|
|
},
|
|
"requests": map[string]any{
|
|
"memory": "256Mi",
|
|
"cpu": "250m",
|
|
},
|
|
},
|
|
"service": map[string]any{
|
|
"type": "LoadBalancer",
|
|
"port": 443,
|
|
"annotations": map[string]any{
|
|
"service.beta.kubernetes.io/aws-load-balancer-type": "nlb",
|
|
},
|
|
},
|
|
"kube-state-metrics": map[string]any{
|
|
"prometheus": map[string]any{
|
|
"metricsRelabel": []any{
|
|
map[string]any{"action": "drop"},
|
|
map[string]any{"action": "keep"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
processor := NewAppendProcessor()
|
|
err := processor.MergeWithAppend(tt.dest, tt.src)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expected, tt.dest)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalWithAppend(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
yamlData string
|
|
expected map[string]any
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "simple append syntax",
|
|
yamlData: `
|
|
values+:
|
|
- item1
|
|
- item2
|
|
name: test
|
|
`,
|
|
expected: map[string]any{
|
|
"values": []any{"item1", "item2"},
|
|
"name": "test",
|
|
},
|
|
},
|
|
{
|
|
name: "nested append syntax",
|
|
yamlData: `
|
|
config:
|
|
items+:
|
|
- existing
|
|
- new
|
|
enabled: true
|
|
`,
|
|
expected: map[string]any{
|
|
"config": map[string]any{
|
|
"items": []any{"existing", "new"},
|
|
"enabled": true,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "complex values file with key+ syntax",
|
|
yamlData: `
|
|
replicas+: 1
|
|
resources+:
|
|
limits:
|
|
memory: 512Mi
|
|
cpu: 500m
|
|
requests:
|
|
memory: 256Mi
|
|
cpu: 250m
|
|
service+:
|
|
type: LoadBalancer
|
|
port: 443
|
|
annotations:
|
|
service.beta.kubernetes.io/aws-load-balancer-type: nlb
|
|
kube-state-metrics:
|
|
prometheus:
|
|
metricsRelabel+:
|
|
- action: keep
|
|
`,
|
|
expected: map[string]any{
|
|
"replicas": 1,
|
|
"resources": map[string]any{
|
|
"limits": map[string]any{
|
|
"memory": "512Mi",
|
|
"cpu": "500m",
|
|
},
|
|
"requests": map[string]any{
|
|
"memory": "256Mi",
|
|
"cpu": "250m",
|
|
},
|
|
},
|
|
"service": map[string]any{
|
|
"type": "LoadBalancer",
|
|
"port": 443,
|
|
"annotations": map[string]any{
|
|
"service.beta.kubernetes.io/aws-load-balancer-type": "nlb",
|
|
},
|
|
},
|
|
"kube-state-metrics": map[string]any{
|
|
"prometheus": map[string]any{
|
|
"metricsRelabel": []any{
|
|
map[string]any{"action": "keep"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var result map[string]any
|
|
err := UnmarshalWithAppend([]byte(tt.yamlData), &result)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsAppendKey(t *testing.T) {
|
|
tests := []struct {
|
|
key string
|
|
expected bool
|
|
}{
|
|
{"key+", true},
|
|
{"key", false},
|
|
{"key++", true},
|
|
{"+key", false},
|
|
{"", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.key, func(t *testing.T) {
|
|
result := IsAppendKey(tt.key)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetBaseKey(t *testing.T) {
|
|
tests := []struct {
|
|
key string
|
|
expected string
|
|
}{
|
|
{"key+", "key"},
|
|
{"key", "key"},
|
|
{"key++", "key+"},
|
|
{"+key", "+key"},
|
|
{"", ""},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.key, func(t *testing.T) {
|
|
result := GetBaseKey(tt.key)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAppendProcessor_ErrorCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input map[string]any
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "invalid map with non-string key",
|
|
input: map[string]any{
|
|
"valid": map[any]any{
|
|
123: "invalid", // non-string key
|
|
},
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "valid map with string keys",
|
|
input: map[string]any{
|
|
"valid": map[string]any{
|
|
"key": "value",
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
processor := NewAppendProcessor()
|
|
_, err := processor.ProcessMap(tt.input)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnmarshalWithAppend_ErrorCases(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
yamlData string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "invalid YAML",
|
|
yamlData: `
|
|
invalid: yaml: content
|
|
- missing: proper: structure
|
|
`,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "valid YAML with key+",
|
|
yamlData: `
|
|
valid: true
|
|
key+: value
|
|
`,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
var result map[string]any
|
|
err := UnmarshalWithAppend([]byte(tt.yamlData), &result)
|
|
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|