@@ -108,3 +108,190 @@ func TestShimsDir(t *testing.T) {
108108 t .Errorf ("ShimsDir() = %q, should be an absolute path" , result )
109109 }
110110}
111+
112+ func TestLookPathExcludingShims (t * testing.T ) {
113+ originalPath := os .Getenv ("PATH" )
114+ defer func () { _ = os .Setenv ("PATH" , originalPath ) }()
115+
116+ // Create temp directories for testing
117+ tempDir := t .TempDir ()
118+ systemDir := filepath .Join (tempDir , "system" )
119+ shimsDir := filepath .Join (tempDir , "shims" )
120+
121+ if err := os .MkdirAll (systemDir , 0755 ); err != nil {
122+ t .Fatalf ("Failed to create system dir: %v" , err )
123+ }
124+ if err := os .MkdirAll (shimsDir , 0755 ); err != nil {
125+ t .Fatalf ("Failed to create shims dir: %v" , err )
126+ }
127+
128+ // Create test executables
129+ execName := "testexec"
130+ var systemExec , shimsExec string
131+ if runtime .GOOS == constants .OSWindows {
132+ systemExec = filepath .Join (systemDir , execName + ".exe" )
133+ shimsExec = filepath .Join (shimsDir , execName + ".exe" )
134+ } else {
135+ systemExec = filepath .Join (systemDir , execName )
136+ shimsExec = filepath .Join (shimsDir , execName )
137+ }
138+
139+ // Create dummy executables
140+ if err := os .WriteFile (systemExec , []byte ("system" ), 0755 ); err != nil {
141+ t .Fatalf ("Failed to create system exec: %v" , err )
142+ }
143+ if err := os .WriteFile (shimsExec , []byte ("shim" ), 0755 ); err != nil {
144+ t .Fatalf ("Failed to create shims exec: %v" , err )
145+ }
146+
147+ t .Run ("Finds executable in system dir" , func (t * testing.T ) {
148+ separator := ":"
149+ if runtime .GOOS == constants .OSWindows {
150+ separator = ";"
151+ }
152+ testPath := strings .Join ([]string {systemDir }, separator )
153+ _ = os .Setenv ("PATH" , testPath )
154+
155+ result := LookPathExcludingShims (execName )
156+ if result != systemExec {
157+ t .Errorf ("LookPathExcludingShims(%q) = %q, want %q" , execName , result , systemExec )
158+ }
159+ })
160+
161+ t .Run ("Returns empty when not found" , func (t * testing.T ) {
162+ _ = os .Setenv ("PATH" , systemDir )
163+
164+ result := LookPathExcludingShims ("nonexistent" )
165+ if result != "" {
166+ t .Errorf ("LookPathExcludingShims(%q) = %q, want empty string" , "nonexistent" , result )
167+ }
168+ })
169+
170+ t .Run ("Returns empty with empty PATH" , func (t * testing.T ) {
171+ _ = os .Setenv ("PATH" , "" )
172+
173+ result := LookPathExcludingShims (execName )
174+ if result != "" {
175+ t .Errorf ("LookPathExcludingShims(%q) with empty PATH = %q, want empty string" , execName , result )
176+ }
177+ })
178+ }
179+
180+ func TestLookPathExcludingShims_SkipsShimsDir (t * testing.T ) {
181+ originalPath := os .Getenv ("PATH" )
182+ defer func () { _ = os .Setenv ("PATH" , originalPath ) }()
183+
184+ // Get the actual shims directory that will be excluded
185+ shimsDir := ShimsDir ()
186+
187+ // Create temp directory for "system" install
188+ tempDir := t .TempDir ()
189+ systemDir := filepath .Join (tempDir , "system" )
190+ if err := os .MkdirAll (systemDir , 0755 ); err != nil {
191+ t .Fatalf ("Failed to create system dir: %v" , err )
192+ }
193+
194+ // Create shims directory if it doesn't exist (for testing)
195+ if err := os .MkdirAll (shimsDir , 0755 ); err != nil {
196+ t .Fatalf ("Failed to create shims dir: %v" , err )
197+ }
198+
199+ execName := "lookuptest"
200+ var systemExec , shimsExec string
201+ if runtime .GOOS == constants .OSWindows {
202+ systemExec = filepath .Join (systemDir , execName + ".exe" )
203+ shimsExec = filepath .Join (shimsDir , execName + ".exe" )
204+ } else {
205+ systemExec = filepath .Join (systemDir , execName )
206+ shimsExec = filepath .Join (shimsDir , execName )
207+ }
208+
209+ // Create dummy executables
210+ if err := os .WriteFile (systemExec , []byte ("system" ), 0755 ); err != nil {
211+ t .Fatalf ("Failed to create system exec: %v" , err )
212+ }
213+ if err := os .WriteFile (shimsExec , []byte ("shim" ), 0755 ); err != nil {
214+ t .Fatalf ("Failed to create shims exec: %v" , err )
215+ }
216+ // Clean up shims exec after test
217+ defer func () { _ = os .Remove (shimsExec ) }()
218+
219+ separator := ":"
220+ if runtime .GOOS == constants .OSWindows {
221+ separator = ";"
222+ }
223+
224+ t .Run ("Skips shims dir and finds system install" , func (t * testing.T ) {
225+ // Put shims dir FIRST in PATH, then system dir
226+ testPath := strings .Join ([]string {shimsDir , systemDir }, separator )
227+ _ = os .Setenv ("PATH" , testPath )
228+
229+ result := LookPathExcludingShims (execName )
230+
231+ // Should find the system exec, NOT the shims exec
232+ if result != systemExec {
233+ t .Errorf ("LookPathExcludingShims(%q) = %q, want %q (should skip shims dir)" , execName , result , systemExec )
234+ }
235+ })
236+
237+ t .Run ("Returns empty when only in shims dir" , func (t * testing.T ) {
238+ // Put ONLY shims dir in PATH
239+ _ = os .Setenv ("PATH" , shimsDir )
240+
241+ result := LookPathExcludingShims (execName )
242+
243+ // Should return empty since shims dir is excluded
244+ if result != "" {
245+ t .Errorf ("LookPathExcludingShims(%q) = %q, want empty (shims dir should be excluded)" , execName , result )
246+ }
247+ })
248+ }
249+
250+ func TestFindExecutableInDir (t * testing.T ) {
251+ tempDir := t .TempDir ()
252+
253+ execName := "findtest"
254+ var execPath string
255+ if runtime .GOOS == constants .OSWindows {
256+ execPath = filepath .Join (tempDir , execName + ".exe" )
257+ } else {
258+ execPath = filepath .Join (tempDir , execName )
259+ }
260+
261+ // Create dummy executable
262+ if err := os .WriteFile (execPath , []byte ("test" ), 0755 ); err != nil {
263+ t .Fatalf ("Failed to create exec: %v" , err )
264+ }
265+
266+ t .Run ("Finds executable" , func (t * testing.T ) {
267+ result := findExecutableInDir (tempDir , execName )
268+ if result != execPath {
269+ t .Errorf ("findExecutableInDir(%q, %q) = %q, want %q" , tempDir , execName , result , execPath )
270+ }
271+ })
272+
273+ t .Run ("Returns empty for nonexistent" , func (t * testing.T ) {
274+ result := findExecutableInDir (tempDir , "nonexistent" )
275+ if result != "" {
276+ t .Errorf ("findExecutableInDir(%q, %q) = %q, want empty" , tempDir , "nonexistent" , result )
277+ }
278+ })
279+
280+ t .Run ("Returns empty for directory with same name" , func (t * testing.T ) {
281+ dirName := "isdir"
282+ var dirPath string
283+ if runtime .GOOS == constants .OSWindows {
284+ dirPath = filepath .Join (tempDir , dirName + ".exe" )
285+ } else {
286+ dirPath = filepath .Join (tempDir , dirName )
287+ }
288+ if err := os .MkdirAll (dirPath , 0755 ); err != nil {
289+ t .Fatalf ("Failed to create dir: %v" , err )
290+ }
291+
292+ result := findExecutableInDir (tempDir , dirName )
293+ if result != "" {
294+ t .Errorf ("findExecutableInDir should not return directories, got %q" , result )
295+ }
296+ })
297+ }
0 commit comments