Adding more tests

This commit is contained in:
Mike Farah 2025-10-12 14:50:41 +11:00
parent 36d410b348
commit ff2c1c930c
4 changed files with 578 additions and 0 deletions

View File

@ -204,3 +204,194 @@ func TestConvertToNodeInfo(t *testing.T) {
test.AssertResult(t, 2, childInfo.Line)
test.AssertResult(t, 3, childInfo.Column)
}
func TestCandidateNodeGetPath(t *testing.T) {
// Test root node with no parent
root := CandidateNode{Value: "root"}
path := root.GetPath()
test.AssertResult(t, 0, len(path))
// Test node with key
key := createStringScalarNode("myKey")
node := CandidateNode{Key: key, Value: "myValue"}
path = node.GetPath()
test.AssertResult(t, 1, len(path))
test.AssertResult(t, "myKey", path[0])
// Test nested path
parent := CandidateNode{}
parentKey := createStringScalarNode("parent")
parent.Key = parentKey
node.Parent = &parent
path = node.GetPath()
test.AssertResult(t, 2, len(path))
test.AssertResult(t, "parent", path[0])
test.AssertResult(t, "myKey", path[1])
}
func TestCandidateNodeGetNicePath(t *testing.T) {
// Test simple key
key := createStringScalarNode("simple")
node := CandidateNode{Key: key}
nicePath := node.GetNicePath()
test.AssertResult(t, "simple", nicePath)
// Test array index
arrayKey := createScalarNode(0, "0")
arrayNode := CandidateNode{Key: arrayKey}
nicePath = arrayNode.GetNicePath()
test.AssertResult(t, "[0]", nicePath)
// Test key with dots (should not be bracketed when it's the first element)
dotKey := createStringScalarNode("key.with.dots")
dotNode := CandidateNode{Key: dotKey}
nicePath = dotNode.GetNicePath()
test.AssertResult(t, "key.with.dots", nicePath)
// Test nested path
parentKey := createStringScalarNode("parent")
parent := CandidateNode{Key: parentKey}
childKey := createStringScalarNode("child")
child := CandidateNode{Key: childKey, Parent: &parent}
nicePath = child.GetNicePath()
test.AssertResult(t, "parent.child", nicePath)
}
func TestCandidateNodeFilterMapContentByKey(t *testing.T) {
// Create a map with multiple key-value pairs
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
key3 := createStringScalarNode("key3")
value3 := createStringScalarNode("value3")
mapNode := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key2, value2, key3, value3},
}
// Filter by key predicate that matches key1 and key3
filtered := mapNode.FilterMapContentByKey(func(key *CandidateNode) bool {
return key.Value == "key1" || key.Value == "key3"
})
// Should return key1, value1, key3, value3
test.AssertResult(t, 4, len(filtered))
test.AssertResult(t, "key1", filtered[0].Value)
test.AssertResult(t, "value1", filtered[1].Value)
test.AssertResult(t, "key3", filtered[2].Value)
test.AssertResult(t, "value3", filtered[3].Value)
}
func TestCandidateNodeVisitValues(t *testing.T) {
// Test mapping node
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
mapNode := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key2, value2},
}
var visited []string
err := mapNode.VisitValues(func(node *CandidateNode) error {
visited = append(visited, node.Value)
return nil
})
test.AssertResult(t, nil, err)
test.AssertResult(t, 2, len(visited))
test.AssertResult(t, "value1", visited[0])
test.AssertResult(t, "value2", visited[1])
// Test sequence node
item1 := createStringScalarNode("item1")
item2 := createStringScalarNode("item2")
seqNode := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{item1, item2},
}
visited = []string{}
err = seqNode.VisitValues(func(node *CandidateNode) error {
visited = append(visited, node.Value)
return nil
})
test.AssertResult(t, nil, err)
test.AssertResult(t, 2, len(visited))
test.AssertResult(t, "item1", visited[0])
test.AssertResult(t, "item2", visited[1])
// Test scalar node (should not visit anything)
scalarNode := &CandidateNode{
Kind: ScalarNode,
Value: "scalar",
}
visited = []string{}
err = scalarNode.VisitValues(func(node *CandidateNode) error {
visited = append(visited, node.Value)
return nil
})
test.AssertResult(t, nil, err)
test.AssertResult(t, 0, len(visited))
}
func TestCandidateNodeCanVisitValues(t *testing.T) {
mapNode := &CandidateNode{Kind: MappingNode}
seqNode := &CandidateNode{Kind: SequenceNode}
scalarNode := &CandidateNode{Kind: ScalarNode}
test.AssertResult(t, true, mapNode.CanVisitValues())
test.AssertResult(t, true, seqNode.CanVisitValues())
test.AssertResult(t, false, scalarNode.CanVisitValues())
}
func TestCandidateNodeAddChild(t *testing.T) {
parent := &CandidateNode{Kind: SequenceNode}
child := createStringScalarNode("child")
parent.AddChild(child)
test.AssertResult(t, 1, len(parent.Content))
test.AssertResult(t, false, parent.Content[0].IsMapKey)
test.AssertResult(t, "0", parent.Content[0].Key.Value)
// Check that parent is set correctly
if parent.Content[0].Parent != parent {
t.Errorf("Expected parent to be set correctly")
}
}
func TestCandidateNodeAddChildren(t *testing.T) {
// Test sequence node
parent := &CandidateNode{Kind: SequenceNode}
child1 := createStringScalarNode("child1")
child2 := createStringScalarNode("child2")
parent.AddChildren([]*CandidateNode{child1, child2})
test.AssertResult(t, 2, len(parent.Content))
test.AssertResult(t, "child1", parent.Content[0].Value)
test.AssertResult(t, "child2", parent.Content[1].Value)
// Test mapping node
mapParent := &CandidateNode{Kind: MappingNode}
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
mapParent.AddChildren([]*CandidateNode{key1, value1, key2, value2})
test.AssertResult(t, 4, len(mapParent.Content))
test.AssertResult(t, true, mapParent.Content[0].IsMapKey) // key1
test.AssertResult(t, false, mapParent.Content[1].IsMapKey) // value1
test.AssertResult(t, true, mapParent.Content[2].IsMapKey) // key2
test.AssertResult(t, false, mapParent.Content[3].IsMapKey) // value2
}

View File

@ -84,3 +84,42 @@ func TestParserExtraArgs(t *testing.T) {
_, err := getExpressionParser().ParseExpression("sortKeys(.) explode(.)")
test.AssertResultComplex(t, "bad expression, please check expression syntax", err.Error())
}
func TestParserEmptyExpression(t *testing.T) {
_, err := getExpressionParser().ParseExpression("")
test.AssertResultComplex(t, nil, err)
}
func TestParserSingleOperation(t *testing.T) {
result, err := getExpressionParser().ParseExpression(".")
test.AssertResultComplex(t, nil, err)
if result == nil {
t.Fatal("Expected non-nil result for single operation")
}
if result.Operation == nil {
t.Fatal("Expected operation to be set")
}
}
func TestParserFirstOpWithZeroArgs(t *testing.T) {
// Test the special case where firstOpType can accept zero args
result, err := getExpressionParser().ParseExpression("first")
test.AssertResultComplex(t, nil, err)
if result == nil {
t.Fatal("Expected non-nil result for first operation with zero args")
}
}
func TestParserInvalidExpressionTree(t *testing.T) {
// This tests the createExpressionTree function with malformed postfix
parser := getExpressionParser().(*expressionParserImpl)
// Create invalid postfix operations that would leave more than one item on stack
invalidOps := []*Operation{
{OperationType: &operationType{NumArgs: 0}},
{OperationType: &operationType{NumArgs: 0}},
}
_, err := parser.createExpressionTree(invalidOps)
test.AssertResultComplex(t, "bad expression, please check expression syntax", err.Error())
}

View File

@ -2,6 +2,7 @@ package yqlib
import (
"fmt"
"strings"
"testing"
"github.com/mikefarah/yq/v4/test"
@ -160,3 +161,250 @@ func TestParseInt64(t *testing.T) {
test.AssertResultComplexWithContext(t, tt.expectedFormatString, fmt.Sprintf(format, actualNumber), fmt.Sprintf("Formatting of: %v", tt.numberString))
}
}
func TestGetContentValueByKey(t *testing.T) {
// Create content with key-value pairs
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
content := []*CandidateNode{key1, value1, key2, value2}
// Test finding existing key
result := getContentValueByKey(content, "key1")
test.AssertResult(t, value1, result)
// Test finding another existing key
result = getContentValueByKey(content, "key2")
test.AssertResult(t, value2, result)
// Test finding non-existing key
result = getContentValueByKey(content, "nonexistent")
test.AssertResult(t, (*CandidateNode)(nil), result)
// Test with empty content
result = getContentValueByKey([]*CandidateNode{}, "key1")
test.AssertResult(t, (*CandidateNode)(nil), result)
}
func TestRecurseNodeArrayEqual(t *testing.T) {
// Create two arrays with same content
array1 := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{
createStringScalarNode("item1"),
createStringScalarNode("item2"),
},
}
array2 := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{
createStringScalarNode("item1"),
createStringScalarNode("item2"),
},
}
array3 := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{
createStringScalarNode("item1"),
createStringScalarNode("different"),
},
}
array4 := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{
createStringScalarNode("item1"),
},
}
test.AssertResult(t, true, recurseNodeArrayEqual(array1, array2))
test.AssertResult(t, false, recurseNodeArrayEqual(array1, array3))
test.AssertResult(t, false, recurseNodeArrayEqual(array1, array4))
}
func TestFindInArray(t *testing.T) {
item1 := createStringScalarNode("item1")
item2 := createStringScalarNode("item2")
item3 := createStringScalarNode("item3")
array := &CandidateNode{
Kind: SequenceNode,
Content: []*CandidateNode{item1, item2, item3},
}
// Test finding existing items
test.AssertResult(t, 0, findInArray(array, item1))
test.AssertResult(t, 1, findInArray(array, item2))
test.AssertResult(t, 2, findInArray(array, item3))
// Test finding non-existing item
nonExistent := createStringScalarNode("nonexistent")
test.AssertResult(t, -1, findInArray(array, nonExistent))
}
func TestFindKeyInMap(t *testing.T) {
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
mapNode := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key2, value2},
}
// Test finding existing keys
test.AssertResult(t, 0, findKeyInMap(mapNode, key1))
test.AssertResult(t, 2, findKeyInMap(mapNode, key2))
// Test finding non-existing key
nonExistent := createStringScalarNode("nonexistent")
test.AssertResult(t, -1, findKeyInMap(mapNode, nonExistent))
}
func TestRecurseNodeObjectEqual(t *testing.T) {
// Create two objects with same content
key1 := createStringScalarNode("key1")
value1 := createStringScalarNode("value1")
key2 := createStringScalarNode("key2")
value2 := createStringScalarNode("value2")
obj1 := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key2, value2},
}
obj2 := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key2, value2},
}
// Create object with different values
value3 := createStringScalarNode("value3")
obj3 := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value3, key2, value2},
}
// Create object with different keys
key3 := createStringScalarNode("key3")
obj4 := &CandidateNode{
Kind: MappingNode,
Content: []*CandidateNode{key1, value1, key3, value2},
}
test.AssertResult(t, true, recurseNodeObjectEqual(obj1, obj2))
test.AssertResult(t, false, recurseNodeObjectEqual(obj1, obj3))
test.AssertResult(t, false, recurseNodeObjectEqual(obj1, obj4))
}
func TestParseInt(t *testing.T) {
type parseIntScenario struct {
numberString string
expectedParsedNumber int
expectedError string
}
scenarios := []parseIntScenario{
{
numberString: "34",
expectedParsedNumber: 34,
},
{
numberString: "10_000",
expectedParsedNumber: 10000,
},
{
numberString: "0x10",
expectedParsedNumber: 16,
},
{
numberString: "0o10",
expectedParsedNumber: 8,
},
{
numberString: "invalid",
expectedError: "strconv.ParseInt",
},
}
for _, tt := range scenarios {
actualNumber, err := parseInt(tt.numberString)
if tt.expectedError != "" {
if err == nil {
t.Errorf("Expected error for '%s' but got none", tt.numberString)
} else if !strings.Contains(err.Error(), tt.expectedError) {
t.Errorf("Expected error containing '%s' for '%s', got '%s'", tt.expectedError, tt.numberString, err.Error())
}
continue
}
if err != nil {
t.Errorf("Unexpected error for '%s': %v", tt.numberString, err)
}
test.AssertResultComplexWithContext(t, tt.expectedParsedNumber, actualNumber, tt.numberString)
}
}
func TestHeadAndLineComment(t *testing.T) {
node := &CandidateNode{
HeadComment: "# head comment",
LineComment: "# line comment",
}
result := headAndLineComment(node)
test.AssertResult(t, " head comment line comment", result)
}
func TestHeadComment(t *testing.T) {
node := &CandidateNode{
HeadComment: "# head comment",
}
result := headComment(node)
test.AssertResult(t, " head comment", result)
// Test without #
node.HeadComment = "no hash comment"
result = headComment(node)
test.AssertResult(t, "no hash comment", result)
}
func TestLineComment(t *testing.T) {
node := &CandidateNode{
LineComment: "# line comment",
}
result := lineComment(node)
test.AssertResult(t, " line comment", result)
// Test without #
node.LineComment = "no hash comment"
result = lineComment(node)
test.AssertResult(t, "no hash comment", result)
}
func TestFootComment(t *testing.T) {
node := &CandidateNode{
FootComment: "# foot comment",
}
result := footComment(node)
test.AssertResult(t, " foot comment", result)
// Test without #
node.FootComment = "no hash comment"
result = footComment(node)
test.AssertResult(t, "no hash comment", result)
}
func TestKindString(t *testing.T) {
test.AssertResult(t, "ScalarNode", KindString(ScalarNode))
test.AssertResult(t, "SequenceNode", KindString(SequenceNode))
test.AssertResult(t, "MappingNode", KindString(MappingNode))
test.AssertResult(t, "AliasNode", KindString(AliasNode))
test.AssertResult(t, "unknown!", KindString(Kind(999))) // Invalid kind
}

View File

@ -414,3 +414,103 @@ func TestPrinterRootUnwrap(t *testing.T) {
`
test.AssertResult(t, expected, output.String())
}
func TestRemoveLastEOL(t *testing.T) {
// Test with \r\n
buffer := bytes.NewBufferString("test\r\n")
removeLastEOL(buffer)
test.AssertResult(t, "test", buffer.String())
// Test with \n only
buffer = bytes.NewBufferString("test\n")
removeLastEOL(buffer)
test.AssertResult(t, "test", buffer.String())
// Test with \r only
buffer = bytes.NewBufferString("test\r")
removeLastEOL(buffer)
test.AssertResult(t, "test", buffer.String())
// Test with no EOL
buffer = bytes.NewBufferString("test")
removeLastEOL(buffer)
test.AssertResult(t, "test", buffer.String())
// Test with empty buffer
buffer = bytes.NewBufferString("")
removeLastEOL(buffer)
test.AssertResult(t, "", buffer.String())
// Test with multiple \r\n
buffer = bytes.NewBufferString("line1\r\nline2\r\n")
removeLastEOL(buffer)
test.AssertResult(t, "line1\r\nline2", buffer.String())
}
func TestPrinterPrintedAnything(t *testing.T) {
var output bytes.Buffer
var writer = bufio.NewWriter(&output)
printer := NewSimpleYamlPrinter(writer, true, 2, true)
// Initially should be false
test.AssertResult(t, false, printer.PrintedAnything())
// Print a scalar value
node := createStringScalarNode("test")
nodeList := nodeToList(node)
err := printer.PrintResults(nodeList)
if err != nil {
t.Fatal(err)
}
// Should now be true
test.AssertResult(t, true, printer.PrintedAnything())
}
func TestPrinterNulSeparatorWithNullChar(t *testing.T) {
var output bytes.Buffer
var writer = bufio.NewWriter(&output)
printer := NewSimpleYamlPrinter(writer, true, 2, false)
printer.SetNulSepOutput(true)
// Create a node with null character
node := createStringScalarNode("test\x00value")
nodeList := nodeToList(node)
err := printer.PrintResults(nodeList)
if err == nil {
t.Fatal("Expected error for null character in NUL separated output")
}
expectedError := "can't serialize value because it contains NUL char and you are using NUL separated output"
if err.Error() != expectedError {
t.Fatalf("Expected error '%s', got '%s'", expectedError, err.Error())
}
}
func TestPrinterSetNulSepOutput(t *testing.T) {
var output bytes.Buffer
var writer = bufio.NewWriter(&output)
printer := NewSimpleYamlPrinter(writer, true, 2, false)
// Test setting NUL separator output
printer.SetNulSepOutput(true)
// No direct way to test this, but it should not cause errors
test.AssertResult(t, true, true) // Placeholder assertion
printer.SetNulSepOutput(false)
// Should also not cause errors
test.AssertResult(t, false, false) // Placeholder assertion
}
func TestPrinterSetAppendix(t *testing.T) {
var output bytes.Buffer
var writer = bufio.NewWriter(&output)
printer := NewSimpleYamlPrinter(writer, true, 2, true)
// Test setting appendix
appendix := strings.NewReader("appendix content")
printer.SetAppendix(appendix)
// No direct way to test this, but it should not cause errors
test.AssertResult(t, true, true) // Placeholder assertion
}