mirror of
https://github.com/mikefarah/yq.git
synced 2026-03-10 15:54:26 +00:00
* Setting golangci to UK english (that's what we use in AU) * Fixing more spelling * Fixing * Include MD files in spell checker
1436 lines
35 KiB
Go
1436 lines
35 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func TestIsAutomaticOutputFormat(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
format string
|
|
expected bool
|
|
}{
|
|
{"empty format", "", true},
|
|
{"auto format", "auto", true},
|
|
{"short auto format", "a", true},
|
|
{"json format", "json", false},
|
|
{"yaml format", "yaml", false},
|
|
{"xml format", "xml", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original value
|
|
originalFormat := outputFormat
|
|
defer func() { outputFormat = originalFormat }()
|
|
|
|
outputFormat = tt.format
|
|
result := isAutomaticOutputFormat()
|
|
if result != tt.expected {
|
|
t.Errorf("isAutomaticOutputFormat() = %v, want %v", result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMaybeFile(t *testing.T) {
|
|
// Create a temporary file for testing
|
|
tempFile, err := os.CreateTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
// Create a temporary directory for testing
|
|
tempDir, err := os.MkdirTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
tests := []struct {
|
|
name string
|
|
path string
|
|
expected bool
|
|
}{
|
|
{"existing file", tempFile.Name(), true},
|
|
{"existing directory", tempDir, false},
|
|
{"non-existent path", "/path/that/does/not/exist", false},
|
|
{"empty string", "", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := maybeFile(tt.path)
|
|
if result != tt.expected {
|
|
t.Errorf("maybeFile(%q) = %v, want %v", tt.path, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProcessArgs(t *testing.T) {
|
|
// Create a temporary file for testing
|
|
tempFile, err := os.CreateTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
// Create a temporary .yq file for testing
|
|
tempYqFile, err := os.Create("test.yq")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp yq file: %v", err)
|
|
}
|
|
defer os.Remove(tempYqFile.Name())
|
|
if _, err = tempYqFile.WriteString(".a.b"); err != nil {
|
|
t.Fatalf("Failed to write to temp yq file: %v", err)
|
|
}
|
|
tempYqFile.Close()
|
|
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
forceExpression string
|
|
expressionFile string
|
|
expectedExpr string
|
|
expectedArgs []string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "empty args",
|
|
args: []string{},
|
|
forceExpression: "",
|
|
expressionFile: "",
|
|
expectedExpr: "",
|
|
expectedArgs: []string{},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "force expression",
|
|
args: []string{"file1"},
|
|
forceExpression: ".a.b",
|
|
expressionFile: "",
|
|
expectedExpr: ".a.b",
|
|
expectedArgs: []string{"file1"},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "expression as first arg",
|
|
args: []string{".a.b", "file1"},
|
|
forceExpression: "",
|
|
expressionFile: "",
|
|
expectedExpr: ".a.b",
|
|
expectedArgs: []string{"file1"},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "file as first arg",
|
|
args: []string{tempFile.Name()},
|
|
forceExpression: "",
|
|
expressionFile: "",
|
|
expectedExpr: "",
|
|
expectedArgs: []string{tempFile.Name()},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "yq file as first arg",
|
|
args: []string{tempYqFile.Name(), "things"},
|
|
forceExpression: "",
|
|
expressionFile: "",
|
|
expectedExpr: ".a.b",
|
|
expectedArgs: []string{"things"},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "dash as first arg",
|
|
args: []string{"-"},
|
|
forceExpression: "",
|
|
expressionFile: "",
|
|
expectedExpr: "",
|
|
expectedArgs: []string{"-"},
|
|
expectError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalForceExpression := forceExpression
|
|
originalExpressionFile := expressionFile
|
|
defer func() {
|
|
forceExpression = originalForceExpression
|
|
expressionFile = originalExpressionFile
|
|
}()
|
|
|
|
forceExpression = tt.forceExpression
|
|
expressionFile = tt.expressionFile
|
|
|
|
expr, args, err := processArgs(tt.args)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("processArgs() expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("processArgs() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if expr != tt.expectedExpr {
|
|
t.Errorf("processArgs() expression = %v, want %v", expr, tt.expectedExpr)
|
|
}
|
|
|
|
if !stringsEqual(args, tt.expectedArgs) {
|
|
t.Errorf("processArgs() args = %v, want %v", args, tt.expectedArgs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureDecoder(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
inputFormat string
|
|
evaluateTogether bool
|
|
expectError bool
|
|
expectType string
|
|
}{
|
|
{
|
|
name: "yaml format",
|
|
inputFormat: "yaml",
|
|
evaluateTogether: false,
|
|
expectError: false,
|
|
expectType: "yamlDecoder",
|
|
},
|
|
{
|
|
name: "json format",
|
|
inputFormat: "json",
|
|
evaluateTogether: true,
|
|
expectError: false,
|
|
expectType: "jsonDecoder",
|
|
},
|
|
{
|
|
name: "xml format",
|
|
inputFormat: "xml",
|
|
evaluateTogether: false,
|
|
expectError: false,
|
|
expectType: "xmlDecoder",
|
|
},
|
|
{
|
|
name: "invalid format",
|
|
inputFormat: "invalid",
|
|
evaluateTogether: false,
|
|
expectError: true,
|
|
expectType: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original value
|
|
originalInputFormat := inputFormat
|
|
defer func() { inputFormat = originalInputFormat }()
|
|
|
|
inputFormat = tt.inputFormat
|
|
|
|
decoder, err := configureDecoder(tt.evaluateTogether)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("configureDecoder() expected error but got none")
|
|
}
|
|
if decoder != nil {
|
|
t.Errorf("configureDecoder() expected nil decoder but got %v", decoder)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("configureDecoder() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if decoder == nil {
|
|
t.Errorf("configureDecoder() expected decoder but got nil")
|
|
return
|
|
}
|
|
|
|
typeStr := fmt.Sprintf("%T", decoder)
|
|
if !strings.Contains(typeStr, tt.expectType) {
|
|
t.Errorf("configureDecoder() expected type to contain %q but got %q", tt.expectType, typeStr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigurePrinterWriter(t *testing.T) {
|
|
yqlib.InitExpressionParser()
|
|
|
|
tests := []struct {
|
|
name string
|
|
splitFileExp string
|
|
format *yqlib.Format
|
|
forceColor bool
|
|
expectError bool
|
|
expectMulti bool
|
|
expectColorsEnabled bool
|
|
}{
|
|
{
|
|
name: "single printer writer",
|
|
splitFileExp: "",
|
|
format: &yqlib.Format{},
|
|
forceColor: false,
|
|
expectError: false,
|
|
expectMulti: false,
|
|
expectColorsEnabled: false,
|
|
},
|
|
{
|
|
name: "multi printer writer with valid expression",
|
|
splitFileExp: ".a.b",
|
|
format: &yqlib.Format{},
|
|
forceColor: true,
|
|
expectError: false,
|
|
expectMulti: true,
|
|
expectColorsEnabled: true,
|
|
},
|
|
{
|
|
name: "multi printer writer with invalid expression",
|
|
splitFileExp: "[invalid",
|
|
format: &yqlib.Format{},
|
|
forceColor: false,
|
|
expectError: true,
|
|
expectMulti: false,
|
|
expectColorsEnabled: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalSplitFileExp := splitFileExp
|
|
originalForceColor := forceColor
|
|
originalColorsEnabled := colorsEnabled
|
|
defer func() {
|
|
splitFileExp = originalSplitFileExp
|
|
forceColor = originalForceColor
|
|
colorsEnabled = originalColorsEnabled
|
|
}()
|
|
|
|
splitFileExp = tt.splitFileExp
|
|
forceColor = tt.forceColor
|
|
colorsEnabled = false // Reset to test the setting
|
|
|
|
writer, err := configurePrinterWriter(tt.format, os.Stdout)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("configurePrinterWriter() expected error but got none")
|
|
}
|
|
if writer != nil {
|
|
t.Errorf("configurePrinterWriter() expected nil writer but got %v", writer)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("configurePrinterWriter() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if writer == nil {
|
|
t.Errorf("configurePrinterWriter() expected writer but got nil")
|
|
return
|
|
}
|
|
|
|
// Explicitly check colorsEnabled
|
|
if colorsEnabled != tt.expectColorsEnabled {
|
|
t.Errorf("configurePrinterWriter() colorsEnabled = %v, want %v", colorsEnabled, tt.expectColorsEnabled)
|
|
}
|
|
|
|
// Check the type of the returned writer
|
|
writerType := fmt.Sprintf("%T", writer)
|
|
if tt.expectMulti {
|
|
if !strings.Contains(writerType, "multiPrintWriter") {
|
|
t.Errorf("configurePrinterWriter() expected multiPrintWriter but got %s", writerType)
|
|
}
|
|
} else {
|
|
if !strings.Contains(writerType, "singlePrinterWriter") {
|
|
t.Errorf("configurePrinterWriter() expected singlePrinterWriter but got %s", writerType)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureEncoder(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
outputFormat string
|
|
expectError bool
|
|
expectType string
|
|
}{
|
|
{
|
|
name: "yaml format",
|
|
outputFormat: "yaml",
|
|
expectError: false,
|
|
expectType: "yamlEncoder",
|
|
},
|
|
{
|
|
name: "json format",
|
|
outputFormat: "json",
|
|
expectError: false,
|
|
expectType: "jsonEncoder",
|
|
},
|
|
{
|
|
name: "xml format",
|
|
outputFormat: "xml",
|
|
expectError: false,
|
|
expectType: "xmlEncoder",
|
|
},
|
|
{
|
|
name: "properties format",
|
|
outputFormat: "properties",
|
|
expectError: false,
|
|
expectType: "propertiesEncoder",
|
|
},
|
|
{
|
|
name: "invalid format",
|
|
outputFormat: "invalid",
|
|
expectError: true,
|
|
expectType: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalOutputFormat := outputFormat
|
|
originalIndent := indent
|
|
originalUnwrapScalar := unwrapScalar
|
|
originalColorsEnabled := colorsEnabled
|
|
originalNoDocSeparators := noDocSeparators
|
|
defer func() {
|
|
outputFormat = originalOutputFormat
|
|
indent = originalIndent
|
|
unwrapScalar = originalUnwrapScalar
|
|
colorsEnabled = originalColorsEnabled
|
|
noDocSeparators = originalNoDocSeparators
|
|
}()
|
|
|
|
outputFormat = tt.outputFormat
|
|
indent = 2
|
|
unwrapScalar = false
|
|
colorsEnabled = false
|
|
noDocSeparators = false
|
|
|
|
encoder, err := configureEncoder()
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("configureEncoder() expected error but got none")
|
|
}
|
|
if encoder != nil {
|
|
t.Errorf("configureEncoder() expected nil encoder but got %v", encoder)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("configureEncoder() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if encoder == nil {
|
|
t.Errorf("configureEncoder() expected encoder but got nil")
|
|
return
|
|
}
|
|
|
|
typeStr := fmt.Sprintf("%T", encoder)
|
|
if !strings.Contains(typeStr, tt.expectType) {
|
|
t.Errorf("configureEncoder() expected type to contain %q but got %q", tt.expectType, typeStr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInitCommand(t *testing.T) {
|
|
// Create a temporary file for testing
|
|
tempFile, err := os.CreateTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
// Create a temporary split file
|
|
tempSplitFile, err := os.CreateTemp("", "split")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp split file: %v", err)
|
|
}
|
|
defer os.Remove(tempSplitFile.Name())
|
|
if _, err = tempSplitFile.WriteString(".a.b"); err != nil {
|
|
t.Fatalf("Failed to write to temp split file: %v", err)
|
|
}
|
|
tempSplitFile.Close()
|
|
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
writeInplace bool
|
|
frontMatter string
|
|
nullInput bool
|
|
splitFileExpFile string
|
|
splitFileExp string
|
|
outputToJSON bool
|
|
expectError bool
|
|
errorContains string
|
|
expectExpr string
|
|
expectArgs []string
|
|
}{
|
|
{
|
|
name: "basic command",
|
|
args: []string{tempFile.Name()},
|
|
writeInplace: false,
|
|
frontMatter: "",
|
|
nullInput: false,
|
|
expectError: false,
|
|
expectExpr: "",
|
|
expectArgs: []string{tempFile.Name()},
|
|
},
|
|
{
|
|
name: "write inplace with no args",
|
|
args: []string{},
|
|
writeInplace: true,
|
|
frontMatter: "",
|
|
nullInput: false,
|
|
expectError: true,
|
|
errorContains: "write in place flag only applicable when giving an expression and at least one file",
|
|
},
|
|
{
|
|
name: "split file expression from file",
|
|
args: []string{tempFile.Name()},
|
|
writeInplace: false,
|
|
frontMatter: "",
|
|
nullInput: false,
|
|
splitFileExpFile: tempSplitFile.Name(),
|
|
expectError: false,
|
|
expectExpr: "",
|
|
expectArgs: []string{tempFile.Name()},
|
|
},
|
|
{
|
|
name: "output to JSON",
|
|
args: []string{tempFile.Name()},
|
|
writeInplace: false,
|
|
frontMatter: "",
|
|
nullInput: false,
|
|
outputToJSON: true,
|
|
expectError: false,
|
|
expectExpr: "",
|
|
expectArgs: []string{tempFile.Name()},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalWriteInplace := writeInplace
|
|
originalFrontMatter := frontMatter
|
|
originalNullInput := nullInput
|
|
originalSplitFileExpFile := splitFileExpFile
|
|
originalSplitFileExp := splitFileExp
|
|
originalOutputToJSON := outputToJSON
|
|
originalInputFormat := inputFormat
|
|
originalOutputFormat := outputFormat
|
|
originalForceColor := forceColor
|
|
originalForceNoColor := forceNoColor
|
|
originalColorsEnabled := colorsEnabled
|
|
defer func() {
|
|
writeInplace = originalWriteInplace
|
|
frontMatter = originalFrontMatter
|
|
nullInput = originalNullInput
|
|
splitFileExpFile = originalSplitFileExpFile
|
|
splitFileExp = originalSplitFileExp
|
|
outputToJSON = originalOutputToJSON
|
|
inputFormat = originalInputFormat
|
|
outputFormat = originalOutputFormat
|
|
forceColor = originalForceColor
|
|
forceNoColor = originalForceNoColor
|
|
colorsEnabled = originalColorsEnabled
|
|
}()
|
|
|
|
writeInplace = tt.writeInplace
|
|
frontMatter = tt.frontMatter
|
|
nullInput = tt.nullInput
|
|
splitFileExpFile = tt.splitFileExpFile
|
|
splitFileExp = tt.splitFileExp
|
|
outputToJSON = tt.outputToJSON
|
|
inputFormat = "auto"
|
|
outputFormat = "auto"
|
|
forceColor = false
|
|
forceNoColor = false
|
|
colorsEnabled = false
|
|
|
|
cmd := &cobra.Command{}
|
|
expr, args, err := initCommand(cmd, tt.args)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("initCommand() expected error but got none")
|
|
return
|
|
}
|
|
if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
|
|
t.Errorf("initCommand() error '%v' does not contain '%v'", err.Error(), tt.errorContains)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("initCommand() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if expr != tt.expectExpr {
|
|
t.Errorf("initCommand() expr = %v, want %v", expr, tt.expectExpr)
|
|
}
|
|
if !stringsEqual(args, tt.expectArgs) {
|
|
t.Errorf("initCommand() args = %v, want %v", args, tt.expectArgs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProcessArgsWithExpressionFile(t *testing.T) {
|
|
// Create a temporary .yq file with Windows line endings
|
|
tempYqFile, err := os.CreateTemp("", "test.yq")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp yq file: %v", err)
|
|
}
|
|
defer os.Remove(tempYqFile.Name())
|
|
if _, err = tempYqFile.WriteString(".a.b\r\n.c.d"); err != nil {
|
|
t.Fatalf("Failed to write to temp yq file: %v", err)
|
|
}
|
|
tempYqFile.Close()
|
|
|
|
// Save original values
|
|
originalExpressionFile := expressionFile
|
|
defer func() { expressionFile = originalExpressionFile }()
|
|
|
|
expressionFile = tempYqFile.Name()
|
|
|
|
expr, args, err := processArgs([]string{"file1"})
|
|
if err != nil {
|
|
t.Errorf("processArgs() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
expectedExpr := ".a.b\n.c.d" // Should convert \r\n to \n
|
|
if expr != expectedExpr {
|
|
t.Errorf("processArgs() expression = %v, want %v", expr, expectedExpr)
|
|
}
|
|
|
|
expectedArgs := []string{"file1"}
|
|
if !stringsEqual(args, expectedArgs) {
|
|
t.Errorf("processArgs() args = %v, want %v", args, expectedArgs)
|
|
}
|
|
}
|
|
|
|
func TestProcessArgsWithNonExistentExpressionFile(t *testing.T) {
|
|
// Save original values
|
|
originalExpressionFile := expressionFile
|
|
defer func() { expressionFile = originalExpressionFile }()
|
|
|
|
expressionFile = "/path/that/does/not/exist"
|
|
|
|
expr, args, err := processArgs([]string{"file1"})
|
|
if err == nil {
|
|
t.Errorf("processArgs() expected error but got none")
|
|
}
|
|
if expr != "" {
|
|
t.Errorf("processArgs() expected empty expression but got %v", expr)
|
|
}
|
|
if args != nil {
|
|
t.Errorf("processArgs() expected nil args but got %v", args)
|
|
}
|
|
}
|
|
|
|
func TestInitCommandWithInvalidOutputFormat(t *testing.T) {
|
|
// Create a temporary file for testing
|
|
tempFile, err := os.CreateTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
// Save original values
|
|
originalInputFormat := inputFormat
|
|
originalOutputFormat := outputFormat
|
|
defer func() {
|
|
inputFormat = originalInputFormat
|
|
outputFormat = originalOutputFormat
|
|
}()
|
|
|
|
inputFormat = "auto"
|
|
outputFormat = "invalid"
|
|
|
|
cmd := &cobra.Command{}
|
|
expr, args, err := initCommand(cmd, []string{tempFile.Name()})
|
|
if err == nil {
|
|
t.Errorf("initCommand() expected error but got none")
|
|
}
|
|
if expr != "" {
|
|
t.Errorf("initCommand() expected empty expression but got %v", expr)
|
|
}
|
|
if args != nil {
|
|
t.Errorf("initCommand() expected nil args but got %v", args)
|
|
}
|
|
}
|
|
|
|
func TestInitCommandWithUnknownInputFormat(t *testing.T) {
|
|
// Create a temporary file with unknown extension
|
|
tempFile, err := os.CreateTemp("", "test.unknown")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
tempFile.Close()
|
|
|
|
// Save original values
|
|
originalInputFormat := inputFormat
|
|
originalOutputFormat := outputFormat
|
|
defer func() {
|
|
inputFormat = originalInputFormat
|
|
outputFormat = originalOutputFormat
|
|
}()
|
|
|
|
inputFormat = "auto"
|
|
outputFormat = "auto"
|
|
|
|
cmd := &cobra.Command{}
|
|
expr, args, err := initCommand(cmd, []string{tempFile.Name()})
|
|
if err != nil {
|
|
t.Errorf("initCommand() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
// expr can be empty when no expression is provided
|
|
_ = expr
|
|
if args == nil {
|
|
t.Errorf("initCommand() expected non-nil args")
|
|
}
|
|
}
|
|
|
|
func TestConfigurePrinterWriterWithInvalidSplitExpression(t *testing.T) {
|
|
// Save original value
|
|
originalSplitFileExp := splitFileExp
|
|
defer func() { splitFileExp = originalSplitFileExp }()
|
|
|
|
splitFileExp = "[invalid expression"
|
|
|
|
writer, err := configurePrinterWriter(&yqlib.Format{}, os.Stdout)
|
|
if err == nil {
|
|
t.Errorf("configurePrinterWriter() expected error but got none")
|
|
}
|
|
if writer != nil {
|
|
t.Errorf("configurePrinterWriter() expected nil writer but got %v", writer)
|
|
}
|
|
if err != nil && !strings.Contains(err.Error(), "bad split document expression") {
|
|
t.Errorf("configurePrinterWriter() error '%v' does not contain expected message", err.Error())
|
|
}
|
|
}
|
|
|
|
func TestMaybeFileWithDirectory(t *testing.T) {
|
|
// Create a temporary directory
|
|
tempDir, err := os.MkdirTemp("", "test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
result := maybeFile(tempDir)
|
|
if result {
|
|
t.Errorf("maybeFile(%q) = %v, want false", tempDir, result)
|
|
}
|
|
}
|
|
|
|
func TestProcessStdInArgsWithDash(t *testing.T) {
|
|
args := []string{"-", "file1"}
|
|
result := processStdInArgs(args)
|
|
if !stringsEqual(result, args) {
|
|
t.Errorf("processStdInArgs() = %v, want %v", result, args)
|
|
}
|
|
}
|
|
|
|
func TestProcessArgsWithYqFileExtension(t *testing.T) {
|
|
tempYqFile, err := os.Create("test.yq")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp yq file: %v", err)
|
|
}
|
|
defer os.Remove(tempYqFile.Name())
|
|
if _, err = tempYqFile.WriteString(".a.b"); err != nil {
|
|
t.Fatalf("Failed to write to temp yq file: %v", err)
|
|
}
|
|
tempYqFile.Close()
|
|
|
|
// Save original values
|
|
originalExpressionFile := expressionFile
|
|
originalForceExpression := forceExpression
|
|
defer func() {
|
|
expressionFile = originalExpressionFile
|
|
forceExpression = originalForceExpression
|
|
}()
|
|
|
|
// Reset expressionFile to empty to test the auto-detection
|
|
expressionFile = ""
|
|
forceExpression = ""
|
|
|
|
// Debug: check the conditions manually
|
|
t.Logf("expressionFile: %q", expressionFile)
|
|
t.Logf("forceExpression: %q", forceExpression)
|
|
t.Logf("tempYqFile.Name(): %q", tempYqFile.Name())
|
|
t.Logf("strings.HasSuffix(tempYqFile.Name(), '.yq'): %v", strings.HasSuffix(tempYqFile.Name(), ".yq"))
|
|
t.Logf("maybeFile(tempYqFile.Name()): %v", maybeFile(tempYqFile.Name()))
|
|
|
|
// Test with only the yq file as argument (should be treated as expression file)
|
|
expr, args, err := processArgs([]string{tempYqFile.Name()})
|
|
if err != nil {
|
|
t.Errorf("processArgs() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if expr != ".a.b" {
|
|
t.Errorf("processArgs() expression = %v, want .a.b", expr)
|
|
}
|
|
|
|
expectedArgs := []string{}
|
|
if !stringsEqual(args, expectedArgs) {
|
|
t.Errorf("processArgs() args = %v, want %v", args, expectedArgs)
|
|
}
|
|
}
|
|
|
|
func TestConfigureEncoderWithYamlFormat(t *testing.T) {
|
|
// Save original values
|
|
originalOutputFormat := outputFormat
|
|
originalIndent := indent
|
|
originalUnwrapScalar := unwrapScalar
|
|
originalColorsEnabled := colorsEnabled
|
|
originalNoDocSeparators := noDocSeparators
|
|
defer func() {
|
|
outputFormat = originalOutputFormat
|
|
indent = originalIndent
|
|
unwrapScalar = originalUnwrapScalar
|
|
colorsEnabled = originalColorsEnabled
|
|
noDocSeparators = originalNoDocSeparators
|
|
}()
|
|
|
|
outputFormat = "yaml"
|
|
indent = 4
|
|
unwrapScalar = true
|
|
colorsEnabled = true
|
|
noDocSeparators = true
|
|
|
|
encoder, err := configureEncoder()
|
|
if err != nil {
|
|
t.Errorf("configureEncoder() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if encoder == nil {
|
|
t.Errorf("configureEncoder() expected encoder but got nil")
|
|
}
|
|
}
|
|
|
|
func TestConfigureEncoderWithPropertiesFormat(t *testing.T) {
|
|
// Save original values
|
|
originalOutputFormat := outputFormat
|
|
originalIndent := indent
|
|
originalUnwrapScalar := unwrapScalar
|
|
originalColorsEnabled := colorsEnabled
|
|
originalNoDocSeparators := noDocSeparators
|
|
defer func() {
|
|
outputFormat = originalOutputFormat
|
|
indent = originalIndent
|
|
unwrapScalar = originalUnwrapScalar
|
|
colorsEnabled = originalColorsEnabled
|
|
noDocSeparators = originalNoDocSeparators
|
|
}()
|
|
|
|
outputFormat = "properties"
|
|
indent = 2
|
|
unwrapScalar = false
|
|
colorsEnabled = false
|
|
noDocSeparators = false
|
|
|
|
encoder, err := configureEncoder()
|
|
if err != nil {
|
|
t.Errorf("configureEncoder() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if encoder == nil {
|
|
t.Errorf("configureEncoder() expected encoder but got nil")
|
|
}
|
|
}
|
|
|
|
// Mock boolFlag for testing
|
|
type mockBoolFlag struct {
|
|
explicitlySet bool
|
|
value bool
|
|
}
|
|
|
|
func (f *mockBoolFlag) IsExplicitlySet() bool {
|
|
return f.explicitlySet
|
|
}
|
|
|
|
func (f *mockBoolFlag) IsSet() bool {
|
|
return f.value
|
|
}
|
|
|
|
func (f *mockBoolFlag) String() string {
|
|
return "mock"
|
|
}
|
|
|
|
func (f *mockBoolFlag) Set(_ string) error {
|
|
return nil
|
|
}
|
|
|
|
func (f *mockBoolFlag) Type() string {
|
|
return "bool"
|
|
}
|
|
|
|
// Helper function to compare string slices
|
|
func stringsEqual(a, b []string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := range a {
|
|
if a[i] != b[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestSetupColors(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
forceColor bool
|
|
forceNoColor bool
|
|
expectColors bool
|
|
}{
|
|
{
|
|
name: "force colour enabled",
|
|
forceColor: true,
|
|
forceNoColor: false,
|
|
expectColors: true,
|
|
},
|
|
{
|
|
name: "force no colour enabled",
|
|
forceColor: false,
|
|
forceNoColor: true,
|
|
expectColors: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalForceColor := forceColor
|
|
originalForceNoColor := forceNoColor
|
|
originalColorsEnabled := colorsEnabled
|
|
defer func() {
|
|
forceColor = originalForceColor
|
|
forceNoColor = originalForceNoColor
|
|
colorsEnabled = originalColorsEnabled
|
|
}()
|
|
|
|
forceColor = tt.forceColor
|
|
forceNoColor = tt.forceNoColor
|
|
colorsEnabled = false // Reset to test the setting
|
|
|
|
setupColors()
|
|
|
|
if colorsEnabled != tt.expectColors {
|
|
t.Errorf("setupColors() colorsEnabled = %v, want %v", colorsEnabled, tt.expectColors)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadSplitFileExpression(t *testing.T) {
|
|
// Create a temporary file with expression content
|
|
tempFile, err := os.CreateTemp("", "split")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp file: %v", err)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
if _, err = tempFile.WriteString(".a.b"); err != nil {
|
|
t.Fatalf("Failed to write to temp file: %v", err)
|
|
}
|
|
tempFile.Close()
|
|
|
|
tests := []struct {
|
|
name string
|
|
splitFileExpFile string
|
|
expectError bool
|
|
expectContent string
|
|
}{
|
|
{
|
|
name: "load from file",
|
|
splitFileExpFile: tempFile.Name(),
|
|
expectError: false,
|
|
expectContent: ".a.b",
|
|
},
|
|
{
|
|
name: "no file specified",
|
|
splitFileExpFile: "",
|
|
expectError: false,
|
|
expectContent: "",
|
|
},
|
|
{
|
|
name: "non-existent file",
|
|
splitFileExpFile: "/path/that/does/not/exist",
|
|
expectError: true,
|
|
expectContent: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original value
|
|
originalSplitFileExpFile := splitFileExpFile
|
|
originalSplitFileExp := splitFileExp
|
|
defer func() {
|
|
splitFileExpFile = originalSplitFileExpFile
|
|
splitFileExp = originalSplitFileExp
|
|
}()
|
|
|
|
splitFileExpFile = tt.splitFileExpFile
|
|
splitFileExp = ""
|
|
|
|
err := loadSplitFileExpression()
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("loadSplitFileExpression() expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("loadSplitFileExpression() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if splitFileExp != tt.expectContent {
|
|
t.Errorf("loadSplitFileExpression() splitFileExp = %v, want %v", splitFileExp, tt.expectContent)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestHandleBackwardsCompatibility(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
outputToJSON bool
|
|
initialFormat string
|
|
expectFormat string
|
|
}{
|
|
{
|
|
name: "outputToJSON true",
|
|
outputToJSON: true,
|
|
initialFormat: "yaml",
|
|
expectFormat: "json",
|
|
},
|
|
{
|
|
name: "outputToJSON false",
|
|
outputToJSON: false,
|
|
initialFormat: "yaml",
|
|
expectFormat: "yaml",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original value
|
|
originalOutputToJSON := outputToJSON
|
|
originalOutputFormat := outputFormat
|
|
defer func() {
|
|
outputToJSON = originalOutputToJSON
|
|
outputFormat = originalOutputFormat
|
|
}()
|
|
|
|
outputToJSON = tt.outputToJSON
|
|
outputFormat = tt.initialFormat
|
|
|
|
handleBackwardsCompatibility()
|
|
|
|
if outputFormat != tt.expectFormat {
|
|
t.Errorf("handleBackwardsCompatibility() outputFormat = %v, want %v", outputFormat, tt.expectFormat)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateCommandFlags(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
writeInplace bool
|
|
frontMatter string
|
|
splitFileExp string
|
|
nullInput bool
|
|
expectError bool
|
|
errorContains string
|
|
}{
|
|
{
|
|
name: "valid flags",
|
|
args: []string{"file.yaml"},
|
|
writeInplace: false,
|
|
frontMatter: "",
|
|
splitFileExp: "",
|
|
nullInput: false,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "write inplace with no args",
|
|
args: []string{},
|
|
writeInplace: true,
|
|
frontMatter: "",
|
|
splitFileExp: "",
|
|
nullInput: false,
|
|
expectError: true,
|
|
errorContains: "write in place flag only applicable when giving an expression and at least one file",
|
|
},
|
|
{
|
|
name: "write inplace with dash",
|
|
args: []string{"-"},
|
|
writeInplace: true,
|
|
frontMatter: "",
|
|
splitFileExp: "",
|
|
nullInput: false,
|
|
expectError: true,
|
|
errorContains: "write in place flag only applicable when giving an expression and at least one file",
|
|
},
|
|
{
|
|
name: "front matter with no args",
|
|
args: []string{},
|
|
writeInplace: false,
|
|
frontMatter: "extract",
|
|
splitFileExp: "",
|
|
nullInput: false,
|
|
expectError: true,
|
|
errorContains: "front matter flag only applicable when giving an expression and at least one file",
|
|
},
|
|
{
|
|
name: "write inplace with split file",
|
|
args: []string{"file.yaml"},
|
|
writeInplace: true,
|
|
frontMatter: "",
|
|
splitFileExp: ".a.b",
|
|
nullInput: false,
|
|
expectError: true,
|
|
errorContains: "write in place cannot be used with split file",
|
|
},
|
|
{
|
|
name: "null input with args",
|
|
args: []string{"file.yaml"},
|
|
writeInplace: false,
|
|
frontMatter: "",
|
|
splitFileExp: "",
|
|
nullInput: true,
|
|
expectError: true,
|
|
errorContains: "cannot pass files in when using null-input flag",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalWriteInplace := writeInplace
|
|
originalFrontMatter := frontMatter
|
|
originalSplitFileExp := splitFileExp
|
|
originalNullInput := nullInput
|
|
defer func() {
|
|
writeInplace = originalWriteInplace
|
|
frontMatter = originalFrontMatter
|
|
splitFileExp = originalSplitFileExp
|
|
nullInput = originalNullInput
|
|
}()
|
|
|
|
writeInplace = tt.writeInplace
|
|
frontMatter = tt.frontMatter
|
|
splitFileExp = tt.splitFileExp
|
|
nullInput = tt.nullInput
|
|
|
|
err := validateCommandFlags(tt.args)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("validateCommandFlags() expected error but got none")
|
|
return
|
|
}
|
|
if tt.errorContains != "" && !strings.Contains(err.Error(), tt.errorContains) {
|
|
t.Errorf("validateCommandFlags() error '%v' does not contain '%v'", err.Error(), tt.errorContains)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("validateCommandFlags() unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureFormats(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
args []string
|
|
inputFormat string
|
|
outputFormat string
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "valid formats",
|
|
args: []string{"file.yaml"},
|
|
inputFormat: "auto",
|
|
outputFormat: "auto",
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "invalid output format",
|
|
args: []string{"file.yaml"},
|
|
inputFormat: "auto",
|
|
outputFormat: "invalid",
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalInputFormat := inputFormat
|
|
originalOutputFormat := outputFormat
|
|
defer func() {
|
|
inputFormat = originalInputFormat
|
|
outputFormat = originalOutputFormat
|
|
}()
|
|
|
|
inputFormat = tt.inputFormat
|
|
outputFormat = tt.outputFormat
|
|
|
|
err := configureFormats(tt.args)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("configureFormats() expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("configureFormats() unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureInputFormat(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
inputFilename string
|
|
inputFormat string
|
|
outputFormat string
|
|
expectInput string
|
|
expectOutput string
|
|
}{
|
|
{
|
|
name: "auto format with yaml file",
|
|
inputFilename: "file.yaml",
|
|
inputFormat: "auto",
|
|
outputFormat: "auto",
|
|
expectInput: "yaml",
|
|
expectOutput: "yaml",
|
|
},
|
|
{
|
|
name: "auto format with json file",
|
|
inputFilename: "file.json",
|
|
inputFormat: "auto",
|
|
outputFormat: "auto",
|
|
expectInput: "json",
|
|
expectOutput: "json",
|
|
},
|
|
{
|
|
name: "auto format with unknown file",
|
|
inputFilename: "file.unknown",
|
|
inputFormat: "auto",
|
|
outputFormat: "auto",
|
|
expectInput: "yaml",
|
|
expectOutput: "yaml",
|
|
},
|
|
{
|
|
name: "explicit format",
|
|
inputFilename: "file.yaml",
|
|
inputFormat: "json",
|
|
outputFormat: "auto",
|
|
expectInput: "json",
|
|
expectOutput: "yaml", // backwards compatibility
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalInputFormat := inputFormat
|
|
originalOutputFormat := outputFormat
|
|
defer func() {
|
|
inputFormat = originalInputFormat
|
|
outputFormat = originalOutputFormat
|
|
}()
|
|
|
|
inputFormat = tt.inputFormat
|
|
outputFormat = tt.outputFormat
|
|
|
|
err := configureInputFormat(tt.inputFilename)
|
|
if err != nil {
|
|
t.Errorf("configureInputFormat() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if inputFormat != tt.expectInput {
|
|
t.Errorf("configureInputFormat() inputFormat = %v, want %v", inputFormat, tt.expectInput)
|
|
}
|
|
if outputFormat != tt.expectOutput {
|
|
t.Errorf("configureInputFormat() outputFormat = %v, want %v", outputFormat, tt.expectOutput)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureOutputFormat(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
outputFormat string
|
|
expectError bool
|
|
expectUnwrap bool
|
|
}{
|
|
{
|
|
name: "yaml format",
|
|
outputFormat: "yaml",
|
|
expectError: false,
|
|
expectUnwrap: true,
|
|
},
|
|
{
|
|
name: "properties format",
|
|
outputFormat: "properties",
|
|
expectError: false,
|
|
expectUnwrap: true,
|
|
},
|
|
{
|
|
name: "json format",
|
|
outputFormat: "json",
|
|
expectError: false,
|
|
expectUnwrap: false,
|
|
},
|
|
{
|
|
name: "invalid format",
|
|
outputFormat: "invalid",
|
|
expectError: true,
|
|
expectUnwrap: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original values
|
|
originalOutputFormat := outputFormat
|
|
originalUnwrapScalar := unwrapScalar
|
|
defer func() {
|
|
outputFormat = originalOutputFormat
|
|
unwrapScalar = originalUnwrapScalar
|
|
}()
|
|
|
|
outputFormat = tt.outputFormat
|
|
unwrapScalar = false // Reset to test the setting
|
|
|
|
err := configureOutputFormat()
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("configureOutputFormat() expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("configureOutputFormat() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if unwrapScalar != tt.expectUnwrap {
|
|
t.Errorf("configureOutputFormat() unwrapScalar = %v, want %v", unwrapScalar, tt.expectUnwrap)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigureUnwrapScalar(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
explicitlySet bool
|
|
flagValue bool
|
|
initialUnwrap bool
|
|
expectUnwrap bool
|
|
}{
|
|
{
|
|
name: "flag not explicitly set",
|
|
explicitlySet: false,
|
|
flagValue: true,
|
|
initialUnwrap: true,
|
|
expectUnwrap: true, // Should remain unchanged
|
|
},
|
|
{
|
|
name: "flag explicitly set to true",
|
|
explicitlySet: true,
|
|
flagValue: true,
|
|
initialUnwrap: false,
|
|
expectUnwrap: true,
|
|
},
|
|
{
|
|
name: "flag explicitly set to false",
|
|
explicitlySet: true,
|
|
flagValue: false,
|
|
initialUnwrap: true,
|
|
expectUnwrap: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Save original value
|
|
originalUnwrapScalar := unwrapScalar
|
|
originalUnwrapScalarFlag := unwrapScalarFlag
|
|
defer func() {
|
|
unwrapScalar = originalUnwrapScalar
|
|
unwrapScalarFlag = originalUnwrapScalarFlag
|
|
}()
|
|
|
|
unwrapScalar = tt.initialUnwrap
|
|
unwrapScalarFlag = &mockBoolFlag{
|
|
explicitlySet: tt.explicitlySet,
|
|
value: tt.flagValue,
|
|
}
|
|
|
|
configureUnwrapScalar()
|
|
|
|
if unwrapScalar != tt.expectUnwrap {
|
|
t.Errorf("configureUnwrapScalar() unwrapScalar = %v, want %v", unwrapScalar, tt.expectUnwrap)
|
|
}
|
|
})
|
|
}
|
|
}
|