@@ -3,7 +3,10 @@ package cmd
33import (
44 "fmt"
55 "os"
6+ "path/filepath"
7+ "runtime"
68 "strings"
9+ "syscall"
710 "testing"
811
912 "github.com/mikefarah/yq/v4/pkg/yqlib"
@@ -964,6 +967,103 @@ func TestSetupColors(t *testing.T) {
964967 }
965968}
966969
970+ // terminalCase is a file/device to test setupColors against, paired with
971+ // whether it should be treated as an interactive terminal - so what does
972+ // and doesn't get colourised output is visible in a single place.
973+ type terminalCase struct {
974+ open func (t * testing.T ) * os.File
975+ isTerm bool
976+ }
977+
978+ func terminalTestCases () map [string ]terminalCase {
979+ return map [string ]terminalCase {
980+ "regular file" : {isTerm : false , open : func (t * testing.T ) * os.File {
981+ f , err := os .CreateTemp (t .TempDir (), "isterminal" )
982+ if err != nil {
983+ t .Fatalf ("failed to create temp file: %v" , err )
984+ }
985+ return f
986+ }},
987+ "/dev/null" : {isTerm : false , open : func (t * testing.T ) * os.File {
988+ f , err := os .OpenFile (os .DevNull , os .O_RDWR , 0644 )
989+ if err != nil {
990+ t .Fatalf ("failed to open %s: %v" , os .DevNull , err )
991+ }
992+ return f
993+ }},
994+ "unnamed pipe, read end" : {isTerm : false , open : func (t * testing.T ) * os.File {
995+ r , w , err := os .Pipe ()
996+ if err != nil {
997+ t .Fatalf ("failed to create pipe: %v" , err )
998+ }
999+ w .Close ()
1000+ return r
1001+ }},
1002+ "unnamed pipe, write end (e.g. piped to a pager)" : {isTerm : false , open : func (t * testing.T ) * os.File {
1003+ r , w , err := os .Pipe ()
1004+ if err != nil {
1005+ t .Fatalf ("failed to create pipe: %v" , err )
1006+ }
1007+ r .Close ()
1008+ return w
1009+ }},
1010+ "named pipe (FIFO)" : {isTerm : false , open : func (t * testing.T ) * os.File {
1011+ if runtime .GOOS == "windows" {
1012+ t .Skip ("named pipes not supported by this test on windows" )
1013+ }
1014+ path := filepath .Join (t .TempDir (), "fifo" )
1015+ if err := syscall .Mkfifo (path , 0600 ); err != nil {
1016+ t .Fatalf ("failed to create named pipe: %v" , err )
1017+ }
1018+ // O_RDWR avoids blocking on open: a FIFO opened only for reading
1019+ // (or only writing) blocks until a peer opens the other end.
1020+ f , err := os .OpenFile (path , os .O_RDWR , os .ModeNamedPipe )
1021+ if err != nil {
1022+ t .Fatalf ("failed to open named pipe: %v" , err )
1023+ }
1024+ return f
1025+ }},
1026+ "controlling terminal (/dev/tty)" : {isTerm : true , open : func (t * testing.T ) * os.File {
1027+ f , err := os .OpenFile ("/dev/tty" , os .O_RDWR , 0 )
1028+ if err != nil {
1029+ t .Skipf ("no controlling terminal available in this environment: %v" , err )
1030+ }
1031+ return f
1032+ }},
1033+ }
1034+ }
1035+
1036+ func TestSetupColorsForFileKind (t * testing.T ) {
1037+ for name , tc := range terminalTestCases () {
1038+ t .Run (name , func (t * testing.T ) {
1039+ f := tc .open (t )
1040+ defer f .Close ()
1041+
1042+ originalStdout := os .Stdout
1043+ originalForceColor := forceColor
1044+ originalForceNoColor := forceNoColor
1045+ originalColorsEnabled := colorsEnabled
1046+ defer func () {
1047+ os .Stdout = originalStdout
1048+ forceColor = originalForceColor
1049+ forceNoColor = originalForceNoColor
1050+ colorsEnabled = originalColorsEnabled
1051+ }()
1052+
1053+ os .Stdout = f
1054+ forceColor = false
1055+ forceNoColor = false
1056+ colorsEnabled = false
1057+
1058+ setupColors ()
1059+
1060+ if colorsEnabled != tc .isTerm {
1061+ t .Errorf ("setupColors() colorsEnabled = %v, want %v for %s" , colorsEnabled , tc .isTerm , name )
1062+ }
1063+ })
1064+ }
1065+ }
1066+
9671067func TestLoadSplitFileExpression (t * testing.T ) {
9681068 // Create a temporary file with expression content
9691069 tempFile , err := os .CreateTemp ("" , "split" )
0 commit comments