github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/inode/api_test.go (about)

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