github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/prog/prog_test.go (about)

     1  package prog_test
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	. "github.com/markusbkk/elvish/pkg/prog"
     9  	"github.com/markusbkk/elvish/pkg/prog/progtest"
    10  	"github.com/markusbkk/elvish/pkg/testutil"
    11  )
    12  
    13  var (
    14  	Test       = progtest.Test
    15  	ThatElvish = progtest.ThatElvish
    16  )
    17  
    18  func TestFlagHandling(t *testing.T) {
    19  	Test(t, &testProgram{},
    20  		ThatElvish("-bad-flag").
    21  			ExitsWith(2).
    22  			WritesStderrContaining("flag provided but not defined: -bad-flag\nUsage:"),
    23  		// -h is treated as a bad flag
    24  		ThatElvish("-h").
    25  			ExitsWith(2).
    26  			WritesStderrContaining("flag provided but not defined: -h\nUsage:"),
    27  
    28  		ThatElvish("-help").
    29  			WritesStdoutContaining("Usage: elvish [flags] [script]"),
    30  	)
    31  }
    32  
    33  func TestLogFlag(t *testing.T) {
    34  	testutil.InTempDir(t)
    35  	Test(t, &testProgram{},
    36  		ThatElvish("-log", "log").DoesNothing())
    37  	_, err := os.Stat("log")
    38  	if err != nil {
    39  		t.Errorf("log file was not created: %v", err)
    40  	}
    41  }
    42  
    43  func TestCustomFlag(t *testing.T) {
    44  	Test(t, &testProgram{customFlag: true},
    45  		ThatElvish("-flag", "foo").
    46  			WritesStdout("-flag foo\n"),
    47  	)
    48  }
    49  
    50  func TestSharedFlags(t *testing.T) {
    51  	Test(t, &testProgram{sharedFlags: true},
    52  		ThatElvish("-sock", "sock", "-db", "db", "-json").
    53  			WritesStdout("-sock sock -db db -json true\n"),
    54  	)
    55  }
    56  
    57  func TestSharedFlags_MultiplePrograms(t *testing.T) {
    58  	Test(t,
    59  		Composite(
    60  			&testProgram{sharedFlags: true, nextProgram: true},
    61  			&testProgram{sharedFlags: true}),
    62  		ThatElvish("-sock", "sock", "-db", "db", "-json").
    63  			WritesStdout("-sock sock -db db -json true\n"),
    64  	)
    65  }
    66  
    67  func TestShowDeprecations(t *testing.T) {
    68  	progtest.SetDeprecationLevel(t, 0)
    69  
    70  	Test(t, &testProgram{},
    71  		ThatElvish("-deprecation-level", "42").DoesNothing(),
    72  	)
    73  
    74  	if DeprecationLevel != 42 {
    75  		t.Errorf("ShowDeprecations = %d, want 42", DeprecationLevel)
    76  	}
    77  }
    78  
    79  func TestNoSuitableSubprogram(t *testing.T) {
    80  	Test(t, &testProgram{nextProgram: true},
    81  		ThatElvish().
    82  			ExitsWith(2).
    83  			WritesStderr("internal error: no suitable subprogram\n"),
    84  	)
    85  }
    86  
    87  func TestComposite(t *testing.T) {
    88  	Test(t,
    89  		Composite(&testProgram{nextProgram: true}, &testProgram{writeOut: "program 2"}),
    90  		ThatElvish().WritesStdout("program 2"),
    91  	)
    92  }
    93  
    94  func TestComposite_NoSuitableSubprogram(t *testing.T) {
    95  	Test(t,
    96  		Composite(&testProgram{nextProgram: true}, &testProgram{nextProgram: true}),
    97  		ThatElvish().
    98  			ExitsWith(2).
    99  			WritesStderr("internal error: no suitable subprogram\n"),
   100  	)
   101  }
   102  
   103  func TestComposite_PreferEarlierSubprogram(t *testing.T) {
   104  	Test(t,
   105  		Composite(
   106  			&testProgram{writeOut: "program 1"}, &testProgram{writeOut: "program 2"}),
   107  		ThatElvish().WritesStdout("program 1"),
   108  	)
   109  }
   110  
   111  func TestBadUsageError(t *testing.T) {
   112  	Test(t,
   113  		&testProgram{returnErr: BadUsage("lorem ipsum")},
   114  		ThatElvish().ExitsWith(2).WritesStderrContaining("lorem ipsum\n"),
   115  	)
   116  }
   117  
   118  func TestExitError(t *testing.T) {
   119  	Test(t, &testProgram{returnErr: Exit(3)},
   120  		ThatElvish().ExitsWith(3),
   121  	)
   122  }
   123  
   124  func TestExitError_0(t *testing.T) {
   125  	Test(t, &testProgram{returnErr: Exit(0)},
   126  		ThatElvish().ExitsWith(0),
   127  	)
   128  }
   129  
   130  type testProgram struct {
   131  	nextProgram bool
   132  	writeOut    string
   133  	returnErr   error
   134  	customFlag  bool
   135  	sharedFlags bool
   136  
   137  	flag        string
   138  	daemonPaths *DaemonPaths
   139  	json        *bool
   140  }
   141  
   142  func (p *testProgram) RegisterFlags(f *FlagSet) {
   143  	if p.customFlag {
   144  		f.StringVar(&p.flag, "flag", "default", "a flag")
   145  	}
   146  	if p.sharedFlags {
   147  		p.daemonPaths = f.DaemonPaths()
   148  		p.json = f.JSON()
   149  	}
   150  }
   151  
   152  func (p *testProgram) Run(fds [3]*os.File, args []string) error {
   153  	if p.nextProgram {
   154  		return ErrNextProgram
   155  	}
   156  	fds[1].WriteString(p.writeOut)
   157  	if p.customFlag {
   158  		fmt.Fprintf(fds[1], "-flag %s\n", p.flag)
   159  	}
   160  	if p.sharedFlags {
   161  		fmt.Fprintf(fds[1], "-sock %s -db %s -json %v\n",
   162  			p.daemonPaths.Sock, p.daemonPaths.DB, *p.json)
   163  	}
   164  	return p.returnErr
   165  }