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