github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/fusetesting/stat.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 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 fusetesting 16 17 import ( 18 "fmt" 19 "os" 20 "reflect" 21 "syscall" 22 "time" 23 24 "github.com/jacobsa/oglematchers" 25 ) 26 27 // Match os.FileInfo values that specify an mtime equal to the given time. 28 func MtimeIs(expected time.Time) oglematchers.Matcher { 29 return oglematchers.NewMatcher( 30 func(c interface{}) error { return mtimeIsWithin(c, expected, 0) }, 31 fmt.Sprintf("mtime is %v", expected)) 32 } 33 34 // Like MtimeIs, but allows for a tolerance. 35 func MtimeIsWithin(expected time.Time, d time.Duration) oglematchers.Matcher { 36 return oglematchers.NewMatcher( 37 func(c interface{}) error { return mtimeIsWithin(c, expected, d) }, 38 fmt.Sprintf("mtime is within %v of %v", d, expected)) 39 } 40 41 func mtimeIsWithin(c interface{}, expected time.Time, d time.Duration) error { 42 fi, ok := c.(os.FileInfo) 43 if !ok { 44 return fmt.Errorf("which is of type %v", reflect.TypeOf(c)) 45 } 46 47 // Check ModTime(). 48 diff := fi.ModTime().Sub(expected) 49 absDiff := diff 50 if absDiff < 0 { 51 absDiff = -absDiff 52 } 53 54 if !(absDiff < d) { 55 return fmt.Errorf("which has mtime %v, off by %v", fi.ModTime(), diff) 56 } 57 58 return nil 59 } 60 61 // Match os.FileInfo values that specify a file birth time within the supplied 62 // radius of the given time. On platforms where there is no birth time 63 // available, match all os.FileInfo values. 64 func BirthtimeIsWithin( 65 expected time.Time, 66 d time.Duration) oglematchers.Matcher { 67 return oglematchers.NewMatcher( 68 func(c interface{}) error { return birthtimeIsWithin(c, expected, d) }, 69 fmt.Sprintf("birthtime is within %v of %v", d, expected)) 70 } 71 72 func birthtimeIsWithin( 73 c interface{}, 74 expected time.Time, 75 d time.Duration) error { 76 fi, ok := c.(os.FileInfo) 77 if !ok { 78 return fmt.Errorf("which is of type %v", reflect.TypeOf(c)) 79 } 80 81 t, ok := extractBirthtime(fi.Sys()) 82 if !ok { 83 return nil 84 } 85 86 diff := t.Sub(expected) 87 absDiff := diff 88 if absDiff < 0 { 89 absDiff = -absDiff 90 } 91 92 if !(absDiff < d) { 93 return fmt.Errorf("which has birth time %v, off by %v", t, diff) 94 } 95 96 return nil 97 } 98 99 // Extract time information from the supplied file info. Panic on platforms 100 // where this is not possible. 101 func GetTimes(fi os.FileInfo) (atime, ctime, mtime time.Time) { 102 return getTimes(fi.Sys().(*syscall.Stat_t)) 103 } 104 105 // Match os.FileInfo values that specify a number of links equal to the given 106 // number. On platforms where there is no nlink field available, match all 107 // os.FileInfo values. 108 func NlinkIs(expected uint64) oglematchers.Matcher { 109 return oglematchers.NewMatcher( 110 func(c interface{}) error { return nlinkIs(c, expected) }, 111 fmt.Sprintf("nlink is %v", expected)) 112 } 113 114 func nlinkIs(c interface{}, expected uint64) error { 115 fi, ok := c.(os.FileInfo) 116 if !ok { 117 return fmt.Errorf("which is of type %v", reflect.TypeOf(c)) 118 } 119 120 if actual, ok := extractNlink(fi.Sys()); ok && actual != expected { 121 return fmt.Errorf("which has nlink == %v", actual) 122 } 123 124 return nil 125 }