1
0
Fork 0
golang-github-twin-deepmerge/yaml_test.go
Daniel Baumann 0759e85aad
Adding upstream version 0.2.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-05-16 22:24:59 +02:00

217 lines
5.4 KiB
Go

package deepmerge_test
import (
"errors"
"testing"
"github.com/TwiN/deepmerge"
"gopkg.in/yaml.v3"
)
func TestYAML(t *testing.T) {
scenarios := []struct {
name string
config deepmerge.Config
dst string
src string
expected string
expectedErr error
}{
{
name: "invalid-dst",
dst: `wat`,
src: ``,
expected: ``,
expectedErr: errors.New("yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `wat` into map[string]interface {}"),
},
{
name: "invalid-src",
dst: ``,
src: `wat`,
expected: ``,
expectedErr: errors.New("yaml: unmarshal errors:\n line 1: cannot unmarshal !!str `wat` into map[string]interface {}"),
},
{
name: "simple-endpoint-merge",
dst: `endpoints:
- name: one
url: https://example.com
client:
timeout: 5s
conditions:
- "[CONNECTED] == true"
- "[STATUS] == 200"
alerts:
- type: slack
failure-threshold: 5
- name: two
url: https://example.org
conditions:
- "len([BODY]) > 0"`,
src: `endpoints:
- name: three
url: https://twin.sh/health
conditions:
- "[STATUS] == 200"
- "[BODY].status == UP"`,
expected: `endpoints:
- name: one
url: https://example.com
client:
timeout: 5s
conditions:
- "[CONNECTED] == true"
- "[STATUS] == 200"
alerts:
- type: slack
failure-threshold: 5
- name: two
url: https://example.org
conditions:
- "len([BODY]) > 0"
- name: three
url: https://twin.sh/health
conditions:
- "[STATUS] == 200"
- "[BODY].status == UP"
`,
},
{
name: "deep-merge-with-map-slice-and-primitive",
dst: `
metrics: true
alerting:
slack:
webhook-url: https://hooks.slack.com/services/xxx/yyy/zzz
default-alert:
description: "health check failed"
send-on-resolved: true
failure-threshold: 5
success-threshold: 5
endpoints:
- name: example
url: https://example.org
interval: 5s`,
src: `
debug: true
alerting:
discord:
webhook-url: https://discord.com/api/webhooks/xxx/yyy
endpoints:
- name: frontend
url: https://example.com`,
expected: `
metrics: true
debug: true
alerting:
discord:
webhook-url: https://discord.com/api/webhooks/xxx/yyy
slack:
webhook-url: https://hooks.slack.com/services/xxx/yyy/zzz
default-alert:
description: "health check failed"
send-on-resolved: true
failure-threshold: 5
success-threshold: 5
endpoints:
- interval: 5s
name: example
url: https://example.org
- name: frontend
url: https://example.com
`,
},
{ // only maps and slices can be merged. If there are duplicate keys that have a primitive value, then that's an error.
name: "duplicate-key-with-primitive-value",
config: deepmerge.Config{PreventMultipleDefinitionsOfKeysWithPrimitiveValue: true}, // NOTE: true is the default
dst: `metrics: true`,
src: `metrics: false`,
expectedErr: deepmerge.ErrKeyWithPrimitiveValueDefinedMoreThanOnce,
},
{
name: "duplicate-key-with-primitive-value-with-preventDuplicateKeysWithPrimitiveValue-set-to-false",
config: deepmerge.Config{PreventMultipleDefinitionsOfKeysWithPrimitiveValue: false},
dst: `metrics: true
debug: true`,
src: `metrics: false`,
expected: `metrics: false
debug: true`,
},
{
name: "readme-example",
dst: `debug: true
client:
insecure: true
users:
- id: 1
firstName: John
lastName: Doe
- id: 2
firstName: Jane
lastName: Doe`,
src: `client:
timeout: 5s
users:
- id: 3
firstName: Bob
lastName: Smith`,
expected: `
client:
insecure: true
timeout: 5s
debug: true
users:
- firstName: John
id: 1
lastName: Doe
- firstName: Jane
id: 2
lastName: Doe
- firstName: Bob
id: 3
lastName: Smith`,
},
}
for _, scenario := range scenarios {
t.Run(scenario.name, func(t *testing.T) {
output, err := deepmerge.YAML([]byte(scenario.dst), []byte(scenario.src), scenario.config)
if !errors.Is(err, scenario.expectedErr) && !(scenario.expectedErr != nil && err.Error() == scenario.expectedErr.Error()) {
t.Errorf("[%s] expected error %v, got %v", scenario.name, scenario.expectedErr, err)
}
// Just so we don't have to worry about the formatting, we'll unmarshal the output and marshal it again.
expectedAsMap, outputAsMap := make(map[string]interface{}), make(map[string]interface{})
if len(output) > 0 {
if err := yaml.Unmarshal(output, &outputAsMap); err != nil {
t.Errorf("[%s] failed to unmarshal output: %v", scenario.name, err)
}
}
if len(scenario.expected) > 0 {
if err := yaml.Unmarshal([]byte(scenario.expected), &expectedAsMap); err != nil {
t.Errorf("[%s] failed to unmarshal expected: %v", scenario.name, err)
}
}
formattedOutput, err := yaml.Marshal(outputAsMap)
if err != nil {
t.Errorf("[%s] should've been able to re-marshal output: %v", scenario.name, err)
}
formattedExpected, err := yaml.Marshal(expectedAsMap)
if err != nil {
t.Errorf("[%s] should've been able to re-marshal expected: %v", scenario.name, err)
}
// Compare what we got vs what we expected
if string(formattedOutput) != string(formattedExpected) {
t.Errorf("[%s] expected:\n%s\n\ngot:\n%s", scenario.name, string(formattedExpected), string(formattedOutput))
}
})
}
}