]> Sergey Matveev's repositories - btrtrc.git/commitdiff
TestUnmountWedged, fs.Destroy
authorMatt Joiner <anacrolix@gmail.com>
Thu, 17 Apr 2014 06:37:54 +0000 (16:37 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 17 Apr 2014 06:37:54 +0000 (16:37 +1000)
fs/torrentfs.go
fs/torrentfs_test.go

index 914c269754d207b932f8e5526b6b870f7f56a413..02c2e306505a17c192779ce7ecfd06f573bcd32d 100644 (file)
@@ -3,6 +3,7 @@ package torrentfs
 import (
        "log"
        "os"
+       "sync"
 
        "bazil.org/fuse"
        fusefs "bazil.org/fuse/fs"
@@ -15,7 +16,9 @@ const (
 )
 
 type torrentFS struct {
-       Client *torrent.Client
+       Client    *torrent.Client
+       destroyed chan struct{}
+       mu        sync.Mutex
 }
 
 var _ fusefs.NodeForgetter = rootNode{}
@@ -75,6 +78,8 @@ func (fn fileNode) Read(req *fuse.ReadRequest, resp *fuse.ReadResponse, intr fus
                case torrent.ErrDataNotReady:
                        select {
                        case <-dataWaiter:
+                       case <-fn.FS.destroyed:
+                               return fuse.EIO
                        case <-intr:
                                return fuse.EINTR
                        }
@@ -217,16 +222,30 @@ func (rootNode) Attr() fuse.Attr {
 }
 
 // TODO(anacrolix): Why should rootNode implement this?
-func (rootNode) Forget() {
+func (me rootNode) Forget() {
+       me.fs.Destroy()
 }
 
 func (tfs *torrentFS) Root() (fusefs.Node, fuse.Error) {
        return rootNode{tfs}, nil
 }
 
+func (me *torrentFS) Destroy() {
+       me.mu.Lock()
+       select {
+       case <-me.destroyed:
+       default:
+               close(me.destroyed)
+       }
+       me.mu.Unlock()
+}
+
+var _ fusefs.FSDestroyer = &torrentFS{}
+
 func New(cl *torrent.Client) *torrentFS {
        fs := &torrentFS{
-               Client: cl,
+               Client:    cl,
+               destroyed: make(chan struct{}),
        }
        return fs
 }
index f43b913de554ff46c569548a7bb78bca4e8bec03..a1ae3f8295035528b3bb19cdd270eb42261826ef 100644 (file)
@@ -3,6 +3,7 @@ package torrentfs
 import (
        "bytes"
        "io/ioutil"
+       "log"
        "net"
        "os"
        "path/filepath"
@@ -39,25 +40,91 @@ func TestTCPAddrString(t *testing.T) {
        }
 }
 
-func TestDownloadOnDemand(t *testing.T) {
-       dir, err := ioutil.TempDir("", "torrentfs")
+type testLayout struct {
+       BaseDir   string
+       MountDir  string
+       Completed string
+       Metainfo  *metainfo.MetaInfo
+}
+
+func (me *testLayout) Destroy() error {
+       return os.RemoveAll(me.BaseDir)
+}
+
+func newGreetingLayout() (tl testLayout, err error) {
+       tl.BaseDir, err = ioutil.TempDir("", "torrentfs")
+       if err != nil {
+               return
+       }
+       tl.Completed = filepath.Join(tl.BaseDir, "completed")
+       os.Mkdir(tl.Completed, 0777)
+       tl.MountDir = filepath.Join(tl.BaseDir, "mnt")
+       os.Mkdir(tl.MountDir, 0777)
+       name := testutil.CreateDummyTorrentData(tl.Completed)
+       metaInfoBuf := &bytes.Buffer{}
+       testutil.CreateMetaInfo(name, metaInfoBuf)
+       tl.Metainfo, err = metainfo.Load(metaInfoBuf)
+       return
+}
+
+func TestUnmountWedged(t *testing.T) {
+       layout, err := newGreetingLayout()
        if err != nil {
                t.Fatal(err)
        }
        defer func() {
-               if err := os.RemoveAll(dir); err != nil {
-                       t.Error(err)
+               err := layout.Destroy()
+               if err != nil {
+                       t.Log(err)
                }
        }()
-       t.Logf("test directory: %s", dir)
-       finishedDir := filepath.Join(dir, "finished")
-       os.Mkdir(finishedDir, 0777)
-       name := testutil.CreateDummyTorrentData(finishedDir)
-       metaInfoBuf := &bytes.Buffer{}
-       testutil.CreateMetaInfo(name, metaInfoBuf)
-       metaInfo, err := metainfo.Load(metaInfoBuf)
+       client := torrent.Client{
+               DataDir:         filepath.Join(layout.BaseDir, "incomplete"),
+               DisableTrackers: true,
+       }
+       client.Start()
+       client.AddTorrent(layout.Metainfo)
+       fs := New(&client)
+       fuseConn, err := fuse.Mount(layout.MountDir)
+       if err != nil {
+               t.Fatal(err)
+       }
+       go func() {
+               server := fusefs.Server{
+                       FS: fs,
+                       Debug: func(msg interface{}) {
+                               log.Print(msg)
+                       },
+               }
+               server.Serve(fuseConn)
+       }()
+       <-fuseConn.Ready
+       if err := fuseConn.MountError; err != nil {
+               log.Fatal(err)
+       }
+       go func() {
+               ioutil.ReadFile(filepath.Join(layout.MountDir, layout.Metainfo.Name))
+       }()
+       time.Sleep(time.Second)
+       fs.Destroy()
+       time.Sleep(time.Second)
+       err = fuse.Unmount(layout.MountDir)
+       if err != nil {
+               log.Print(err)
+       }
+       err = fuseConn.Close()
+       if err != nil {
+               t.Log(err)
+       }
+}
+
+func TestDownloadOnDemand(t *testing.T) {
+       layout, err := newGreetingLayout()
+       if err != nil {
+               t.Fatal(err)
+       }
        seeder := torrent.Client{
-               DataDir: finishedDir,
+               DataDir: layout.Completed,
                Listener: func() net.Listener {
                        conn, err := net.Listen("tcp", ":0")
                        if err != nil {
@@ -69,24 +136,23 @@ func TestDownloadOnDemand(t *testing.T) {
        defer seeder.Listener.Close()
        seeder.Start()
        defer seeder.Stop()
-       seeder.AddTorrent(metaInfo)
+       seeder.AddTorrent(layout.Metainfo)
        leecher := torrent.Client{
-               DataDir: filepath.Join(dir, "download"),
+               DataDir: filepath.Join(layout.BaseDir, "download"),
        }
        leecher.Start()
        defer leecher.Stop()
-       leecher.AddTorrent(metaInfo)
-       leecher.AddPeers(torrent.BytesInfoHash(metaInfo.InfoHash), []torrent.Peer{func() torrent.Peer {
+       leecher.AddTorrent(layout.Metainfo)
+       leecher.AddPeers(torrent.BytesInfoHash(layout.Metainfo.InfoHash), []torrent.Peer{func() torrent.Peer {
                tcpAddr := seeder.Listener.Addr().(*net.TCPAddr)
                return torrent.Peer{
                        IP:   tcpAddr.IP,
                        Port: tcpAddr.Port,
                }
        }()})
-       mountDir := filepath.Join(dir, "mnt")
-       os.Mkdir(mountDir, 0777)
        fs := New(&leecher)
-       fuseConn, err := fuse.Mount(mountDir)
+       mountDir := layout.MountDir
+       fuseConn, err := fuse.Mount(layout.MountDir)
        if err != nil {
                t.Fatal(err)
        }