github.com/cli/safeexec@v1.0.1/lookpath_test.go (about) 1 package safeexec 2 3 import ( 4 "errors" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "runtime" 9 "strings" 10 "testing" 11 ) 12 13 func TestLookPath(t *testing.T) { 14 root, wderr := os.Getwd() 15 if wderr != nil { 16 t.Fatal(wderr) 17 } 18 19 if err := os.Chdir(filepath.Join(root, "_fixtures", "cwd")); err != nil { 20 t.Fatal(err) 21 } 22 23 testCases := []struct { 24 desc string 25 path []string 26 pathext string 27 arg string 28 wants string 29 wantErr bool 30 }{ 31 { 32 desc: "no extension", 33 path: []string{ 34 filepath.Join(root, "_fixtures", "nonexist"), 35 filepath.Join(root, "_fixtures", "system"), 36 }, 37 pathext: "", 38 arg: "ls", 39 wants: filepath.Join(root, "_fixtures", "system", "ls"+winonly(".exe")), 40 wantErr: false, 41 }, 42 { 43 desc: "with extension", 44 path: []string{filepath.Join(root, "_fixtures", "system")}, 45 pathext: "", 46 arg: "ls.exe", 47 wants: filepath.Join(root, "_fixtures", "system", "ls.exe"), 48 wantErr: false, 49 }, 50 { 51 desc: "with path", 52 path: []string{filepath.Join(root, "_fixtures", "system")}, 53 pathext: "", 54 arg: filepath.Join("..", "system", "ls"), 55 wants: filepath.Join("..", "system", "ls"+winonly(".exe")), 56 wantErr: false, 57 }, 58 { 59 desc: "with path+extension", 60 path: []string{filepath.Join(root, "_fixtures", "system")}, 61 pathext: "", 62 arg: filepath.Join("..", "system", "ls.bat"), 63 wants: filepath.Join("..", "system", "ls.bat"), 64 wantErr: false, 65 }, 66 { 67 desc: "no extension, PATHEXT", 68 path: []string{filepath.Join(root, "_fixtures", "system")}, 69 pathext: ".com;.bat", 70 arg: "ls", 71 wants: filepath.Join(root, "_fixtures", "system", "ls"+winonly(".bat")), 72 wantErr: false, 73 }, 74 { 75 desc: "with extension, PATHEXT", 76 path: []string{filepath.Join(root, "_fixtures", "system")}, 77 pathext: ".com;.bat", 78 arg: "ls.exe", 79 wants: filepath.Join(root, "_fixtures", "system", "ls.exe"), 80 wantErr: false, 81 }, 82 { 83 desc: "no extension, not found", 84 path: []string{ 85 filepath.Join(root, "_fixtures", "nonexist"), 86 filepath.Join(root, "_fixtures", "system"), 87 }, 88 pathext: "", 89 arg: "cat", 90 wants: "", 91 wantErr: true, 92 }, 93 { 94 desc: "with extension, not found", 95 path: []string{filepath.Join(root, "_fixtures", "system")}, 96 pathext: "", 97 arg: "cat.exe", 98 wants: "", 99 wantErr: true, 100 }, 101 { 102 desc: "no extension, PATHEXT, not found", 103 path: []string{filepath.Join(root, "_fixtures", "system")}, 104 pathext: ".com;.bat", 105 arg: "cat", 106 wants: "", 107 wantErr: true, 108 }, 109 { 110 desc: "with extension, PATHEXT, not found", 111 path: []string{filepath.Join(root, "_fixtures", "system")}, 112 pathext: ".com;.bat", 113 arg: "cat.exe", 114 wants: "", 115 wantErr: true, 116 }, 117 { 118 desc: "relative path", 119 path: []string{filepath.Join("..", "system")}, 120 pathext: "", 121 arg: "ls", 122 wants: filepath.Join("..", "system", "ls"+winonly(".exe")), 123 wantErr: false, 124 }, 125 } 126 for _, tC := range testCases { 127 t.Run(tC.desc, func(t *testing.T) { 128 setenv(t, "PATH", strings.Join(tC.path, string(filepath.ListSeparator))) 129 setenv(t, "PATHEXT", tC.pathext) 130 got, err := LookPath(tC.arg) 131 132 if tC.wantErr != (err != nil) { 133 t.Errorf("expects error: %v, got: %v", tC.wantErr, err) 134 } 135 if err != nil && !errors.Is(err, exec.ErrNotFound) { 136 t.Errorf("expected exec.ErrNotFound; got %#v", err) 137 } 138 if got != tC.wants { 139 t.Errorf("expected result %q, got %q", tC.wants, got) 140 } 141 }) 142 } 143 } 144 145 func setenv(t *testing.T, name, newValue string) { 146 oldValue, hasOldValue := os.LookupEnv(name) 147 if err := os.Setenv(name, newValue); err != nil { 148 t.Errorf("error setting environment variable %s: %v", name, err) 149 } 150 t.Cleanup(func() { 151 if hasOldValue { 152 _ = os.Setenv(name, oldValue) 153 } else { 154 _ = os.Unsetenv(name) 155 } 156 }) 157 } 158 159 func winonly(s string) string { 160 if runtime.GOOS == "windows" { 161 return s 162 } 163 return "" 164 }