TestUnmountWedged, fs.Destroy
This commit is contained in:
parent
1aa1063863
commit
8245f119ef
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue