github.com/camlistore/go4@v0.0.0-20200104003542-c7e774b10ea0/osutil/exec_test.go (about)

     1  // Copyright 2015 The go4 Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package osutil
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	osexec "os/exec"
    21  	"path/filepath"
    22  	"runtime"
    23  	"testing"
    24  )
    25  
    26  const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH"
    27  
    28  func TestExecutable(t *testing.T) {
    29  	if runtime.GOOS == "nacl" {
    30  		t.Skip()
    31  	}
    32  	ep, err := Executable()
    33  	if err != nil {
    34  		switch goos := runtime.GOOS; goos {
    35  		case "openbsd": // procfs is not mounted by default
    36  			t.Skipf("Executable failed on %s: %v, expected", goos, err)
    37  		}
    38  		t.Fatalf("Executable failed: %v", err)
    39  	}
    40  	// we want fn to be of the form "dir/prog"
    41  	dir := filepath.Dir(filepath.Dir(ep))
    42  	fn, err := filepath.Rel(dir, ep)
    43  	if err != nil {
    44  		t.Fatalf("filepath.Rel: %v", err)
    45  	}
    46  	cmd := &osexec.Cmd{}
    47  	// make child start with a relative program path
    48  	cmd.Dir = dir
    49  	cmd.Path = fn
    50  	// forge argv[0] for child, so that we can verify we could correctly
    51  	// get real path of the executable without influenced by argv[0].
    52  	cmd.Args = []string{"-", "-test.run=XXXX"}
    53  	cmd.Env = []string{fmt.Sprintf("%s=1", executable_EnvVar)}
    54  	out, err := cmd.CombinedOutput()
    55  	if err != nil {
    56  		t.Fatalf("exec(self) failed: %v", err)
    57  	}
    58  	outs := string(out)
    59  	if !filepath.IsAbs(outs) {
    60  		t.Fatalf("Child returned %q, want an absolute path", out)
    61  	}
    62  	if !sameFile(outs, ep) {
    63  		t.Fatalf("Child returned %q, not the same file as %q", out, ep)
    64  	}
    65  }
    66  
    67  func sameFile(fn1, fn2 string) bool {
    68  	fi1, err := os.Stat(fn1)
    69  	if err != nil {
    70  		return false
    71  	}
    72  	fi2, err := os.Stat(fn2)
    73  	if err != nil {
    74  		return false
    75  	}
    76  	return os.SameFile(fi1, fi2)
    77  }
    78  
    79  func init() {
    80  	if e := os.Getenv(executable_EnvVar); e != "" {
    81  		// first chdir to another path
    82  		dir := "/"
    83  		if runtime.GOOS == "windows" {
    84  			dir = filepath.VolumeName(".")
    85  		}
    86  		os.Chdir(dir)
    87  		if ep, err := Executable(); err != nil {
    88  			fmt.Fprint(os.Stderr, "ERROR: ", err)
    89  		} else {
    90  			fmt.Fprint(os.Stderr, ep)
    91  		}
    92  		os.Exit(0)
    93  	}
    94  }