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 }