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

     1  // Copyright (c) 2015-2021, NVIDIA CORPORATION.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"io/ioutil"
     9  	"math"
    10  	"math/rand"
    11  	"os"
    12  	"testing"
    13  )
    14  
    15  var (
    16  	testFile         *os.File
    17  	testFileContents []byte
    18  	testFilePath     string
    19  	testFileLastByte byte
    20  )
    21  
    22  func TestSimpleWriteReadClose(t *testing.T) {
    23  	const (
    24  		testFileName       = "testSimpleWriteReadCloseFileName"
    25  		totalBytes   int64 = 100
    26  		randSeed     int64 = 0x0123456789ABCDEF
    27  	)
    28  	var (
    29  		err         error
    30  		readBackBuf []byte
    31  		writtenBuf  []byte
    32  	)
    33  
    34  	testSetup(t)
    35  
    36  	testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName
    37  
    38  	testFile, err = os.Create(testFilePath)
    39  	if nil != err {
    40  		t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err)
    41  	}
    42  
    43  	writtenBuf = make([]byte, totalBytes)
    44  
    45  	rand.Seed(randSeed)
    46  
    47  	_, _ = rand.Read(writtenBuf)
    48  
    49  	_, err = testFile.WriteAt(writtenBuf, 0)
    50  	if nil != err {
    51  		t.Fatalf("testFile.WriteAt(writtenBuf, 0) failed: %v", err)
    52  	}
    53  
    54  	readBackBuf = make([]byte, totalBytes)
    55  
    56  	_, err = testFile.ReadAt(readBackBuf, 0)
    57  	if nil != err {
    58  		t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Sync() failed: %v", err)
    59  	}
    60  
    61  	if 0 != bytes.Compare(writtenBuf, readBackBuf) {
    62  		t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's")
    63  	}
    64  
    65  	err = testFile.Close()
    66  	if nil != err {
    67  		t.Fatalf("testFile.Close() failed: %v", err)
    68  	}
    69  
    70  	err = os.Remove(testFilePath)
    71  	if nil != err {
    72  		t.Fatalf("os.Remove(testFilePath) failed: %v", err)
    73  	}
    74  
    75  	testTeardown(t)
    76  }
    77  
    78  func TestRandomOverwrites(t *testing.T) {
    79  	const (
    80  		testFileName       = "testRandomeOverwritesFileName"
    81  		totalBytes   int64 = 1000
    82  		minWriteSize int64 = 1
    83  		maxWriteSize int64 = 10
    84  		numWrites    int64 = 10000
    85  		randSeed     int64 = 0x0123456789ABCDEF
    86  	)
    87  	var (
    88  		err           error
    89  		readBackBuf   []byte
    90  		toWriteBuf    []byte
    91  		toWriteBufLen int64
    92  		toWriteOffset int64
    93  		writeNumber   int64
    94  		writtenBuf    []byte
    95  	)
    96  
    97  	testSetup(t)
    98  
    99  	testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName
   100  
   101  	testFile, err = os.Create(testFilePath)
   102  	if nil != err {
   103  		t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err)
   104  	}
   105  
   106  	writtenBuf = make([]byte, totalBytes)
   107  
   108  	rand.Seed(randSeed)
   109  
   110  	_, _ = rand.Read(writtenBuf)
   111  
   112  	_, err = testFile.WriteAt(writtenBuf, 0)
   113  	if nil != err {
   114  		t.Fatalf("testFile.WriteAt(writtenBuf, 0) failed: %v", err)
   115  	}
   116  
   117  	toWriteBuf = make([]byte, maxWriteSize)
   118  
   119  	for writeNumber = 0; writeNumber < numWrites; writeNumber++ {
   120  		toWriteBufLen = minWriteSize + rand.Int63n(maxWriteSize-minWriteSize+1)
   121  		toWriteOffset = rand.Int63n(totalBytes - toWriteBufLen + 1)
   122  		_, _ = rand.Read(toWriteBuf[:toWriteBufLen])
   123  
   124  		_, err = testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset)
   125  		if nil != err {
   126  			t.Fatalf("testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) after Create() failed: %v", err)
   127  		}
   128  
   129  		_ = copy(writtenBuf[toWriteOffset:(toWriteOffset+toWriteBufLen)], toWriteBuf[:toWriteBufLen])
   130  	}
   131  
   132  	readBackBuf = make([]byte, totalBytes)
   133  
   134  	_, err = testFile.ReadAt(readBackBuf, 0)
   135  	if nil != err {
   136  		t.Fatalf("testFile.ReadAt(readBackBuf, 0) before Sync() failed: %v", err)
   137  	}
   138  
   139  	if 0 != bytes.Compare(writtenBuf, readBackBuf) {
   140  		t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's before Sync()")
   141  	}
   142  
   143  	err = testFile.Sync()
   144  	if nil != err {
   145  		t.Fatalf("testFile.Sync() after write pass 1 failed: %v", err)
   146  	}
   147  
   148  	_, err = testFile.ReadAt(readBackBuf, 0)
   149  	if nil != err {
   150  		t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Sync() failed: %v", err)
   151  	}
   152  
   153  	if 0 != bytes.Compare(writtenBuf, readBackBuf) {
   154  		t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after Sync()")
   155  	}
   156  
   157  	err = testFile.Close()
   158  	if nil != err {
   159  		t.Fatalf("testFile.Close() after Sync() failed: %v", err)
   160  	}
   161  
   162  	testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0)
   163  	if nil != err {
   164  		t.Fatalf("os.OpenFile(\"%s\",,) failed: %v", testFilePath, err)
   165  	}
   166  
   167  	_, err = testFile.ReadAt(readBackBuf, 0)
   168  	if nil != err {
   169  		t.Fatalf("testFile.ReadAt(readBackBuf, 0) after Open() failed: %v", err)
   170  	}
   171  
   172  	if 0 != bytes.Compare(writtenBuf, readBackBuf) {
   173  		t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after Sync()")
   174  	}
   175  
   176  	for writeNumber = 0; writeNumber < numWrites; writeNumber++ {
   177  		toWriteBufLen = minWriteSize + rand.Int63n(maxWriteSize-minWriteSize+1)
   178  		toWriteOffset = rand.Int63n(totalBytes - toWriteBufLen + 1)
   179  		_, _ = rand.Read(toWriteBuf[:toWriteBufLen])
   180  
   181  		_, err = testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset)
   182  		if nil != err {
   183  			t.Fatalf("testFile.WriteAt(toWriteBuf[:toWriteBufLen], toWriteOffset) after Open() failed: %v", err)
   184  		}
   185  
   186  		_ = copy(writtenBuf[toWriteOffset:(toWriteOffset+toWriteBufLen)], toWriteBuf[:toWriteBufLen])
   187  	}
   188  
   189  	_, err = testFile.ReadAt(readBackBuf, 0)
   190  	if nil != err {
   191  		t.Fatalf("testFile.ReadAt(readBackBuf, 0) after overwrite failed: %v", err)
   192  	}
   193  
   194  	if 0 != bytes.Compare(writtenBuf, readBackBuf) {
   195  		t.Fatalf("bytes.Compare(writtenBuf, readBackBuf) reports un-equal buf's after overwrite")
   196  	}
   197  
   198  	err = testFile.Sync()
   199  	if nil != err {
   200  		t.Fatalf("testFile.Sync() after write pass 2 failed: %v", err)
   201  	}
   202  
   203  	err = testFile.Close()
   204  	if nil != err {
   205  		t.Fatalf("testFile.Close() after Open() failed: %v", err)
   206  	}
   207  
   208  	err = os.Remove(testFilePath)
   209  	if nil != err {
   210  		t.Fatalf("os.Remove(testFilePath) failed: %v", err)
   211  	}
   212  
   213  	testTeardown(t)
   214  }
   215  
   216  func optionallyReopenTestFile(t *testing.T, prefix string, reopenBeforeEachWrite bool, step string) {
   217  	var (
   218  		err error
   219  	)
   220  
   221  	err = testFile.Close()
   222  	if nil != err {
   223  		t.Fatalf("%s: testFile.Close() before \"%s\" failed: %v", prefix, step, err)
   224  	}
   225  
   226  	testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0)
   227  	if nil != err {
   228  		t.Fatalf("%s: os.OpenFile(\"%s\",,) before \"%s\" failed: %v", prefix, testFilePath, step, err)
   229  	}
   230  }
   231  
   232  func writeNextByteSlice(t *testing.T, prefix string, offset int, toWriteLen int, step string) {
   233  	var (
   234  		err        error
   235  		extension  int
   236  		index      int
   237  		toWriteBuf []byte
   238  	)
   239  
   240  	extension = (offset + toWriteLen) - len(testFileContents)
   241  
   242  	if 0 < extension {
   243  		testFileContents = append(testFileContents, make([]byte, extension)...)
   244  	}
   245  
   246  	toWriteBuf = make([]byte, toWriteLen)
   247  
   248  	for index = 0; index < toWriteLen; index++ {
   249  		if math.MaxUint8 == testFileLastByte {
   250  			testFileLastByte = 1
   251  		} else {
   252  			testFileLastByte++
   253  		}
   254  		toWriteBuf[index] = testFileLastByte
   255  		testFileContents[offset+index] = testFileLastByte
   256  	}
   257  
   258  	_, err = testFile.WriteAt(toWriteBuf, int64(offset))
   259  	if nil != err {
   260  		t.Fatalf("%s: testFile.WriteAt(,0) for \"%s\" failed: %v", prefix, step, err)
   261  	}
   262  }
   263  
   264  func optionallyFlushTestFile(t *testing.T, prefix string, flushAfterEachWrite bool, step string) {
   265  	var (
   266  		err error
   267  	)
   268  
   269  	if flushAfterEachWrite {
   270  		err = testFile.Sync()
   271  		if nil != err {
   272  			t.Fatalf("%s: testFile.Sync() for \"%s\" failed: %v", prefix, step, err)
   273  		}
   274  	}
   275  }
   276  
   277  func verifyTestFileContents(t *testing.T, prefix string, step string) {
   278  	var (
   279  		err         error
   280  		readBackBuf []byte
   281  	)
   282  
   283  	_, err = testFile.Seek(0, os.SEEK_SET)
   284  	if nil != err {
   285  		t.Fatalf("%s: testFile.Seek(0, os.SEEK_SET) for \"%s\" failed: %v", prefix, step, err)
   286  	}
   287  	readBackBuf, err = ioutil.ReadAll(testFile)
   288  	if nil != err {
   289  		t.Fatalf("%s: ioutil.ReadAll(testFile) for \"%s\" failed: %v", prefix, step, err)
   290  	}
   291  	if 0 != bytes.Compare(readBackBuf, testFileContents) {
   292  		t.Fatalf("%s: bytes.Compare(readBackBuf, testFileContents) for \"%s\" reports unequal bufs", prefix, step)
   293  	}
   294  }
   295  
   296  func testExhaustiveOverwrites(t *testing.T, prefix string, reopenBeforeEachWrite bool, flushAfterEachWrite bool) {
   297  	// Non-overlapping extent
   298  
   299  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Non-overlapping extent")
   300  	writeNextByteSlice(t, prefix, 0, 3, "Non-overlapping extent")
   301  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Non-overlapping extent")
   302  	verifyTestFileContents(t, prefix, "Non-overlapping extent")
   303  
   304  	// Overlapping existing extent precisely
   305  
   306  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping existing extent precisely")
   307  	writeNextByteSlice(t, prefix, 0, 3, "Overlapping existing extent precisely")
   308  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping existing extent precisely")
   309  	verifyTestFileContents(t, prefix, "Overlapping existing extent precisely")
   310  
   311  	// Overlapping the right of an existing extent
   312  
   313  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the right of an existing extent")
   314  	writeNextByteSlice(t, prefix, 2, 3, "Overlapping the right of an existing extent")
   315  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the right of an existing extent")
   316  	verifyTestFileContents(t, prefix, "Overlapping the right of an existing extent")
   317  
   318  	// Overlapping the middle of an existing extent
   319  
   320  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the middle of an existing extent")
   321  	writeNextByteSlice(t, prefix, 1, 3, "Overlapping the middle of an existing extent")
   322  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the middle of an existing extent")
   323  	verifyTestFileContents(t, prefix, "Overlapping the middle of an existing extent")
   324  
   325  	// Overlapping the left of an existing extent
   326  
   327  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping the left of an existing extent")
   328  	writeNextByteSlice(t, prefix, 8, 3, "Overlapping the left of an existing extent")
   329  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the left of an existing extent")
   330  	verifyTestFileContents(t, prefix, "Overlapping the left of an existing extent")
   331  	writeNextByteSlice(t, prefix, 6, 3, "Overlapping the left of an existing extent")
   332  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping the left of an existing extent")
   333  	verifyTestFileContents(t, prefix, "Overlapping the left of an existing extent")
   334  
   335  	// Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left
   336  
   337  	optionallyReopenTestFile(t, prefix, reopenBeforeEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   338  	writeNextByteSlice(t, prefix, 12, 3, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   339  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   340  	verifyTestFileContents(t, prefix, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   341  	writeNextByteSlice(t, prefix, 1, 13, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   342  	optionallyFlushTestFile(t, prefix, flushAfterEachWrite, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   343  	verifyTestFileContents(t, prefix, "Overlapping one existing extent on the right, another existing extent entirely, & a 3rd existing extent on the left")
   344  }
   345  
   346  func TestExhaustiveOverwrites(t *testing.T) {
   347  	const (
   348  		testFileName = "testExhaustiveOverwritesFileName"
   349  	)
   350  	var (
   351  		err error
   352  	)
   353  
   354  	testSetup(t)
   355  
   356  	testFilePath = globals.config.FUSEMountPointPath + "/" + testFileName
   357  
   358  	testFile, err = os.Create(testFilePath)
   359  	if nil != err {
   360  		t.Fatalf("os.Create(\"%s\") failed: %v", testFilePath, err)
   361  	}
   362  	err = testFile.Close()
   363  	if nil != err {
   364  		t.Fatalf("testFile.Close() failed: %v", err)
   365  	}
   366  	testFile, err = os.OpenFile(testFilePath, os.O_RDWR, 0)
   367  	if nil != err {
   368  		t.Fatalf("os.OpenFile(\"%s\",,) failed: %v", testFilePath, err)
   369  	}
   370  
   371  	testFileContents = []byte{}
   372  
   373  	testExhaustiveOverwrites(t, "Phase1", false, false)
   374  	testExhaustiveOverwrites(t, "Phase2", false, true)
   375  	testExhaustiveOverwrites(t, "Phase2", true, false)
   376  	testExhaustiveOverwrites(t, "Phase2", true, true)
   377  
   378  	err = testFile.Close()
   379  	if nil != err {
   380  		t.Fatalf("testFile.Close() failed: %v", err)
   381  	}
   382  
   383  	err = os.Remove(testFilePath)
   384  	if nil != err {
   385  		t.Fatalf("os.Remove(testFilePath) failed: %v", err)
   386  	}
   387  
   388  	testTeardown(t)
   389  }