github.com/sunvim/utils@v0.1.0/fs/fs_test.go (about)

     1  package fs
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  const (
    12  	lockTestPath = "test.lock"
    13  )
    14  
    15  var (
    16  	lockTestMode = os.FileMode(0666)
    17  )
    18  
    19  func testLockFile(t *testing.T, fs FileSystem) {
    20  	_ = fs.Remove(lockTestPath)
    21  	lock, acquiredExisting, err := fs.CreateLockFile(lockTestPath, lockTestMode)
    22  	if lock == nil || acquiredExisting || err != nil {
    23  		t.Fatal(lock, err, acquiredExisting)
    24  	}
    25  	lock2, acquiredExisting2, err2 := fs.CreateLockFile(lockTestPath, lockTestMode)
    26  	if lock2 != nil || acquiredExisting2 || err2 != os.ErrExist {
    27  		t.Fatal(lock2, acquiredExisting2, err2)
    28  	}
    29  
    30  	err = lock.Unlock()
    31  	assert.Nil(t, err)
    32  
    33  	_, err = fs.Stat(lockTestPath)
    34  	assert.NotNil(t, err)
    35  }
    36  
    37  func touchFile(fs FileSystem, path string) error {
    38  	f, err := fs.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(0666))
    39  	if err != nil {
    40  		return err
    41  	}
    42  	return f.Close()
    43  }
    44  
    45  func testLockFileAcquireExisting(t *testing.T, fs FileSystem) {
    46  	err := touchFile(fs, lockTestPath)
    47  	assert.Nil(t, err)
    48  
    49  	lock, acquiredExisting, err := fs.CreateLockFile(lockTestPath, lockTestMode)
    50  	if lock == nil || !acquiredExisting || err != nil {
    51  		t.Fatal(lock, err, acquiredExisting)
    52  	}
    53  
    54  	err = lock.Unlock()
    55  	assert.Nil(t, err)
    56  
    57  	_, err = fs.Stat(lockTestPath)
    58  	assert.NotNil(t, err)
    59  }
    60  
    61  func testFS(t *testing.T, fsys FileSystem) {
    62  	f, err := fsys.OpenFile("test", os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.FileMode(0666))
    63  	assert.Nil(t, err)
    64  
    65  	buf := make([]byte, 10)
    66  
    67  	t.Run("Empty file", func(t *testing.T) {
    68  		off, err := f.Seek(0, io.SeekCurrent)
    69  		assert.Nil(t, err)
    70  		assert.Equal(t, int64(0), off)
    71  
    72  		n, err := f.Read(buf)
    73  		assert.Equal(t, 0, n)
    74  		assert.Equal(t, io.EOF, err)
    75  
    76  		n, err = f.ReadAt(buf, 0)
    77  		assert.Equal(t, 0, n)
    78  		assert.Equal(t, io.EOF, err)
    79  
    80  		n, err = f.ReadAt(buf, 10)
    81  		assert.Equal(t, 0, n)
    82  		assert.Equal(t, io.EOF, err)
    83  
    84  		b, err := f.Slice(1, 10)
    85  		assert.Equal(t, io.EOF, err)
    86  		assert.Nil(t, b)
    87  	})
    88  
    89  	testData := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    90  
    91  	t.Run("Write", func(t *testing.T) {
    92  		n, err := f.Write(testData[:9])
    93  		assert.Nil(t, err)
    94  		assert.Equal(t, 9, n)
    95  
    96  		off, err := f.Seek(0, io.SeekCurrent)
    97  		assert.Nil(t, err)
    98  		assert.Equal(t, int64(9), off)
    99  	})
   100  
   101  	t.Run("Write beyond EOF", func(t *testing.T) {
   102  		off, err := f.Seek(2, io.SeekStart)
   103  		assert.Nil(t, err)
   104  		assert.Equal(t, int64(2), off)
   105  
   106  		n, err := f.Write(testData[2:])
   107  		assert.Nil(t, err)
   108  		assert.Equal(t, 8, n)
   109  
   110  		off, err = f.Seek(0, io.SeekCurrent)
   111  		assert.Nil(t, err)
   112  		assert.Equal(t, int64(10), off)
   113  	})
   114  
   115  	t.Run("Slice", func(t *testing.T) {
   116  		b, err := f.Slice(1, 9)
   117  		assert.Nil(t, err)
   118  		assert.Equal(t, testData[1:9], b)
   119  
   120  		b, err = f.Slice(0, 10)
   121  		assert.Nil(t, err)
   122  		assert.Equal(t, testData, b)
   123  
   124  		// Offset larger than mapping.
   125  		b, err = f.Slice(0, 12)
   126  		assert.Equal(t, io.EOF, err)
   127  		assert.Nil(t, b)
   128  	})
   129  
   130  	t.Run("WriteAt", func(t *testing.T) {
   131  		n, err := f.WriteAt(testData[1:4], 1)
   132  		assert.Nil(t, err)
   133  		assert.Equal(t, 3, n)
   134  
   135  		// WriteAt doesn't move offset.
   136  		off, err := f.Seek(0, io.SeekCurrent)
   137  		assert.Nil(t, err)
   138  		assert.Equal(t, int64(10), off)
   139  	})
   140  
   141  	t.Run("Sync", func(t *testing.T) {
   142  		// Not tested yet, just make sure it doesn't return an error.
   143  		assert.Nil(t, f.Sync())
   144  	})
   145  
   146  	t.Run("ReadAt", func(t *testing.T) {
   147  		n, err := f.ReadAt(buf, 0)
   148  		assert.Nil(t, err)
   149  		assert.Equal(t, len(testData), n)
   150  		assert.Equal(t, testData, buf)
   151  	})
   152  
   153  	t.Run("Read EOF", func(t *testing.T) {
   154  		n, err := f.Read(buf)
   155  		assert.Equal(t, io.EOF, err)
   156  		assert.Equal(t, 0, n)
   157  	})
   158  
   159  	t.Run("Read", func(t *testing.T) {
   160  		// SeekEnd and Read
   161  		off, err := f.Seek(0, io.SeekEnd)
   162  		assert.Nil(t, err)
   163  		assert.Equal(t, int64(len(testData)), off)
   164  
   165  		n, err := f.Read(buf)
   166  		assert.Equal(t, io.EOF, err)
   167  		assert.Equal(t, 0, n)
   168  
   169  		// SeekStart and Read
   170  		off, err = f.Seek(0, io.SeekStart)
   171  		assert.Nil(t, err)
   172  		assert.Equal(t, int64(0), off)
   173  
   174  		n, err = f.Read(buf)
   175  		assert.Nil(t, err)
   176  		assert.Equal(t, len(testData), n)
   177  		assert.Equal(t, testData, buf)
   178  
   179  		off, err = f.Seek(0, io.SeekCurrent)
   180  		assert.Equal(t, int64(n), off)
   181  		assert.Nil(t, err)
   182  
   183  		// SeekStart 2 and Read
   184  		testOff := int64(2)
   185  		lbuf := make([]byte, 8)
   186  		off, err = f.Seek(testOff, io.SeekStart)
   187  		assert.Nil(t, err)
   188  		assert.Equal(t, testOff, off)
   189  
   190  		n, err = f.Read(lbuf)
   191  		assert.Nil(t, err)
   192  		assert.Equal(t, len(testData)-int(testOff), n)
   193  		assert.Equal(t, testData[testOff:], lbuf)
   194  	})
   195  
   196  	t.Run("Read larger than file", func(t *testing.T) {
   197  		off, err := f.Seek(0, io.SeekStart)
   198  		assert.Nil(t, err)
   199  		assert.Equal(t, int64(0), off)
   200  
   201  		lbuf := make([]byte, 4096)
   202  		n, err := f.Read(lbuf)
   203  		assert.Nil(t, err)
   204  		assert.Equal(t, len(testData), n)
   205  		assert.Equal(t, testData, lbuf[:n])
   206  
   207  		n, err = f.Read(lbuf)
   208  		assert.Equal(t, io.EOF, err)
   209  		assert.Equal(t, 0, n)
   210  	})
   211  
   212  	t.Run("Close and Open again", func(t *testing.T) {
   213  		assert.Nil(t, f.Close())
   214  
   215  		f, err = fsys.OpenFile("test", os.O_RDWR, os.FileMode(0666))
   216  		assert.Nil(t, err)
   217  
   218  		b, err := f.Slice(1, 10)
   219  		assert.Nil(t, err)
   220  		assert.Equal(t, testData[1:], b)
   221  	})
   222  
   223  	t.Run("Truncate extend", func(t *testing.T) {
   224  		err := f.Truncate(11)
   225  		assert.Nil(t, err)
   226  
   227  		lbuf := make([]byte, 11)
   228  		n, err := f.ReadAt(lbuf, 0)
   229  		assert.Nil(t, err)
   230  		assert.Equal(t, 11, n)
   231  		assert.Equal(t, testData, lbuf[:10])
   232  
   233  		b, err := f.Slice(0, 11)
   234  		assert.Nil(t, err)
   235  		assert.Equal(t, testData, b[:10])
   236  
   237  		fi, err := f.Stat()
   238  		assert.Nil(t, err)
   239  		assert.Equal(t, int64(11), fi.Size())
   240  	})
   241  
   242  	t.Run("Truncate shrink", func(t *testing.T) {
   243  		err := f.Truncate(1)
   244  		assert.Nil(t, err)
   245  
   246  		lbuf := make([]byte, 1)
   247  		n, err := f.ReadAt(lbuf, 0)
   248  		assert.Nil(t, err)
   249  		assert.Equal(t, 1, n)
   250  		assert.Equal(t, testData[:1], lbuf)
   251  
   252  		b, err := f.Slice(0, 1)
   253  		assert.Nil(t, err)
   254  		assert.Equal(t, testData[:1], b)
   255  
   256  		b, err = f.Slice(0, 10)
   257  		assert.Equal(t, io.EOF, err)
   258  		assert.Nil(t, b)
   259  
   260  		fi, err := f.Stat()
   261  		assert.Nil(t, err)
   262  		assert.Equal(t, int64(1), fi.Size())
   263  	})
   264  
   265  	t.Run("Truncate shrink to zero", func(t *testing.T) {
   266  		err := f.Truncate(0)
   267  		assert.Nil(t, err)
   268  
   269  		n, err := f.ReadAt(buf, 0)
   270  		assert.Equal(t, io.EOF, err)
   271  		assert.Equal(t, 0, n)
   272  
   273  		b, err := f.Slice(0, 1)
   274  		assert.Equal(t, io.EOF, err)
   275  		assert.Nil(t, b)
   276  
   277  		fi, err := f.Stat()
   278  		assert.Nil(t, err)
   279  		assert.Equal(t, int64(0), fi.Size())
   280  	})
   281  
   282  	t.Run("Close", func(t *testing.T) {
   283  		assert.Nil(t, f.Close())
   284  
   285  		err := f.Close()
   286  		assert.NotNil(t, err)
   287  
   288  		_, err = f.Seek(1, io.SeekStart)
   289  		assert.NotNil(t, err)
   290  	})
   291  
   292  	t.Run("Rename", func(t *testing.T) {
   293  		err := fsys.Rename("foobar", "baz")
   294  		assert.NotNil(t, err)
   295  
   296  		assert.Nil(t, fsys.Rename("test", "test2"))
   297  		fi, err := fsys.Stat("test2")
   298  		assert.Nil(t, err)
   299  		assert.Equal(t, int64(0), fi.Size())
   300  		assert.Equal(t, "test2", fi.Name())
   301  	})
   302  
   303  	t.Run("ReadDir", func(t *testing.T) {
   304  		fis, err := fsys.ReadDir(".")
   305  		assert.Nil(t, err)
   306  
   307  		var hasTestFile bool
   308  		for _, fi := range fis {
   309  			if fi.Name() == "test2" {
   310  				hasTestFile = true
   311  			}
   312  		}
   313  		assert.Equal(t, true, hasTestFile)
   314  	})
   315  
   316  	t.Run("Remove", func(t *testing.T) {
   317  		err := fsys.Remove("test2")
   318  		assert.Nil(t, err)
   319  
   320  		_, err = fsys.Stat("test2")
   321  		assert.NotNil(t, err)
   322  	})
   323  }