golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/internal/robustio/robustio_test.go (about) 1 // Copyright 2022 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 robustio_test 6 7 import ( 8 "os" 9 "path/filepath" 10 "runtime" 11 "testing" 12 "time" 13 14 "golang.org/x/tools/internal/robustio" 15 ) 16 17 func checkOSLink(t *testing.T, err error) { 18 if err == nil { 19 return 20 } 21 22 t.Helper() 23 switch runtime.GOOS { 24 case "aix", "darwin", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris": 25 // Non-mobile OS known to always support os.Symlink and os.Link. 26 t.Fatal(err) 27 default: 28 t.Skipf("skipping due to error on %v: %v", runtime.GOOS, err) 29 } 30 } 31 32 func TestFileInfo(t *testing.T) { 33 // A nonexistent file has no ID. 34 nonexistent := filepath.Join(t.TempDir(), "nonexistent") 35 if _, _, err := robustio.GetFileID(nonexistent); err == nil { 36 t.Fatalf("GetFileID(nonexistent) succeeded unexpectedly") 37 } 38 39 // A regular file has an ID. 40 real := filepath.Join(t.TempDir(), "real") 41 if err := os.WriteFile(real, nil, 0644); err != nil { 42 t.Fatalf("can't create regular file: %v", err) 43 } 44 realID, realMtime, err := robustio.GetFileID(real) 45 if err != nil { 46 t.Fatalf("can't get ID of regular file: %v", err) 47 } 48 49 // Sleep so that we get a new mtime for subsequent writes. 50 time.Sleep(2 * time.Second) 51 52 // A second regular file has a different ID. 53 real2 := filepath.Join(t.TempDir(), "real2") 54 if err := os.WriteFile(real2, nil, 0644); err != nil { 55 t.Fatalf("can't create second regular file: %v", err) 56 } 57 real2ID, real2Mtime, err := robustio.GetFileID(real2) 58 if err != nil { 59 t.Fatalf("can't get ID of second regular file: %v", err) 60 } 61 if realID == real2ID { 62 t.Errorf("realID %+v == real2ID %+v", realID, real2ID) 63 } 64 if realMtime.Equal(real2Mtime) { 65 t.Errorf("realMtime %v == real2Mtime %v", realMtime, real2Mtime) 66 } 67 68 // A symbolic link has the same ID as its target. 69 t.Run("symlink", func(t *testing.T) { 70 symlink := filepath.Join(t.TempDir(), "symlink") 71 checkOSLink(t, os.Symlink(real, symlink)) 72 73 symlinkID, symlinkMtime, err := robustio.GetFileID(symlink) 74 if err != nil { 75 t.Fatalf("can't get ID of symbolic link: %v", err) 76 } 77 if realID != symlinkID { 78 t.Errorf("realID %+v != symlinkID %+v", realID, symlinkID) 79 } 80 if !realMtime.Equal(symlinkMtime) { 81 t.Errorf("realMtime %v != symlinkMtime %v", realMtime, symlinkMtime) 82 } 83 }) 84 85 // Two hard-linked files have the same ID. 86 t.Run("hardlink", func(t *testing.T) { 87 hardlink := filepath.Join(t.TempDir(), "hardlink") 88 checkOSLink(t, os.Link(real, hardlink)) 89 90 hardlinkID, hardlinkMtime, err := robustio.GetFileID(hardlink) 91 if err != nil { 92 t.Fatalf("can't get ID of hard link: %v", err) 93 } 94 if realID != hardlinkID { 95 t.Errorf("realID %+v != hardlinkID %+v", realID, hardlinkID) 96 } 97 if !realMtime.Equal(hardlinkMtime) { 98 t.Errorf("realMtime %v != hardlinkMtime %v", realMtime, hardlinkMtime) 99 } 100 }) 101 }