src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/shell/shell_test.go (about)

     1  package shell
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"src.elv.sh/pkg/env"
     9  	. "src.elv.sh/pkg/prog/progtest"
    10  	"src.elv.sh/pkg/testutil"
    11  )
    12  
    13  func TestShell_LibPath_XDGPaths(t *testing.T) {
    14  	xdgConfigHome := testutil.TempDir(t)
    15  	testutil.ApplyDirIn(testutil.Dir{
    16  		"elvish": testutil.Dir{
    17  			"lib": testutil.Dir{
    18  				"a.elv": "echo a from xdg-config-home",
    19  			},
    20  		},
    21  	}, xdgConfigHome)
    22  	testutil.Setenv(t, env.XDG_CONFIG_HOME, xdgConfigHome)
    23  
    24  	xdgDataHome := testutil.TempDir(t)
    25  	testutil.ApplyDirIn(testutil.Dir{
    26  		"elvish": testutil.Dir{
    27  			"lib": testutil.Dir{
    28  				"a.elv": "echo a from xdg-data-home",
    29  				"b.elv": "echo b from xdg-data-home",
    30  			},
    31  		},
    32  	}, xdgDataHome)
    33  	testutil.Setenv(t, env.XDG_DATA_HOME, xdgDataHome)
    34  
    35  	xdgDataDir1 := testutil.TempDir(t)
    36  	testutil.ApplyDirIn(testutil.Dir{
    37  		"elvish": testutil.Dir{
    38  			"lib": testutil.Dir{
    39  				"a.elv": "echo a from xdg-data-dir-1",
    40  				"b.elv": "echo b from xdg-data-dir-1",
    41  				"c.elv": "echo c from xdg-data-dir-1",
    42  			},
    43  		},
    44  	}, xdgDataDir1)
    45  	xdgDataDir2 := testutil.TempDir(t)
    46  	testutil.ApplyDirIn(testutil.Dir{
    47  		"elvish": testutil.Dir{
    48  			"lib": testutil.Dir{
    49  				"a.elv": "echo a from xdg-data-dir-2",
    50  				"b.elv": "echo b from xdg-data-dir-2",
    51  				"c.elv": "echo c from xdg-data-dir-2",
    52  				"d.elv": "echo d from xdg-data-dir-2",
    53  			},
    54  		},
    55  	}, xdgDataDir2)
    56  	testutil.Setenv(t, env.XDG_DATA_DIRS,
    57  		xdgDataDir1+string(filepath.ListSeparator)+xdgDataDir2)
    58  
    59  	Test(t, &Program{},
    60  		ThatElvish("-c", "use a").WritesStdout("a from xdg-config-home\n"),
    61  		ThatElvish("-c", "use b").WritesStdout("b from xdg-data-home\n"),
    62  		ThatElvish("-c", "use c").WritesStdout("c from xdg-data-dir-1\n"),
    63  		ThatElvish("-c", "use d").WritesStdout("d from xdg-data-dir-2\n"),
    64  	)
    65  }
    66  
    67  // Most high-level tests against Program are specific to either script mode or
    68  // interactive mode, and are found in script_test.go and interact_test.go.
    69  
    70  var noColorTests = []struct {
    71  	name       string
    72  	value      string
    73  	unset      bool
    74  	wantRedFoo string
    75  }{
    76  	{name: "unset", unset: true, wantRedFoo: "\033[;31mfoo\033[m"},
    77  	{name: "empty", value: "", wantRedFoo: "\033[;31mfoo\033[m"},
    78  	{name: "non-empty", value: "yes", wantRedFoo: "\033[mfoo"},
    79  }
    80  
    81  func TestShell_NO_COLOR(t *testing.T) {
    82  	for _, test := range noColorTests {
    83  		t.Run(test.name, func(t *testing.T) {
    84  			setOrUnsetenv(t, env.NO_COLOR, test.unset, test.value)
    85  			Test(t, &Program{},
    86  				ThatElvish("-c", "print (styled foo red)").
    87  					WritesStdout(test.wantRedFoo))
    88  		})
    89  	}
    90  }
    91  
    92  var incSHLVLTests = []struct {
    93  	name    string
    94  	old     string
    95  	unset   bool
    96  	wantNew string
    97  }{
    98  	{name: "normal", old: "10", wantNew: "11"},
    99  	{name: "unset", unset: true, wantNew: "1"},
   100  	{name: "invalid", old: "invalid", wantNew: "1"},
   101  	// Other shells don't agree on what to do when SHLVL is negative:
   102  	//
   103  	// ~> E:SHLVL=-100 bash -c 'echo $SHLVL'
   104  	// 0
   105  	// ~> E:SHLVL=-100 zsh -c 'echo $SHLVL'
   106  	// -99
   107  	// ~> E:SHLVL=-100 fish -c 'echo $SHLVL'
   108  	// 1
   109  	//
   110  	// Elvish follows Zsh here.
   111  	{name: "negative", old: "-100", wantNew: "-99"},
   112  }
   113  
   114  func TestShell_SHLVL(t *testing.T) {
   115  	for _, test := range incSHLVLTests {
   116  		t.Run(test.name, func(t *testing.T) {
   117  			setOrUnsetenv(t, env.SHLVL, test.unset, test.old)
   118  			Test(t, &Program{},
   119  				ThatElvish("-c", "print $E:SHLVL").WritesStdout(test.wantNew))
   120  
   121  			// Test that state of SHLVL is restored.
   122  			restored, restoredSet := os.LookupEnv(env.SHLVL)
   123  			if test.unset {
   124  				if restoredSet {
   125  					t.Errorf("SHLVL not unset")
   126  				}
   127  			} else {
   128  				if restored != test.old {
   129  					t.Errorf("SHLVL restored to %q, want %q", restored, test.old)
   130  				}
   131  			}
   132  		})
   133  	}
   134  }
   135  
   136  func setOrUnsetenv(t *testing.T, name string, unset bool, set string) {
   137  	if unset {
   138  		testutil.Unsetenv(t, name)
   139  	} else {
   140  		testutil.Setenv(t, name, set)
   141  	}
   142  }
   143  
   144  // Common test utilities.
   145  
   146  func setupCleanHomePaths(t testutil.Cleanuper) string {
   147  	testutil.Unsetenv(t, env.XDG_CONFIG_HOME)
   148  	testutil.Unsetenv(t, env.XDG_DATA_HOME)
   149  	return testutil.TempHome(t)
   150  }