mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-08 14:55:42 +00:00
211 lines
5.1 KiB
Go
211 lines
5.1 KiB
Go
package yqlib
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/mikefarah/yq/v4/test"
|
|
)
|
|
|
|
var testYamlDocs = []string{
|
|
`---
|
|
name: John
|
|
age: 30
|
|
address:
|
|
street: 123 Main St
|
|
city: Anytown
|
|
state: ST
|
|
zip: 12345
|
|
hobbies:
|
|
- reading
|
|
- swimming
|
|
- cooking
|
|
`,
|
|
`---
|
|
# This is a comment
|
|
version: "1.0"
|
|
database:
|
|
host: localhost
|
|
port: 5432
|
|
name: myapp
|
|
credentials:
|
|
username: admin
|
|
password: secret123
|
|
servers:
|
|
- name: web1
|
|
ip: 192.168.1.10
|
|
- name: web2
|
|
ip: 192.168.1.11
|
|
`,
|
|
`---
|
|
# Complex YAML with various types
|
|
config:
|
|
enabled: true
|
|
timeout: 30
|
|
ratio: 3.14159
|
|
options:
|
|
debug: false
|
|
verbose: true
|
|
items: []
|
|
metadata: null
|
|
multiline: |
|
|
This is a multiline
|
|
string with line breaks
|
|
and proper formatting
|
|
`,
|
|
}
|
|
|
|
func TestYamlParsersStructuralEquivalence(t *testing.T) {
|
|
// Save original preferences
|
|
originalPrefs := ConfiguredYamlPreferences.Copy()
|
|
defer func() {
|
|
ConfiguredYamlPreferences = originalPrefs
|
|
}()
|
|
|
|
for i, yamlDoc := range testYamlDocs {
|
|
t.Run(fmt.Sprintf("Document_%d", i), func(t *testing.T) {
|
|
// Test with yaml.v3 parser
|
|
ConfiguredYamlPreferences.UseGoccyParser = false
|
|
v3Node := parseYamlDocument(t, yamlDoc)
|
|
|
|
// Test with goccy parser
|
|
ConfiguredYamlPreferences.UseGoccyParser = true
|
|
goccyNode := parseYamlDocument(t, yamlDoc)
|
|
|
|
// Compare the parsed structures (not text output)
|
|
if !recursiveNodeEqual(v3Node, goccyNode) {
|
|
t.Errorf("Parsed structures differ between yaml.v3 and goccy for document %d", i)
|
|
t.Logf("yaml.v3 result: %s", NodeToString(v3Node))
|
|
t.Logf("goccy result: %s", NodeToString(goccyNode))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func parseYamlDocument(t *testing.T, yamlDoc string) *CandidateNode {
|
|
decoder := YamlFormat.DecoderFactory()
|
|
|
|
inputs, err := readDocuments(strings.NewReader(yamlDoc), "test.yml", 0, decoder)
|
|
if err != nil {
|
|
t.Fatalf("Failed to decode YAML: %v", err)
|
|
}
|
|
|
|
if inputs.Len() == 0 {
|
|
t.Fatal("No documents found")
|
|
}
|
|
|
|
return inputs.Front().Value.(*CandidateNode)
|
|
}
|
|
|
|
func TestYamlParsersEquivalence(t *testing.T) {
|
|
// Save original preferences
|
|
originalPrefs := ConfiguredYamlPreferences.Copy()
|
|
defer func() {
|
|
ConfiguredYamlPreferences = originalPrefs
|
|
}()
|
|
|
|
// Note: This test documents the differences in output formatting between parsers
|
|
// These differences are acceptable as they don't affect semantic meaning
|
|
t.Log("Note: yaml.v3 and goccy may produce different key ordering, which is semantically equivalent")
|
|
|
|
for i, yamlDoc := range testYamlDocs {
|
|
t.Run(fmt.Sprintf("Document_%d", i), func(t *testing.T) {
|
|
// Test with yaml.v3 parser
|
|
ConfiguredYamlPreferences.UseGoccyParser = false
|
|
v3Result := processYamlDocument(t, yamlDoc)
|
|
|
|
// Test with goccy parser
|
|
ConfiguredYamlPreferences.UseGoccyParser = true
|
|
goccyResult := processYamlDocument(t, yamlDoc)
|
|
|
|
// Log the differences for documentation purposes
|
|
if v3Result != goccyResult {
|
|
t.Logf("Output format differs (this is expected):")
|
|
t.Logf("yaml.v3 output:\n%s", v3Result)
|
|
t.Logf("goccy output:\n%s", goccyResult)
|
|
|
|
// But both should be valid YAML that parses to the same structure
|
|
v3Reparse := parseYamlDocument(t, v3Result)
|
|
goccyReparse := parseYamlDocument(t, goccyResult)
|
|
|
|
if !recursiveNodeEqual(v3Reparse, goccyReparse) {
|
|
t.Error("Reparsed structures differ - this indicates a semantic issue")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func processYamlDocument(t *testing.T, yamlDoc string) string {
|
|
decoder := YamlFormat.DecoderFactory()
|
|
encoder := YamlFormat.EncoderFactory()
|
|
|
|
inputs, err := readDocuments(strings.NewReader(yamlDoc), "test.yml", 0, decoder)
|
|
if err != nil {
|
|
t.Fatalf("Failed to decode YAML: %v", err)
|
|
}
|
|
|
|
if inputs.Len() == 0 {
|
|
t.Fatal("No documents found")
|
|
}
|
|
|
|
node := inputs.Front().Value.(*CandidateNode)
|
|
|
|
var output bytes.Buffer
|
|
err = encoder.Encode(&output, node)
|
|
if err != nil {
|
|
t.Fatalf("Failed to encode YAML: %v", err)
|
|
}
|
|
|
|
return output.String()
|
|
}
|
|
|
|
func TestGoccyParserBasicFunctionality(t *testing.T) {
|
|
// Save original preferences
|
|
originalPrefs := ConfiguredYamlPreferences.Copy()
|
|
defer func() {
|
|
ConfiguredYamlPreferences = originalPrefs
|
|
}()
|
|
|
|
// Enable goccy parser
|
|
ConfiguredYamlPreferences.UseGoccyParser = true
|
|
|
|
yamlDoc := `---
|
|
test:
|
|
field1: value1
|
|
field2: 42
|
|
field3: true
|
|
`
|
|
|
|
decoder := YamlFormat.DecoderFactory()
|
|
encoder := YamlFormat.EncoderFactory()
|
|
|
|
inputs, err := readDocuments(strings.NewReader(yamlDoc), "test.yml", 0, decoder)
|
|
test.AssertResult(t, nil, err)
|
|
test.AssertResult(t, 1, inputs.Len())
|
|
|
|
node := inputs.Front().Value.(*CandidateNode)
|
|
|
|
var output bytes.Buffer
|
|
err = encoder.Encode(&output, node)
|
|
test.AssertResult(t, nil, err)
|
|
|
|
result := output.String()
|
|
|
|
// Basic checks - the exact format might differ but structure should be preserved
|
|
if !strings.Contains(result, "test:") {
|
|
t.Error("Expected 'test:' in output")
|
|
}
|
|
if !strings.Contains(result, "field1: value1") {
|
|
t.Error("Expected 'field1: value1' in output")
|
|
}
|
|
if !strings.Contains(result, "field2: 42") {
|
|
t.Error("Expected 'field2: 42' in output")
|
|
}
|
|
if !strings.Contains(result, "field3: true") {
|
|
t.Error("Expected 'field3: true' in output")
|
|
}
|
|
}
|