github.com/rohankumardubey/proxyfs@v0.0.0-20210108201508-653efa9ab00e/inode/api_test.go (about)

     1  package inode
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/swiftstack/ProxyFS/swiftclient"
    12  	"github.com/swiftstack/ProxyFS/utils"
    13  )
    14  
    15  const durationToDelayOrSkew = "100ms"
    16  
    17  var AllMetadataFields = map[string]bool{
    18  	"InodeType":            true,
    19  	"LinkCount":            true,
    20  	"Size":                 true,
    21  	"CreationTime":         true,
    22  	"ModificationTime":     true,
    23  	"AccessTime":           true,
    24  	"AttrChangeTime":       true,
    25  	"NumWrites":            true,
    26  	"InodeStreamNameSlice": true,
    27  	"Mode":                 true,
    28  	"UserID":               true,
    29  	"GroupID":              true,
    30  }
    31  
    32  var MetadataPermFields = map[string]bool{
    33  	"Mode":    true,
    34  	"UserID":  true,
    35  	"GroupID": true,
    36  }
    37  
    38  var MetadataLinkCountField = map[string]bool{
    39  	"LinkCount": true,
    40  }
    41  
    42  var MetadataCrTimeField = map[string]bool{
    43  	"CreationTime": true,
    44  }
    45  
    46  var MetadataModTimeField = map[string]bool{
    47  	"ModificationTime": true,
    48  }
    49  
    50  var MetadataSizeField = map[string]bool{
    51  	"Size": true,
    52  }
    53  
    54  var MetadataTimeFields = map[string]bool{
    55  	"CreationTime":     true,
    56  	"AttrChangeTime":   true,
    57  	"ModificationTime": true,
    58  	"AccessTime":       true,
    59  }
    60  
    61  var MetadataNotAttrTimeFields = map[string]bool{
    62  	"CreationTime":     true,
    63  	"ModificationTime": true,
    64  	"AccessTime":       true,
    65  }
    66  
    67  var MetadataNumWritesField = map[string]bool{
    68  	"NumWrites": true,
    69  }
    70  
    71  func checkMetadata(t *testing.T, md *MetadataStruct, expMd *MetadataStruct, fieldsToCheck map[string]bool, errorPrefix string) {
    72  	for field := range fieldsToCheck {
    73  		switch field {
    74  
    75  		case "InodeType":
    76  			value := md.InodeType
    77  			expValue := expMd.InodeType
    78  			if value != expValue {
    79  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
    80  			}
    81  
    82  		case "LinkCount":
    83  			value := md.LinkCount
    84  			expValue := expMd.LinkCount
    85  			if value != expValue {
    86  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
    87  			}
    88  
    89  		case "Size":
    90  			value := md.Size
    91  			expValue := expMd.Size
    92  			if value != expValue {
    93  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
    94  			}
    95  
    96  		case "CreationTime":
    97  			value := md.CreationTime
    98  			expValue := expMd.CreationTime
    99  			if !value.Equal(expValue) {
   100  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   101  			}
   102  
   103  		case "ModificationTime":
   104  			value := md.ModificationTime
   105  			expValue := expMd.ModificationTime
   106  			if !value.Equal(expValue) {
   107  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   108  			}
   109  
   110  		case "AccessTime":
   111  			value := md.AccessTime
   112  			expValue := expMd.AccessTime
   113  			if !value.Equal(expValue) {
   114  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   115  			}
   116  
   117  		case "AttrChangeTime":
   118  			value := md.AttrChangeTime
   119  			expValue := expMd.AttrChangeTime
   120  			if !value.Equal(expValue) {
   121  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   122  			}
   123  
   124  		case "NumWrites":
   125  			value := md.NumWrites
   126  			expValue := expMd.NumWrites
   127  			if value != expValue {
   128  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   129  			}
   130  
   131  		case "InodeStreamNameSlice":
   132  			value := len(md.InodeStreamNameSlice)
   133  			expValue := len(expMd.InodeStreamNameSlice)
   134  			if value != expValue {
   135  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   136  			}
   137  			for i, streamName := range md.InodeStreamNameSlice {
   138  				value := streamName
   139  				expValue := expMd.InodeStreamNameSlice[i]
   140  				if value != expValue {
   141  					t.Fatalf("%s returned %s[%d] %v, expected %v", errorPrefix,
   142  						field, i, value, expValue)
   143  				}
   144  			}
   145  
   146  		case "Mode":
   147  			value := md.Mode
   148  			expValue := expMd.Mode
   149  
   150  			// Add the file type to the expected mode
   151  			if md.InodeType == DirType {
   152  				expValue |= PosixModeDir
   153  			} else if md.InodeType == SymlinkType {
   154  				expValue |= PosixModeSymlink
   155  			} else if md.InodeType == FileType {
   156  				expValue |= PosixModeFile
   157  			}
   158  			if value != expValue {
   159  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   160  			}
   161  
   162  		case "UserID":
   163  			value := md.UserID
   164  			expValue := expMd.UserID
   165  			if value != expValue {
   166  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   167  			}
   168  
   169  		case "GroupID":
   170  			value := md.GroupID
   171  			expValue := expMd.GroupID
   172  			if value != expValue {
   173  				t.Fatalf("%s returned %s %v, expected %v", errorPrefix, field, value, expValue)
   174  			}
   175  
   176  		default:
   177  			// catch field name typos
   178  			t.Fatalf("%s specified unknown field '%v'", errorPrefix, field)
   179  		}
   180  	}
   181  }
   182  
   183  func checkMetadataTimeChanges(t *testing.T, oldMd *MetadataStruct, newMd *MetadataStruct, creationTimeShouldChange bool, modificationTimeShouldChange bool, accessTimeShouldChange bool, attrChangeTimeShouldChange bool, errorPrefix string) {
   184  	if creationTimeShouldChange {
   185  		if oldMd.CreationTime == newMd.CreationTime {
   186  			t.Fatalf("%s should have changed CreationTime", errorPrefix)
   187  		}
   188  	} else {
   189  		if oldMd.CreationTime != newMd.CreationTime {
   190  			t.Fatalf("%s should not have changed CreationTime", errorPrefix)
   191  		}
   192  	}
   193  
   194  	if modificationTimeShouldChange {
   195  		if oldMd.ModificationTime == newMd.ModificationTime {
   196  			t.Fatalf("%s should have changed ModificationTime", errorPrefix)
   197  		}
   198  	} else {
   199  		if oldMd.ModificationTime != newMd.ModificationTime {
   200  			t.Fatalf("%s should not have changed ModificationTime", errorPrefix)
   201  		}
   202  	}
   203  
   204  	if accessTimeShouldChange {
   205  		if oldMd.AccessTime == newMd.AccessTime {
   206  			t.Fatalf("%s should have changed AccessTime", errorPrefix)
   207  		}
   208  	} else {
   209  		if oldMd.AccessTime != newMd.AccessTime {
   210  			t.Fatalf("%s should not have changed AccessTime", errorPrefix)
   211  		}
   212  	}
   213  
   214  	if attrChangeTimeShouldChange {
   215  		if oldMd.AttrChangeTime == newMd.AttrChangeTime {
   216  			t.Fatalf("%s should have changed AttrChangeTime", errorPrefix)
   217  		}
   218  	} else {
   219  		if oldMd.AttrChangeTime != newMd.AttrChangeTime {
   220  			t.Fatalf("%s should not have changed AttrChangeTime", errorPrefix)
   221  		}
   222  	}
   223  }
   224  
   225  func TestAPI(t *testing.T) {
   226  	var (
   227  		timeBeforeOp time.Time
   228  		timeAfterOp  time.Time
   229  	)
   230  
   231  	testSetup(t, false)
   232  
   233  	_, ok := AccountNameToVolumeName("BadAccountName")
   234  	if ok {
   235  		t.Fatalf("AccountNameToVolumeName(\"BadAccountName\") should have failed")
   236  	}
   237  
   238  	goodVolumeName, ok := AccountNameToVolumeName("AUTH_test")
   239  	if !ok {
   240  		t.Fatalf("AccountNameToVolumeName(\"AUTH_test\") should have succeeded")
   241  	}
   242  	if "TestVolume" != goodVolumeName {
   243  		t.Fatalf("AccountNameToVolumeName(\"AUTH_test\") should have returned \"TestVolume\"")
   244  	}
   245  
   246  	_, ok = VolumeNameToActivePeerPrivateIPAddr("BadVolumeName")
   247  	if ok {
   248  		t.Fatalf("VolumeNameToActivePeerPrivateIPAddr(\"BadVolumeName\") should have failed")
   249  	}
   250  
   251  	goodActivePeerPrivateIPAddr, ok := VolumeNameToActivePeerPrivateIPAddr("TestVolume")
   252  	if !ok {
   253  		t.Fatalf("VolumeNameToActivePeerPrivateIPAddr(\"TestVolume\") should have succeeded")
   254  	}
   255  	if "127.0.0.1" != goodActivePeerPrivateIPAddr {
   256  		t.Fatalf("VolumeNameToActivePeerPrivateIPAddr(\"TestVolume\") should have returned \"127.0.0.1\"")
   257  	}
   258  
   259  	_, err := FetchVolumeHandle("BadVolumeName")
   260  	if nil == err {
   261  		t.Fatalf("FetchVolumeHandle(\"BadVolumeName\") should have failed")
   262  	}
   263  
   264  	testVolumeHandle, err := FetchVolumeHandle("TestVolume")
   265  	if nil != err {
   266  		t.Fatalf("FetchVolumeHandle(\"TestVolume\") should have worked - got error: %v", err)
   267  	}
   268  
   269  	fsid := testVolumeHandle.GetFSID()
   270  	if 1 != fsid {
   271  		t.Fatalf("GetFSID() returned unexpected FSID")
   272  	}
   273  
   274  	fileInodeNumber, err := testVolumeHandle.CreateFile(InodeMode(0000), InodeRootUserID, InodeGroupID(0))
   275  	if nil != err {
   276  		t.Fatalf("CreateFile() failed: %v", err)
   277  	}
   278  
   279  	if !testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(0), nil, F_OK, NoOverride) {
   280  		t.Fatalf("Access(fileInodeNumber,,,,F_OK) after CreateFile() should not have failed")
   281  	}
   282  
   283  	if !testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(456), nil,
   284  		R_OK|W_OK, NoOverride) {
   285  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,R_OK|W_OK) should have returned true")
   286  	}
   287  
   288  	// not even root can execute a file without any execute bits set
   289  	if testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(456), nil,
   290  		X_OK, NoOverride) {
   291  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,R_OK|W_OK|X_OK) should have returned false")
   292  	}
   293  
   294  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(0), nil,
   295  		R_OK|W_OK|X_OK, NoOverride) {
   296  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),InodeGroupID(0),,R_OK|W_OK|X_OK) should have returned false")
   297  	}
   298  
   299  	if testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(0), nil,
   300  		R_OK|P_OK, NoOverride) {
   301  		t.Fatalf("Access(fileInodeNumber,,,,R_OK|X_OK) should have returned false")
   302  	}
   303  
   304  	err = testVolumeHandle.SetOwnerUserID(fileInodeNumber, InodeUserID(123))
   305  	if nil != err {
   306  		t.Fatalf("SetOwnerUserID(,InodeUserID(123)) failed: %v", err)
   307  	}
   308  
   309  	if !testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(0), nil, P_OK, NoOverride) {
   310  		t.Fatalf("Access(fileInodeNumber,InodeRootUserID,,,P_OK should have returned true")
   311  	}
   312  
   313  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(0), nil, P_OK, NoOverride) {
   314  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,P_OK should have returned true")
   315  	}
   316  
   317  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(0), nil, P_OK, OwnerOverride) {
   318  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,P_OK,UserOveride should have returned true")
   319  	}
   320  
   321  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(789), InodeGroupID(0), nil, P_OK, NoOverride) {
   322  		t.Fatalf("Access(fileInodeNumber,InodeUserID(789),,,P_OK should have returned false")
   323  	}
   324  
   325  	err = testVolumeHandle.SetPermMode(fileInodeNumber, InodeMode(0600))
   326  	if nil != err {
   327  		t.Fatalf("SetPermMode(,InodeMode(0600)) failed: %v", err)
   328  	}
   329  
   330  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, R_OK, NoOverride) {
   331  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,R_OK) should have returned true")
   332  	}
   333  
   334  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, W_OK, NoOverride) {
   335  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,W_OK) should have returned true")
   336  	}
   337  
   338  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, X_OK, NoOverride) {
   339  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,X_OK) should have returned false")
   340  	}
   341  
   342  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, R_OK|W_OK, NoOverride) {
   343  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,R_OK|W_OK) should have returned true")
   344  	}
   345  
   346  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   347  		R_OK|W_OK|X_OK, NoOverride) {
   348  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),,,R_OK|W_OK|X_OK) should have returned false")
   349  	}
   350  
   351  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   352  		R_OK|W_OK|X_OK, OwnerOverride) {
   353  		t.Fatalf("Access(fileInodeNumber,InodeUserID(123),OwnerOverride,,R_OK|W_OK|X_OK) should have returned false")
   354  	}
   355  
   356  	err = testVolumeHandle.SetOwnerUserIDGroupID(fileInodeNumber, InodeRootUserID, InodeGroupID(456))
   357  	if nil != err {
   358  		t.Fatalf("SetOwnerUserIDGroupID(,InodeRootUserID,InodeGroupID(456)) failed: %v", err)
   359  	}
   360  
   361  	err = testVolumeHandle.SetPermMode(fileInodeNumber, InodeMode(0060))
   362  	if nil != err {
   363  		t.Fatalf("SetPermMode(,InodeMode(0060)) failed: %v", err)
   364  	}
   365  
   366  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, R_OK, NoOverride) {
   367  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,R_OK) should have returned true")
   368  	}
   369  
   370  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, W_OK, NoOverride) {
   371  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,W_OK) should have returned true")
   372  	}
   373  
   374  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, X_OK, NoOverride) {
   375  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,X_OK) should have returned false")
   376  	}
   377  
   378  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, X_OK, OwnerOverride) {
   379  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,X_OK,OwnerOverride) should have returned false")
   380  	}
   381  
   382  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   383  		R_OK|W_OK, NoOverride) {
   384  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,R_OK|W_OK) should have returned true")
   385  	}
   386  
   387  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   388  		R_OK|W_OK|X_OK, NoOverride) {
   389  		t.Fatalf("Access(fileInodeNumber,,InodeGroupID(456),,R_OK|W_OK|X_OK) should have returned false")
   390  	}
   391  
   392  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(789),
   393  		[]InodeGroupID{InodeGroupID(456)}, R_OK, NoOverride) {
   394  		t.Fatalf("Access(fileInodeNumber,,,[]InodeGroupID{InodeGroupID(456)},R_OK) should have returned true")
   395  	}
   396  
   397  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(789),
   398  		[]InodeGroupID{InodeGroupID(456)}, W_OK, NoOverride) {
   399  		t.Fatalf("Access(fileInodeNumber,,,[]InodeGroupID{InodeGroupID(456)},W_OK) should have returned true")
   400  	}
   401  
   402  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(789),
   403  		[]InodeGroupID{InodeGroupID(456)}, X_OK, NoOverride) {
   404  		t.Fatalf("Access(fileInodeNumber,,,[]InodeGroupID{InodeGroupID(456)},X_OK) should have returned false")
   405  	}
   406  
   407  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(789),
   408  		[]InodeGroupID{InodeGroupID(456)}, R_OK|W_OK, NoOverride) {
   409  		t.Fatalf("Access(fileInodeNumber,,,[]InodeGroupID{InodeGroupID(456)},R_OK|W_OK) should have returned true")
   410  	}
   411  
   412  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(789),
   413  		[]InodeGroupID{InodeGroupID(456)}, R_OK|W_OK|X_OK, NoOverride) {
   414  		t.Fatalf("Access(fileInodeNumber,,,[]InodeGroupID{InodeGroupID(456)},R_OK|W_OK|X_OK) should have returned false")
   415  	}
   416  
   417  	err = testVolumeHandle.SetPermMode(fileInodeNumber, InodeMode(0006))
   418  	if nil != err {
   419  		t.Fatalf("SetPermMode(,InodeMode(0006)) failed: %v", err)
   420  	}
   421  	err = testVolumeHandle.SetOwnerUserIDGroupID(fileInodeNumber, InodeUserID(456), InodeGroupID(0))
   422  	if nil != err {
   423  		t.Fatalf("SetOwnerUserIDGroupID(,InodeRootUserID,InodeGroupID(0)) failed: %v", err)
   424  	}
   425  
   426  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, R_OK, NoOverride) {
   427  		t.Fatalf("Access(fileInodeNumber,,,,R_OK) should have returned true")
   428  	}
   429  
   430  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, W_OK, NoOverride) {
   431  		t.Fatalf("Access(fileInodeNumber,,,,W_OK) should have returned true")
   432  	}
   433  
   434  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil, X_OK, NoOverride) {
   435  		t.Fatalf("Access(fileInodeNumber,,,,X_OK) should have returned false")
   436  	}
   437  
   438  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   439  		R_OK|W_OK, NoOverride) {
   440  		t.Fatalf("Access(fileInodeNumber,,,,R_OK|W_OK) should have returned true")
   441  	}
   442  
   443  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(123), InodeGroupID(456), nil,
   444  		R_OK|W_OK|X_OK, NoOverride) {
   445  		t.Fatalf("Access(fileInodeNumber,,,,R_OK|W_OK|X_OK) should have returned false")
   446  	}
   447  
   448  	// Test the ability of OwnerOverride to override permissions checks for owner (except for exec)
   449  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, R_OK, NoOverride) {
   450  		t.Fatalf("Access(fileInodeNumber,,,,R_OK) should have returned false")
   451  	}
   452  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, R_OK, OwnerOverride) {
   453  		t.Fatalf("Access(fileInodeNumber,,,,R_OK) should have returned true")
   454  	}
   455  
   456  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, W_OK, NoOverride) {
   457  		t.Fatalf("Access(fileInodeNumber,,,,W_OK) should have returned false")
   458  	}
   459  	if !testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, W_OK, OwnerOverride) {
   460  		t.Fatalf("Access(fileInodeNumber,,,,W_OK) should have returned true")
   461  	}
   462  
   463  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, X_OK, NoOverride) {
   464  		t.Fatalf("Access(fileInodeNumber,,,,X_OK) should have returned false")
   465  	}
   466  	if testVolumeHandle.Access(fileInodeNumber, InodeUserID(456), InodeGroupID(456), nil, X_OK, OwnerOverride) {
   467  		t.Fatalf("Access(fileInodeNumber,,,,X_OK) should have returned false")
   468  	}
   469  
   470  	err = testVolumeHandle.Destroy(fileInodeNumber)
   471  	if nil != err {
   472  		t.Fatalf("Destroy(fileInodeNumber) failed: %v", err)
   473  	}
   474  
   475  	if testVolumeHandle.Access(fileInodeNumber, InodeRootUserID, InodeGroupID(0), nil, F_OK, NoOverride) {
   476  		t.Fatalf("Access(fileInodeNumber,,,,F_OK) after Destroy() should have failed")
   477  	}
   478  
   479  	rootDirInodeType, err := testVolumeHandle.GetType(RootDirInodeNumber)
   480  	if nil != err {
   481  		t.Fatalf("GetType(RootDirInodeNumber) failed: %v", err)
   482  	}
   483  	if DirType != rootDirInodeType {
   484  		t.Fatalf("GetType(RootDirInodeNumber) returned unexpected type: %v", rootDirInodeType)
   485  	}
   486  
   487  	rootDirLinkCount, err := testVolumeHandle.GetLinkCount(RootDirInodeNumber)
   488  	if nil != err {
   489  		t.Fatalf("GetLinkCount(RootDirInodeNumber) failed: %v", err)
   490  	}
   491  	if 2 != rootDirLinkCount {
   492  		t.Fatalf("GetLinkCount(RootDirInodeNumber) returned unexpected linkCount: %v", rootDirLinkCount)
   493  	}
   494  
   495  	numEntries, err := testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   496  
   497  	if nil != err {
   498  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   499  	}
   500  	if 2 != numEntries {
   501  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 2")
   502  	}
   503  
   504  	dirEntrySlice, moreEntries, err := testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
   505  
   506  	if nil != err {
   507  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
   508  	}
   509  	if moreEntries {
   510  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
   511  	}
   512  	if 2 != len(dirEntrySlice) {
   513  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements")
   514  	}
   515  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
   516  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
   517  	}
   518  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
   519  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
   520  	}
   521  
   522  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1))
   523  
   524  	if nil != err {
   525  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1)) failed: %v", err)
   526  	}
   527  	if moreEntries {
   528  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1)) should have returned moreEntries == false")
   529  	}
   530  	if 2 != len(dirEntrySlice) {
   531  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1)) should have returned dirEntrySlice with 2 elements")
   532  	}
   533  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
   534  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1)) returned unexpected dirEntrySlice[0]")
   535  	}
   536  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
   537  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(-1)) returned unexpected dirEntrySlice[1]")
   538  	}
   539  
   540  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0, "")
   541  
   542  	if nil != err {
   543  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"\") failed: %v", err)
   544  	}
   545  	if moreEntries {
   546  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"\") should have returned moreEntries == false")
   547  	}
   548  	if 2 != len(dirEntrySlice) {
   549  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"\") should have returned dirEntrySlice with 2 elements")
   550  	}
   551  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
   552  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"\") returned unexpected dirEntrySlice[0]")
   553  	}
   554  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
   555  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"\") returned unexpected dirEntrySlice[1]")
   556  	}
   557  
   558  	testMetadata := &MetadataStruct{
   559  		InodeType: FileType,
   560  		NumWrites: 0,
   561  		LinkCount: 0,
   562  		Mode:      PosixModePerm,
   563  		UserID:    InodeUserID(123),
   564  		GroupID:   InodeGroupID(456),
   565  	}
   566  
   567  	fileInodeNumber, err = testVolumeHandle.CreateFile(testMetadata.Mode, testMetadata.UserID, testMetadata.GroupID)
   568  	if nil != err {
   569  		t.Fatalf("CreateFile() failed: %v", err)
   570  	}
   571  
   572  	fileInodeType, err := testVolumeHandle.GetType(fileInodeNumber)
   573  	if nil != err {
   574  		t.Fatalf("GetType(fileInodeNumber) failed: %v", err)
   575  	}
   576  	if FileType != fileInodeType {
   577  		t.Fatalf("GetType(fileInodeNumber) returned unexpected type: %v", fileInodeType)
   578  	}
   579  
   580  	fileLinkCount, err := testVolumeHandle.GetLinkCount(fileInodeNumber)
   581  	if nil != err {
   582  		t.Fatalf("GetLinkCount(fileInodeNumber) failed: %v", err)
   583  	}
   584  	if 0 != fileLinkCount {
   585  		t.Fatalf("GetLinkCount(fileInodeNumber) returned unexpected linkCount: %v", fileLinkCount)
   586  	}
   587  
   588  	postMetadata, err := testVolumeHandle.GetMetadata(fileInodeNumber)
   589  	if nil != err {
   590  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   591  	}
   592  	if FileType != postMetadata.InodeType {
   593  		t.Fatalf("GetMetadata(fileInodeNumber) returned unexpected InodeType")
   594  	}
   595  	checkMetadata(t, postMetadata, testMetadata, MetadataLinkCountField, "GetMetadata() after CreateFile()")
   596  
   597  	// XXX TODO: Add more tests related to CreateFile(): mode > 0777, etc.
   598  
   599  	preMetadata, err := testVolumeHandle.GetMetadata(fileInodeNumber)
   600  	if nil != err {
   601  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   602  	}
   603  	time.Sleep(time.Millisecond)
   604  
   605  	testMetadata.Mode = PosixModePerm - 1
   606  
   607  	err = testVolumeHandle.SetPermMode(fileInodeNumber, testMetadata.Mode)
   608  	if nil != err {
   609  		t.Fatalf("SetPermMode(fileInodeNumber, %v) failed: %v", testMetadata.Mode, err)
   610  	}
   611  
   612  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   613  	if nil != err {
   614  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   615  	}
   616  	checkMetadata(t, postMetadata, testMetadata, MetadataPermFields, "GetMetadata() after SetPermMode()")
   617  	checkMetadataTimeChanges(t, preMetadata, postMetadata, false, false, false, true, "SetPermMode()")
   618  
   619  	preMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   620  	if nil != err {
   621  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   622  	}
   623  	time.Sleep(time.Millisecond)
   624  
   625  	testMetadata.UserID = 9753
   626  
   627  	err = testVolumeHandle.SetOwnerUserID(fileInodeNumber, testMetadata.UserID)
   628  	if nil != err {
   629  		t.Fatalf("SetOwnerUserID(fileInodeNumber, %v) failed: %v", testMetadata.UserID, err)
   630  	}
   631  
   632  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   633  	if nil != err {
   634  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   635  	}
   636  	checkMetadata(t, postMetadata, testMetadata, MetadataPermFields, "GetMetadata() after SetOwnerUserID()")
   637  	checkMetadataTimeChanges(t, preMetadata, postMetadata, false, false, false, true, "SetOwnerUserID()")
   638  
   639  	preMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   640  	if nil != err {
   641  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   642  	}
   643  	time.Sleep(time.Millisecond)
   644  
   645  	testMetadata.GroupID = 12345678
   646  
   647  	err = testVolumeHandle.SetOwnerGroupID(fileInodeNumber, testMetadata.GroupID)
   648  	if nil != err {
   649  		t.Fatalf("SetOwnerGroupID(fileInodeNumber, %v) failed: %v", testMetadata.GroupID, err)
   650  	}
   651  
   652  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   653  	if nil != err {
   654  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   655  	}
   656  	checkMetadata(t, postMetadata, testMetadata, MetadataPermFields, "GetMetadata() after SetOwnerGroupID()")
   657  	checkMetadataTimeChanges(t, preMetadata, postMetadata, false, false, false, true, "SetOwnerGroupID()")
   658  
   659  	preMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   660  	if nil != err {
   661  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   662  	}
   663  	time.Sleep(time.Millisecond)
   664  
   665  	testMetadata.UserID = 3579
   666  	testMetadata.GroupID = 87654321
   667  
   668  	err = testVolumeHandle.SetOwnerUserIDGroupID(fileInodeNumber, testMetadata.UserID, testMetadata.GroupID)
   669  	if nil != err {
   670  		t.Fatalf("SetOwnerUserIDGroupID(fileInodeNumber, %v, %v) failed: %v", testMetadata.UserID, testMetadata.GroupID, err)
   671  	}
   672  
   673  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   674  	if nil != err {
   675  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   676  	}
   677  	checkMetadata(t, postMetadata, testMetadata, MetadataPermFields, "GetMetadata() after SetOwnerUserIDGroupID()")
   678  	checkMetadataTimeChanges(t, preMetadata, postMetadata, false, false, false, true, "SetOwnerUserIDGroupID()")
   679  
   680  	err = testVolumeHandle.Link(RootDirInodeNumber, "link_1_to_file_inode", fileInodeNumber, false)
   681  	if nil != err {
   682  		t.Fatalf("Link(RootDirInodeNumber, \"link_1_to_file_inode\", fileInodeNumber, false) failed: %v", err)
   683  	}
   684  
   685  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   686  
   687  	if nil != err {
   688  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   689  	}
   690  	if 3 != numEntries {
   691  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 3")
   692  	}
   693  
   694  	fileLinkCount, err = testVolumeHandle.GetLinkCount(fileInodeNumber)
   695  	if nil != err {
   696  		t.Fatalf("GetLinkCount(fileInodeNumber) failed: %v", err)
   697  	}
   698  	if 1 != fileLinkCount {
   699  		t.Fatalf("GetLinkCount(fileInodeNumber) returned unexpected linkCount: %v", fileLinkCount)
   700  	}
   701  
   702  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   703  	if nil != err {
   704  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   705  	}
   706  	testMetadata.LinkCount = 1
   707  	checkMetadata(t, postMetadata, testMetadata, MetadataLinkCountField, "GetMetadata() after Link()")
   708  
   709  	err = testVolumeHandle.Link(RootDirInodeNumber, "link_2_to_file_inode", fileInodeNumber, false)
   710  	if nil != err {
   711  		t.Fatalf("Link(RootDirInodeNumber, \"link_2_to_file_inode\", fileInodeNumber, false) failed: %v", err)
   712  	}
   713  
   714  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   715  
   716  	if nil != err {
   717  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   718  	}
   719  	if 4 != numEntries {
   720  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 4")
   721  	}
   722  
   723  	fileLinkCount, err = testVolumeHandle.GetLinkCount(fileInodeNumber)
   724  	if nil != err {
   725  		t.Fatalf("GetLinkCount(fileInodeNumber) failed: %v", err)
   726  	}
   727  	if 2 != fileLinkCount {
   728  		t.Fatalf("GetLinkCount(fileInodeNumber) returned unexpected linkCount: %v", fileLinkCount)
   729  	}
   730  
   731  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   732  	if nil != err {
   733  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   734  	}
   735  	testMetadata.LinkCount = 2
   736  	checkMetadata(t, postMetadata, testMetadata, MetadataLinkCountField, "GetMetadata() after Link()")
   737  
   738  	symlinkInodeToLink1ToFileInode, err := testVolumeHandle.CreateSymlink("link_1_to_file_inode", PosixModePerm, 0, 0)
   739  	if nil != err {
   740  		t.Fatalf("CreateSymlink(\"link_1_to_file_inode\") failed: %v", err)
   741  	}
   742  
   743  	symlinkInodeToLink1ToFileInodeType, err := testVolumeHandle.GetType(symlinkInodeToLink1ToFileInode)
   744  	if nil != err {
   745  		t.Fatalf("GetType(symlinkInodeToLink1ToFileInode) failed: %v", err)
   746  	}
   747  	if SymlinkType != symlinkInodeToLink1ToFileInodeType {
   748  		t.Fatalf("GetType(symlinkInodeToLink1ToFileInode) returned unexpected type: %v", symlinkInodeToLink1ToFileInodeType)
   749  	}
   750  
   751  	symlinkToLink1ToFileInodeLinkCount, err := testVolumeHandle.GetLinkCount(symlinkInodeToLink1ToFileInode)
   752  	if nil != err {
   753  		t.Fatalf("GetLinkCount(symlinkInodeToLink1ToFileInode) failed: %v", err)
   754  	}
   755  	if 0 != symlinkToLink1ToFileInodeLinkCount {
   756  		t.Fatalf("GetLinkCount(symlinkInodeToLink1ToFileInode) returned unexpected linkCount: %v", symlinkToLink1ToFileInodeLinkCount)
   757  	}
   758  
   759  	symlinkInodeToLink1ToFileInodeTarget, err := testVolumeHandle.GetSymlink(symlinkInodeToLink1ToFileInode)
   760  	if nil != err {
   761  		t.Fatalf("GetSymlink(symlinkInodeToLink1ToFileInode) failed: %v", err)
   762  	}
   763  	if "link_1_to_file_inode" != symlinkInodeToLink1ToFileInodeTarget {
   764  		t.Fatalf("GetSymlink(symlinkInodeToLink1ToFileInode) should have returned target == \"%v\"... instead got \"%v\"", "link_1_to_file_inode", symlinkInodeToLink1ToFileInodeTarget)
   765  	}
   766  
   767  	err = testVolumeHandle.Link(RootDirInodeNumber, "symlink_to_link_1_to_file_inode", symlinkInodeToLink1ToFileInode, false)
   768  	if nil != err {
   769  		t.Fatalf("Link(RootDirInodeNumber, \"symlink_to_link_1_to_file_inode\", symlinkInodeToLink1ToFileInode, false) failed: %v", err)
   770  	}
   771  
   772  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   773  
   774  	if nil != err {
   775  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   776  	}
   777  	if 5 != numEntries {
   778  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 5")
   779  	}
   780  
   781  	symlinkToLink1ToFileInodeLinkCount, err = testVolumeHandle.GetLinkCount(symlinkInodeToLink1ToFileInode)
   782  	if nil != err {
   783  		t.Fatalf("GetLinkCount(symlinkInodeToLink1ToFileInode) failed: %v", err)
   784  	}
   785  	if 1 != symlinkToLink1ToFileInodeLinkCount {
   786  		t.Fatalf("GetLinkCount(symlinkInodeToLink1ToFileInode) returned unexpected linkCount: %v", symlinkToLink1ToFileInodeLinkCount)
   787  	}
   788  
   789  	symlinkInodeToLink1ToFileInodeLookupResult, err := testVolumeHandle.Lookup(RootDirInodeNumber, "symlink_to_link_1_to_file_inode")
   790  	if nil != err {
   791  		t.Fatalf("Lookup(RootDirInodeNumber, \"symlink_to_link_1_to_file_inode\") failed: %v", err)
   792  	}
   793  	if symlinkInodeToLink1ToFileInodeLookupResult != symlinkInodeToLink1ToFileInode {
   794  		t.Fatalf("Lookup(RootDirInodeNumber, \"symlink_to_link_1_to_file_inode\") returned unexpected InodeNumber")
   795  	}
   796  
   797  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 1, 0)
   798  	if nil != err {
   799  		t.Fatalf("ReadDir(RootDirInodeNumber, 1, 0) failed: %v", err)
   800  	}
   801  	if !moreEntries {
   802  		t.Fatalf("ReadDir(RootDirInodeNumber, 1, 0) should have returned moreEntries == true")
   803  	}
   804  	if 1 != len(dirEntrySlice) {
   805  		t.Fatalf("ReadDir(RootDirInodeNumber, 1, 0) should have returned dirEntrySlice with 1 element, got %v elements", len(dirEntrySlice))
   806  	}
   807  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
   808  		t.Fatalf("ReadDir(RootDirInodeNumber, 1, 0) returned unexpected dirEntrySlice[0]")
   809  	}
   810  
   811  	// 60 = ".." entry length (8 + (2 + 1) + 2 + 8) + "link_1_to_file_inode" entry length (8 + (20 + 1) + 2 + 8)
   812  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0))
   813  	if nil != err {
   814  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0)) failed: %v", err)
   815  	}
   816  	if !moreEntries {
   817  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0)) should have returned moreEntries == true")
   818  	}
   819  	if 2 != len(dirEntrySlice) {
   820  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0)) should have returned dirEntrySlice with 2 elements, got %v elements", len(dirEntrySlice))
   821  	}
   822  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != "..") || (dirEntrySlice[0].NextDirLocation != 2) {
   823  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0)) returned unexpected dirEntrySlice[0]")
   824  	}
   825  	if (dirEntrySlice[1].InodeNumber != fileInodeNumber) || (dirEntrySlice[1].Basename != "link_1_to_file_inode") || (dirEntrySlice[1].NextDirLocation != 3) {
   826  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, InodeDirLocation(0)) returned unexpected dirEntrySlice[1]")
   827  	}
   828  
   829  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 60, ".")
   830  	if nil != err {
   831  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, \".\") failed: %v", err)
   832  	}
   833  	if !moreEntries {
   834  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, \".\") should have returned moreEntries == true")
   835  	}
   836  	if 2 != len(dirEntrySlice) {
   837  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, \".\") should have returned dirEntrySlice with 2 elements, got %v elements", len(dirEntrySlice))
   838  	}
   839  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != "..") || (dirEntrySlice[0].NextDirLocation != 2) {
   840  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, \".\") returned unexpected dirEntrySlice[0]")
   841  	}
   842  	if (dirEntrySlice[1].InodeNumber != fileInodeNumber) || (dirEntrySlice[1].Basename != "link_1_to_file_inode") || (dirEntrySlice[1].NextDirLocation != 3) {
   843  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 60, \".\") returned unexpected dirEntrySlice[1]")
   844  	}
   845  
   846  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2))
   847  	if nil != err {
   848  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2)) failed: %v", err)
   849  	}
   850  	if moreEntries {
   851  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2)) should have returned moreEntries == false")
   852  	}
   853  	if 2 != len(dirEntrySlice) {
   854  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2)) should have returned dirEntrySlice with 2 elements")
   855  	}
   856  	if (dirEntrySlice[0].InodeNumber != fileInodeNumber) || (dirEntrySlice[0].Basename != "link_2_to_file_inode") || (dirEntrySlice[0].NextDirLocation != 4) {
   857  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2)) returned unexpected dirEntrySlice[0]")
   858  	}
   859  	if (dirEntrySlice[1].InodeNumber != symlinkInodeToLink1ToFileInode) || (dirEntrySlice[1].Basename != "symlink_to_link_1_to_file_inode") || (dirEntrySlice[1].NextDirLocation != 5) {
   860  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, InodeDirLocation(2)) returned unexpected dirEntrySlice[1]")
   861  	}
   862  
   863  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0, "link_1_to_file_inode")
   864  	if nil != err {
   865  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"link_1_to_file_inode\") failed: %v", err)
   866  	}
   867  	if moreEntries {
   868  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"link_1_to_file_inode\") should have returned moreEntries == false")
   869  	}
   870  	if 2 != len(dirEntrySlice) {
   871  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"link_1_to_file_inode\") should have returned dirEntrySlice with 2 elements")
   872  	}
   873  	if (dirEntrySlice[0].InodeNumber != fileInodeNumber) || (dirEntrySlice[0].Basename != "link_2_to_file_inode") || (dirEntrySlice[0].NextDirLocation != 4) {
   874  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"link_1_to_file_inode\") returned unexpected dirEntrySlice[0]")
   875  	}
   876  	if (dirEntrySlice[1].InodeNumber != symlinkInodeToLink1ToFileInode) || (dirEntrySlice[1].Basename != "symlink_to_link_1_to_file_inode") || (dirEntrySlice[1].NextDirLocation != 5) {
   877  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0, \"link_1_to_file_inode\") returned unexpected dirEntrySlice[1]")
   878  	}
   879  
   880  	err = testVolumeHandle.Unlink(RootDirInodeNumber, "link_1_to_file_inode", false)
   881  	if nil != err {
   882  		t.Fatalf("Unlink(RootDirInodeNumber, \"link_1_to_file_inode\", false) failed: %v", err)
   883  	}
   884  
   885  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   886  
   887  	if nil != err {
   888  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   889  	}
   890  	if 4 != numEntries {
   891  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 4")
   892  	}
   893  
   894  	err = testVolumeHandle.Unlink(RootDirInodeNumber, "link_2_to_file_inode", false)
   895  	if nil != err {
   896  		t.Fatalf("Unlink(RootDirInodeNumber, \"link_2_to_file_inode\", false) failed: %v", err)
   897  	}
   898  
   899  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   900  
   901  	if nil != err {
   902  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   903  	}
   904  	if 3 != numEntries {
   905  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 3")
   906  	}
   907  
   908  	err = testVolumeHandle.Unlink(RootDirInodeNumber, "symlink_to_link_1_to_file_inode", false)
   909  	if nil != err {
   910  		t.Fatalf("Unlink(RootDirInodeNumber, \"symlink_to_link_1_to_file_inode\", false) failed: %v", err)
   911  	}
   912  
   913  	numEntries, err = testVolumeHandle.NumDirEntries(RootDirInodeNumber)
   914  
   915  	if nil != err {
   916  		t.Fatalf("NumDirEntries(RootDirInodeNumber) failed: %v", err)
   917  	}
   918  	if 2 != numEntries {
   919  		t.Fatalf("NumDirEntries(RootDirInodeNumber) should have returned numEntries == 2")
   920  	}
   921  
   922  	err = testVolumeHandle.Destroy(symlinkInodeToLink1ToFileInode)
   923  	if nil != err {
   924  		t.Fatalf("Destroy(symlinkInodeToLink1ToFileInode) failed: %v", err)
   925  	}
   926  
   927  	err = testVolumeHandle.Flush(fileInodeNumber, false)
   928  	if nil != err {
   929  		t.Fatalf("Flush(fileInodeNumber, false) failed: %v", err)
   930  	}
   931  	err = testVolumeHandle.Purge(fileInodeNumber)
   932  	if nil != err {
   933  		t.Fatalf("Purge(fileInodeNumber) failed: %v", err)
   934  	}
   935  
   936  	err = testVolumeHandle.PutStream(fileInodeNumber, "test_stream", []byte{0x00, 0x01, 0x02})
   937  	if nil != err {
   938  		t.Fatalf("PutStream(fileInodeNumber, \"test_stream\", []byte{0x00, 0x01, 0x02}) failed: %v", err)
   939  	}
   940  
   941  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   942  	if nil != err {
   943  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   944  	}
   945  	if 1 != len(postMetadata.InodeStreamNameSlice) {
   946  		t.Fatalf("GetMetadata(fileInodeNumber) should have returned postMetadata.InodeStreamNameSlice with 1 element")
   947  	}
   948  	if postMetadata.InodeStreamNameSlice[0] != "test_stream" {
   949  		t.Fatalf("GetMetadata(fileInodeNumber) returned unexpected postMetadata.InodeStreamNameSlice[0]")
   950  	}
   951  
   952  	testStreamData, err := testVolumeHandle.GetStream(fileInodeNumber, "test_stream")
   953  	if nil != err {
   954  		t.Fatalf("GetStream(fileInodeNumber, \"test_stream\") failed: %v", err)
   955  	}
   956  	if 0 != bytes.Compare(testStreamData, []byte{0x00, 0x01, 0x02}) {
   957  		t.Fatalf("GetStream(fileInodeNumber, \"test_stream\") returned unexpected testStreamData")
   958  	}
   959  
   960  	err = testVolumeHandle.DeleteStream(fileInodeNumber, "test_stream")
   961  	if nil != err {
   962  		t.Fatalf("DeleteStream(fileInodeNumber, \"test_stream\") failed: %v", err)
   963  	}
   964  
   965  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   966  	if nil != err {
   967  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   968  	}
   969  	if 0 != len(postMetadata.InodeStreamNameSlice) {
   970  		t.Fatalf("GetMetadata(fileInodeNumber) should have returned postMetadata.InodeStreamNameSlice with 0 elements")
   971  	}
   972  
   973  	testMetadata.CreationTime = time.Now().Add(time.Hour)
   974  	err = testVolumeHandle.SetCreationTime(fileInodeNumber, testMetadata.CreationTime)
   975  	if nil != err {
   976  		t.Fatalf("SetCreationTime(fileInodeNumber, oneHourFromNow) failed: %v", err)
   977  	}
   978  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   979  	if nil != err {
   980  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   981  	}
   982  	checkMetadata(t, postMetadata, testMetadata, MetadataCrTimeField,
   983  		"GetMetadata() after SetCreationTime() test 1")
   984  
   985  	testMetadata.ModificationTime = time.Now().Add(2 * time.Hour)
   986  	err = testVolumeHandle.SetModificationTime(fileInodeNumber, testMetadata.ModificationTime)
   987  	if nil != err {
   988  		t.Fatalf("SetModificationTime(fileInodeNumber, twoHoursFromNow) failed: %v", err)
   989  	}
   990  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
   991  	if nil != err {
   992  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
   993  	}
   994  	checkMetadata(t, postMetadata, testMetadata, MetadataModTimeField, "GetMetadata() after SetModificationTime()")
   995  
   996  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() before Write()")
   997  	err = testVolumeHandle.Write(fileInodeNumber, 0, []byte{0x00, 0x01, 0x02, 0x03, 0x04}, nil)
   998  	if nil != err {
   999  		t.Fatalf("Write(fileInodeNumber, 0, []byte{0x00, 0x01, 0x02, 0x03, 0x04}) failed: %v", err)
  1000  	}
  1001  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1002  	if nil != err {
  1003  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1004  	}
  1005  	testMetadata.NumWrites = 1
  1006  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() after Write()")
  1007  
  1008  	err = testVolumeHandle.Flush(fileInodeNumber, false)
  1009  	if err != nil {
  1010  		t.Fatalf("Flush(fileInodeNumber) failed: %v", err)
  1011  	}
  1012  
  1013  	fileInodeObjectPath, err := testVolumeHandle.ProvisionObject()
  1014  	if nil != err {
  1015  		t.Fatalf("ProvisionObjectPath() failed: %v", err)
  1016  	}
  1017  
  1018  	accountName, containerName, objectName, err := utils.PathToAcctContObj(fileInodeObjectPath)
  1019  	if err != nil {
  1020  		t.Fatalf("couldn't parse %v as object path", fileInodeObjectPath)
  1021  	}
  1022  
  1023  	putContext, err := swiftclient.ObjectFetchChunkedPutContext(accountName, containerName, objectName, "")
  1024  
  1025  	if err != nil {
  1026  		t.Fatalf("fetching chunked put context failed")
  1027  	}
  1028  	err = putContext.SendChunk([]byte{0x11, 0x22, 0x33})
  1029  	if err != nil {
  1030  		t.Fatalf("sending chunk failed")
  1031  	}
  1032  	err = putContext.Close()
  1033  	if err != nil {
  1034  		t.Fatalf("closing chunked PUT failed")
  1035  	}
  1036  
  1037  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1038  	if nil != err {
  1039  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1040  	}
  1041  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() before Wrote(,,,,,,true)")
  1042  	err = testVolumeHandle.Wrote(fileInodeNumber, containerName, objectName, []uint64{1}, []uint64{0}, []uint64{3}, true)
  1043  	if nil != err {
  1044  		t.Fatalf("Wrote(fileInodeNumber, containerName, objectName, []uint64{1}, []uint64{0}, []uint64{3}, true) failed: %v", err)
  1045  	}
  1046  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1047  	if nil != err {
  1048  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1049  	}
  1050  	testMetadata.NumWrites = 2
  1051  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() after Wrote(,,,,,,true)")
  1052  
  1053  	testFileInodeData, err := testVolumeHandle.Read(fileInodeNumber, 0, 5, nil)
  1054  	if nil != err {
  1055  		t.Fatalf("Read(fileInodeNumber, 0, 5) failed: %v", err)
  1056  	}
  1057  	if 0 != bytes.Compare(testFileInodeData, []byte{0x00, 0x11, 0x22, 0x33, 0x04}) {
  1058  		t.Fatalf("Read(fileInodeNumber, 0, 5) returned unexpected testFileInodeData")
  1059  	}
  1060  
  1061  	offset := uint64(0)
  1062  	length := uint64(5)
  1063  	testReadPlan, err := testVolumeHandle.GetReadPlan(fileInodeNumber, &offset, &length)
  1064  	if nil != err {
  1065  		t.Fatalf("GetReadPlan(fileInodeNumber, 0, 5) failed: %v", err)
  1066  	}
  1067  	if 3 != len(testReadPlan) {
  1068  		t.Fatalf("GetReadPlan(fileInodeNumber, 0, 5) should have returned testReadPlan with 3 elements")
  1069  	}
  1070  	if (1 != testReadPlan[0].Length) || (fileInodeObjectPath != testReadPlan[1].ObjectPath) || (0 != testReadPlan[1].Offset) || (3 != testReadPlan[1].Length) || (1 != testReadPlan[2].Length) {
  1071  		t.Fatalf("GetReadPlan(fileInodeNumber, 0, 5) returned unexpected testReadPlan")
  1072  	}
  1073  
  1074  	testExtentMapChunk, err := testVolumeHandle.FetchExtentMapChunk(fileInodeNumber, uint64(2), 2, 1)
  1075  	if nil != err {
  1076  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) failed: %v", err)
  1077  	}
  1078  	if 0 != testExtentMapChunk.FileOffsetRangeStart {
  1079  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) should have returned testExtentMapChunk.FileOffsetRangeStart == 0")
  1080  	}
  1081  	if 5 != testExtentMapChunk.FileOffsetRangeEnd {
  1082  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) should have returned testExtentMapChunk.FileOffsetRangeEnd == 5")
  1083  	}
  1084  	if 5 != testExtentMapChunk.FileSize {
  1085  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) should have returned testExtentMapChunk.FileSize == 5")
  1086  	}
  1087  	if 3 != len(testExtentMapChunk.ExtentMapEntry) {
  1088  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) should have returned testExtentMapChunk.ExtentMapEntry slice with 3 elements")
  1089  	}
  1090  	fileInodeObjectPathSplit := strings.Split(fileInodeObjectPath, "/")
  1091  	fileInodeObjectPathContainerName := fileInodeObjectPathSplit[len(fileInodeObjectPathSplit)-2]
  1092  	fileInodeObjectPathObjectName := fileInodeObjectPathSplit[len(fileInodeObjectPathSplit)-1]
  1093  	if (0 != testExtentMapChunk.ExtentMapEntry[0].FileOffset) ||
  1094  		(0 != testExtentMapChunk.ExtentMapEntry[0].LogSegmentOffset) ||
  1095  		(1 != testExtentMapChunk.ExtentMapEntry[0].Length) ||
  1096  		(1 != testExtentMapChunk.ExtentMapEntry[1].FileOffset) ||
  1097  		(0 != testExtentMapChunk.ExtentMapEntry[1].LogSegmentOffset) ||
  1098  		(3 != testExtentMapChunk.ExtentMapEntry[1].Length) ||
  1099  		(fileInodeObjectPathContainerName != testExtentMapChunk.ExtentMapEntry[1].ContainerName) ||
  1100  		(fileInodeObjectPathObjectName != testExtentMapChunk.ExtentMapEntry[1].ObjectName) ||
  1101  		(4 != testExtentMapChunk.ExtentMapEntry[2].FileOffset) ||
  1102  		(4 != testExtentMapChunk.ExtentMapEntry[2].LogSegmentOffset) ||
  1103  		(1 != testExtentMapChunk.ExtentMapEntry[2].Length) {
  1104  		t.Fatalf("FetchExtentMap(fileInodeNumber, uint64(2), 2, 1) returned unexpected testExtentMapChunk.ExtentMapEntry slice")
  1105  	}
  1106  
  1107  	// Suffix byte range query, like "Range: bytes=-2"
  1108  	length = uint64(3)
  1109  	testSuffixReadPlan, err := testVolumeHandle.GetReadPlan(fileInodeNumber, nil, &length)
  1110  	if nil != err {
  1111  		t.Fatalf("GetReadPlan(fileInodeNumber, nil, 3) failed: %v", err)
  1112  	}
  1113  	bytesFromReadPlan := []byte{}
  1114  	for _, rps := range testSuffixReadPlan {
  1115  		pathParts := strings.SplitN(rps.ObjectPath, "/", 5)
  1116  		b, err := swiftclient.ObjectGet(pathParts[2], pathParts[3], pathParts[4], rps.Offset, rps.Length)
  1117  		if err != nil {
  1118  			t.Fatalf("ObjectGet() returned unexpected error %v", err)
  1119  		}
  1120  		bytesFromReadPlan = append(bytesFromReadPlan, b...)
  1121  	}
  1122  	if !bytes.Equal(bytesFromReadPlan, []byte{0x22, 0x33, 0x04}) {
  1123  		t.Fatalf("expected bytes from suffix read plan 0x22, 0x33, 0x04; got %v", bytesFromReadPlan)
  1124  	}
  1125  
  1126  	// Long suffix byte range query, like "Range: bytes=-200" (for a file of size < 200)
  1127  	length = uint64(10) // our file has only 5 bytes
  1128  	testSuffixReadPlan, err = testVolumeHandle.GetReadPlan(fileInodeNumber, nil, &length)
  1129  	if nil != err {
  1130  		t.Fatalf("GetReadPlan(fileInodeNumber, nil, 10) failed: %v", err)
  1131  	}
  1132  	bytesFromReadPlan = []byte{}
  1133  	for _, rps := range testSuffixReadPlan {
  1134  		pathParts := strings.SplitN(rps.ObjectPath, "/", 5)
  1135  		b, err := swiftclient.ObjectGet(pathParts[2], pathParts[3], pathParts[4], rps.Offset, rps.Length)
  1136  		if err != nil {
  1137  			t.Fatalf("ObjectGet() returned unexpected error %v", err)
  1138  		}
  1139  		bytesFromReadPlan = append(bytesFromReadPlan, b...)
  1140  	}
  1141  	if !bytes.Equal(bytesFromReadPlan, []byte{0x00, 0x11, 0x22, 0x33, 0x04}) {
  1142  		t.Fatalf("expected bytes from suffix read plan 0x00, 0x11, 0x22, 0x33, 0x04; got %v", bytesFromReadPlan)
  1143  	}
  1144  
  1145  	// Prefix byte range query, like "Range: bytes=4-"
  1146  	offset = uint64(3)
  1147  	testPrefixReadPlan, err := testVolumeHandle.GetReadPlan(fileInodeNumber, &offset, nil)
  1148  	if nil != err {
  1149  		t.Fatalf("GetReadPlan(fileInodeNumber, 3, nil) failed: %v", err)
  1150  	}
  1151  	bytesFromReadPlan = []byte{}
  1152  	for _, rps := range testPrefixReadPlan {
  1153  		pathParts := strings.SplitN(rps.ObjectPath, "/", 5)
  1154  		b, err := swiftclient.ObjectGet(pathParts[2], pathParts[3], pathParts[4], rps.Offset, rps.Length)
  1155  		if err != nil {
  1156  			t.Fatalf("ObjectGet() returned unexpected error %v", err)
  1157  		}
  1158  		bytesFromReadPlan = append(bytesFromReadPlan, b...)
  1159  	}
  1160  	if !bytes.Equal(bytesFromReadPlan, []byte{0x33, 0x04}) {
  1161  		t.Fatalf("expected bytes from prefix read plan 0x33, 0x04; got %v", bytesFromReadPlan)
  1162  	}
  1163  
  1164  	accountName, containerName, objectName, err = utils.PathToAcctContObj(testReadPlan[0].ObjectPath)
  1165  	if nil != err {
  1166  		t.Fatalf("expected %q to be a legal object path", testReadPlan[0].ObjectPath)
  1167  	}
  1168  
  1169  	headSlice, err := swiftclient.ObjectGet(accountName, containerName, objectName, testReadPlan[0].Offset, 1)
  1170  	if nil != err {
  1171  		t.Fatalf("ObjectGet() returned unexpected error: %v", err)
  1172  	}
  1173  	if 0 != bytes.Compare(headSlice, []byte{0x00}) {
  1174  		t.Fatalf("expected byte of %v to be 0x00, got %x", testReadPlan[0].ObjectPath, headSlice)
  1175  	}
  1176  
  1177  	accountName, containerName, objectName, err = utils.PathToAcctContObj(testReadPlan[1].ObjectPath)
  1178  	if nil != err {
  1179  		t.Fatalf("expected %q to be a legal object path", testReadPlan[1].ObjectPath)
  1180  	}
  1181  	middleSlice, err := swiftclient.ObjectGet(accountName, containerName, objectName, testReadPlan[1].Offset, 3)
  1182  	if nil != err {
  1183  		t.Fatalf("ObjectGet() returned unexpected error: %v", err)
  1184  	}
  1185  	if 0 != bytes.Compare(middleSlice, []byte{0x11, 0x22, 0x33}) {
  1186  		t.Fatalf("expected byte of %v to be 0x00, got %x", testReadPlan[0].ObjectPath, headSlice)
  1187  	}
  1188  
  1189  	accountName, containerName, objectName, err = utils.PathToAcctContObj(testReadPlan[2].ObjectPath)
  1190  	if nil != err {
  1191  		t.Fatalf("expected %q to be a legal object path", testReadPlan[2].ObjectPath)
  1192  	}
  1193  	tailSlice, err := swiftclient.ObjectGet(accountName, containerName, objectName, testReadPlan[2].Offset, 1)
  1194  	if nil != err {
  1195  		t.Fatalf("objectContext.Get() returned unexpected error: %v", err)
  1196  	}
  1197  	if 0 != bytes.Compare(tailSlice, []byte{0x04}) {
  1198  		t.Fatalf("expected byte of %v to be 0x04, got %x", testReadPlan[0].ObjectPath, tailSlice)
  1199  	}
  1200  
  1201  	fileInodeObjectPath, err = testVolumeHandle.ProvisionObject()
  1202  	if nil != err {
  1203  		t.Fatalf("ProvisionObjectPath() failed: %v", err)
  1204  	}
  1205  
  1206  	accountName, containerName, objectName, err = utils.PathToAcctContObj(fileInodeObjectPath)
  1207  	if err != nil {
  1208  		t.Fatalf("couldn't parse %v as object path", fileInodeObjectPath)
  1209  	}
  1210  
  1211  	putContext, err = swiftclient.ObjectFetchChunkedPutContext(accountName, containerName, objectName, "")
  1212  	if err != nil {
  1213  		t.Fatalf("fetching chunked put context failed")
  1214  	}
  1215  	err = putContext.SendChunk([]byte{0xFE, 0xFF})
  1216  	if err != nil {
  1217  		t.Fatalf("sending chunk failed")
  1218  	}
  1219  	err = putContext.Close()
  1220  	if err != nil {
  1221  		t.Fatalf("closing chunked PUT failed")
  1222  	}
  1223  
  1224  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1225  	if nil != err {
  1226  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1227  	}
  1228  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() before Wrote(,,,,,,false)")
  1229  	err = testVolumeHandle.Wrote(fileInodeNumber, containerName, objectName, []uint64{0}, []uint64{0}, []uint64{2}, false)
  1230  	if nil != err {
  1231  		t.Fatalf("Wrote(fileInodeNumber, containerName, objectName, []uint64{0}, []uint64{0}, []uint64{2}, false) failed: %v", err)
  1232  	}
  1233  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1234  	if nil != err {
  1235  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1236  	}
  1237  	testMetadata.NumWrites = 1
  1238  	checkMetadata(t, postMetadata, testMetadata, MetadataNumWritesField, "GetMetadata() after Wrote(,,,,,,false)")
  1239  
  1240  	testFileInodeData, err = testVolumeHandle.Read(fileInodeNumber, 0, 4, nil)
  1241  	if nil != err {
  1242  		t.Fatalf("Read(fileInodeNumber, 0, 4) failed: %v", err)
  1243  	}
  1244  	if 0 != bytes.Compare(testFileInodeData, []byte{0xFE, 0xFF}) {
  1245  		t.Fatalf("Read(fileInodeNumber, 0, 4) returned unexpected testFileInodeData")
  1246  	}
  1247  
  1248  	preResizeMetadata, err := testVolumeHandle.GetMetadata(fileInodeNumber)
  1249  	if nil != err {
  1250  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1251  	}
  1252  
  1253  	testMetadata.Size = 0
  1254  	err = testVolumeHandle.SetSize(fileInodeNumber, testMetadata.Size)
  1255  	if nil != err {
  1256  		t.Fatalf("SetSize(fileInodeNumber, 0) failed: %v", err)
  1257  	}
  1258  
  1259  	postMetadata, err = testVolumeHandle.GetMetadata(fileInodeNumber)
  1260  	if nil != err {
  1261  		t.Fatalf("GetMetadata(fileInodeNumber) failed: %v", err)
  1262  	}
  1263  	checkMetadata(t, postMetadata, testMetadata, MetadataSizeField, "GetMetadata() after SetSize()")
  1264  	checkMetadataTimeChanges(t, preResizeMetadata, postMetadata, false, true, false, true, "SetSize changed metadata times inappropriately")
  1265  
  1266  	err = testVolumeHandle.Flush(fileInodeNumber, true)
  1267  	if nil != err {
  1268  		t.Fatalf("Flush(fileInodeNumber, true) failed: %v", err)
  1269  	}
  1270  
  1271  	err = testVolumeHandle.Destroy(fileInodeNumber)
  1272  	if nil != err {
  1273  		t.Fatalf("Destroy(fileInodeNumber) failed: %v", err)
  1274  	}
  1275  
  1276  	file1Inode, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0)
  1277  	if nil != err {
  1278  		t.Fatalf("CreateFile() failed: %v", err)
  1279  	}
  1280  
  1281  	file2Inode, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0)
  1282  	if nil != err {
  1283  		t.Fatalf("CreateFile() failed: %v", err)
  1284  	}
  1285  
  1286  	err = testVolumeHandle.Link(RootDirInodeNumber, "1stLocation", file1Inode, false)
  1287  	if nil != err {
  1288  		t.Fatalf("Link(RootDirInodeNumber, \"1stLocation\", file1Inode, false) failed: %v", err)
  1289  	}
  1290  
  1291  	err = testVolumeHandle.Link(RootDirInodeNumber, "3rdLocation", file2Inode, false)
  1292  	if nil != err {
  1293  		t.Fatalf("Link(RootDirInodeNumber, \"3rdLocation\", file2Inode, false) failed: %v", err)
  1294  	}
  1295  
  1296  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
  1297  	if nil != err {
  1298  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
  1299  	}
  1300  	if moreEntries {
  1301  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
  1302  	}
  1303  	if 4 != len(dirEntrySlice) {
  1304  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements")
  1305  	}
  1306  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1307  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
  1308  	}
  1309  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1310  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
  1311  	}
  1312  	if (dirEntrySlice[2].InodeNumber != file1Inode) || (dirEntrySlice[2].Basename != "1stLocation") || (dirEntrySlice[2].NextDirLocation != 3) {
  1313  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1314  	}
  1315  	if (dirEntrySlice[3].InodeNumber != file2Inode) || (dirEntrySlice[3].Basename != "3rdLocation") || (dirEntrySlice[3].NextDirLocation != 4) {
  1316  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1317  	}
  1318  
  1319  	err = testVolumeHandle.Move(RootDirInodeNumber, "1stLocation", RootDirInodeNumber, "2ndLocation")
  1320  	if nil != err {
  1321  		t.Fatalf("Move(RootDirInodeNumber, \"1stLocation\", RootDirInodeNumber, \"2ndLocation\") failed: %v", err)
  1322  	}
  1323  
  1324  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
  1325  	if nil != err {
  1326  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
  1327  	}
  1328  	if moreEntries {
  1329  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
  1330  	}
  1331  	if 4 != len(dirEntrySlice) {
  1332  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements")
  1333  	}
  1334  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1335  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
  1336  	}
  1337  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1338  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
  1339  	}
  1340  	if (dirEntrySlice[2].InodeNumber != file1Inode) || (dirEntrySlice[2].Basename != "2ndLocation") || (dirEntrySlice[2].NextDirLocation != 3) {
  1341  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1342  	}
  1343  	if (dirEntrySlice[3].InodeNumber != file2Inode) || (dirEntrySlice[3].Basename != "3rdLocation") || (dirEntrySlice[3].NextDirLocation != 4) {
  1344  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1345  	}
  1346  
  1347  	err = testVolumeHandle.Unlink(RootDirInodeNumber, "3rdLocation", false)
  1348  	if nil != err {
  1349  		t.Fatalf("Unlink(RootDirInodeNumber, \"3rdLocation\", false) failed: %v", err)
  1350  	}
  1351  	err = testVolumeHandle.Move(RootDirInodeNumber, "2ndLocation", RootDirInodeNumber, "3rdLocation")
  1352  	if nil != err {
  1353  		t.Fatalf("Move(RootDirInodeNumber, \"2ndLocation\", RootDirInodeNumber, \"3rdLocation\") failed: %v", err)
  1354  	}
  1355  
  1356  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
  1357  	if nil != err {
  1358  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
  1359  	}
  1360  	if moreEntries {
  1361  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
  1362  	}
  1363  	if 3 != len(dirEntrySlice) {
  1364  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements")
  1365  	}
  1366  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1367  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
  1368  	}
  1369  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1370  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
  1371  	}
  1372  	if (dirEntrySlice[2].InodeNumber != file1Inode) || (dirEntrySlice[2].Basename != "3rdLocation") || (dirEntrySlice[2].NextDirLocation != 3) {
  1373  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1374  	}
  1375  
  1376  	err = testVolumeHandle.Destroy(file2Inode)
  1377  	if nil != err {
  1378  		t.Fatalf("Destroy(file2Inode) failed: %v", err)
  1379  	}
  1380  
  1381  	postMetadata, err = testVolumeHandle.GetMetadata(RootDirInodeNumber)
  1382  	if nil != err {
  1383  		t.Fatalf("GetMetadata(RootDirInodeNumber) failed: %v", err)
  1384  	}
  1385  	testMetadata.LinkCount = 2
  1386  	checkMetadata(t, postMetadata, testMetadata, MetadataLinkCountField, "GetMetadata() after multiple calls to Link()")
  1387  
  1388  	subDirInode, err := testVolumeHandle.CreateDir(PosixModePerm, 0, 0)
  1389  	if nil != err {
  1390  		t.Fatalf("CreateDir() failed: %v", err)
  1391  	}
  1392  
  1393  	subDirInodeType, err := testVolumeHandle.GetType(subDirInode)
  1394  	if nil != err {
  1395  		t.Fatalf("GetType(subDirInode) failed: %v", err)
  1396  	}
  1397  	if DirType != subDirInodeType {
  1398  		t.Fatalf("GetType(subDirInode) returned unexpected type: %v", subDirInodeType)
  1399  	}
  1400  
  1401  	subDirLinkCount, err := testVolumeHandle.GetLinkCount(subDirInode)
  1402  	if nil != err {
  1403  		t.Fatalf("GetLinkCount(subDirInode) failed: %v", err)
  1404  	}
  1405  	if 1 != subDirLinkCount {
  1406  		t.Fatalf("GetLinkCount(subDirInode) returned unexpected linkCount: %v", subDirLinkCount)
  1407  	}
  1408  
  1409  	err = testVolumeHandle.SetLinkCount(subDirInode, uint64(2))
  1410  	if nil != err {
  1411  		t.Fatalf("SetLinkCount(subDirInode, uint64(2)) failed: %v", err)
  1412  	}
  1413  
  1414  	subDirLinkCount, err = testVolumeHandle.GetLinkCount(subDirInode)
  1415  	if nil != err {
  1416  		t.Fatalf("GetLinkCount(subDirInode) failed: %v", err)
  1417  	}
  1418  	if 2 != subDirLinkCount {
  1419  		t.Fatalf("GetLinkCount(subDirInode) returned unexpected linkCount: %v", subDirLinkCount)
  1420  	}
  1421  
  1422  	err = testVolumeHandle.SetLinkCount(subDirInode, uint64(1))
  1423  	if nil != err {
  1424  		t.Fatalf("SetLinkCount(subDirInode, uint64(1)) failed: %v", err)
  1425  	}
  1426  
  1427  	subDirLinkCount, err = testVolumeHandle.GetLinkCount(subDirInode)
  1428  	if nil != err {
  1429  		t.Fatalf("GetLinkCount(subDirInode) failed: %v", err)
  1430  	}
  1431  	if 1 != subDirLinkCount {
  1432  		t.Fatalf("GetLinkCount(subDirInode) returned unexpected linkCount: %v", subDirLinkCount)
  1433  	}
  1434  
  1435  	// it should be illeagal to link to a directory
  1436  	err = testVolumeHandle.Link(RootDirInodeNumber, "subDir", subDirInode, false)
  1437  	if nil != err {
  1438  		t.Fatalf("Link(RootDirInodeNumber, \"subDir\", subDirInode, false) failed: %v", err)
  1439  	}
  1440  
  1441  	rootDirLinkCount, err = testVolumeHandle.GetLinkCount(RootDirInodeNumber)
  1442  	if nil != err {
  1443  		t.Fatalf("GetLinkCount(RootDirInodeNumber) failed: %v", err)
  1444  	}
  1445  	if 3 != rootDirLinkCount {
  1446  		t.Fatalf("GetLinkCount(RootDirInodeNumber) returned unexpected linkCount: %v", rootDirLinkCount)
  1447  	}
  1448  
  1449  	subDirLinkCount, err = testVolumeHandle.GetLinkCount(subDirInode)
  1450  	if nil != err {
  1451  		t.Fatalf("GetLinkCount(subDirInode) failed: %v", err)
  1452  	}
  1453  	if 2 != subDirLinkCount {
  1454  		t.Fatalf("GetLinkCount(subDirInode) returned unexpected linkCount: %v", subDirLinkCount)
  1455  	}
  1456  
  1457  	postMetadata, err = testVolumeHandle.GetMetadata(RootDirInodeNumber)
  1458  	if nil != err {
  1459  		t.Fatalf("GetMetadata(RootDirInodeNumber) failed: %v", err)
  1460  	}
  1461  	testMetadata.LinkCount = 3
  1462  	checkMetadata(t, postMetadata, testMetadata, MetadataLinkCountField, "GetMetadata() after Link()")
  1463  
  1464  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
  1465  	if nil != err {
  1466  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
  1467  	}
  1468  	if moreEntries {
  1469  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
  1470  	}
  1471  	if 4 != len(dirEntrySlice) {
  1472  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements, got %#v, which is of length %v", dirEntrySlice, len(dirEntrySlice))
  1473  	}
  1474  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1475  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
  1476  	}
  1477  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1478  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
  1479  	}
  1480  	if (dirEntrySlice[2].InodeNumber != file1Inode) || (dirEntrySlice[2].Basename != "3rdLocation") || (dirEntrySlice[2].NextDirLocation != 3) {
  1481  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1482  	}
  1483  	if (dirEntrySlice[3].InodeNumber != subDirInode) || (dirEntrySlice[3].Basename != "subDir") || (dirEntrySlice[3].NextDirLocation != 4) {
  1484  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[3]")
  1485  	}
  1486  
  1487  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(subDirInode, 0, 0)
  1488  	if nil != err {
  1489  		t.Fatalf("ReadDir(subDirInode, 0, 0) failed: %v", err)
  1490  	}
  1491  	if moreEntries {
  1492  		t.Fatalf("ReadDir(subDirInode, 0, 0) should have returned moreEntries == false")
  1493  	}
  1494  	if 2 != len(dirEntrySlice) {
  1495  		t.Fatalf("ReadDir(subDirInode, 0, 0) should have returned dirEntrySlice with 2 elements")
  1496  	}
  1497  	if (dirEntrySlice[0].InodeNumber != subDirInode) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1498  		t.Fatalf("ReadDir(subDirInode, 0, 0) returned unexpected dirEntrySlice[0]")
  1499  	}
  1500  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1501  		t.Fatalf("ReadDir(subDirInode, 0, 0) returned unexpected dirEntrySlice[1]")
  1502  	}
  1503  
  1504  	err = testVolumeHandle.Move(RootDirInodeNumber, "3rdLocation", subDirInode, "4thLocation")
  1505  	if nil != err {
  1506  		t.Fatalf("Move(RootDirInodeNumber, \"3rdLocation\", subDirInode, \"4thLocation\") failed: %v", err)
  1507  	}
  1508  
  1509  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(RootDirInodeNumber, 0, 0)
  1510  	if nil != err {
  1511  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) failed: %v", err)
  1512  	}
  1513  	if moreEntries {
  1514  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned moreEntries == false")
  1515  	}
  1516  	if 3 != len(dirEntrySlice) {
  1517  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) should have returned dirEntrySlice with 2 elements, got %#v", dirEntrySlice)
  1518  	}
  1519  	if (dirEntrySlice[0].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1520  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[0]")
  1521  	}
  1522  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1523  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[1]")
  1524  	}
  1525  	if (dirEntrySlice[2].InodeNumber != subDirInode) || (dirEntrySlice[2].Basename != "subDir") || (dirEntrySlice[2].NextDirLocation != 3) {
  1526  		t.Fatalf("ReadDir(RootDirInodeNumber, 0, 0) returned unexpected dirEntrySlice[2]")
  1527  	}
  1528  
  1529  	dirEntrySlice, moreEntries, err = testVolumeHandle.ReadDir(subDirInode, 0, 0)
  1530  	if nil != err {
  1531  		t.Fatalf("ReadDir(subDirInode, 0, 0) failed: %v", err)
  1532  	}
  1533  	if moreEntries {
  1534  		t.Fatalf("ReadDir(subDirInode, 0, 0) should have returned moreEntries == false")
  1535  	}
  1536  	if 3 != len(dirEntrySlice) {
  1537  		t.Fatalf("ReadDir(subDirInode, 0, 0) should have returned dirEntrySlice with 2 elements")
  1538  	}
  1539  	if (dirEntrySlice[0].InodeNumber != subDirInode) || (dirEntrySlice[0].Basename != ".") || (dirEntrySlice[0].NextDirLocation != 1) {
  1540  		t.Fatalf("ReadDir(subDirInode, 0, 0) returned unexpected dirEntrySlice[0]")
  1541  	}
  1542  	if (dirEntrySlice[1].InodeNumber != RootDirInodeNumber) || (dirEntrySlice[1].Basename != "..") || (dirEntrySlice[1].NextDirLocation != 2) {
  1543  		t.Fatalf("ReadDir(subDirInode, 0, 0) returned unexpected dirEntrySlice[1]")
  1544  	}
  1545  	if (dirEntrySlice[2].InodeNumber != file1Inode) || (dirEntrySlice[2].Basename != "4thLocation") || (dirEntrySlice[2].NextDirLocation != 3) {
  1546  		t.Fatalf("ReadDir(subDirInode, 0, 0) returned unexpected dirEntrySlice[2]")
  1547  	}
  1548  
  1549  	err = testVolumeHandle.Unlink(subDirInode, "4thLocation", false)
  1550  	if nil != err {
  1551  		t.Fatalf("Unlink(subDirInode, \"4thLocation\", false) failed: %v", err)
  1552  	}
  1553  
  1554  	err = testVolumeHandle.Destroy(file1Inode)
  1555  	if nil != err {
  1556  		t.Fatalf("Destroy(file1Inode) failed: %v", err)
  1557  	}
  1558  
  1559  	err = testVolumeHandle.Unlink(RootDirInodeNumber, "subDir", false)
  1560  	if nil != err {
  1561  		t.Fatalf("Unlink(RootDirInodeNumber, \"subDir\", false) failed: %v", err)
  1562  	}
  1563  
  1564  	rootDirLinkCount, err = testVolumeHandle.GetLinkCount(RootDirInodeNumber)
  1565  	if nil != err {
  1566  		t.Fatalf("GetLinkCount(RootDirInodeNumber) failed: %v", err)
  1567  	}
  1568  	if 2 != rootDirLinkCount {
  1569  		t.Fatalf("GetLinkCount(RootDirInodeNumber) returned unexpected linkCount: %v", rootDirLinkCount)
  1570  	}
  1571  
  1572  	subDirLinkCount, err = testVolumeHandle.GetLinkCount(subDirInode)
  1573  	if nil != err {
  1574  		t.Fatalf("GetLinkCount(subDirInode) failed: %v", err)
  1575  	}
  1576  	if 1 != subDirLinkCount {
  1577  		t.Fatalf("GetLinkCount(subDirInode) returned unexpected linkCount: %v", subDirLinkCount)
  1578  	}
  1579  
  1580  	err = testVolumeHandle.Destroy(subDirInode)
  1581  	if nil != err {
  1582  		t.Fatalf("Destroy(subDirInode) failed: %v", err)
  1583  	}
  1584  
  1585  	positiveDurationToDelayOrSkew, err := time.ParseDuration("+" + durationToDelayOrSkew)
  1586  	if nil != err {
  1587  		t.Fatalf("time.ParseDuration(\"100ms\") failed: %v", err)
  1588  	}
  1589  	negativeDurationToDelayOrSkew, err := time.ParseDuration("-" + durationToDelayOrSkew)
  1590  	if nil != err {
  1591  		t.Fatalf("time.ParseDuration(\"-100ms\") failed: %v", err)
  1592  	}
  1593  
  1594  	timeBeforeCreateDir := time.Now()
  1595  
  1596  	time.Sleep(positiveDurationToDelayOrSkew)
  1597  
  1598  	testMetadata.Mode = InodeMode(0744)
  1599  	testMetadata.UserID = InodeUserID(987)
  1600  	testMetadata.GroupID = InodeGroupID(654)
  1601  	dirInode, err := testVolumeHandle.CreateDir(testMetadata.Mode, testMetadata.UserID, testMetadata.GroupID)
  1602  	if nil != err {
  1603  		t.Fatalf("CreateDir() failed: %v", err)
  1604  	}
  1605  
  1606  	time.Sleep(positiveDurationToDelayOrSkew)
  1607  
  1608  	timeAfterCreateDir := time.Now()
  1609  
  1610  	dirInodeMetadataAfterCreateDir, err := testVolumeHandle.GetMetadata(dirInode)
  1611  	if nil != err {
  1612  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1613  	}
  1614  	if dirInodeMetadataAfterCreateDir.CreationTime.Before(timeBeforeCreateDir) || dirInodeMetadataAfterCreateDir.CreationTime.After(timeAfterCreateDir) {
  1615  		t.Fatalf("dirInodeMetadataAfterCreateDir.CreationTime unexpected")
  1616  	}
  1617  	if !dirInodeMetadataAfterCreateDir.ModificationTime.Equal(dirInodeMetadataAfterCreateDir.CreationTime) {
  1618  		t.Fatalf("dirInodeMetadataAfterCreateDir.ModificationTime unexpected")
  1619  	}
  1620  	if !dirInodeMetadataAfterCreateDir.AccessTime.Equal(dirInodeMetadataAfterCreateDir.CreationTime) {
  1621  		t.Fatalf("dirInodeMetadataAfterCreateDir.AccessTime unexpected")
  1622  	}
  1623  	if !dirInodeMetadataAfterCreateDir.AttrChangeTime.Equal(dirInodeMetadataAfterCreateDir.CreationTime) {
  1624  		t.Fatalf("dirInodeMetadataAfterCreateDir.AttrChangeTime unexpected")
  1625  	}
  1626  	checkMetadata(t, dirInodeMetadataAfterCreateDir, testMetadata, MetadataPermFields, "GetMetadata() after CreateDir()")
  1627  
  1628  	// XXX TODO: Add more tests related to mode/uid/gid and CreateDir(): mode > 0777, etc.
  1629  
  1630  	testMetadata.CreationTime = dirInodeMetadataAfterCreateDir.CreationTime.Add(negativeDurationToDelayOrSkew)
  1631  	testMetadata.ModificationTime = dirInodeMetadataAfterCreateDir.ModificationTime
  1632  	testMetadata.AccessTime = dirInodeMetadataAfterCreateDir.AccessTime
  1633  	testMetadata.AttrChangeTime = dirInodeMetadataAfterCreateDir.AttrChangeTime
  1634  
  1635  	timeBeforeOp = time.Now()
  1636  	time.Sleep(positiveDurationToDelayOrSkew)
  1637  
  1638  	err = testVolumeHandle.SetCreationTime(dirInode, testMetadata.CreationTime)
  1639  	if nil != err {
  1640  		t.Fatalf("SetCreationTime(dirInode,) failed: %v", err)
  1641  	}
  1642  	time.Sleep(positiveDurationToDelayOrSkew)
  1643  	timeAfterOp = time.Now()
  1644  
  1645  	dirInodeMetadataAfterSetCreationTime, err := testVolumeHandle.GetMetadata(dirInode)
  1646  	if nil != err {
  1647  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1648  	}
  1649  	checkMetadata(t, dirInodeMetadataAfterSetCreationTime, testMetadata, MetadataNotAttrTimeFields,
  1650  		"GetMetadata() after SetCreationTime() test 2")
  1651  	if dirInodeMetadataAfterSetCreationTime.AttrChangeTime.Before(timeBeforeOp) ||
  1652  		dirInodeMetadataAfterSetCreationTime.AttrChangeTime.After(timeAfterOp) {
  1653  		t.Fatalf("dirInodeMetadataAfterSetCreationTime.AttrChangeTime unexpected")
  1654  	}
  1655  
  1656  	testMetadata.ModificationTime = dirInodeMetadataAfterSetCreationTime.ModificationTime.Add(negativeDurationToDelayOrSkew)
  1657  	timeBeforeOp = time.Now()
  1658  	time.Sleep(positiveDurationToDelayOrSkew)
  1659  
  1660  	err = testVolumeHandle.SetModificationTime(dirInode, testMetadata.ModificationTime)
  1661  	if nil != err {
  1662  		t.Fatalf("SetModificationTime(dirInode,) failed: %v", err)
  1663  	}
  1664  	time.Sleep(positiveDurationToDelayOrSkew)
  1665  	timeAfterOp = time.Now()
  1666  
  1667  	dirInodeMetadataAfterSetModificationTime, err := testVolumeHandle.GetMetadata(dirInode)
  1668  	if nil != err {
  1669  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1670  	}
  1671  	checkMetadata(t, dirInodeMetadataAfterSetModificationTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after SetModificationTime()")
  1672  	if dirInodeMetadataAfterSetModificationTime.AttrChangeTime.Before(timeBeforeOp) ||
  1673  		dirInodeMetadataAfterSetModificationTime.AttrChangeTime.After(timeAfterOp) {
  1674  		t.Fatalf("dirInodeMetadataAfterSetModificationTime.AttrChangeTime unexpected")
  1675  	}
  1676  
  1677  	testMetadata.AccessTime = dirInodeMetadataAfterSetModificationTime.AccessTime.Add(negativeDurationToDelayOrSkew)
  1678  	timeBeforeOp = time.Now()
  1679  	time.Sleep(positiveDurationToDelayOrSkew)
  1680  
  1681  	err = testVolumeHandle.SetAccessTime(dirInode, testMetadata.AccessTime)
  1682  	if nil != err {
  1683  		t.Fatalf("SetAccessTime(dirInode,) failed: %v", err)
  1684  	}
  1685  	time.Sleep(positiveDurationToDelayOrSkew)
  1686  	timeAfterOp = time.Now()
  1687  
  1688  	dirInodeMetadataAfterSetAccessTime, err := testVolumeHandle.GetMetadata(dirInode)
  1689  	if nil != err {
  1690  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1691  	}
  1692  	checkMetadata(t, dirInodeMetadataAfterSetAccessTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after testVolumeHandle.SetAccessTime()")
  1693  	if dirInodeMetadataAfterSetAccessTime.AttrChangeTime.Before(timeBeforeOp) ||
  1694  		dirInodeMetadataAfterSetAccessTime.AttrChangeTime.After(timeAfterOp) {
  1695  		t.Fatalf("dirInodeMetadataAfterSetAccessTime.AttrChangeTime unexpected")
  1696  	}
  1697  
  1698  	timeBeforeDirInodePutStream := time.Now()
  1699  
  1700  	time.Sleep(positiveDurationToDelayOrSkew)
  1701  
  1702  	err = testVolumeHandle.PutStream(dirInode, "stream_name", []byte{})
  1703  	if nil != err {
  1704  		t.Fatalf("PutStream(dirInode,,) failed: %v", err)
  1705  	}
  1706  	time.Sleep(positiveDurationToDelayOrSkew)
  1707  
  1708  	timeAfterDirInodePutStream := time.Now()
  1709  
  1710  	dirInodeMetadataAfterPutStream, err := testVolumeHandle.GetMetadata(dirInode)
  1711  	if nil != err {
  1712  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1713  	}
  1714  	testMetadata.CreationTime = dirInodeMetadataAfterSetAccessTime.CreationTime
  1715  	testMetadata.ModificationTime = dirInodeMetadataAfterSetAccessTime.ModificationTime
  1716  	testMetadata.AccessTime = dirInodeMetadataAfterSetAccessTime.AccessTime
  1717  	checkMetadata(t, dirInodeMetadataAfterPutStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after PutStream()")
  1718  	if dirInodeMetadataAfterPutStream.AttrChangeTime.Before(timeBeforeDirInodePutStream) || dirInodeMetadataAfterPutStream.AttrChangeTime.After(timeAfterDirInodePutStream) {
  1719  		t.Fatalf("dirInodeMetadataAfterPutStream.AttrChangeTime unexpected")
  1720  	}
  1721  
  1722  	timeBeforeDirInodeDeleteStream := time.Now()
  1723  
  1724  	time.Sleep(positiveDurationToDelayOrSkew)
  1725  
  1726  	err = testVolumeHandle.DeleteStream(dirInode, "stream_name")
  1727  	if nil != err {
  1728  		t.Fatalf("DeleteStream(dirInode,) failed: %v", err)
  1729  	}
  1730  
  1731  	time.Sleep(positiveDurationToDelayOrSkew)
  1732  
  1733  	timeAfterDirInodeDeleteStream := time.Now()
  1734  
  1735  	dirInodeMetadataAfterDeleteStream, err := testVolumeHandle.GetMetadata(dirInode)
  1736  	if nil != err {
  1737  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  1738  	}
  1739  	checkMetadata(t, dirInodeMetadataAfterPutStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after PutStream()")
  1740  	if dirInodeMetadataAfterDeleteStream.AttrChangeTime.Before(timeBeforeDirInodeDeleteStream) || dirInodeMetadataAfterDeleteStream.AttrChangeTime.After(timeAfterDirInodeDeleteStream) {
  1741  		t.Fatalf("dirInodeMetadataAfterDeleteStream.AttrChangeTime unexpected")
  1742  	}
  1743  
  1744  	timeBeforeCreateFile := time.Now()
  1745  
  1746  	time.Sleep(positiveDurationToDelayOrSkew)
  1747  
  1748  	fileInode, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0)
  1749  	if nil != err {
  1750  		t.Fatalf("CreateFile() failed: %v", err)
  1751  	}
  1752  
  1753  	time.Sleep(positiveDurationToDelayOrSkew)
  1754  
  1755  	timeAfterCreateFile := time.Now()
  1756  
  1757  	fileInodeMetadataAfterCreateFile, err := testVolumeHandle.GetMetadata(fileInode)
  1758  	if nil != err {
  1759  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1760  	}
  1761  	if fileInodeMetadataAfterCreateFile.CreationTime.Before(timeBeforeCreateFile) || fileInodeMetadataAfterCreateFile.CreationTime.After(timeAfterCreateFile) {
  1762  		t.Fatalf("fileInodeMetadataAfterCreateDir.CreationTime unexpected")
  1763  	}
  1764  	if !fileInodeMetadataAfterCreateFile.ModificationTime.Equal(fileInodeMetadataAfterCreateFile.CreationTime) {
  1765  		t.Fatalf("fileInodeMetadataAfterCreateDir.ModificationTime unexpected")
  1766  	}
  1767  	if !fileInodeMetadataAfterCreateFile.AccessTime.Equal(fileInodeMetadataAfterCreateFile.CreationTime) {
  1768  		t.Fatalf("fileInodeMetadataAfterCreateDir.AccessTime unexpected")
  1769  	}
  1770  	if !fileInodeMetadataAfterCreateFile.AttrChangeTime.Equal(fileInodeMetadataAfterCreateFile.CreationTime) {
  1771  		t.Fatalf("fileInodeMetadataAfterCreateDir.AttrChangeTime unexpected")
  1772  	}
  1773  
  1774  	testMetadata.CreationTime = fileInodeMetadataAfterCreateFile.CreationTime.Add(negativeDurationToDelayOrSkew)
  1775  	testMetadata.ModificationTime = fileInodeMetadataAfterCreateFile.ModificationTime
  1776  	testMetadata.AccessTime = fileInodeMetadataAfterCreateFile.AccessTime
  1777  	testMetadata.AttrChangeTime = fileInodeMetadataAfterCreateFile.AttrChangeTime
  1778  
  1779  	timeBeforeOp = time.Now()
  1780  	time.Sleep(positiveDurationToDelayOrSkew)
  1781  
  1782  	err = testVolumeHandle.SetCreationTime(fileInode, testMetadata.CreationTime)
  1783  	if nil != err {
  1784  		t.Fatalf("SetCreationTime(fileInode,) failed: %v", err)
  1785  	}
  1786  	time.Sleep(positiveDurationToDelayOrSkew)
  1787  	timeAfterOp = time.Now()
  1788  
  1789  	fileInodeMetadataAfterSetCreationTime, err := testVolumeHandle.GetMetadata(fileInode)
  1790  	if nil != err {
  1791  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1792  	}
  1793  	checkMetadata(t, fileInodeMetadataAfterSetCreationTime, testMetadata, MetadataNotAttrTimeFields,
  1794  		"GetMetadata() after SetCreationTime() test 3")
  1795  	if fileInodeMetadataAfterSetCreationTime.AttrChangeTime.Before(timeBeforeOp) ||
  1796  		fileInodeMetadataAfterSetCreationTime.AttrChangeTime.After(timeAfterOp) {
  1797  		t.Fatalf("fileInodeMetadataAfterSetCreationTime.AttrChangeTime unexpected")
  1798  	}
  1799  
  1800  	testMetadata.ModificationTime = fileInodeMetadataAfterSetCreationTime.ModificationTime.Add(negativeDurationToDelayOrSkew)
  1801  	err = testVolumeHandle.SetModificationTime(fileInode, testMetadata.ModificationTime)
  1802  	if nil != err {
  1803  		t.Fatalf("SetModificationTime(fileInode,) failed: %v", err)
  1804  	}
  1805  	fileInodeMetadataAfterSetModificationTime, err := testVolumeHandle.GetMetadata(fileInode)
  1806  	if nil != err {
  1807  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1808  	}
  1809  	checkMetadata(t, fileInodeMetadataAfterSetModificationTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after SetModificationTime()")
  1810  
  1811  	testMetadata.AccessTime = fileInodeMetadataAfterSetModificationTime.AccessTime.Add(negativeDurationToDelayOrSkew)
  1812  	err = testVolumeHandle.SetAccessTime(fileInode, testMetadata.AccessTime)
  1813  	if nil != err {
  1814  		t.Fatalf("SetAccessTime(fileInode,) failed: %v", err)
  1815  	}
  1816  	fileInodeMetadataAfterSetAccessTime, err := testVolumeHandle.GetMetadata(fileInode)
  1817  	if nil != err {
  1818  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1819  	}
  1820  	checkMetadata(t, fileInodeMetadataAfterSetAccessTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after SetAccessTime() test 1")
  1821  
  1822  	timeBeforeFileInodePutStream := time.Now()
  1823  
  1824  	time.Sleep(positiveDurationToDelayOrSkew)
  1825  
  1826  	err = testVolumeHandle.PutStream(fileInode, "stream_name", []byte{})
  1827  	if nil != err {
  1828  		t.Fatalf("PutStream(fileInode,,) failed: %v", err)
  1829  	}
  1830  
  1831  	time.Sleep(positiveDurationToDelayOrSkew)
  1832  
  1833  	timeAfterFileInodePutStream := time.Now()
  1834  
  1835  	fileInodeMetadataAfterPutStream, err := testVolumeHandle.GetMetadata(fileInode)
  1836  	if nil != err {
  1837  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1838  	}
  1839  	checkMetadata(t, fileInodeMetadataAfterPutStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after PutStream()")
  1840  	if fileInodeMetadataAfterPutStream.AttrChangeTime.Before(timeBeforeFileInodePutStream) || fileInodeMetadataAfterPutStream.AttrChangeTime.After(timeAfterFileInodePutStream) {
  1841  		t.Fatalf("fileInodeMetadataAfterPutStream.AttrChangeTime unexpected")
  1842  	}
  1843  
  1844  	timeBeforeFileInodeDeleteStream := time.Now()
  1845  
  1846  	time.Sleep(positiveDurationToDelayOrSkew)
  1847  
  1848  	err = testVolumeHandle.DeleteStream(fileInode, "stream_name")
  1849  	if nil != err {
  1850  		t.Fatalf("DeleteStream(fileInode,) failed: %v", err)
  1851  	}
  1852  
  1853  	time.Sleep(positiveDurationToDelayOrSkew)
  1854  
  1855  	timeAfterFileInodeDeleteStream := time.Now()
  1856  
  1857  	fileInodeMetadataAfterDeleteStream, err := testVolumeHandle.GetMetadata(fileInode)
  1858  	if nil != err {
  1859  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  1860  	}
  1861  	checkMetadata(t, fileInodeMetadataAfterDeleteStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after DeleteStream()")
  1862  	if fileInodeMetadataAfterDeleteStream.AttrChangeTime.Before(timeBeforeFileInodeDeleteStream) || fileInodeMetadataAfterDeleteStream.AttrChangeTime.After(timeAfterFileInodeDeleteStream) {
  1863  		t.Fatalf("fileInodeMetadataAfterDeleteStream.AttrChangeTime unexpected")
  1864  	}
  1865  
  1866  	timeBeforeCreateSymlink := time.Now()
  1867  
  1868  	time.Sleep(positiveDurationToDelayOrSkew)
  1869  
  1870  	testMetadata.Mode = PosixModePerm
  1871  	testMetadata.UserID = InodeUserID(1111)
  1872  	testMetadata.GroupID = InodeGroupID(7777)
  1873  	symlinkInode, err := testVolumeHandle.CreateSymlink("nowhere", testMetadata.Mode, testMetadata.UserID, testMetadata.GroupID)
  1874  	if nil != err {
  1875  		t.Fatalf("CreateSymlink(\"nowhere\") failed: %v", err)
  1876  	}
  1877  
  1878  	time.Sleep(positiveDurationToDelayOrSkew)
  1879  
  1880  	timeAfterCreateSymlink := time.Now()
  1881  
  1882  	symlinkInodeMetadataAfterCreateSymlink, err := testVolumeHandle.GetMetadata(symlinkInode)
  1883  	if nil != err {
  1884  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1885  	}
  1886  	if symlinkInodeMetadataAfterCreateSymlink.CreationTime.Before(timeBeforeCreateSymlink) || symlinkInodeMetadataAfterCreateSymlink.CreationTime.After(timeAfterCreateSymlink) {
  1887  		t.Fatalf("symlinkInodeMetadataAfterCreateDir.CreationTime unexpected")
  1888  	}
  1889  	if !symlinkInodeMetadataAfterCreateSymlink.ModificationTime.Equal(symlinkInodeMetadataAfterCreateSymlink.CreationTime) {
  1890  		t.Fatalf("symlinkInodeMetadataAfterCreateDir.ModificationTime unexpected")
  1891  	}
  1892  	if !symlinkInodeMetadataAfterCreateSymlink.AccessTime.Equal(symlinkInodeMetadataAfterCreateSymlink.CreationTime) {
  1893  		t.Fatalf("symlinkInodeMetadataAfterCreateDir.AccessTime unexpected")
  1894  	}
  1895  	if !symlinkInodeMetadataAfterCreateSymlink.AttrChangeTime.Equal(symlinkInodeMetadataAfterCreateSymlink.CreationTime) {
  1896  		t.Fatalf("symlinkInodeMetadataAfterCreateDir.AttrChangeTime unexpected")
  1897  	}
  1898  	checkMetadata(t, symlinkInodeMetadataAfterCreateSymlink, testMetadata, MetadataPermFields, "GetMetadata() after CreateSymlink()")
  1899  
  1900  	// XXX TODO: Add more tests related to mode/uid/gid and CreateFile(): mode > 0777, etc.
  1901  
  1902  	testMetadata.CreationTime = symlinkInodeMetadataAfterCreateSymlink.CreationTime.Add(negativeDurationToDelayOrSkew)
  1903  	testMetadata.ModificationTime = symlinkInodeMetadataAfterCreateSymlink.ModificationTime
  1904  	testMetadata.AccessTime = symlinkInodeMetadataAfterCreateSymlink.AccessTime
  1905  	testMetadata.AttrChangeTime = symlinkInodeMetadataAfterCreateSymlink.AttrChangeTime
  1906  	timeBeforeOp = time.Now()
  1907  	time.Sleep(positiveDurationToDelayOrSkew)
  1908  
  1909  	err = testVolumeHandle.SetCreationTime(symlinkInode, testMetadata.CreationTime)
  1910  	if nil != err {
  1911  		t.Fatalf("SetCreationTime(symlinkInode,) failed: %v", err)
  1912  	}
  1913  	time.Sleep(positiveDurationToDelayOrSkew)
  1914  	timeAfterOp = time.Now()
  1915  
  1916  	symlinkInodeMetadataAfterSetCreationTime, err := testVolumeHandle.GetMetadata(symlinkInode)
  1917  	if nil != err {
  1918  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1919  	}
  1920  	checkMetadata(t, symlinkInodeMetadataAfterSetCreationTime, testMetadata, MetadataNotAttrTimeFields,
  1921  		"GetMetadata() after SetCreationTime() test 4")
  1922  	if symlinkInodeMetadataAfterSetCreationTime.AttrChangeTime.Before(timeBeforeOp) ||
  1923  		symlinkInodeMetadataAfterSetCreationTime.AttrChangeTime.After(timeAfterOp) {
  1924  		t.Fatalf("symlinkInodeMetadataAfterSetCreationTime.AttrChangeTime unexpected")
  1925  	}
  1926  
  1927  	testMetadata.ModificationTime = symlinkInodeMetadataAfterSetCreationTime.ModificationTime.Add(negativeDurationToDelayOrSkew)
  1928  	err = testVolumeHandle.SetModificationTime(symlinkInode, testMetadata.ModificationTime)
  1929  	if nil != err {
  1930  		t.Fatalf("SetModificationTime(symlinkInode,) failed: %v", err)
  1931  	}
  1932  	symlinkInodeMetadataAfterSetModificationTime, err := testVolumeHandle.GetMetadata(symlinkInode)
  1933  	if nil != err {
  1934  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1935  	}
  1936  	checkMetadata(t, symlinkInodeMetadataAfterSetModificationTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after SetModificationTime()")
  1937  
  1938  	testMetadata.AccessTime = symlinkInodeMetadataAfterSetModificationTime.AccessTime.Add(negativeDurationToDelayOrSkew)
  1939  	err = testVolumeHandle.SetAccessTime(symlinkInode, testMetadata.AccessTime)
  1940  	if nil != err {
  1941  		t.Fatalf("SetAccessTime(symlinkInode,) failed: %v", err)
  1942  	}
  1943  	symlinkInodeMetadataAfterSetAccessTime, err := testVolumeHandle.GetMetadata(symlinkInode)
  1944  	if nil != err {
  1945  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1946  	}
  1947  	checkMetadata(t, symlinkInodeMetadataAfterSetAccessTime, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after SetAccessTime() test 2")
  1948  
  1949  	timeBeforeSymlinkInodePutStream := time.Now()
  1950  
  1951  	time.Sleep(positiveDurationToDelayOrSkew)
  1952  
  1953  	err = testVolumeHandle.PutStream(symlinkInode, "stream_name", []byte{})
  1954  	if nil != err {
  1955  		t.Fatalf("PutStream(symlinkInode,,) failed: %v", err)
  1956  	}
  1957  
  1958  	time.Sleep(positiveDurationToDelayOrSkew)
  1959  
  1960  	timeAfterSymlinkInodePutStream := time.Now()
  1961  
  1962  	symlinkInodeMetadataAfterPutStream, err := testVolumeHandle.GetMetadata(symlinkInode)
  1963  	if nil != err {
  1964  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1965  	}
  1966  	checkMetadata(t, symlinkInodeMetadataAfterPutStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after PutStream()")
  1967  	if symlinkInodeMetadataAfterPutStream.AttrChangeTime.Before(timeBeforeSymlinkInodePutStream) || symlinkInodeMetadataAfterPutStream.AttrChangeTime.After(timeAfterSymlinkInodePutStream) {
  1968  		t.Fatalf("symlinkInodeMetadataAfterPutStream.AttrChangeTime unexpected")
  1969  	}
  1970  
  1971  	timeBeforeSymlinkInodeDeleteStream := time.Now()
  1972  
  1973  	time.Sleep(positiveDurationToDelayOrSkew)
  1974  
  1975  	err = testVolumeHandle.DeleteStream(symlinkInode, "stream_name")
  1976  	if nil != err {
  1977  		t.Fatalf("DeleteStream(symlinkInode,) failed: %v", err)
  1978  	}
  1979  
  1980  	time.Sleep(positiveDurationToDelayOrSkew)
  1981  
  1982  	timeAfterSymlinkInodeDeleteStream := time.Now()
  1983  
  1984  	symlinkInodeMetadataAfterDeleteStream, err := testVolumeHandle.GetMetadata(symlinkInode)
  1985  	if nil != err {
  1986  		t.Fatalf("GetMetadata(symlinkInode) failed: %v", err)
  1987  	}
  1988  	checkMetadata(t, symlinkInodeMetadataAfterDeleteStream, testMetadata, MetadataNotAttrTimeFields, "GetMetadata() after DeleteStream()")
  1989  	if symlinkInodeMetadataAfterDeleteStream.AttrChangeTime.Before(timeBeforeSymlinkInodeDeleteStream) || symlinkInodeMetadataAfterDeleteStream.AttrChangeTime.After(timeAfterSymlinkInodeDeleteStream) {
  1990  		t.Fatalf("symlinkInodeMetadataAfterDeleteStream.AttrChangeTime unexpected")
  1991  	}
  1992  
  1993  	timeBeforeLink := time.Now()
  1994  
  1995  	time.Sleep(positiveDurationToDelayOrSkew)
  1996  
  1997  	err = testVolumeHandle.Link(dirInode, "loc_1", fileInode, false)
  1998  	if nil != err {
  1999  		t.Fatalf("Link(dirInode, \"loc_1\", fileInode, false) failed: %v", err)
  2000  	}
  2001  
  2002  	time.Sleep(positiveDurationToDelayOrSkew)
  2003  
  2004  	timeAfterLink := time.Now()
  2005  
  2006  	dirInodeMetadataAfterLink, err := testVolumeHandle.GetMetadata(dirInode)
  2007  	if nil != err {
  2008  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  2009  	}
  2010  	fileInodeMetadataAfterLink, err := testVolumeHandle.GetMetadata(fileInode)
  2011  	if nil != err {
  2012  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2013  	}
  2014  
  2015  	if !dirInodeMetadataAfterLink.CreationTime.Equal(dirInodeMetadataAfterDeleteStream.CreationTime) {
  2016  		t.Fatalf("dirInodeMetadataAfterLink.CreationTime unexpected")
  2017  	}
  2018  	if dirInodeMetadataAfterLink.ModificationTime.Before(timeBeforeLink) || dirInodeMetadataAfterLink.ModificationTime.After(timeAfterLink) {
  2019  		t.Fatalf("dirInodeMetadataAfterLink.ModificationTime unexpected")
  2020  	}
  2021  	if !dirInodeMetadataAfterLink.AccessTime.Equal(dirInodeMetadataAfterDeleteStream.AccessTime) {
  2022  		t.Fatalf("dirInodeMetadataAfterLink.AccessTime unexpected changed")
  2023  	}
  2024  	if dirInodeMetadataAfterLink.AttrChangeTime.Before(timeBeforeLink) || dirInodeMetadataAfterLink.AttrChangeTime.After(timeAfterLink) {
  2025  		t.Fatalf("dirInodeMetadataAfterLink.AttrChangeTime unexpected")
  2026  	}
  2027  	if !dirInodeMetadataAfterLink.AttrChangeTime.Equal(dirInodeMetadataAfterLink.ModificationTime) {
  2028  		t.Fatalf("dirInodeMetadataAfterLink.AttrChangeTime should equal dirInodeMetadataAfterLink.ModificationTime")
  2029  	}
  2030  	if !fileInodeMetadataAfterLink.CreationTime.Equal(fileInodeMetadataAfterDeleteStream.CreationTime) {
  2031  		t.Fatalf("fileInodeMetadataAfterLink.CreationTime unexpected")
  2032  	}
  2033  	if !fileInodeMetadataAfterLink.ModificationTime.Equal(fileInodeMetadataAfterDeleteStream.ModificationTime) {
  2034  		t.Fatalf("fileInodeMetadataAfterLink.ModificationTime unexpected")
  2035  	}
  2036  	if !fileInodeMetadataAfterLink.AccessTime.Equal(fileInodeMetadataAfterDeleteStream.AccessTime) {
  2037  		t.Fatalf("fileInodeMetadataAfterLink.AccessTime unexpected")
  2038  	}
  2039  	if fileInodeMetadataAfterLink.AttrChangeTime.Before(timeBeforeLink) || fileInodeMetadataAfterLink.AttrChangeTime.After(timeAfterLink) {
  2040  		t.Fatalf("fileInodeMetadataAfterLink.AttrChangeTime unexpected")
  2041  	}
  2042  
  2043  	time.Sleep(positiveDurationToDelayOrSkew)
  2044  
  2045  	err = testVolumeHandle.Move(dirInode, "loc_1", dirInode, "loc_2")
  2046  	if nil != err {
  2047  		t.Fatalf("Move(dirInode, \"loc_1\", dirInode, \"loc_2\") failed: %v", err)
  2048  	}
  2049  
  2050  	time.Sleep(positiveDurationToDelayOrSkew)
  2051  
  2052  	timeAfterMove := time.Now()
  2053  
  2054  	dirInodeMetadataAfterMove, err := testVolumeHandle.GetMetadata(dirInode)
  2055  	if nil != err {
  2056  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  2057  	}
  2058  	fileInodeMetadataAfterMove, err := testVolumeHandle.GetMetadata(fileInode)
  2059  	if nil != err {
  2060  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2061  	}
  2062  
  2063  	if !dirInodeMetadataAfterMove.CreationTime.Equal(dirInodeMetadataAfterLink.CreationTime) {
  2064  		t.Fatalf("dirInodeMetadataAfterMove.CreationTime unexpected")
  2065  	}
  2066  	if dirInodeMetadataAfterMove.ModificationTime.Before(timeAfterLink) || dirInodeMetadataAfterMove.ModificationTime.After(timeAfterMove) {
  2067  		t.Fatalf("dirInodeMetadataAfterMove.ModificationTime unexpected")
  2068  	}
  2069  	if !dirInodeMetadataAfterMove.AccessTime.Equal(dirInodeMetadataAfterLink.AccessTime) {
  2070  		t.Fatalf("dirInodeMetadataAfterMove.AccessTime unexpected change")
  2071  	}
  2072  	if dirInodeMetadataAfterMove.AttrChangeTime.Equal(dirInodeMetadataAfterLink.AttrChangeTime) {
  2073  		t.Fatalf("dirInodeMetadataAfterMove.AttrChangeTime unchanged")
  2074  	}
  2075  	if !fileInodeMetadataAfterMove.CreationTime.Equal(fileInodeMetadataAfterLink.CreationTime) {
  2076  		t.Fatalf("fileInodeMetadataAfterMove.CreationTime unexpected")
  2077  	}
  2078  	if !fileInodeMetadataAfterMove.ModificationTime.Equal(fileInodeMetadataAfterLink.ModificationTime) {
  2079  		t.Fatalf("fileInodeMetadataAfterMove.ModificationTime unexpected")
  2080  	}
  2081  	if !fileInodeMetadataAfterMove.AccessTime.Equal(fileInodeMetadataAfterLink.AccessTime) {
  2082  		t.Fatalf("fileInodeMetadataAfterMove.AccessTime unexpected")
  2083  	}
  2084  	if fileInodeMetadataAfterMove.AttrChangeTime.Equal(fileInodeMetadataAfterLink.AttrChangeTime) {
  2085  		t.Fatalf("fileInodeMetadataAfterMove.AttrChangeTime should change after move")
  2086  	}
  2087  
  2088  	time.Sleep(positiveDurationToDelayOrSkew)
  2089  
  2090  	err = testVolumeHandle.Unlink(dirInode, "loc_2", false)
  2091  	if nil != err {
  2092  		t.Fatalf("Unlink(dirInode, \"loc_2\", false) failed: %v", err)
  2093  	}
  2094  
  2095  	time.Sleep(positiveDurationToDelayOrSkew)
  2096  
  2097  	timeAfterUnlink := time.Now()
  2098  
  2099  	dirInodeMetadataAfterUnlink, err := testVolumeHandle.GetMetadata(dirInode)
  2100  	if nil != err {
  2101  		t.Fatalf("GetMetadata(dirInode) failed: %v", err)
  2102  	}
  2103  	fileInodeMetadataAfterUnlink, err := testVolumeHandle.GetMetadata(fileInode)
  2104  	if nil != err {
  2105  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2106  	}
  2107  
  2108  	if !dirInodeMetadataAfterUnlink.CreationTime.Equal(dirInodeMetadataAfterMove.CreationTime) {
  2109  		t.Fatalf("dirInodeMetadataAfterUnlink.CreationTime unexpected")
  2110  	}
  2111  	if dirInodeMetadataAfterUnlink.ModificationTime.Before(timeAfterMove) || dirInodeMetadataAfterUnlink.ModificationTime.After(timeAfterUnlink) {
  2112  		t.Fatalf("dirInodeMetadataAfterUnlink.ModificationTime unexpected")
  2113  	}
  2114  	if !dirInodeMetadataAfterUnlink.AccessTime.Equal(dirInodeMetadataAfterMove.AccessTime) {
  2115  		t.Fatalf("dirInodeMetadataAfterUnlink.AccessTime unexpected change")
  2116  	}
  2117  	if dirInodeMetadataAfterUnlink.AttrChangeTime.Before(timeAfterMove) || dirInodeMetadataAfterUnlink.AttrChangeTime.After(timeAfterUnlink) {
  2118  		t.Fatalf("dirInodeMetadataAfterUnlink.AttrChangeTime unexpected")
  2119  	}
  2120  	if !fileInodeMetadataAfterUnlink.CreationTime.Equal(fileInodeMetadataAfterMove.CreationTime) {
  2121  		t.Fatalf("fileInodeMetadataAfterUnlink.CreationTime unexpected")
  2122  	}
  2123  	if !fileInodeMetadataAfterUnlink.ModificationTime.Equal(fileInodeMetadataAfterMove.ModificationTime) {
  2124  		t.Fatalf("fileInodeMetadataAfterUnlink.ModificationTime unexpected")
  2125  	}
  2126  	if !fileInodeMetadataAfterUnlink.AccessTime.Equal(fileInodeMetadataAfterMove.AccessTime) {
  2127  		t.Fatalf("fileInodeMetadataAfterUnlink.AccessTime unexpected")
  2128  	}
  2129  	if fileInodeMetadataAfterUnlink.AttrChangeTime.Before(timeAfterMove) || fileInodeMetadataAfterUnlink.AttrChangeTime.After(timeAfterUnlink) {
  2130  		t.Fatalf("fileInodeMetadataAfterUnlink.AttrChangeTime unexpected")
  2131  	}
  2132  
  2133  	time.Sleep(positiveDurationToDelayOrSkew)
  2134  
  2135  	err = testVolumeHandle.Write(fileInode, uint64(0), []byte{0x00}, nil)
  2136  	if nil != err {
  2137  		t.Fatalf("Write(fileInode, uint64(0), []byte{0x00}) failed: %v", err)
  2138  	}
  2139  
  2140  	time.Sleep(positiveDurationToDelayOrSkew)
  2141  
  2142  	timeAfterWrite := time.Now()
  2143  
  2144  	fileInodeMetadataAfterWrite, err := testVolumeHandle.GetMetadata(fileInode)
  2145  	if nil != err {
  2146  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2147  	}
  2148  
  2149  	if !fileInodeMetadataAfterWrite.CreationTime.Equal(fileInodeMetadataAfterUnlink.CreationTime) {
  2150  		t.Fatalf("fileInodeMetadataAfterWrite.CreationTime unexpected")
  2151  	}
  2152  	if fileInodeMetadataAfterWrite.ModificationTime.Before(timeAfterUnlink) || fileInodeMetadataAfterWrite.ModificationTime.After(timeAfterWrite) {
  2153  		t.Fatalf("fileInodeMetadataAfterWrite.ModificationTime unexpected")
  2154  	}
  2155  	if !fileInodeMetadataAfterWrite.AttrChangeTime.Equal(fileInodeMetadataAfterWrite.ModificationTime) {
  2156  		t.Fatalf("fileInodeMetadataAfterWrite.AttrChangeTime unexpected")
  2157  	}
  2158  	if !fileInodeMetadataAfterWrite.AccessTime.Equal(fileInodeMetadataAfterUnlink.AccessTime) {
  2159  		t.Fatalf("fileInodeMetadataAfterWrite.AccessTime unexpected change")
  2160  	}
  2161  
  2162  	time.Sleep(positiveDurationToDelayOrSkew)
  2163  
  2164  	objectPath, err := testVolumeHandle.ProvisionObject()
  2165  	if nil != err {
  2166  		t.Fatalf("ProvisionObject() failed: %v", err)
  2167  	}
  2168  	_, containerName, objectName, err = utils.PathToAcctContObj(objectPath)
  2169  	if err != nil {
  2170  		t.Fatalf("couldn't parse %v as object path", objectPath)
  2171  	}
  2172  	err = testVolumeHandle.Wrote(fileInode, containerName, objectName, []uint64{0}, []uint64{0}, []uint64{2}, false)
  2173  	if nil != err {
  2174  		t.Fatalf("Wrote(fileInode, objectPath, []uint64{0}, []uint64{0}, []uint64{2}, false) failed: %v", err)
  2175  	}
  2176  
  2177  	time.Sleep(positiveDurationToDelayOrSkew)
  2178  
  2179  	timeAfterWrote := time.Now()
  2180  
  2181  	fileInodeMetadataAfterWrote, err := testVolumeHandle.GetMetadata(fileInode)
  2182  	if nil != err {
  2183  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2184  	}
  2185  
  2186  	if !fileInodeMetadataAfterWrote.CreationTime.Equal(fileInodeMetadataAfterWrite.CreationTime) {
  2187  		t.Fatalf("fileInodeMetadataAfterWrote.CreationTime unexpected")
  2188  	}
  2189  	if fileInodeMetadataAfterWrote.ModificationTime.Before(timeAfterWrite) || fileInodeMetadataAfterWrote.ModificationTime.After(timeAfterWrote) {
  2190  		t.Fatalf("fileInodeMetadataAfterWrote.ModificationTime unexpected")
  2191  	}
  2192  	if !fileInodeMetadataAfterWrote.AttrChangeTime.Equal(fileInodeMetadataAfterWrote.ModificationTime) {
  2193  		t.Fatalf("fileInodeMetadataAfterWrote.AttrChangeTime should equal fileInodeMetadataAfterWrote.ModificationTime")
  2194  	}
  2195  	if !fileInodeMetadataAfterWrote.AccessTime.Equal(fileInodeMetadataAfterWrite.AccessTime) {
  2196  		t.Fatalf("fileInodeMetadataAfterWrote.AccessTime unexpected change")
  2197  	}
  2198  
  2199  	time.Sleep(positiveDurationToDelayOrSkew)
  2200  
  2201  	err = testVolumeHandle.SetSize(fileInode, uint64(0))
  2202  	if nil != err {
  2203  		t.Fatalf("SetSize(fileInode, uint64(0)) failed: %v", err)
  2204  	}
  2205  
  2206  	time.Sleep(positiveDurationToDelayOrSkew)
  2207  
  2208  	timeAfterSetSize := time.Now()
  2209  
  2210  	fileInodeMetadataAfterSetSize, err := testVolumeHandle.GetMetadata(fileInode)
  2211  	if nil != err {
  2212  		t.Fatalf("GetMetadata(fileInode) failed: %v", err)
  2213  	}
  2214  
  2215  	if !fileInodeMetadataAfterSetSize.CreationTime.Equal(fileInodeMetadataAfterWrote.CreationTime) {
  2216  		t.Fatalf("fileInodeMetadataAfterSetSize.CreationTime unexpected")
  2217  	}
  2218  	if fileInodeMetadataAfterSetSize.ModificationTime.Before(timeAfterWrote) || fileInodeMetadataAfterSetSize.ModificationTime.After(timeAfterSetSize) {
  2219  		t.Fatalf("fileInodeMetadataAfterSetSize.ModificationTime unexpected")
  2220  	}
  2221  	if !fileInodeMetadataAfterSetSize.AttrChangeTime.Equal(fileInodeMetadataAfterSetSize.ModificationTime) {
  2222  		t.Fatalf("fileInodeMetadataAfterSetsize.AttrChangeTime should equal fileInodeMetadataAfterSetSize.ModificationTime")
  2223  	}
  2224  	if !fileInodeMetadataAfterSetSize.AccessTime.Equal(fileInodeMetadataAfterWrote.AccessTime) {
  2225  		t.Fatalf("fileInodeMetadataAfterSetSize.AccessTime unexpected change")
  2226  	}
  2227  
  2228  	// TODO: Need to test GetFragmentationReport()
  2229  
  2230  	// TODO: Once implemented, need to test Optimize()
  2231  
  2232  	testTeardown(t)
  2233  }
  2234  
  2235  func TestInodeDiscard(t *testing.T) {
  2236  	testSetup(t, false)
  2237  
  2238  	assert := assert.New(t)
  2239  	testVolumeHandle, err := FetchVolumeHandle("TestVolume")
  2240  	if nil != err {
  2241  		t.Fatalf("FetchVolumeHandle(\"TestVolume\") should have worked - got error: %v", err)
  2242  	}
  2243  
  2244  	// Calculate how many inodes we must create to make sure the inode cache discard
  2245  	// routine will find something to discard.
  2246  	vS := testVolumeHandle.(*volumeStruct)
  2247  	maxBytes := vS.inodeCacheLRUMaxBytes
  2248  	iSize := globals.inodeSize
  2249  	entriesNeeded := maxBytes / iSize
  2250  	entriesNeeded = entriesNeeded * 6
  2251  	for i := uint64(0); i < entriesNeeded; i++ {
  2252  		fileInodeNumber, err := testVolumeHandle.CreateFile(InodeMode(0000), InodeRootUserID, InodeGroupID(0))
  2253  		if nil != err {
  2254  			t.Fatalf("CreateFile() failed: %v", err)
  2255  		}
  2256  
  2257  		fName := fmt.Sprintf("file-%v i: %v", fileInodeNumber, i)
  2258  		err = testVolumeHandle.Link(RootDirInodeNumber, fName, fileInodeNumber, false)
  2259  		if nil != err {
  2260  			t.Fatalf("Link(RootDirInodeNumber, \"%v\", file1Inode, false) failed: %v", fName, err)
  2261  		}
  2262  
  2263  		fileInode, ok, err := vS.fetchInode(fileInodeNumber)
  2264  		assert.Nil(err, nil, "Unable to fetchInode due to err - even though just created")
  2265  		assert.True(ok, "fetchInode returned !ok - even though just created")
  2266  		assert.False(fileInode.dirty, "fetchInode.dirty == true - even though just linked")
  2267  	}
  2268  
  2269  	discarded, dirty, locked, lruItems := vS.inodeCacheDiscard()
  2270  
  2271  	assert.NotEqual(discarded, uint64(0), "Number of inodes discarded should be non-zero")
  2272  	assert.Equal(dirty, uint64(0), "Number of inodes dirty should zero")
  2273  	assert.Equal(locked, uint64(0), "Number of inodes locked should zero")
  2274  	assert.Equal((lruItems * iSize), (maxBytes/iSize)*iSize, "Number of inodes in cache not same as max")
  2275  
  2276  	testTeardown(t)
  2277  }