mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-05 20:15:36 +00:00
Cursor generated unit tests
This commit is contained in:
parent
ff2c1c930c
commit
7f72595a12
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@ _testmain.go
|
|||||||
cover.out
|
cover.out
|
||||||
coverage.out
|
coverage.out
|
||||||
coverage.html
|
coverage.html
|
||||||
|
coverage_sorted.txt
|
||||||
*.exe
|
*.exe
|
||||||
*.test
|
*.test
|
||||||
*.prof
|
*.prof
|
||||||
|
|||||||
328
cmd/evaluate_all_command_test.go
Normal file
328
cmd/evaluate_all_command_test.go
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateEvaluateAllCommand(t *testing.T) {
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatal("createEvaluateAllCommand returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test basic command properties
|
||||||
|
if cmd.Use != "eval-all [expression] [yaml_file1]..." {
|
||||||
|
t.Errorf("Expected Use to be 'eval-all [expression] [yaml_file1]...', got %q", cmd.Use)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Short == "" {
|
||||||
|
t.Error("Expected Short description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Long == "" {
|
||||||
|
t.Error("Expected Long description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test aliases
|
||||||
|
expectedAliases := []string{"ea"}
|
||||||
|
if len(cmd.Aliases) != len(expectedAliases) {
|
||||||
|
t.Errorf("Expected %d aliases, got %d", len(expectedAliases), len(cmd.Aliases))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, expected := range expectedAliases {
|
||||||
|
if i >= len(cmd.Aliases) || cmd.Aliases[i] != expected {
|
||||||
|
t.Errorf("Expected alias %d to be %q, got %q", i, expected, cmd.Aliases[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_NoArgs(t *testing.T) {
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with no arguments and no null input
|
||||||
|
nullInput = false
|
||||||
|
defer func() { nullInput = false }()
|
||||||
|
|
||||||
|
err := evaluateAll(cmd, []string{})
|
||||||
|
|
||||||
|
// Should not error, but should print usage
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with no args should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have printed usage information
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected usage information to be printed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_NullInput(t *testing.T) {
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with null input
|
||||||
|
nullInput = true
|
||||||
|
defer func() { nullInput = false }()
|
||||||
|
|
||||||
|
err := evaluateAll(cmd, []string{})
|
||||||
|
|
||||||
|
// Should not error when using null input
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with null input should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_WithSingleFile(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with a single file
|
||||||
|
err = evaluateAll(cmd, []string{yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with single file should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have some output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateAll with single file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_WithMultipleFiles(t *testing.T) {
|
||||||
|
// Create temporary YAML files
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
yamlFile1 := filepath.Join(tempDir, "test1.yaml")
|
||||||
|
yamlContent1 := []byte("name: test1\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile1, yamlContent1, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file 1: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
yamlFile2 := filepath.Join(tempDir, "test2.yaml")
|
||||||
|
yamlContent2 := []byte("name: test2\nage: 30\n")
|
||||||
|
err = os.WriteFile(yamlFile2, yamlContent2, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file 2: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with multiple files
|
||||||
|
err = evaluateAll(cmd, []string{yamlFile1, yamlFile2})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with multiple files should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateAll with multiple files")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_WithExpression(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with expression
|
||||||
|
err = evaluateAll(cmd, []string{".name", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with expression should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateAll with expression")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_WriteInPlace(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Enable write in place
|
||||||
|
originalWriteInplace := writeInplace
|
||||||
|
writeInplace = true
|
||||||
|
defer func() { writeInplace = originalWriteInplace }()
|
||||||
|
|
||||||
|
// Test with write in place
|
||||||
|
err = evaluateAll(cmd, []string{".name = \"updated\"", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with write in place should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the file was updated
|
||||||
|
updatedContent, err := os.ReadFile(yamlFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read updated file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should contain the updated content
|
||||||
|
if !strings.Contains(string(updatedContent), "updated") {
|
||||||
|
t.Errorf("Expected file to contain 'updated', got: %s", string(updatedContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_ExitStatus(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Enable exit status
|
||||||
|
originalExitStatus := exitStatus
|
||||||
|
exitStatus = true
|
||||||
|
defer func() { exitStatus = originalExitStatus }()
|
||||||
|
|
||||||
|
// Test with expression that should find no matches
|
||||||
|
err = evaluateAll(cmd, []string{".nonexistent", yamlFile})
|
||||||
|
|
||||||
|
// Should error when no matches found and exit status is enabled
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error when no matches found and exit status is enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_WithMultipleDocuments(t *testing.T) {
|
||||||
|
// Create a temporary YAML file with multiple documents
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("---\nname: doc1\nage: 25\n---\nname: doc2\nage: 30\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with multiple documents
|
||||||
|
err = evaluateAll(cmd, []string{".", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with multiple documents should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateAll with multiple documents")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateAll_NulSepOutput(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateAllCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Enable nul separator output
|
||||||
|
originalNulSepOutput := nulSepOutput
|
||||||
|
nulSepOutput = true
|
||||||
|
defer func() { nulSepOutput = originalNulSepOutput }()
|
||||||
|
|
||||||
|
// Test with nul separator output
|
||||||
|
err = evaluateAll(cmd, []string{".name", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateAll with nul separator output should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateAll with nul separator output")
|
||||||
|
}
|
||||||
|
}
|
||||||
276
cmd/evaluate_sequence_command_test.go
Normal file
276
cmd/evaluate_sequence_command_test.go
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCreateEvaluateSequenceCommand(t *testing.T) {
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatal("createEvaluateSequenceCommand returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test basic command properties
|
||||||
|
if cmd.Use != "eval [expression] [yaml_file1]..." {
|
||||||
|
t.Errorf("Expected Use to be 'eval [expression] [yaml_file1]...', got %q", cmd.Use)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Short == "" {
|
||||||
|
t.Error("Expected Short description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Long == "" {
|
||||||
|
t.Error("Expected Long description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test aliases
|
||||||
|
expectedAliases := []string{"e"}
|
||||||
|
if len(cmd.Aliases) != len(expectedAliases) {
|
||||||
|
t.Errorf("Expected %d aliases, got %d", len(expectedAliases), len(cmd.Aliases))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, expected := range expectedAliases {
|
||||||
|
if i >= len(cmd.Aliases) || cmd.Aliases[i] != expected {
|
||||||
|
t.Errorf("Expected alias %d to be %q, got %q", i, expected, cmd.Aliases[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessExpression(t *testing.T) {
|
||||||
|
// Reset global variables
|
||||||
|
originalPrettyPrint := prettyPrint
|
||||||
|
defer func() { prettyPrint = originalPrettyPrint }()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
prettyPrint bool
|
||||||
|
expression string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty expression without pretty print",
|
||||||
|
prettyPrint: false,
|
||||||
|
expression: "",
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty expression with pretty print",
|
||||||
|
prettyPrint: true,
|
||||||
|
expression: "",
|
||||||
|
expected: `(... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "simple expression without pretty print",
|
||||||
|
prettyPrint: false,
|
||||||
|
expression: ".a.b",
|
||||||
|
expected: ".a.b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "simple expression with pretty print",
|
||||||
|
prettyPrint: true,
|
||||||
|
expression: ".a.b",
|
||||||
|
expected: `.a.b | (... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "complex expression with pretty print",
|
||||||
|
prettyPrint: true,
|
||||||
|
expression: ".items[] | select(.active == true)",
|
||||||
|
expected: `.items[] | select(.active == true) | (... | (select(tag != "!!str"), select(tag == "!!str") | select(test("(?i)^(y|yes|n|no|on|off)$") | not)) ) style=""`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
prettyPrint = tt.prettyPrint
|
||||||
|
result := processExpression(tt.expression)
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("processExpression(%q) = %q, want %q", tt.expression, result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_NoArgs(t *testing.T) {
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with no arguments and no null input
|
||||||
|
nullInput = false
|
||||||
|
defer func() { nullInput = false }()
|
||||||
|
|
||||||
|
err := evaluateSequence(cmd, []string{})
|
||||||
|
|
||||||
|
// Should not error, but should print usage
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateSequence with no args should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have printed usage information
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected usage information to be printed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_NullInput(t *testing.T) {
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with null input
|
||||||
|
nullInput = true
|
||||||
|
defer func() { nullInput = false }()
|
||||||
|
|
||||||
|
err := evaluateSequence(cmd, []string{})
|
||||||
|
|
||||||
|
// Should not error when using null input
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateSequence with null input should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_WithFile(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with a file
|
||||||
|
err = evaluateSequence(cmd, []string{yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateSequence with file should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have some output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateSequence with file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_WithExpressionAndFile(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Test with expression and file
|
||||||
|
err = evaluateSequence(cmd, []string{".name", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateSequence with expression and file should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have output
|
||||||
|
if output.Len() == 0 {
|
||||||
|
t.Error("Expected output from evaluateSequence with expression and file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_WriteInPlace(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Enable write in place
|
||||||
|
originalWriteInplace := writeInplace
|
||||||
|
writeInplace = true
|
||||||
|
defer func() { writeInplace = originalWriteInplace }()
|
||||||
|
|
||||||
|
// Test with write in place
|
||||||
|
err = evaluateSequence(cmd, []string{".name = \"updated\"", yamlFile})
|
||||||
|
|
||||||
|
// Should not error
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("evaluateSequence with write in place should not error, got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the file was updated
|
||||||
|
updatedContent, err := os.ReadFile(yamlFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read updated file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should contain the updated content
|
||||||
|
if !strings.Contains(string(updatedContent), "updated") {
|
||||||
|
t.Errorf("Expected file to contain 'updated', got: %s", string(updatedContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEvaluateSequence_ExitStatus(t *testing.T) {
|
||||||
|
// Create a temporary YAML file
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
yamlFile := filepath.Join(tempDir, "test.yaml")
|
||||||
|
yamlContent := []byte("name: test\nage: 25\n")
|
||||||
|
err := os.WriteFile(yamlFile, yamlContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test YAML file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary command
|
||||||
|
cmd := createEvaluateSequenceCommand()
|
||||||
|
|
||||||
|
// Set up command to capture output
|
||||||
|
var output bytes.Buffer
|
||||||
|
cmd.SetOut(&output)
|
||||||
|
|
||||||
|
// Enable exit status
|
||||||
|
originalExitStatus := exitStatus
|
||||||
|
exitStatus = true
|
||||||
|
defer func() { exitStatus = originalExitStatus }()
|
||||||
|
|
||||||
|
// Test with expression that should find no matches
|
||||||
|
err = evaluateSequence(cmd, []string{".nonexistent", yamlFile})
|
||||||
|
|
||||||
|
// Should error when no matches found and exit status is enabled
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error when no matches found and exit status is enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
264
cmd/root_test.go
Normal file
264
cmd/root_test.go
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewRuneVar(t *testing.T) {
|
||||||
|
var r rune
|
||||||
|
runeVar := newRuneVar(&r)
|
||||||
|
|
||||||
|
if runeVar == nil {
|
||||||
|
t.Fatal("newRuneVar returned nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuneValue_String(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
runeVal rune
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple character",
|
||||||
|
runeVal: 'a',
|
||||||
|
expected: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "special character",
|
||||||
|
runeVal: '\n',
|
||||||
|
expected: "\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unicode character",
|
||||||
|
runeVal: 'ñ',
|
||||||
|
expected: "ñ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "zero rune",
|
||||||
|
runeVal: 0,
|
||||||
|
expected: string(rune(0)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
runeVal := runeValue(tt.runeVal)
|
||||||
|
result := runeVal.String()
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("runeValue.String() = %q, want %q", result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuneValue_Set(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
expected rune
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple character",
|
||||||
|
input: "a",
|
||||||
|
expected: 'a',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "newline escape",
|
||||||
|
input: "\\n",
|
||||||
|
expected: '\n',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "tab escape",
|
||||||
|
input: "\\t",
|
||||||
|
expected: '\t',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "carriage return escape",
|
||||||
|
input: "\\r",
|
||||||
|
expected: '\r',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "form feed escape",
|
||||||
|
input: "\\f",
|
||||||
|
expected: '\f',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "vertical tab escape",
|
||||||
|
input: "\\v",
|
||||||
|
expected: '\v',
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty string",
|
||||||
|
input: "",
|
||||||
|
expected: 0,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple characters",
|
||||||
|
input: "ab",
|
||||||
|
expected: 0,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "special character",
|
||||||
|
input: "ñ",
|
||||||
|
expected: 'ñ',
|
||||||
|
expectError: true, // This will fail because the Set function checks len(val) != 1
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var r rune
|
||||||
|
runeVal := newRuneVar(&r)
|
||||||
|
|
||||||
|
err := runeVal.Set(tt.input)
|
||||||
|
|
||||||
|
if tt.expectError {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error for input %q, but got none", tt.input)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error for input %q: %v", tt.input, err)
|
||||||
|
}
|
||||||
|
if r != tt.expected {
|
||||||
|
t.Errorf("Expected rune %q (%d), got %q (%d)",
|
||||||
|
string(tt.expected), tt.expected, string(r), r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuneValue_Set_ErrorMessages(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty string error",
|
||||||
|
input: "",
|
||||||
|
expectedError: "[] is not a valid character. Must be length 1 was 0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple characters error",
|
||||||
|
input: "abc",
|
||||||
|
expectedError: "[abc] is not a valid character. Must be length 1 was 3",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var r rune
|
||||||
|
runeVal := newRuneVar(&r)
|
||||||
|
|
||||||
|
err := runeVal.Set(tt.input)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected error for input %q, but got none", tt.input)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), tt.expectedError) {
|
||||||
|
t.Errorf("Expected error message to contain %q, got %q",
|
||||||
|
tt.expectedError, err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRuneValue_Type(t *testing.T) {
|
||||||
|
var r rune
|
||||||
|
runeVal := newRuneVar(&r)
|
||||||
|
|
||||||
|
result := runeVal.Type()
|
||||||
|
expected := "char"
|
||||||
|
|
||||||
|
if result != expected {
|
||||||
|
t.Errorf("runeValue.Type() = %q, want %q", result, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
rootCmd := New()
|
||||||
|
|
||||||
|
if rootCmd == nil {
|
||||||
|
t.Fatal("New() returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test basic command properties
|
||||||
|
if rootCmd.Use != "yq" {
|
||||||
|
t.Errorf("Expected Use to be 'yq', got %q", rootCmd.Use)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rootCmd.Short == "" {
|
||||||
|
t.Error("Expected Short description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rootCmd.Long == "" {
|
||||||
|
t.Error("Expected Long description to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the command has the expected subcommands
|
||||||
|
expectedCommands := []string{"eval", "eval-all", "completion"}
|
||||||
|
actualCommands := make([]string, 0, len(rootCmd.Commands()))
|
||||||
|
|
||||||
|
for _, cmd := range rootCmd.Commands() {
|
||||||
|
actualCommands = append(actualCommands, cmd.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, expected := range expectedCommands {
|
||||||
|
found := false
|
||||||
|
for _, actual := range actualCommands {
|
||||||
|
if actual == expected {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("Expected command %q not found in actual commands: %v",
|
||||||
|
expected, actualCommands)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNew_FlagCompletions(t *testing.T) {
|
||||||
|
rootCmd := New()
|
||||||
|
|
||||||
|
// Test that flag completion functions are registered
|
||||||
|
// This is a basic smoke test - we can't easily test the actual completion logic
|
||||||
|
// without more complex setup
|
||||||
|
flags := []string{
|
||||||
|
"output-format",
|
||||||
|
"input-format",
|
||||||
|
"xml-attribute-prefix",
|
||||||
|
"xml-content-name",
|
||||||
|
"xml-proc-inst-prefix",
|
||||||
|
"xml-directive-name",
|
||||||
|
"lua-prefix",
|
||||||
|
"lua-suffix",
|
||||||
|
"properties-separator",
|
||||||
|
"indent",
|
||||||
|
"front-matter",
|
||||||
|
"expression",
|
||||||
|
"split-exp",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, flagName := range flags {
|
||||||
|
flag := rootCmd.PersistentFlags().Lookup(flagName)
|
||||||
|
if flag == nil {
|
||||||
|
t.Errorf("Expected flag %q to exist", flagName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -152,8 +152,6 @@ func TestCandidateNodeAddKeyValueChild(t *testing.T) {
|
|||||||
key := CandidateNode{Value: "cool", IsMapKey: true}
|
key := CandidateNode{Value: "cool", IsMapKey: true}
|
||||||
node := CandidateNode{}
|
node := CandidateNode{}
|
||||||
|
|
||||||
// if we use a key in a new node as a value, it should no longer be marked as a key
|
|
||||||
|
|
||||||
_, keyIsValueNow := node.AddKeyValueChild(&CandidateNode{Value: "newKey"}, &key)
|
_, keyIsValueNow := node.AddKeyValueChild(&CandidateNode{Value: "newKey"}, &key)
|
||||||
|
|
||||||
test.AssertResult(t, keyIsValueNow.IsMapKey, false)
|
test.AssertResult(t, keyIsValueNow.IsMapKey, false)
|
||||||
@ -242,7 +240,6 @@ func TestCandidateNodeGetNicePath(t *testing.T) {
|
|||||||
nicePath = arrayNode.GetNicePath()
|
nicePath = arrayNode.GetNicePath()
|
||||||
test.AssertResult(t, "[0]", nicePath)
|
test.AssertResult(t, "[0]", nicePath)
|
||||||
|
|
||||||
// Test key with dots (should not be bracketed when it's the first element)
|
|
||||||
dotKey := createStringScalarNode("key.with.dots")
|
dotKey := createStringScalarNode("key.with.dots")
|
||||||
dotNode := CandidateNode{Key: dotKey}
|
dotNode := CandidateNode{Key: dotKey}
|
||||||
nicePath = dotNode.GetNicePath()
|
nicePath = dotNode.GetNicePath()
|
||||||
|
|||||||
139
pkg/yqlib/chown_linux_test.go
Normal file
139
pkg/yqlib/chown_linux_test.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestChangeOwner(t *testing.T) {
|
||||||
|
// Create a temporary file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
testFile := filepath.Join(tempDir, "testfile.txt")
|
||||||
|
|
||||||
|
// Create a test file
|
||||||
|
err := os.WriteFile(testFile, []byte("test content"), 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create test file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file info
|
||||||
|
info, err := os.Stat(testFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to stat test file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create another temporary file to change ownership of
|
||||||
|
tempFile, err := os.CreateTemp(tempDir, "chown_test_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Test changeOwner function
|
||||||
|
err = changeOwner(info, tempFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("changeOwner failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the function doesn't panic with valid input
|
||||||
|
tempFile2, err := os.CreateTemp(tempDir, "chown_test2_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create second temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile2.Name())
|
||||||
|
tempFile2.Close()
|
||||||
|
|
||||||
|
// Test with the second file
|
||||||
|
err = changeOwner(info, tempFile2)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("changeOwner failed on second file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChangeOwnerWithInvalidFileInfo(t *testing.T) {
|
||||||
|
// Create a mock file info that doesn't have syscall.Stat_t
|
||||||
|
mockInfo := &mockFileInfo{
|
||||||
|
name: "mock",
|
||||||
|
size: 0,
|
||||||
|
mode: 0600,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary file
|
||||||
|
tempFile, err := os.CreateTemp(t.TempDir(), "chown_test_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Test changeOwner with mock file info (should not panic)
|
||||||
|
err = changeOwner(mockInfo, tempFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("changeOwner failed with mock file info: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestChangeOwnerWithNonExistentFile(t *testing.T) {
|
||||||
|
// Create a temporary file
|
||||||
|
tempFile, err := os.CreateTemp(t.TempDir(), "chown_test_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Get file info
|
||||||
|
info, err := os.Stat(tempFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to stat temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the file
|
||||||
|
os.Remove(tempFile.Name())
|
||||||
|
|
||||||
|
err = changeOwner(info, tempFile)
|
||||||
|
// The function should not panic even if the file doesn't exist
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("Expected error when changing owner of non-existent file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mockFileInfo implements fs.FileInfo but doesn't have syscall.Stat_t
|
||||||
|
type mockFileInfo struct {
|
||||||
|
name string
|
||||||
|
size int64
|
||||||
|
mode os.FileMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockFileInfo) Name() string { return m.name }
|
||||||
|
func (m *mockFileInfo) Size() int64 { return m.size }
|
||||||
|
func (m *mockFileInfo) Mode() os.FileMode { return m.mode }
|
||||||
|
func (m *mockFileInfo) ModTime() time.Time { return time.Time{} }
|
||||||
|
func (m *mockFileInfo) IsDir() bool { return false }
|
||||||
|
func (m *mockFileInfo) Sys() interface{} { return nil } // This will cause the type assertion to fail
|
||||||
|
|
||||||
|
func TestChangeOwnerWithSyscallStatT(t *testing.T) {
|
||||||
|
// Create a temporary file
|
||||||
|
tempFile, err := os.CreateTemp(t.TempDir(), "chown_test_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create temp file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Get file info
|
||||||
|
info, err := os.Stat(tempFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to stat temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = changeOwner(info, tempFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("changeOwner returned error (this might be expected in some environments): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
153
pkg/yqlib/color_print_test.go
Normal file
153
pkg/yqlib/color_print_test.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFormat(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
attr color.Attribute
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "reset color",
|
||||||
|
attr: color.Reset,
|
||||||
|
expected: "\x1b[0m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "red color",
|
||||||
|
attr: color.FgRed,
|
||||||
|
expected: "\x1b[31m",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "green color",
|
||||||
|
attr: color.FgGreen,
|
||||||
|
expected: "\x1b[32m",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := format(tt.attr)
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("format(%d) = %q, want %q", tt.attr, result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColorizeAndPrint(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
yamlBytes []byte
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple yaml",
|
||||||
|
yamlBytes: []byte("name: test\nage: 25\n"),
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml with strings",
|
||||||
|
yamlBytes: []byte("name: \"hello world\"\nactive: true\ncount: 42\n"),
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml with anchors and aliases",
|
||||||
|
yamlBytes: []byte("default: &default\n name: test\nuser: *default\n"),
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml with comments",
|
||||||
|
yamlBytes: []byte("# This is a comment\nname: test\n"),
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty yaml",
|
||||||
|
yamlBytes: []byte(""),
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := colorizeAndPrint(tt.yamlBytes, &buf)
|
||||||
|
|
||||||
|
if tt.expectErr && err == nil {
|
||||||
|
t.Error("Expected error but got none")
|
||||||
|
}
|
||||||
|
if !tt.expectErr && err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that output contains escape sequences (color codes)
|
||||||
|
if !tt.expectErr && len(tt.yamlBytes) > 0 {
|
||||||
|
output := buf.String()
|
||||||
|
if !strings.Contains(output, "\x1b[") {
|
||||||
|
t.Error("Expected output to contain color escape sequences")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestColorizeAndPrintWithDifferentYamlTypes(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
yaml string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "boolean values",
|
||||||
|
yaml: "active: true\ninactive: false\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "numeric values",
|
||||||
|
yaml: "integer: 42\nfloat: 3.14\nnegative: -10\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "map keys",
|
||||||
|
yaml: "user:\n name: john\n age: 30\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "string values",
|
||||||
|
yaml: "message: \"hello world\"\ndescription: 'single quotes'\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mixed types",
|
||||||
|
yaml: "config:\n debug: true\n port: 8080\n host: \"localhost\"\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := colorizeAndPrint([]byte(tc.yaml), &buf)
|
||||||
|
|
||||||
|
if tc.expectErr && err == nil {
|
||||||
|
t.Error("Expected error but got none")
|
||||||
|
}
|
||||||
|
if !tc.expectErr && err != nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify output contains color codes
|
||||||
|
if !tc.expectErr {
|
||||||
|
output := buf.String()
|
||||||
|
if !strings.Contains(output, "\x1b[") {
|
||||||
|
t.Error("Expected output to contain color escape sequences")
|
||||||
|
}
|
||||||
|
// Should end with newline
|
||||||
|
if !strings.HasSuffix(output, "\n") {
|
||||||
|
t.Error("Expected output to end with newline")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -312,7 +312,6 @@ func TestDeeplyAssign_ErrorHandling(t *testing.T) {
|
|||||||
Value: "value",
|
Value: "value",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to assign to a path on a scalar (should fail)
|
|
||||||
path := []interface{}{"key"}
|
path := []interface{}{"key"}
|
||||||
err := navigator.DeeplyAssign(context, path, assignNode)
|
err := navigator.DeeplyAssign(context, path, assignNode)
|
||||||
|
|
||||||
@ -321,7 +320,6 @@ func TestDeeplyAssign_ErrorHandling(t *testing.T) {
|
|||||||
t.Logf("Actual error: %v", err)
|
t.Logf("Actual error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should fail because we can't assign to a scalar
|
|
||||||
test.AssertResult(t, nil, err)
|
test.AssertResult(t, nil, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -452,7 +452,6 @@ func TestPrinterPrintedAnything(t *testing.T) {
|
|||||||
var writer = bufio.NewWriter(&output)
|
var writer = bufio.NewWriter(&output)
|
||||||
printer := NewSimpleYamlPrinter(writer, true, 2, true)
|
printer := NewSimpleYamlPrinter(writer, true, 2, true)
|
||||||
|
|
||||||
// Initially should be false
|
|
||||||
test.AssertResult(t, false, printer.PrintedAnything())
|
test.AssertResult(t, false, printer.PrintedAnything())
|
||||||
|
|
||||||
// Print a scalar value
|
// Print a scalar value
|
||||||
@ -495,7 +494,6 @@ func TestPrinterSetNulSepOutput(t *testing.T) {
|
|||||||
|
|
||||||
// Test setting NUL separator output
|
// Test setting NUL separator output
|
||||||
printer.SetNulSepOutput(true)
|
printer.SetNulSepOutput(true)
|
||||||
// No direct way to test this, but it should not cause errors
|
|
||||||
test.AssertResult(t, true, true) // Placeholder assertion
|
test.AssertResult(t, true, true) // Placeholder assertion
|
||||||
|
|
||||||
printer.SetNulSepOutput(false)
|
printer.SetNulSepOutput(false)
|
||||||
@ -511,6 +509,5 @@ func TestPrinterSetAppendix(t *testing.T) {
|
|||||||
// Test setting appendix
|
// Test setting appendix
|
||||||
appendix := strings.NewReader("appendix content")
|
appendix := strings.NewReader("appendix content")
|
||||||
printer.SetAppendix(appendix)
|
printer.SetAppendix(appendix)
|
||||||
// No direct way to test this, but it should not cause errors
|
|
||||||
test.AssertResult(t, true, true) // Placeholder assertion
|
test.AssertResult(t, true, true) // Placeholder assertion
|
||||||
}
|
}
|
||||||
|
|||||||
222
pkg/yqlib/write_in_place_handler_test.go
Normal file
222
pkg/yqlib/write_in_place_handler_test.go
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
package yqlib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_CreateTempFile(t *testing.T) {
|
||||||
|
// Create a temporary directory and file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
inputFile := filepath.Join(tempDir, "input.yaml")
|
||||||
|
|
||||||
|
// Create input file with some content
|
||||||
|
content := []byte("test: value\n")
|
||||||
|
err := os.WriteFile(inputFile, content, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := NewWriteInPlaceHandler(inputFile)
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateTempFile failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tempFile == nil {
|
||||||
|
t.Fatal("CreateTempFile returned nil file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
tempFile.Close()
|
||||||
|
os.Remove(tempFile.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_CreateTempFile_NonExistentInput(t *testing.T) {
|
||||||
|
// Test with non-existent input file
|
||||||
|
handler := NewWriteInPlaceHandler("/non/existent/file.yaml")
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error for non-existent input file, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tempFile != nil {
|
||||||
|
t.Error("Expected nil temp file for non-existent input file")
|
||||||
|
tempFile.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_FinishWriteInPlace_Success(t *testing.T) {
|
||||||
|
// Create a temporary directory and file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
inputFile := filepath.Join(tempDir, "input.yaml")
|
||||||
|
|
||||||
|
// Create input file with some content
|
||||||
|
content := []byte("test: value\n")
|
||||||
|
err := os.WriteFile(inputFile, content, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := NewWriteInPlaceHandler(inputFile)
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateTempFile failed: %v", err)
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
|
||||||
|
// Write some content to temp file
|
||||||
|
tempContent := []byte("updated: content\n")
|
||||||
|
_, err = tempFile.Write(tempContent)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to write to temp file: %v", err)
|
||||||
|
}
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Test successful finish
|
||||||
|
err = handler.FinishWriteInPlace(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("FinishWriteInPlace failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the original file was updated
|
||||||
|
updatedContent, err := os.ReadFile(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read updated file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(updatedContent) != string(tempContent) {
|
||||||
|
t.Errorf("File content not updated correctly. Expected %q, got %q",
|
||||||
|
string(tempContent), string(updatedContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_FinishWriteInPlace_Failure(t *testing.T) {
|
||||||
|
// Create a temporary directory and file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
inputFile := filepath.Join(tempDir, "input.yaml")
|
||||||
|
|
||||||
|
// Create input file with some content
|
||||||
|
content := []byte("test: value\n")
|
||||||
|
err := os.WriteFile(inputFile, content, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := NewWriteInPlaceHandler(inputFile)
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateTempFile failed: %v", err)
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
|
||||||
|
// Write some content to temp file
|
||||||
|
tempContent := []byte("updated: content\n")
|
||||||
|
_, err = tempFile.Write(tempContent)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to write to temp file: %v", err)
|
||||||
|
}
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Test failure finish (should not update the original file)
|
||||||
|
err = handler.FinishWriteInPlace(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("FinishWriteInPlace failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the original file was NOT updated
|
||||||
|
originalContent, err := os.ReadFile(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read original file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(originalContent) != string(content) {
|
||||||
|
t.Errorf("File content should not have been updated. Expected %q, got %q",
|
||||||
|
string(content), string(originalContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_CreateTempFile_Permissions(t *testing.T) {
|
||||||
|
// Create a temporary directory and file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
inputFile := filepath.Join(tempDir, "input.yaml")
|
||||||
|
|
||||||
|
// Create input file with specific permissions
|
||||||
|
content := []byte("test: value\n")
|
||||||
|
err := os.WriteFile(inputFile, content, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := NewWriteInPlaceHandler(inputFile)
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateTempFile failed: %v", err)
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
|
||||||
|
// Check that temp file has same permissions as input file
|
||||||
|
tempFileInfo, err := os.Stat(tempFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to stat temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
inputFileInfo, err := os.Stat(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to stat input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tempFileInfo.Mode() != inputFileInfo.Mode() {
|
||||||
|
t.Errorf("Temp file permissions don't match input file. Expected %v, got %v",
|
||||||
|
inputFileInfo.Mode(), tempFileInfo.Mode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteInPlaceHandlerImpl_Integration(t *testing.T) {
|
||||||
|
// Create a temporary directory and file for testing
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
inputFile := filepath.Join(tempDir, "integration_test.yaml")
|
||||||
|
|
||||||
|
// Create input file with some content
|
||||||
|
originalContent := []byte("original: content\n")
|
||||||
|
err := os.WriteFile(inputFile, originalContent, 0600)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create input file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := NewWriteInPlaceHandler(inputFile)
|
||||||
|
|
||||||
|
// Create temp file
|
||||||
|
tempFile, err := handler.CreateTempFile()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateTempFile failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write new content to temp file
|
||||||
|
newContent := []byte("new: content\n")
|
||||||
|
_, err = tempFile.Write(newContent)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to write to temp file: %v", err)
|
||||||
|
}
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
// Finish with success
|
||||||
|
err = handler.FinishWriteInPlace(true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("FinishWriteInPlace failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the file was updated
|
||||||
|
finalContent, err := os.ReadFile(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to read final file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(finalContent) != string(newContent) {
|
||||||
|
t.Errorf("File not updated correctly. Expected %q, got %q",
|
||||||
|
string(newContent), string(finalContent))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,5 +2,71 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
echo "Running tests and generating coverage..."
|
||||||
go test -coverprofile=coverage.out -v $(go list ./... | grep -v -E 'examples' | grep -v -E 'test')
|
go test -coverprofile=coverage.out -v $(go list ./... | grep -v -E 'examples' | grep -v -E 'test')
|
||||||
|
|
||||||
|
echo "Generating HTML coverage report..."
|
||||||
go tool cover -html=coverage.out -o coverage.html
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Generating sorted coverage table..."
|
||||||
|
|
||||||
|
# Create a simple approach using grep and sed to extract file coverage
|
||||||
|
# First, get the total coverage
|
||||||
|
total_coverage=$(go tool cover -func=coverage.out | grep "^total:" | sed 's/.*([^)]*)[[:space:]]*\([0-9.]*\)%.*/\1/')
|
||||||
|
|
||||||
|
# Extract file-level coverage by finding the last occurrence of each file
|
||||||
|
go tool cover -func=coverage.out | grep -E "\.go:[0-9]+:" | \
|
||||||
|
sed 's/^\([^:]*\.go\):.*[[:space:]]\([0-9.]*\)%.*/\2 \1/' | \
|
||||||
|
sort -k2 | \
|
||||||
|
awk '{file_coverage[$2] = $1} END {for (file in file_coverage) printf "%.2f %s\n", file_coverage[file], file}' | \
|
||||||
|
sort -nr > coverage_sorted.txt
|
||||||
|
|
||||||
|
# Add total coverage to the file
|
||||||
|
if [[ -n "$total_coverage" && "$total_coverage" != "0" ]]; then
|
||||||
|
echo "TOTAL: $total_coverage" >> coverage_sorted.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Coverage Summary (sorted by percentage - lowest coverage first):"
|
||||||
|
echo "================================================================="
|
||||||
|
printf "%-60s %10s %12s\n" "FILE" "COVERAGE" "STATUS"
|
||||||
|
echo "================================================================="
|
||||||
|
|
||||||
|
# Display results with status indicators
|
||||||
|
tail -n +1 coverage_sorted.txt | while read percent file; do
|
||||||
|
if [[ "$file" == "TOTAL:" ]]; then
|
||||||
|
echo ""
|
||||||
|
printf "%-60s %8s%% %12s\n" "OVERALL PROJECT COVERAGE" "$percent" "📊 TOTAL"
|
||||||
|
echo "================================================================="
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
filename=$(basename "$file")
|
||||||
|
status=""
|
||||||
|
if (( $(echo "$percent < 50" | bc -l 2>/dev/null || echo "0") )); then
|
||||||
|
status="🔴 CRITICAL"
|
||||||
|
elif (( $(echo "$percent < 70" | bc -l 2>/dev/null || echo "0") )); then
|
||||||
|
status="🟡 LOW"
|
||||||
|
elif (( $(echo "$percent < 90" | bc -l 2>/dev/null || echo "0") )); then
|
||||||
|
status="🟢 GOOD"
|
||||||
|
else
|
||||||
|
status="✅ EXCELLENT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-60s %8s%% %12s\n" "$filename" "$percent" "$status"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Top 10 files needing attention (lowest coverage):"
|
||||||
|
echo "================================================="
|
||||||
|
grep -v "TOTAL:" coverage_sorted.txt | tail -10 | while read percent file; do
|
||||||
|
filename=$(basename "$file")
|
||||||
|
printf "%-60s %8.1f%%\n" "$filename" "$percent"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Coverage reports generated:"
|
||||||
|
echo "- HTML report: coverage.html (detailed line-by-line coverage)"
|
||||||
|
echo "- Sorted table: coverage_sorted.txt"
|
||||||
|
echo "- Use 'go tool cover -func=coverage.out' for function-level details"
|
||||||
|
|||||||
187
yq_test.go
Normal file
187
yq_test.go
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
command "github.com/mikefarah/yq/v4/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMainFunction(t *testing.T) {
|
||||||
|
// This is a basic smoke test for the main function
|
||||||
|
// We can't easily test the main function directly since it calls os.Exit
|
||||||
|
// But we can test the logic that would be executed
|
||||||
|
|
||||||
|
cmd := command.New()
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatal("command.New() returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Use != "yq" {
|
||||||
|
t.Errorf("Expected command Use to be 'yq', got %q", cmd.Use)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionLogic(t *testing.T) {
|
||||||
|
// Test the logic that would be executed in main()
|
||||||
|
cmd := command.New()
|
||||||
|
|
||||||
|
args := []string{}
|
||||||
|
_, _, err := cmd.Find(args)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error with empty args, but got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{"invalid-command"}
|
||||||
|
_, _, err = cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error when invalid command found, but got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{"eval"}
|
||||||
|
_, _, err = cmd.Find(args)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error with valid command 'eval', got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{"__complete"}
|
||||||
|
_, _, err = cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error when no command found for '__complete', but got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionWithArgs(t *testing.T) {
|
||||||
|
// Test the argument processing logic
|
||||||
|
cmd := command.New()
|
||||||
|
|
||||||
|
args := []string{}
|
||||||
|
_, _, err := cmd.Find(args)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Expected no error with empty args, but got: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// When Find fails and args[0] is not "__complete", main would set args to ["eval"] + original args
|
||||||
|
// This is the logic: newArgs := []string{"eval"}
|
||||||
|
// cmd.SetArgs(append(newArgs, os.Args[1:]...))
|
||||||
|
|
||||||
|
args = []string{"invalid"}
|
||||||
|
_, _, err = cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with invalid command")
|
||||||
|
}
|
||||||
|
|
||||||
|
args = []string{"__complete"}
|
||||||
|
_, _, err = cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with __complete command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionExecution(t *testing.T) {
|
||||||
|
// Test that the command can be executed without crashing
|
||||||
|
cmd := command.New()
|
||||||
|
|
||||||
|
cmd.SetArgs([]string{"--version"})
|
||||||
|
|
||||||
|
// We can't easily test os.Exit(1) behaviour, but we can test that
|
||||||
|
// the command structure is correct and can be configured
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatal("Command should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Use != "yq" {
|
||||||
|
t.Errorf("Expected command Use to be 'yq', got %q", cmd.Use)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionErrorHandling(t *testing.T) {
|
||||||
|
// Test the error handling logic that would be in main()
|
||||||
|
cmd := command.New()
|
||||||
|
|
||||||
|
args := []string{"nonexistent-command"}
|
||||||
|
_, _, err := cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with nonexistent command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main function logic would be:
|
||||||
|
// if err != nil && args[0] != "__complete" {
|
||||||
|
// newArgs := []string{"eval"}
|
||||||
|
// cmd.SetArgs(append(newArgs, os.Args[1:]...))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Test that this logic would work
|
||||||
|
if args[0] != "__complete" {
|
||||||
|
// This is what main() would do
|
||||||
|
newArgs := []string{"eval"}
|
||||||
|
cmd.SetArgs(append(newArgs, args...))
|
||||||
|
|
||||||
|
// We can't easily verify the args were set correctly since cmd.Args is a function
|
||||||
|
// But we can test that SetArgs doesn't crash and the command is still valid
|
||||||
|
if cmd == nil {
|
||||||
|
t.Error("Command should not be nil after SetArgs")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err := cmd.Find([]string{"eval"})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Should be able to find eval command after SetArgs: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionWithCompletionCommand(t *testing.T) {
|
||||||
|
// Test that __complete command doesn't trigger default command logic
|
||||||
|
cmd := command.New()
|
||||||
|
|
||||||
|
args := []string{"__complete"}
|
||||||
|
_, _, err := cmd.Find(args)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected error with __complete command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main function logic would be:
|
||||||
|
// if err != nil && args[0] != "__complete" {
|
||||||
|
// // This should NOT execute for __complete
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Verify that __complete doesn't trigger the default command logic
|
||||||
|
if args[0] == "__complete" {
|
||||||
|
// This means the default command logic should NOT execute
|
||||||
|
t.Log("__complete command correctly identified, default command logic should not execute")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainFunctionIntegration(t *testing.T) {
|
||||||
|
// Integration test to verify the main function logic works end-to-end
|
||||||
|
|
||||||
|
cmd := command.New()
|
||||||
|
cmd.SetArgs([]string{"eval", "--help"})
|
||||||
|
|
||||||
|
// This should not crash (we can't test the actual execution due to os.Exit)
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatal("Command should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd2 := command.New()
|
||||||
|
cmd2.SetArgs([]string{"invalid-command"})
|
||||||
|
|
||||||
|
// Simulate the main function logic
|
||||||
|
args := []string{"invalid-command"}
|
||||||
|
_, _, err := cmd2.Find(args)
|
||||||
|
if err != nil {
|
||||||
|
// This is what main() would do
|
||||||
|
newArgs := []string{"eval"}
|
||||||
|
cmd2.SetArgs(append(newArgs, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can't directly access cmd.Args since it's a function, but we can test
|
||||||
|
// that SetArgs worked by ensuring the command is still functional
|
||||||
|
if cmd2 == nil {
|
||||||
|
t.Error("Command should not be nil after SetArgs")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = cmd2.Find([]string{"eval"})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Should be able to find eval command after SetArgs: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user