package torrent
import (
+ "encoding/binary"
"fmt"
+ "io"
+ "io/ioutil"
"log"
"net"
"os"
"testing"
"time"
- "bitbucket.org/anacrolix/go.torrent/testutil"
+ "bitbucket.org/anacrolix/go.torrent/data/blob"
+ "github.com/anacrolix/libtorgo/metainfo"
+
+ "github.com/bradfitz/iter"
+
+ "bitbucket.org/anacrolix/go.torrent/internal/testutil"
"bitbucket.org/anacrolix/go.torrent/util"
"bitbucket.org/anacrolix/utp"
"github.com/anacrolix/libtorgo/bencode"
)
+var TestingConfig = Config{
+ ListenAddr: ":0",
+ NoDHT: true,
+ DisableTrackers: true,
+ NoDefaultBlocklist: true,
+ DisableMetainfoCache: true,
+}
+
func TestClientDefault(t *testing.T) {
cl, err := NewClient(&Config{
NoDefaultBlocklist: true,
if err != nil {
t.Fatal(err)
}
- if len(tor.Pieces) != 1 {
+ if len(tor.Pieces) != 3 {
t.Fatal("wrong number of pieces")
}
p := tor.Pieces[0]
if len(p.PendingChunkSpecs) != 1 {
t.Fatalf("should only be 1 chunk: %v", p.PendingChunkSpecs)
}
- if _, ok := p.PendingChunkSpecs[chunkSpec{
- Length: 13,
- }]; !ok {
- t.Fatal("pending chunk spec is incorrect")
+ // TODO: Set chunkSize to 2, to test odd/even silliness.
+ if false {
+ if _, ok := p.PendingChunkSpecs[chunkSpec{
+ Length: 13,
+ }]; !ok {
+ t.Fatal("pending chunk spec is incorrect")
+ }
}
}
defer cl.Stop()
}
}
+
+func TestAddDropManyTorrents(t *testing.T) {
+ cl, _ := NewClient(&TestingConfig)
+ defer cl.Stop()
+ var m Magnet
+ for i := range iter.N(1000) {
+ binary.PutVarint(m.InfoHash[:], int64(i))
+ cl.AddMagnet(m.String())
+ }
+}
+
+func TestClientTransfer(t *testing.T) {
+ greetingTempDir, mi := testutil.GreetingTestTorrent()
+ defer os.RemoveAll(greetingTempDir)
+ cfg := TestingConfig
+ cfg.DataDir = greetingTempDir
+ seeder, err := NewClient(&cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer seeder.Stop()
+ seeder.AddTorrent(mi)
+ leecherDataDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(leecherDataDir)
+ cfg.TorrentDataOpener = func(info *metainfo.Info) (Data, error) {
+ return blob.TorrentData(info, leecherDataDir), nil
+ }
+ leecher, _ := NewClient(&cfg)
+ defer leecher.Stop()
+ leecherGreeting, _ := leecher.AddTorrent(mi)
+ leecherGreeting.AddPeers([]Peer{
+ Peer{
+ IP: util.AddrIP(seeder.ListenAddr()),
+ Port: util.AddrPort(seeder.ListenAddr()),
+ },
+ })
+ _greeting, err := ioutil.ReadAll(io.NewSectionReader(leecherGreeting, 0, leecherGreeting.Length()))
+ if err != nil {
+ t.Fatal(err)
+ }
+ greeting := string(_greeting)
+ if greeting != testutil.GreetingFileContents {
+ t.Fatal(":(")
+ }
+}
--- /dev/null
+package blob
+
+import (
+ "encoding/hex"
+ "errors"
+ "io"
+ "os"
+
+ "github.com/anacrolix/libtorgo/metainfo"
+)
+
+type data struct {
+ info *metainfo.Info
+ baseDir string
+}
+
+func TorrentData(info *metainfo.Info, baseDir string) *data {
+ return &data{info, baseDir}
+}
+
+func (me *data) pieceHashHex(i int) string {
+ return hex.EncodeToString(me.info.Pieces[i*20 : (i+1)*20])
+}
+
+func (me *data) Close() {}
+
+func (me *data) ReadAt(p []byte, off int64) (n int, err error) {
+ hash := me.pieceHashHex(int(off / me.info.PieceLength))
+ f, err := os.Open(me.baseDir + "/complete/" + hash)
+ if os.IsNotExist(err) {
+ f, err = os.Open(me.baseDir + "/incomplete/" + hash)
+ if os.IsNotExist(err) {
+ err = io.EOF
+ return
+ }
+ if err != nil {
+ return
+ }
+ } else if err != nil {
+ return
+ }
+ defer f.Close()
+ off %= me.info.PieceLength
+ return f.ReadAt(p, off)
+}
+
+func (me *data) openComplete(piece int) (f *os.File, err error) {
+ return os.OpenFile(me.baseDir+"/complete/"+me.pieceHashHex(piece), os.O_RDWR, 0660)
+}
+
+func (me *data) WriteAt(p []byte, off int64) (n int, err error) {
+ i := int(off / me.info.PieceLength)
+ off %= me.info.PieceLength
+ for len(p) != 0 {
+ _, err = os.Stat(me.baseDir + "/complete/" + me.pieceHashHex(i))
+ if err == nil {
+ err = errors.New("can't write to completed piece")
+ return
+ }
+ os.MkdirAll(me.baseDir+"/incomplete", 0750)
+ var f *os.File
+ f, err = os.OpenFile(me.baseDir+"/incomplete/"+me.pieceHashHex(i), os.O_WRONLY|os.O_CREATE, 0640)
+ if err != nil {
+ return
+ }
+ p1 := p
+ maxN := me.info.Piece(i).Length() - off
+ if int64(len(p1)) > maxN {
+ p1 = p1[:maxN]
+ }
+ var n1 int
+ n1, err = f.WriteAt(p1, off)
+ f.Close()
+ n += n1
+ if err != nil {
+ return
+ }
+ p = p[n1:]
+ off = 0
+ }
+ return
+}
+
+func (me *data) pieceReader(piece int, off int64) (ret io.ReadCloser, err error) {
+ hash := me.pieceHashHex(piece)
+ f, err := os.Open(me.baseDir + "/complete/" + hash)
+ if os.IsNotExist(err) {
+ f, err = os.Open(me.baseDir + "/incomplete/" + hash)
+ if os.IsNotExist(err) {
+ err = io.EOF
+ return
+ }
+ if err != nil {
+ return
+ }
+ } else if err != nil {
+ return
+ }
+ return struct {
+ io.Reader
+ io.Closer
+ }{io.NewSectionReader(f, off, me.info.Piece(piece).Length()-off), f}, nil
+}
+
+func (me *data) WriteSectionTo(w io.Writer, off, n int64) (written int64, err error) {
+ i := int(off / me.info.PieceLength)
+ off %= me.info.PieceLength
+ for n != 0 {
+ var pr io.ReadCloser
+ pr, err = me.pieceReader(i, off)
+ if err != nil {
+ if err == io.EOF {
+ err = nil
+ }
+ return
+ }
+ var n1 int64
+ n1, err = io.CopyN(w, pr, n)
+ written += n1
+ n -= n1
+ if err != nil {
+ return
+ }
+ off = 0
+ }
+ return
+}
"bitbucket.org/anacrolix/go.torrent"
"bitbucket.org/anacrolix/go.torrent/data/mmap"
- "bitbucket.org/anacrolix/go.torrent/testutil"
+ "bitbucket.org/anacrolix/go.torrent/internal/testutil"
"bitbucket.org/anacrolix/go.torrent/util"
"github.com/anacrolix/libtorgo/metainfo"
fusefs "bazil.org/fuse/fs"
)
-func init() {
- go http.ListenAndServe(":6061", nil)
-}
-
func TestTCPAddrString(t *testing.T) {
l, err := net.Listen("tcp4", "localhost:0")
if err != nil {
builder := metainfo.Builder{}
builder.AddFile(name)
builder.AddAnnounceGroup([]string{"lol://cheezburger"})
+ builder.SetPieceLength(5)
batch, err := builder.Submit()
if err != nil {
panic(err)