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  }