github.com/fawick/restic@v0.1.1-0.20171126184616-c02923fbfc79/internal/restic/node_unix_test.go (about) 1 // +build !windows 2 3 package restic 4 5 import ( 6 "os" 7 "runtime" 8 "syscall" 9 "testing" 10 "time" 11 ) 12 13 func stat(t testing.TB, filename string) (fi os.FileInfo, ok bool) { 14 fi, err := os.Lstat(filename) 15 if err != nil && os.IsNotExist(err) { 16 return fi, false 17 } 18 19 if err != nil { 20 t.Fatal(err) 21 } 22 23 return fi, true 24 } 25 26 func checkFile(t testing.TB, stat *syscall.Stat_t, node *Node) { 27 if uint32(node.Mode.Perm()) != uint32(stat.Mode&0777) { 28 t.Errorf("Mode does not match, want %v, got %v", stat.Mode&0777, node.Mode) 29 } 30 31 if node.Inode != uint64(stat.Ino) { 32 t.Errorf("Inode does not match, want %v, got %v", stat.Ino, node.Inode) 33 } 34 35 if node.DeviceID != uint64(stat.Dev) { 36 t.Errorf("Dev does not match, want %v, got %v", stat.Dev, node.DeviceID) 37 } 38 39 if node.Size != uint64(stat.Size) { 40 t.Errorf("Size does not match, want %v, got %v", stat.Size, node.Size) 41 } 42 43 if node.Links != uint64(stat.Nlink) { 44 t.Errorf("Links does not match, want %v, got %v", stat.Nlink, node.Links) 45 } 46 47 if node.UID != stat.Uid { 48 t.Errorf("UID does not match, want %v, got %v", stat.Uid, node.UID) 49 } 50 51 if node.GID != stat.Gid { 52 t.Errorf("UID does not match, want %v, got %v", stat.Gid, node.GID) 53 } 54 55 // use the os dependent function to compare the timestamps 56 s, ok := toStatT(stat) 57 if !ok { 58 return 59 } 60 61 mtime := s.mtim() 62 if node.ModTime != time.Unix(mtime.Unix()) { 63 t.Errorf("ModTime does not match, want %v, got %v", time.Unix(mtime.Unix()), node.ModTime) 64 } 65 66 ctime := s.ctim() 67 if node.ChangeTime != time.Unix(ctime.Unix()) { 68 t.Errorf("ChangeTime does not match, want %v, got %v", time.Unix(ctime.Unix()), node.ChangeTime) 69 } 70 71 atime := s.atim() 72 if node.AccessTime != time.Unix(atime.Unix()) { 73 t.Errorf("AccessTime does not match, want %v, got %v", time.Unix(atime.Unix()), node.AccessTime) 74 } 75 76 } 77 78 func checkDevice(t testing.TB, stat *syscall.Stat_t, node *Node) { 79 if node.Device != uint64(stat.Rdev) { 80 t.Errorf("Rdev does not match, want %v, got %v", stat.Rdev, node.Device) 81 } 82 } 83 84 func TestNodeFromFileInfo(t *testing.T) { 85 type Test struct { 86 filename string 87 canSkip bool 88 } 89 var tests = []Test{ 90 {"node_test.go", false}, 91 {"/dev/sda", true}, 92 } 93 94 // on darwin, users are not permitted to list the extended attributes of 95 // /dev/null, therefore skip it. 96 if runtime.GOOS != "darwin" { 97 tests = append(tests, Test{"/dev/null", true}) 98 } 99 100 for _, test := range tests { 101 t.Run("", func(t *testing.T) { 102 fi, found := stat(t, test.filename) 103 if !found && test.canSkip { 104 t.Skipf("%v not found in filesystem") 105 return 106 } 107 108 if fi.Sys() == nil { 109 t.Skip("fi.Sys() is nil") 110 return 111 } 112 113 s, ok := fi.Sys().(*syscall.Stat_t) 114 if !ok { 115 t.Skip("fi type is %T, not stat_t", fi.Sys()) 116 return 117 } 118 119 node, err := NodeFromFileInfo(test.filename, fi) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 switch node.Type { 125 case "file": 126 checkFile(t, s, node) 127 case "dev", "chardev": 128 checkFile(t, s, node) 129 checkDevice(t, s, node) 130 default: 131 t.Fatalf("invalid node type %q", node.Type) 132 } 133 }) 134 } 135 }