Skip to content

Commit 9bdd53b

Browse files
Improve tests for read/write, handle ENOTEMPTY correctly
1 parent 0c8b1c5 commit 9bdd53b

File tree

3 files changed

+130
-18
lines changed

3 files changed

+130
-18
lines changed

component/libfuse/libfuse2_handler.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"io/fs"
3333
"os"
3434
"runtime"
35+
"syscall"
3536
"time"
3637

3738
"github.com/Seagate/cloudfuse/common"
@@ -714,6 +715,8 @@ func fuseErrnoFromError(err error) int {
714715
switch {
715716
case err == nil:
716717
return 0
718+
case errors.Is(err, syscall.ENOTEMPTY):
719+
return -fuse.ENOTEMPTY
717720
case errors.Is(err, fs.ErrNotExist):
718721
return -fuse.ENOENT
719722
case errors.Is(err, fs.ErrPermission):

component/libfuse/libfuse2_handler_test_wrapper.go

Lines changed: 115 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,35 @@ func testStatFsCloudStorageCapacity(suite *libfuseTestSuite) {
179179
ret := cfuseFS.Statfs(path, buf)
180180

181181
suite.assert.Equal(0, ret)
182-
blocksUnavailable := uint64(attr.Blocks - attr.Bavail)
183-
displayCapacityBlocks := fuseFS.displayCapacityMb * common.MbToBytes / uint64(attr.Bsize)
184-
expectedBlocks := max(displayCapacityBlocks, blocksUnavailable)
185-
suite.assert.Equal(expectedBlocks, buf.Blocks)
186-
suite.assert.Equal(expectedBlocks-blocksUnavailable, buf.Bavail)
187-
suite.assert.Equal(expectedBlocks-uint64(attr.Blocks-attr.Bfree), buf.Bfree)
182+
suite.assert.Equal(uint64(1024), buf.Blocks)
183+
suite.assert.Equal(uint64(1014), buf.Bavail)
184+
suite.assert.Equal(uint64(1014), buf.Bfree)
185+
}
186+
187+
func testStatFsCloudStorageCapacityUsedExceedsDisplay(suite *libfuseTestSuite) {
188+
defer suite.cleanupTest()
189+
path := "/"
190+
191+
fuseFS.displayCapacityMb = 1
192+
attr := &common.Statfs_t{
193+
Frsize: 1,
194+
Blocks: 5000,
195+
Bavail: 0,
196+
Bfree: 0,
197+
Bsize: 1024,
198+
Files: 6,
199+
Ffree: 7,
200+
Namemax: 255,
201+
}
202+
suite.mock.EXPECT().StatFs().Return(attr, true, nil)
203+
204+
buf := &fuse.Statfs_t{}
205+
ret := cfuseFS.Statfs(path, buf)
206+
207+
suite.assert.Equal(0, ret)
208+
suite.assert.Equal(uint64(5000), buf.Blocks)
209+
suite.assert.Equal(uint64(0), buf.Bavail)
210+
suite.assert.Equal(uint64(0), buf.Bfree)
188211
}
189212

190213
func testStatFsError(suite *libfuseTestSuite) {
@@ -461,9 +484,19 @@ func testReadFromComponent(suite *libfuseTestSuite) {
461484
defer handlemap.Delete(handle.ID)
462485

463486
buf := make([]byte, 4)
464-
suite.mock.EXPECT().ReadInBuffer(gomock.Any()).Return(4, nil)
465-
read := cfuseFS.Read("/file", buf, 0, uint64(fh))
487+
suite.mock.EXPECT().
488+
ReadInBuffer(gomock.AssignableToTypeOf(&internal.ReadInBufferOptions{})).
489+
DoAndReturn(func(opt *internal.ReadInBufferOptions) (int, error) {
490+
suite.assert.Equal(handle.ID, opt.Handle.ID)
491+
suite.assert.Equal("file", opt.Handle.Path)
492+
suite.assert.Equal(int64(7), opt.Offset)
493+
suite.assert.Equal(4, len(opt.Data))
494+
copy(opt.Data, []byte("ping"))
495+
return 4, nil
496+
})
497+
read := cfuseFS.Read("/file", buf, 7, uint64(fh))
466498
suite.assert.Equal(4, read)
499+
suite.assert.Equal("ping", string(buf))
467500
}
468501

469502
func testReadAccessDenied(suite *libfuseTestSuite) {
@@ -473,8 +506,15 @@ func testReadAccessDenied(suite *libfuseTestSuite) {
473506
defer handlemap.Delete(handle.ID)
474507

475508
buf := make([]byte, 4)
476-
suite.mock.EXPECT().ReadInBuffer(gomock.Any()).Return(0, os.ErrPermission)
477-
read := cfuseFS.Read("/file", buf, 0, uint64(fh))
509+
suite.mock.EXPECT().
510+
ReadInBuffer(gomock.AssignableToTypeOf(&internal.ReadInBufferOptions{})).
511+
DoAndReturn(func(opt *internal.ReadInBufferOptions) (int, error) {
512+
suite.assert.Equal(handle.ID, opt.Handle.ID)
513+
suite.assert.Equal(int64(3), opt.Offset)
514+
suite.assert.Equal(4, len(opt.Data))
515+
return 0, os.ErrPermission
516+
})
517+
read := cfuseFS.Read("/file", buf, 3, uint64(fh))
478518
suite.assert.Equal(-fuse.EACCES, read)
479519
}
480520

@@ -485,8 +525,15 @@ func testReadError(suite *libfuseTestSuite) {
485525
defer handlemap.Delete(handle.ID)
486526

487527
buf := make([]byte, 4)
488-
suite.mock.EXPECT().ReadInBuffer(gomock.Any()).Return(0, errors.New("boom"))
489-
read := cfuseFS.Read("/file", buf, 0, uint64(fh))
528+
suite.mock.EXPECT().
529+
ReadInBuffer(gomock.AssignableToTypeOf(&internal.ReadInBufferOptions{})).
530+
DoAndReturn(func(opt *internal.ReadInBufferOptions) (int, error) {
531+
suite.assert.Equal(handle.ID, opt.Handle.ID)
532+
suite.assert.Equal(int64(5), opt.Offset)
533+
suite.assert.Equal(4, len(opt.Data))
534+
return 0, errors.New("boom")
535+
})
536+
read := cfuseFS.Read("/file", buf, 5, uint64(fh))
490537
suite.assert.Equal(-fuse.EIO, read)
491538
}
492539

@@ -504,8 +551,16 @@ func testWriteSuccess(suite *libfuseTestSuite) {
504551
defer handlemap.Delete(handle.ID)
505552

506553
buf := []byte("data")
507-
suite.mock.EXPECT().WriteFile(gomock.Any()).Return(len(buf), nil)
508-
written := cfuseFS.Write("/file", buf, 0, uint64(fh))
554+
suite.mock.EXPECT().
555+
WriteFile(gomock.AssignableToTypeOf(&internal.WriteFileOptions{})).
556+
DoAndReturn(func(opt *internal.WriteFileOptions) (int, error) {
557+
suite.assert.Equal(handle.ID, opt.Handle.ID)
558+
suite.assert.Equal("file", opt.Handle.Path)
559+
suite.assert.Equal(int64(9), opt.Offset)
560+
suite.assert.Equal("data", string(opt.Data))
561+
return len(opt.Data), nil
562+
})
563+
written := cfuseFS.Write("/file", buf, 9, uint64(fh))
509564
suite.assert.Equal(len(buf), written)
510565
}
511566

@@ -516,8 +571,15 @@ func testWriteError(suite *libfuseTestSuite) {
516571
defer handlemap.Delete(handle.ID)
517572

518573
buf := []byte("data")
519-
suite.mock.EXPECT().WriteFile(gomock.Any()).Return(0, errors.New("boom"))
520-
written := cfuseFS.Write("/file", buf, 0, uint64(fh))
574+
suite.mock.EXPECT().
575+
WriteFile(gomock.AssignableToTypeOf(&internal.WriteFileOptions{})).
576+
DoAndReturn(func(opt *internal.WriteFileOptions) (int, error) {
577+
suite.assert.Equal(handle.ID, opt.Handle.ID)
578+
suite.assert.Equal(int64(11), opt.Offset)
579+
suite.assert.Equal("data", string(opt.Data))
580+
return 0, errors.New("boom")
581+
})
582+
written := cfuseFS.Write("/file", buf, 11, uint64(fh))
521583
suite.assert.Equal(-fuse.EIO, written)
522584
}
523585

@@ -528,8 +590,15 @@ func testWriteAccessDenied(suite *libfuseTestSuite) {
528590
defer handlemap.Delete(handle.ID)
529591

530592
buf := []byte("data")
531-
suite.mock.EXPECT().WriteFile(gomock.Any()).Return(0, os.ErrPermission)
532-
written := cfuseFS.Write("/file", buf, 0, uint64(fh))
593+
suite.mock.EXPECT().
594+
WriteFile(gomock.AssignableToTypeOf(&internal.WriteFileOptions{})).
595+
DoAndReturn(func(opt *internal.WriteFileOptions) (int, error) {
596+
suite.assert.Equal(handle.ID, opt.Handle.ID)
597+
suite.assert.Equal(int64(13), opt.Offset)
598+
suite.assert.Equal("data", string(opt.Data))
599+
return 0, os.ErrPermission
600+
})
601+
written := cfuseFS.Write("/file", buf, 13, uint64(fh))
533602
suite.assert.Equal(-fuse.EACCES, written)
534603
}
535604

@@ -884,6 +953,19 @@ func testRmDirPermission(suite *libfuseTestSuite) {
884953
suite.assert.Equal(-fuse.EACCES, err)
885954
}
886955

956+
func testRmDirRaceNotEmpty(suite *libfuseTestSuite) {
957+
defer suite.cleanupTest()
958+
name := "path"
959+
path := "/" + name
960+
isDirEmptyOptions := internal.IsDirEmptyOptions{Name: name}
961+
suite.mock.EXPECT().IsDirEmpty(isDirEmptyOptions).Return(true)
962+
deleteDirOptions := internal.DeleteDirOptions{Name: name}
963+
suite.mock.EXPECT().DeleteDir(deleteDirOptions).Return(syscall.ENOTEMPTY)
964+
965+
err := cfuseFS.Rmdir(path)
966+
suite.assert.Equal(-fuse.ENOTEMPTY, err)
967+
}
968+
887969
func testCreate(suite *libfuseTestSuite) {
888970
defer suite.cleanupTest()
889971
name := "path"
@@ -1044,6 +1126,21 @@ func testRenameDirPermission(suite *libfuseTestSuite) {
10441126
suite.assert.Equal(-fuse.EACCES, err)
10451127
}
10461128

1129+
func testRenameDirDstGetAttrPermission(suite *libfuseTestSuite) {
1130+
defer suite.cleanupTest()
1131+
1132+
src := "src"
1133+
dst := "dst"
1134+
srcAttr := &internal.ObjAttr{Flags: internal.NewDirBitMap()}
1135+
1136+
suite.mock.EXPECT().GetAttr(internal.GetAttrOptions{Name: src}).Return(srcAttr, nil)
1137+
suite.mock.EXPECT().GetAttr(internal.GetAttrOptions{Name: dst}).Return(nil, os.ErrPermission)
1138+
suite.mock.EXPECT().RenameDir(gomock.Any()).Times(0)
1139+
1140+
err := cfuseFS.Rename("/"+src, "/"+dst)
1141+
suite.assert.Equal(-fuse.EACCES, err)
1142+
}
1143+
10471144
func testOpen(suite *libfuseTestSuite) {
10481145
defer suite.cleanupTest()
10491146
name := "path"

component/libfuse/libfuse_handler_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ func (suite *libfuseTestSuite) TestRmDirPermission() {
400400
testRmDirPermission(suite)
401401
}
402402

403+
func (suite *libfuseTestSuite) TestRmDirRaceNotEmpty() {
404+
testRmDirRaceNotEmpty(suite)
405+
}
406+
403407
func (suite *libfuseTestSuite) TestCreate() {
404408
testCreate(suite)
405409
}
@@ -572,6 +576,10 @@ func (suite *libfuseTestSuite) TestRenameDirPermission() {
572576
testRenameDirPermission(suite)
573577
}
574578

579+
func (suite *libfuseTestSuite) TestRenameDirDstGetAttrPermission() {
580+
testRenameDirDstGetAttrPermission(suite)
581+
}
582+
575583
func (suite *libfuseTestSuite) TestSymlink() {
576584
testSymlink(suite)
577585
}
@@ -648,6 +656,10 @@ func (suite *libfuseTestSuite) TestStatFsCloudStorageCapacity() {
648656
testStatFsCloudStorageCapacity(suite)
649657
}
650658

659+
func (suite *libfuseTestSuite) TestStatFsCloudStorageCapacityUsedExceedsDisplay() {
660+
testStatFsCloudStorageCapacityUsedExceedsDisplay(suite)
661+
}
662+
651663
func (suite *libfuseTestSuite) TestStatFsError() {
652664
testStatFsError(suite)
653665
}

0 commit comments

Comments
 (0)