github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/file/fsnodefuse/err_test.go (about) 1 package fsnodefuse 2 3 import ( 4 "context" 5 "io/ioutil" 6 "os" 7 "path" 8 "sync/atomic" 9 "testing" 10 11 "github.com/Schaudge/grailbase/file/fsnode" 12 "github.com/Schaudge/grailbase/ioctx/fsctx" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 // TestPanic* panic while handling a FUSE operation, then repeat the operation to make 18 // sure the mount isn't broken. 19 // TODO: Test operations exhaustively, maybe with something like fuzzing. 20 21 func TestPanicOpen(t *testing.T) { 22 const success = "success" 23 var ( 24 info = fsnode.NewRegInfo("panicOnce") 25 panicked int32 26 ) 27 root := fsnode.NewParent(fsnode.NewDirInfo("root"), 28 fsnode.ConstChildren( 29 fsnode.FuncLeaf( 30 info, 31 func(ctx context.Context, flag int) (fsctx.File, error) { 32 if atomic.AddInt32(&panicked, 1) == 1 { 33 panic("it's a panic!") 34 } 35 return fsnode.Open(ctx, fsnode.ConstLeaf(info, []byte(success))) 36 }, 37 ), 38 ), 39 ) 40 withMounted(t, root, func(mountDir string) { 41 _, err := os.Open(path.Join(mountDir, "panicOnce")) 42 require.Error(t, err) 43 f, err := os.Open(path.Join(mountDir, "panicOnce")) 44 require.NoError(t, err) 45 defer func() { require.NoError(t, f.Close()) }() 46 content, err := ioutil.ReadAll(f) 47 require.NoError(t, err) 48 assert.Equal(t, success, string(content)) 49 }) 50 } 51 52 func TestPanicList(t *testing.T) { 53 const success = "success" 54 var panicked int32 55 root := fsnode.NewParent(fsnode.NewDirInfo("root"), 56 fsnode.FuncChildren(func(context.Context) ([]fsnode.T, error) { 57 if atomic.AddInt32(&panicked, 1) == 1 { 58 panic("it's a panic!") 59 } 60 return []fsnode.T{ 61 fsnode.ConstLeaf(fsnode.NewRegInfo(success), nil), 62 }, nil 63 }), 64 ) 65 withMounted(t, root, func(mountDir string) { 66 dir, err := os.Open(mountDir) 67 require.NoError(t, err) 68 ents, _ := dir.Readdirnames(0) 69 // It seems like Readdirnames returns nil error despite the panic. 70 // TODO: Confirm this is expected. 71 assert.Empty(t, ents) 72 require.NoError(t, dir.Close()) 73 dir, err = os.Open(mountDir) 74 require.NoError(t, err) 75 defer func() { require.NoError(t, dir.Close()) }() 76 ents, err = dir.Readdirnames(0) 77 assert.NoError(t, err) 78 assert.Equal(t, []string{success}, ents) 79 }) 80 }