aboutsummaryrefslogtreecommitdiff
path: root/src/os/os_windows_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/os_windows_test.go')
-rw-r--r--src/os/os_windows_test.go82
1 files changed, 80 insertions, 2 deletions
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index 17b03e9508..1133639105 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -14,6 +14,7 @@ import (
"io"
"io/fs"
"os"
+ "os/exec"
"path/filepath"
"reflect"
"runtime"
@@ -713,11 +714,13 @@ func TestReadStdin(t *testing.T) {
func TestStatPagefile(t *testing.T) {
t.Parallel()
- fi, err := os.Stat(`c:\pagefile.sys`)
+ const path = `c:\pagefile.sys`
+ fi, err := os.Stat(path)
if err == nil {
if fi.Name() == "" {
- t.Fatal(`FileInfo of c:\pagefile.sys has empty name`)
+ t.Fatalf("Stat(%q).Name() is empty", path)
}
+ t.Logf("Stat(%q).Size() = %v", path, fi.Size())
return
}
if os.IsNotExist(err) {
@@ -1290,3 +1293,78 @@ func TestOpenDirTOCTOU(t *testing.T) {
t.Error(err)
}
}
+
+func TestAppExecLinkStat(t *testing.T) {
+ // We expect executables installed to %LOCALAPPDATA%\Microsoft\WindowsApps to
+ // be reparse points with tag IO_REPARSE_TAG_APPEXECLINK. Here we check that
+ // such reparse points are treated as irregular (but executable) files, not
+ // broken symlinks.
+ appdata := os.Getenv("LOCALAPPDATA")
+ if appdata == "" {
+ t.Skipf("skipping: LOCALAPPDATA not set")
+ }
+
+ pythonExeName := "python3.exe"
+ pythonPath := filepath.Join(appdata, `Microsoft\WindowsApps`, pythonExeName)
+
+ lfi, err := os.Lstat(pythonPath)
+ if err != nil {
+ t.Skip("skipping test, because Python 3 is not installed via the Windows App Store on this system; see https://golang.org/issue/42919")
+ }
+
+ // An APPEXECLINK reparse point is not a symlink, so os.Readlink should return
+ // a non-nil error for it, and Stat should return results identical to Lstat.
+ linkName, err := os.Readlink(pythonPath)
+ if err == nil {
+ t.Errorf("os.Readlink(%q) = %q, but expected an error\n(should be an APPEXECLINK reparse point, not a symlink)", pythonPath, linkName)
+ }
+
+ sfi, err := os.Stat(pythonPath)
+ if err != nil {
+ t.Fatalf("Stat %s: %v", pythonPath, err)
+ }
+
+ if lfi.Name() != sfi.Name() {
+ t.Logf("os.Lstat(%q) = %+v", pythonPath, lfi)
+ t.Logf("os.Stat(%q) = %+v", pythonPath, sfi)
+ t.Errorf("files should be same")
+ }
+
+ if lfi.Name() != pythonExeName {
+ t.Errorf("Stat %s: got %q, but wanted %q", pythonPath, lfi.Name(), pythonExeName)
+ }
+ if m := lfi.Mode(); m&fs.ModeSymlink != 0 {
+ t.Errorf("%q should be a file, not a link (mode=0x%x)", pythonPath, uint32(m))
+ }
+ if m := lfi.Mode(); m&fs.ModeDir != 0 {
+ t.Errorf("%q should be a file, not a directory (mode=0x%x)", pythonPath, uint32(m))
+ }
+ if m := lfi.Mode(); m&fs.ModeIrregular == 0 {
+ // A reparse point is not a regular file, but we don't have a more appropriate
+ // ModeType bit for it, so it should be marked as irregular.
+ t.Errorf("%q should not be a regular file (mode=0x%x)", pythonPath, uint32(m))
+ }
+
+ if sfi.Name() != pythonExeName {
+ t.Errorf("Stat %s: got %q, but wanted %q", pythonPath, sfi.Name(), pythonExeName)
+ }
+ if m := sfi.Mode(); m&fs.ModeSymlink != 0 {
+ t.Errorf("%q should be a file, not a link (mode=0x%x)", pythonPath, uint32(m))
+ }
+ if m := sfi.Mode(); m&fs.ModeDir != 0 {
+ t.Errorf("%q should be a file, not a directory (mode=0x%x)", pythonPath, uint32(m))
+ }
+ if m := sfi.Mode(); m&fs.ModeIrregular == 0 {
+ // A reparse point is not a regular file, but we don't have a more appropriate
+ // ModeType bit for it, so it should be marked as irregular.
+ t.Errorf("%q should not be a regular file (mode=0x%x)", pythonPath, uint32(m))
+ }
+
+ p, err := exec.LookPath(pythonPath)
+ if err != nil {
+ t.Errorf("exec.LookPath(%q): %v", pythonPath, err)
+ }
+ if p != pythonPath {
+ t.Errorf("exec.LookPath(%q) = %q; want %q", pythonPath, p, pythonPath)
+ }
+}