From 00fae5cc2d4eb04961bb46971d6888183395faea Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Tue, 3 Jun 2025 21:02:04 +1000 Subject: [PATCH] Add Go version of fs/test.sh --- fs/stream-sintel_test.go | 159 +++++++++++++++++++++++++++++++++++++++ fs/test.sh | 4 +- 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 fs/stream-sintel_test.go diff --git a/fs/stream-sintel_test.go b/fs/stream-sintel_test.go new file mode 100644 index 00000000..3db62294 --- /dev/null +++ b/fs/stream-sintel_test.go @@ -0,0 +1,159 @@ +package torrentfs_test + +import ( + "context" + "crypto/md5" + "encoding/hex" + "errors" + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "testing" + "time" + + "github.com/anacrolix/fuse" + fusefs "github.com/anacrolix/fuse/fs" + "github.com/anacrolix/missinggo/v2/panicif" + "github.com/anacrolix/torrent" + torrentfs "github.com/anacrolix/torrent/fs" + "github.com/anacrolix/torrent/internal/testutil" + "github.com/anacrolix/torrent/metainfo" + "github.com/go-quicktest/qt" + "golang.org/x/sync/errgroup" +) + +func copyFile(src, dst string) (err error) { + from, err := os.Open(src) + if err != nil { + return + } + defer from.Close() + to, err := os.Create(dst) + if err != nil { + return + } + defer to.Close() + _, err = io.Copy(to, from) + if err != nil { + return + } + return to.Close() +} + +func TestStreamSintelMagnet(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode") + } + dir := t.TempDir() + t.Logf("temp dir: %v", dir) + metainfoDir := filepath.Join(dir, "torrents") + mountDir := filepath.Join(dir, "mnt") + sourceTorrentDir := `../testdata` + dummyTorrent := filepath.Join(sourceTorrentDir, `debian-10.8.0-amd64-netinst.iso.torrent`) + t.Log(os.Getwd()) + dummyTorrentDst := filepath.Join(metainfoDir, filepath.Base(dummyTorrent)) + err := os.MkdirAll(filepath.Dir(dummyTorrentDst), 0o700) + panicif.Err(err) + err = copyFile(dummyTorrent, dummyTorrentDst) + panicif.Err(err) + mi, err := metainfo.LoadFromFile(filepath.Join(sourceTorrentDir, `sintel.torrent`)) + panicif.Err(err) + m, err := mi.MagnetV2() + panicif.Err(err) + err = os.WriteFile(filepath.Join(metainfoDir, "sintel.magnet"), []byte(m.String()), 0600) + panicif.Err(err) + cl, err := torrent.NewClient(nil) + panicif.Err(err) + testutil.ExportStatusWriter(cl, "", t) + defer cl.Close() + + err = os.Mkdir(mountDir, 0700) + panicif.Err(err) + conn, err := fuse.Mount(mountDir) + panicif.Err(err) + t.Cleanup(func() { fuse.Unmount(mountDir) }) + t.Cleanup(func() { conn.Close() }) + fs := torrentfs.New(cl) + var eg errgroup.Group + eg.Go(func() (err error) { + err = fusefs.Serve(conn, fs) + if err != nil { + err = fmt.Errorf("serving fuse: %w", err) + t.Log(err) + return + } + return + }) + <-conn.Ready + err = conn.MountError + if err != nil { + err = fmt.Errorf("conn mount error: %w", err) + } + + go func() { + _, err := cl.AddTorrent(mi) + panicif.Err(err) + _, err = cl.AddMagnet(m.String()) + panicif.Err(err) + }() + + f, err := openFileWhenExists(t, filepath.Join(mountDir, "Sintel", "Sintel.mp4")) + panicif.Err(err) + t.Logf("opened %v", f.Name()) + t.Cleanup(func() { f.Close() }) + + fi, err := f.Stat() + panicif.Err(err) + + var written int64 + w := writer{ + onWrite: func(p []byte) (n int, err error) { + written += int64(len(p)) + t.Logf("wrote %v bytes", len(p)) + t.Logf("progress %v", float64(written)/float64(fi.Size())) + return len(p), nil + }, + } + h := md5.New() + _, err = f.WriteTo(io.MultiWriter(h, &w)) + panicif.Err(err) + err = f.Close() + panicif.Err(err) + + qt.Assert(t, qt.Equals(hex.EncodeToString(h.Sum(nil)), "083e808d56aa7b146f513b3458658292")) + + err = fuse.Unmount(mountDir) + panicif.Err(err) + err = eg.Wait() + panicif.Err(err) +} + +func openFileWhenExists(t *testing.T, name string) (f *os.File, err error) { + ctx := t.Context() + for { + f, err = os.Open(name) + if err == nil { + return + } + if !errors.Is(err, fs.ErrNotExist) { + return + } + t.Logf("file does not yet exist: %v", name) + select { + case <-ctx.Done(): + err = context.Cause(ctx) + return + case <-time.After(1 * time.Second): + } + } +} + +type writer struct { + onWrite func(b []byte) (n int, err error) +} + +func (w writer) Write(p []byte) (n int, err error) { + return w.onWrite(p) +} diff --git a/fs/test.sh b/fs/test.sh index 7ac309a8..c8eb43c2 100755 --- a/fs/test.sh +++ b/fs/test.sh @@ -13,13 +13,13 @@ popd #file="$debian_file" file=Sintel/Sintel.mp4 -GOPPROF=http godo -v -- "$repopath/fs/cmd/torrentfs" -mountDir=mnt -metainfoDir=torrents & +GOPPROF=http godo -v -- "$repopath/fs/cmd/torrentfs" -mountDir=mnt -metainfoDir=torrents &> torrentfs.log & torrentfs_pid=$! trap 'kill "$torrentfs_pid"' EXIT check_file() { while [ ! -e "mnt/$file" ]; do sleep 1; done - pv -f "mnt/$file" | md5sum -c <(cat <<-EOF + pv -f "mnt/$file" | gmd5sum -c <(cat <<-EOF 083e808d56aa7b146f513b3458658292 - EOF ) -- 2.51.0