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  }