github.com/tristanisham/sys@v0.0.0-20240326010300-a16cbabb7555/execabs/execabs_test.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package execabs
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"runtime"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  // hasExec reports whether the current system can start new processes
    19  // using os.StartProcess or (more commonly) exec.Command.
    20  // Copied from internal/testenv.HasExec
    21  func hasExec() bool {
    22  	switch runtime.GOOS {
    23  	case "wasip1", "js", "ios":
    24  		return false
    25  	}
    26  	return true
    27  }
    28  
    29  // mustHaveExec checks that the current system can start new processes
    30  // using os.StartProcess or (more commonly) exec.Command.
    31  // If not, mustHaveExec calls t.Skip with an explanation.
    32  // Copied from internal/testenv.MustHaveExec
    33  func mustHaveExec(t testing.TB) {
    34  	if !hasExec() {
    35  		t.Skipf("skipping test: cannot exec subprocess on %s/%s", runtime.GOOS, runtime.GOARCH)
    36  	}
    37  }
    38  
    39  func TestFixCmd(t *testing.T) {
    40  	cmd := &exec.Cmd{Path: "hello"}
    41  	fixCmd("hello", cmd)
    42  	if cmd.Path != "" {
    43  		t.Errorf("fixCmd didn't clear cmd.Path")
    44  	}
    45  	expectedErr := fmt.Sprintf("hello resolves to executable in current directory (.%chello)", filepath.Separator)
    46  	if err := cmd.Run(); err == nil {
    47  		t.Fatal("Command.Run didn't fail")
    48  	} else if err.Error() != expectedErr {
    49  		t.Fatalf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
    50  	}
    51  }
    52  
    53  func TestCommand(t *testing.T) {
    54  	mustHaveExec(t)
    55  
    56  	for _, cmd := range []func(string) *Cmd{
    57  		func(s string) *Cmd { return Command(s) },
    58  		func(s string) *Cmd { return CommandContext(context.Background(), s) },
    59  	} {
    60  		tmpDir := t.TempDir()
    61  		executable := "execabs-test"
    62  		if runtime.GOOS == "windows" {
    63  			executable += ".exe"
    64  		}
    65  		if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
    66  			t.Fatal(err)
    67  		}
    68  		cwd, err := os.Getwd()
    69  		if err != nil {
    70  			t.Fatalf("os.Getwd failed: %s", err)
    71  		}
    72  		defer os.Chdir(cwd)
    73  		if err = os.Chdir(tmpDir); err != nil {
    74  			t.Fatalf("os.Chdir failed: %s", err)
    75  		}
    76  		if runtime.GOOS != "windows" {
    77  			// add "." to PATH so that exec.LookPath looks in the current directory on
    78  			// non-windows platforms as well
    79  			origPath := os.Getenv("PATH")
    80  			defer os.Setenv("PATH", origPath)
    81  			os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
    82  		}
    83  		expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
    84  		if err = cmd("execabs-test").Run(); err == nil {
    85  			t.Fatalf("Command.Run didn't fail when exec.LookPath returned a relative path")
    86  		} else if err.Error() != expectedErr && !isGo119ErrDot(err) {
    87  			t.Errorf("Command.Run returned unexpected error: want %q, got %q", expectedErr, err.Error())
    88  		}
    89  	}
    90  }
    91  
    92  func TestLookPath(t *testing.T) {
    93  	mustHaveExec(t)
    94  
    95  	tmpDir := t.TempDir()
    96  	executable := "execabs-test"
    97  	if runtime.GOOS == "windows" {
    98  		executable += ".exe"
    99  	}
   100  	if err := os.WriteFile(filepath.Join(tmpDir, executable), []byte{1, 2, 3}, 0111); err != nil {
   101  		t.Fatal(err)
   102  	}
   103  	cwd, err := os.Getwd()
   104  	if err != nil {
   105  		t.Fatalf("os.Getwd failed: %s", err)
   106  	}
   107  	defer os.Chdir(cwd)
   108  	if err = os.Chdir(tmpDir); err != nil {
   109  		t.Fatalf("os.Chdir failed: %s", err)
   110  	}
   111  	if runtime.GOOS != "windows" {
   112  		// add "." to PATH so that exec.LookPath looks in the current directory on
   113  		// non-windows platforms as well
   114  		origPath := os.Getenv("PATH")
   115  		defer os.Setenv("PATH", origPath)
   116  		os.Setenv("PATH", fmt.Sprintf(".:%s", origPath))
   117  	}
   118  	expectedErr := fmt.Sprintf("execabs-test resolves to executable in current directory (.%c%s)", filepath.Separator, executable)
   119  	if _, err := LookPath("execabs-test"); err == nil {
   120  		t.Fatalf("LookPath didn't fail when finding a non-relative path")
   121  	} else if err.Error() != expectedErr {
   122  		t.Errorf("LookPath returned unexpected error: want %q, got %q", expectedErr, err.Error())
   123  	}
   124  }
   125  
   126  // Issue #58606
   127  func TestDoesNotExist(t *testing.T) {
   128  	err := Command("this-executable-should-not-exist").Start()
   129  	if err == nil {
   130  		t.Fatal("command should have failed")
   131  	}
   132  	if strings.Contains(err.Error(), "resolves to executable in current directory") {
   133  		t.Errorf("error (%v) should not refer to current directory", err)
   134  	}
   135  }