2014-03-17 14:44:22 +00:00
|
|
|
package torrent
|
|
|
|
|
|
|
|
import (
|
2015-02-26 14:46:02 +00:00
|
|
|
"encoding/binary"
|
2014-12-04 01:57:43 +00:00
|
|
|
"fmt"
|
2015-06-02 14:16:38 +00:00
|
|
|
"io"
|
2015-02-26 14:46:02 +00:00
|
|
|
"io/ioutil"
|
2014-03-20 05:58:09 +00:00
|
|
|
"os"
|
2016-09-21 11:02:18 +00:00
|
|
|
"path/filepath"
|
2018-06-09 12:10:08 +00:00
|
|
|
"reflect"
|
2014-03-17 14:44:22 +00:00
|
|
|
"testing"
|
2014-11-18 00:04:09 +00:00
|
|
|
"time"
|
2014-08-21 08:24:19 +00:00
|
|
|
|
2019-07-19 03:23:36 +00:00
|
|
|
"github.com/bradfitz/iter"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2019-08-10 08:46:07 +00:00
|
|
|
"github.com/anacrolix/dht/v2"
|
2015-08-03 14:29:01 +00:00
|
|
|
"github.com/anacrolix/missinggo"
|
2020-01-09 11:58:23 +00:00
|
|
|
"github.com/anacrolix/missinggo/v2/filecache"
|
2019-08-21 10:58:40 +00:00
|
|
|
|
2015-04-29 14:31:34 +00:00
|
|
|
"github.com/anacrolix/torrent/bencode"
|
2015-03-20 05:37:44 +00:00
|
|
|
"github.com/anacrolix/torrent/internal/testutil"
|
2015-08-03 15:07:22 +00:00
|
|
|
"github.com/anacrolix/torrent/iplist"
|
2015-06-02 14:16:38 +00:00
|
|
|
"github.com/anacrolix/torrent/metainfo"
|
2016-03-28 09:38:30 +00:00
|
|
|
"github.com/anacrolix/torrent/storage"
|
2014-03-17 14:44:22 +00:00
|
|
|
)
|
|
|
|
|
2014-08-21 08:07:06 +00:00
|
|
|
func TestClientDefault(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
|
|
|
require.NoError(t, err)
|
|
|
|
cl.Close()
|
|
|
|
}
|
|
|
|
|
2018-04-12 13:34:31 +00:00
|
|
|
func TestClientNilConfig(t *testing.T) {
|
|
|
|
cl, err := NewClient(nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
cl.Close()
|
|
|
|
}
|
|
|
|
|
2017-06-01 12:57:08 +00:00
|
|
|
func TestBoltPieceCompletionClosedWhenClientClosed(t *testing.T) {
|
|
|
|
cfg := TestingConfig()
|
|
|
|
pc, err := storage.NewBoltPieceCompletion(cfg.DataDir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
ci := storage.NewFileWithCompletion(cfg.DataDir, pc)
|
|
|
|
defer ci.Close()
|
|
|
|
cfg.DefaultStorage = ci
|
|
|
|
cl, err := NewClient(cfg)
|
|
|
|
require.NoError(t, err)
|
|
|
|
cl.Close()
|
|
|
|
// And again, https://github.com/anacrolix/torrent/issues/158
|
|
|
|
cl, err = NewClient(cfg)
|
2016-03-28 10:57:04 +00:00
|
|
|
require.NoError(t, err)
|
2015-03-08 06:28:14 +00:00
|
|
|
cl.Close()
|
2014-08-21 08:07:06 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 03:54:59 +00:00
|
|
|
func TestAddDropTorrent(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2016-03-28 10:57:04 +00:00
|
|
|
require.NoError(t, err)
|
2015-03-08 06:28:14 +00:00
|
|
|
defer cl.Close()
|
2015-02-06 03:54:59 +00:00
|
|
|
dir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(dir)
|
2015-03-18 07:32:31 +00:00
|
|
|
tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
2016-03-28 10:57:04 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, new)
|
2016-07-05 14:42:16 +00:00
|
|
|
tt.SetMaxEstablishedConns(0)
|
|
|
|
tt.SetMaxEstablishedConns(1)
|
2015-02-06 03:54:59 +00:00
|
|
|
tt.Drop()
|
|
|
|
}
|
|
|
|
|
2014-03-17 14:44:22 +00:00
|
|
|
func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
|
2018-01-09 06:26:46 +00:00
|
|
|
// TODO?
|
2014-03-17 14:44:22 +00:00
|
|
|
t.SkipNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddTorrentNoUsableURLs(t *testing.T) {
|
2018-01-09 06:26:46 +00:00
|
|
|
// TODO?
|
2014-03-17 14:44:22 +00:00
|
|
|
t.SkipNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddPeersToUnknownTorrent(t *testing.T) {
|
2018-01-09 06:26:46 +00:00
|
|
|
// TODO?
|
2014-03-17 14:44:22 +00:00
|
|
|
t.SkipNow()
|
|
|
|
}
|
2014-03-20 05:58:09 +00:00
|
|
|
|
|
|
|
func TestPieceHashSize(t *testing.T) {
|
2018-01-09 06:26:46 +00:00
|
|
|
assert.Equal(t, 20, pieceHash.Size())
|
2014-03-20 05:58:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTorrentInitialState(t *testing.T) {
|
|
|
|
dir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(dir)
|
2018-06-16 06:30:04 +00:00
|
|
|
cl := &Client{
|
2019-08-21 00:43:06 +00:00
|
|
|
config: TestingConfig(),
|
2018-06-16 06:30:04 +00:00
|
|
|
}
|
2018-01-29 07:19:53 +00:00
|
|
|
cl.initLogger()
|
2018-01-28 05:07:11 +00:00
|
|
|
tor := cl.newTorrent(
|
|
|
|
mi.HashInfoBytes(),
|
2020-02-20 02:57:24 +00:00
|
|
|
storage.NewFileWithCompletion(TestingTempDir.NewSub(), storage.NewMapPieceCompletion()),
|
2018-01-28 05:07:11 +00:00
|
|
|
)
|
|
|
|
tor.setChunkSize(2)
|
2018-07-25 03:41:50 +00:00
|
|
|
tor.cl.lock()
|
2016-08-26 10:29:05 +00:00
|
|
|
err := tor.setInfoBytes(mi.InfoBytes)
|
2018-07-25 03:41:50 +00:00
|
|
|
tor.cl.unlock()
|
2016-03-28 09:38:30 +00:00
|
|
|
require.NoError(t, err)
|
2016-04-03 06:50:53 +00:00
|
|
|
require.Len(t, tor.pieces, 3)
|
2014-12-09 03:59:01 +00:00
|
|
|
tor.pendAllChunkSpecs(0)
|
2018-07-25 03:41:50 +00:00
|
|
|
tor.cl.lock()
|
2016-01-13 06:11:59 +00:00
|
|
|
assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
|
2018-07-25 03:41:50 +00:00
|
|
|
tor.cl.unlock()
|
2015-07-15 05:31:18 +00:00
|
|
|
assert.EqualValues(t, chunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
|
2014-03-20 05:58:09 +00:00
|
|
|
}
|
2014-06-29 09:07:43 +00:00
|
|
|
|
2014-11-18 00:04:09 +00:00
|
|
|
func TestReducedDialTimeout(t *testing.T) {
|
2018-06-16 06:30:04 +00:00
|
|
|
cfg := NewDefaultClientConfig()
|
2014-11-18 00:04:09 +00:00
|
|
|
for _, _case := range []struct {
|
|
|
|
Max time.Duration
|
|
|
|
HalfOpenLimit int
|
|
|
|
PendingPeers int
|
|
|
|
ExpectedReduced time.Duration
|
|
|
|
}{
|
2017-11-07 18:14:13 +00:00
|
|
|
{cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
|
|
|
|
{cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
|
|
|
|
{cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
|
|
|
|
{cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
|
|
|
|
{cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
|
|
|
|
{cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
|
2014-11-18 00:04:09 +00:00
|
|
|
} {
|
2017-11-07 18:14:13 +00:00
|
|
|
reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
|
2014-11-19 03:53:00 +00:00
|
|
|
expected := _case.ExpectedReduced
|
2017-11-07 18:14:13 +00:00
|
|
|
if expected < cfg.MinDialTimeout {
|
|
|
|
expected = cfg.MinDialTimeout
|
2014-11-19 03:53:00 +00:00
|
|
|
}
|
|
|
|
if reduced != expected {
|
2014-11-18 00:04:09 +00:00
|
|
|
t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-04 01:57:43 +00:00
|
|
|
|
2015-02-26 14:46:02 +00:00
|
|
|
func TestAddDropManyTorrents(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2016-03-24 12:52:38 +00:00
|
|
|
require.NoError(t, err)
|
2015-03-08 06:28:14 +00:00
|
|
|
defer cl.Close()
|
2015-02-26 14:46:02 +00:00
|
|
|
for i := range iter.N(1000) {
|
2015-03-18 07:32:31 +00:00
|
|
|
var spec TorrentSpec
|
|
|
|
binary.PutVarint(spec.InfoHash[:], int64(i))
|
|
|
|
tt, new, err := cl.AddTorrentSpec(&spec)
|
2016-03-24 12:52:38 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, new)
|
2015-03-18 07:32:31 +00:00
|
|
|
defer tt.Drop()
|
2015-02-26 14:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:12:44 +00:00
|
|
|
func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImplCloser {
|
2016-05-16 12:02:03 +00:00
|
|
|
return storage.NewResourcePieces(fc.AsResourceProvider())
|
2016-05-16 10:11:00 +00:00
|
|
|
}
|
|
|
|
|
2015-08-03 06:23:05 +00:00
|
|
|
func TestMergingTrackersByAddingSpecs(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2016-02-22 03:30:02 +00:00
|
|
|
require.NoError(t, err)
|
2015-03-27 15:50:55 +00:00
|
|
|
defer cl.Close()
|
|
|
|
spec := TorrentSpec{}
|
|
|
|
T, new, _ := cl.AddTorrentSpec(&spec)
|
|
|
|
if !new {
|
2015-08-03 06:23:05 +00:00
|
|
|
t.FailNow()
|
2015-03-27 15:50:55 +00:00
|
|
|
}
|
|
|
|
spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
|
|
|
|
_, new, _ = cl.AddTorrentSpec(&spec)
|
2016-05-22 12:45:08 +00:00
|
|
|
assert.False(t, new)
|
|
|
|
assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
|
|
|
|
// Because trackers are disabled in TestingConfig.
|
|
|
|
assert.EqualValues(t, 0, len(T.trackerAnnouncers))
|
2015-03-27 15:50:55 +00:00
|
|
|
}
|
2015-06-02 14:16:38 +00:00
|
|
|
|
|
|
|
// We read from a piece which is marked completed, but is missing data.
|
|
|
|
func TestCompletedPieceWrongSize(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-03-28 09:38:30 +00:00
|
|
|
cfg.DefaultStorage = badStorage{}
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-05-11 11:11:52 +00:00
|
|
|
require.NoError(t, err)
|
2015-06-02 14:16:38 +00:00
|
|
|
defer cl.Close()
|
2016-08-26 10:29:05 +00:00
|
|
|
info := metainfo.Info{
|
|
|
|
PieceLength: 15,
|
|
|
|
Pieces: make([]byte, 20),
|
|
|
|
Files: []metainfo.FileInfo{
|
2016-11-22 03:01:09 +00:00
|
|
|
{Path: []string{"greeting"}, Length: 13},
|
2015-06-02 14:16:38 +00:00
|
|
|
},
|
2016-05-09 05:47:39 +00:00
|
|
|
}
|
2016-08-26 10:29:05 +00:00
|
|
|
b, err := bencode.Marshal(info)
|
2017-11-07 05:11:59 +00:00
|
|
|
require.NoError(t, err)
|
2016-05-09 05:47:39 +00:00
|
|
|
tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
|
2016-08-26 10:29:05 +00:00
|
|
|
InfoBytes: b,
|
|
|
|
InfoHash: metainfo.HashBytes(b),
|
2015-06-02 14:16:38 +00:00
|
|
|
})
|
2016-02-17 07:26:10 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer tt.Drop()
|
|
|
|
assert.True(t, new)
|
2015-06-02 14:16:38 +00:00
|
|
|
r := tt.NewReader()
|
|
|
|
defer r.Close()
|
2016-08-26 10:29:05 +00:00
|
|
|
b, err = ioutil.ReadAll(r)
|
2016-02-17 07:26:10 +00:00
|
|
|
assert.Len(t, b, 13)
|
|
|
|
assert.NoError(t, err)
|
2015-06-02 14:16:38 +00:00
|
|
|
}
|
2015-06-22 09:43:22 +00:00
|
|
|
|
|
|
|
func BenchmarkAddLargeTorrent(b *testing.B) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2015-06-22 09:43:22 +00:00
|
|
|
cfg.DisableTCP = true
|
|
|
|
cfg.DisableUTP = true
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-08-30 04:09:01 +00:00
|
|
|
require.NoError(b, err)
|
2015-06-22 09:43:22 +00:00
|
|
|
defer cl.Close()
|
2019-01-30 04:19:32 +00:00
|
|
|
b.ReportAllocs()
|
2015-06-22 09:43:22 +00:00
|
|
|
for range iter.N(b.N) {
|
|
|
|
t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
|
|
|
|
if err != nil {
|
|
|
|
b.Fatal(err)
|
|
|
|
}
|
|
|
|
t.Drop()
|
|
|
|
}
|
|
|
|
}
|
2015-07-15 05:51:42 +00:00
|
|
|
|
|
|
|
func TestResponsive(t *testing.T) {
|
|
|
|
seederDataDir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(seederDataDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2015-07-15 05:51:42 +00:00
|
|
|
cfg.Seed = true
|
|
|
|
cfg.DataDir = seederDataDir
|
2017-06-01 12:57:08 +00:00
|
|
|
seeder, err := NewClient(cfg)
|
2015-07-15 05:51:42 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer seeder.Close()
|
2017-09-15 09:22:32 +00:00
|
|
|
seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
|
|
|
seederTorrent.VerifyData()
|
2015-07-15 05:51:42 +00:00
|
|
|
leecherDataDir, err := ioutil.TempDir("", "")
|
|
|
|
require.Nil(t, err)
|
|
|
|
defer os.RemoveAll(leecherDataDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg = TestingConfig()
|
2015-07-15 05:51:42 +00:00
|
|
|
cfg.DataDir = leecherDataDir
|
2017-06-01 12:57:08 +00:00
|
|
|
leecher, err := NewClient(cfg)
|
2015-07-15 05:51:42 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer leecher.Close()
|
|
|
|
leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
|
|
|
|
ret = TorrentSpecFromMetaInfo(mi)
|
|
|
|
ret.ChunkSize = 2
|
|
|
|
return
|
|
|
|
}())
|
2018-04-12 01:41:07 +00:00
|
|
|
leecherTorrent.AddClientPeer(seeder)
|
2015-07-15 05:51:42 +00:00
|
|
|
reader := leecherTorrent.NewReader()
|
2016-02-04 14:17:26 +00:00
|
|
|
defer reader.Close()
|
2015-07-15 05:51:42 +00:00
|
|
|
reader.SetReadahead(0)
|
|
|
|
reader.SetResponsive()
|
|
|
|
b := make([]byte, 2)
|
2017-11-07 05:11:59 +00:00
|
|
|
_, err = reader.Seek(3, io.SeekStart)
|
2016-01-18 07:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = io.ReadFull(reader, b)
|
2015-07-15 05:51:42 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.EqualValues(t, "lo", string(b))
|
2017-11-07 05:11:59 +00:00
|
|
|
_, err = reader.Seek(11, io.SeekStart)
|
2016-01-18 07:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
n, err := io.ReadFull(reader, b)
|
2015-07-15 05:51:42 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.EqualValues(t, 2, n)
|
|
|
|
assert.EqualValues(t, "d\n", string(b))
|
|
|
|
}
|
2015-08-03 15:07:22 +00:00
|
|
|
|
2015-11-05 13:40:47 +00:00
|
|
|
func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
|
|
|
|
seederDataDir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(seederDataDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2015-11-05 13:40:47 +00:00
|
|
|
cfg.Seed = true
|
|
|
|
cfg.DataDir = seederDataDir
|
2017-06-01 12:57:08 +00:00
|
|
|
seeder, err := NewClient(cfg)
|
2015-11-05 13:40:47 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer seeder.Close()
|
2017-09-15 09:22:32 +00:00
|
|
|
seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
|
|
|
seederTorrent.VerifyData()
|
2015-11-05 13:40:47 +00:00
|
|
|
leecherDataDir, err := ioutil.TempDir("", "")
|
|
|
|
require.Nil(t, err)
|
|
|
|
defer os.RemoveAll(leecherDataDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg = TestingConfig()
|
2015-11-05 13:40:47 +00:00
|
|
|
cfg.DataDir = leecherDataDir
|
2017-06-01 12:57:08 +00:00
|
|
|
leecher, err := NewClient(cfg)
|
2015-11-05 13:40:47 +00:00
|
|
|
require.Nil(t, err)
|
|
|
|
defer leecher.Close()
|
|
|
|
leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
|
|
|
|
ret = TorrentSpecFromMetaInfo(mi)
|
|
|
|
ret.ChunkSize = 2
|
|
|
|
return
|
|
|
|
}())
|
2018-04-12 01:41:07 +00:00
|
|
|
leecherTorrent.AddClientPeer(seeder)
|
2015-11-05 13:40:47 +00:00
|
|
|
reader := leecherTorrent.NewReader()
|
2016-02-04 14:17:26 +00:00
|
|
|
defer reader.Close()
|
2015-11-05 13:40:47 +00:00
|
|
|
reader.SetReadahead(0)
|
|
|
|
reader.SetResponsive()
|
|
|
|
b := make([]byte, 2)
|
2017-11-07 05:11:59 +00:00
|
|
|
_, err = reader.Seek(3, io.SeekStart)
|
2016-01-18 07:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = io.ReadFull(reader, b)
|
2015-11-05 13:40:47 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.EqualValues(t, "lo", string(b))
|
|
|
|
go leecherTorrent.Drop()
|
2017-11-07 05:11:59 +00:00
|
|
|
_, err = reader.Seek(11, io.SeekStart)
|
2016-01-18 07:35:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
n, err := reader.Read(b)
|
2015-11-05 13:40:47 +00:00
|
|
|
assert.EqualError(t, err, "torrent closed")
|
|
|
|
assert.EqualValues(t, 0, n)
|
|
|
|
}
|
|
|
|
|
2015-08-03 15:07:22 +00:00
|
|
|
func TestDHTInheritBlocklist(t *testing.T) {
|
|
|
|
ipl := iplist.New(nil)
|
|
|
|
require.NotNil(t, ipl)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-01-16 13:12:53 +00:00
|
|
|
cfg.IPBlocklist = ipl
|
|
|
|
cfg.NoDHT = false
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2015-08-03 15:07:22 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2018-04-12 01:41:07 +00:00
|
|
|
numServers := 0
|
2020-02-20 06:46:29 +00:00
|
|
|
cl.eachDhtServer(func(s DhtServer) {
|
|
|
|
assert.Equal(t, ipl, s.(anacrolixDhtServerWrapper).IPBlocklist())
|
2018-04-12 01:41:07 +00:00
|
|
|
numServers++
|
|
|
|
})
|
|
|
|
assert.EqualValues(t, 2, numServers)
|
2015-08-03 15:07:22 +00:00
|
|
|
}
|
2015-08-23 02:50:32 +00:00
|
|
|
|
|
|
|
// Check that stuff is merged in subsequent AddTorrentSpec for the same
|
|
|
|
// infohash.
|
|
|
|
func TestAddTorrentSpecMerging(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2015-08-23 02:50:32 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
dir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(dir)
|
2016-05-05 12:40:38 +00:00
|
|
|
tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
|
2016-08-26 10:29:05 +00:00
|
|
|
InfoHash: mi.HashInfoBytes(),
|
2016-05-05 12:40:38 +00:00
|
|
|
})
|
2015-08-23 02:50:32 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, new)
|
|
|
|
require.Nil(t, tt.Info())
|
|
|
|
_, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.False(t, new)
|
|
|
|
require.NotNil(t, tt.Info())
|
|
|
|
}
|
|
|
|
|
2015-09-17 02:53:52 +00:00
|
|
|
func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
|
|
|
|
dir, mi := testutil.GreetingTestTorrent()
|
|
|
|
os.RemoveAll(dir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, _ := NewClient(TestingConfig())
|
2015-09-17 02:53:52 +00:00
|
|
|
defer cl.Close()
|
2016-05-05 12:40:38 +00:00
|
|
|
tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
|
2016-08-26 10:29:05 +00:00
|
|
|
InfoHash: mi.HashInfoBytes(),
|
2016-05-05 12:40:38 +00:00
|
|
|
})
|
2015-09-17 02:53:52 +00:00
|
|
|
tt.Drop()
|
|
|
|
assert.EqualValues(t, 0, len(cl.Torrents()))
|
|
|
|
select {
|
|
|
|
case <-tt.GotInfo():
|
|
|
|
t.FailNow()
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
2016-02-17 06:09:05 +00:00
|
|
|
|
2016-09-02 05:10:57 +00:00
|
|
|
func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
|
2016-03-29 00:14:34 +00:00
|
|
|
for i := range iter.N(info.NumPieces()) {
|
2016-09-02 05:10:57 +00:00
|
|
|
p := info.Piece(i)
|
|
|
|
ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
|
2016-03-29 00:14:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:12:44 +00:00
|
|
|
func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImplCloser) {
|
2016-03-29 00:14:34 +00:00
|
|
|
fileCacheDir, err := ioutil.TempDir("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.RemoveAll(fileCacheDir)
|
|
|
|
fileCache, err := filecache.NewCache(fileCacheDir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(greetingDataTempDir)
|
2016-05-16 10:11:00 +00:00
|
|
|
filePieceStore := csf(fileCache)
|
2017-09-15 09:22:32 +00:00
|
|
|
defer filePieceStore.Close()
|
2016-09-20 08:39:07 +00:00
|
|
|
info, err := greetingMetainfo.UnmarshalInfo()
|
|
|
|
require.NoError(t, err)
|
2016-08-26 10:29:05 +00:00
|
|
|
ih := greetingMetainfo.HashInfoBytes()
|
2016-09-02 05:10:57 +00:00
|
|
|
greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
|
2016-03-29 00:14:34 +00:00
|
|
|
require.NoError(t, err)
|
2016-08-26 10:29:05 +00:00
|
|
|
writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
|
2016-03-29 00:14:34 +00:00
|
|
|
// require.Equal(t, len(testutil.GreetingFileContents), written)
|
|
|
|
// require.NoError(t, err)
|
2016-08-26 10:29:05 +00:00
|
|
|
for i := 0; i < info.NumPieces(); i++ {
|
|
|
|
p := info.Piece(i)
|
2016-03-29 00:14:34 +00:00
|
|
|
if alreadyCompleted {
|
2017-09-15 09:22:32 +00:00
|
|
|
require.NoError(t, greetingData.Piece(p).MarkComplete())
|
2016-03-29 00:14:34 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-03-29 00:14:34 +00:00
|
|
|
// TODO: Disable network option?
|
|
|
|
cfg.DisableTCP = true
|
|
|
|
cfg.DisableUTP = true
|
|
|
|
cfg.DefaultStorage = filePieceStore
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-03-29 00:14:34 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
tt, err := cl.AddTorrent(greetingMetainfo)
|
|
|
|
require.NoError(t, err)
|
|
|
|
psrs := tt.PieceStateRuns()
|
|
|
|
assert.Len(t, psrs, 1)
|
|
|
|
assert.EqualValues(t, 3, psrs[0].Length)
|
|
|
|
assert.Equal(t, alreadyCompleted, psrs[0].Complete)
|
|
|
|
if alreadyCompleted {
|
|
|
|
r := tt.NewReader()
|
|
|
|
b, err := ioutil.ReadAll(r)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.EqualValues(t, testutil.GreetingFileContents, b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
|
2016-05-16 10:11:00 +00:00
|
|
|
testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
|
2016-03-29 00:14:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
|
2016-05-16 10:11:00 +00:00
|
|
|
testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
|
2016-03-29 00:14:34 +00:00
|
|
|
}
|
2016-02-23 14:48:44 +00:00
|
|
|
|
2016-02-24 10:56:50 +00:00
|
|
|
func TestAddMetainfoWithNodes(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2018-04-12 05:06:53 +00:00
|
|
|
cfg.ListenHost = func(string) string { return "" }
|
2016-02-23 14:48:44 +00:00
|
|
|
cfg.NoDHT = false
|
2018-04-12 01:41:07 +00:00
|
|
|
cfg.DhtStartingNodes = func() ([]dht.Addr, error) { return nil, nil }
|
2016-02-24 10:56:50 +00:00
|
|
|
// For now, we want to just jam the nodes into the table, without
|
|
|
|
// verifying them first. Also the DHT code doesn't support mixing secure
|
|
|
|
// and insecure nodes if security is enabled (yet).
|
2018-04-12 01:41:07 +00:00
|
|
|
// cfg.DHTConfig.NoSecurity = true
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-02-23 14:48:44 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2018-04-12 06:11:22 +00:00
|
|
|
sum := func() (ret int64) {
|
2020-02-20 06:46:29 +00:00
|
|
|
cl.eachDhtServer(func(s DhtServer) {
|
|
|
|
ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
|
2018-04-12 01:41:07 +00:00
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
assert.EqualValues(t, 0, sum())
|
2016-02-23 14:48:44 +00:00
|
|
|
tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
|
|
|
|
require.NoError(t, err)
|
2017-07-20 14:40:49 +00:00
|
|
|
// Nodes are not added or exposed in Torrent's metainfo. We just randomly
|
|
|
|
// check if the announce-list is here instead. TODO: Add nodes.
|
2016-05-22 12:45:08 +00:00
|
|
|
assert.Len(t, tt.metainfo.AnnounceList, 5)
|
2017-07-20 14:40:49 +00:00
|
|
|
// There are 6 nodes in the torrent file.
|
2019-01-21 21:36:40 +00:00
|
|
|
for sum() != int64(6*len(cl.dhtServers)) {
|
|
|
|
time.Sleep(time.Millisecond)
|
|
|
|
}
|
2016-02-23 14:48:44 +00:00
|
|
|
}
|
2016-02-26 11:10:29 +00:00
|
|
|
|
|
|
|
type testDownloadCancelParams struct {
|
|
|
|
SetLeecherStorageCapacity bool
|
|
|
|
LeecherStorageCapacity int64
|
|
|
|
Cancel bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
|
|
|
|
greetingTempDir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(greetingTempDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-02-26 11:10:29 +00:00
|
|
|
cfg.Seed = true
|
|
|
|
cfg.DataDir = greetingTempDir
|
2017-06-01 12:57:08 +00:00
|
|
|
seeder, err := NewClient(cfg)
|
2016-02-26 11:10:29 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer seeder.Close()
|
2018-06-26 09:54:48 +00:00
|
|
|
defer testutil.ExportStatusWriter(seeder, "s")()
|
2017-09-15 09:22:32 +00:00
|
|
|
seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
|
|
|
seederTorrent.VerifyData()
|
2016-02-26 11:10:29 +00:00
|
|
|
leecherDataDir, err := ioutil.TempDir("", "")
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer os.RemoveAll(leecherDataDir)
|
2016-03-29 00:14:34 +00:00
|
|
|
fc, err := filecache.NewCache(leecherDataDir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
if ps.SetLeecherStorageCapacity {
|
|
|
|
fc.SetCapacity(ps.LeecherStorageCapacity)
|
|
|
|
}
|
2017-01-05 06:00:59 +00:00
|
|
|
cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
|
2016-03-28 09:38:30 +00:00
|
|
|
cfg.DataDir = leecherDataDir
|
2019-07-19 06:17:10 +00:00
|
|
|
leecher, err := NewClient(cfg)
|
|
|
|
require.NoError(t, err)
|
2016-02-26 11:10:29 +00:00
|
|
|
defer leecher.Close()
|
2018-06-26 09:54:48 +00:00
|
|
|
defer testutil.ExportStatusWriter(leecher, "l")()
|
2016-02-26 11:10:29 +00:00
|
|
|
leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
|
|
|
|
ret = TorrentSpecFromMetaInfo(mi)
|
|
|
|
ret.ChunkSize = 2
|
|
|
|
return
|
|
|
|
}())
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, new)
|
|
|
|
psc := leecherGreeting.SubscribePieceStateChanges()
|
|
|
|
defer psc.Close()
|
2018-01-27 03:31:31 +00:00
|
|
|
|
2018-07-25 03:41:50 +00:00
|
|
|
leecherGreeting.cl.lock()
|
2018-01-27 03:31:31 +00:00
|
|
|
leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
|
2016-02-26 11:10:29 +00:00
|
|
|
if ps.Cancel {
|
2018-01-27 03:31:31 +00:00
|
|
|
leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
|
2016-02-26 11:10:29 +00:00
|
|
|
}
|
2018-07-25 03:41:50 +00:00
|
|
|
leecherGreeting.cl.unlock()
|
2018-06-12 10:19:53 +00:00
|
|
|
done := make(chan struct{})
|
|
|
|
defer close(done)
|
2018-06-13 12:02:30 +00:00
|
|
|
go leecherGreeting.AddClientPeer(seeder)
|
2016-02-26 11:10:29 +00:00
|
|
|
completes := make(map[int]bool, 3)
|
2018-06-09 12:10:08 +00:00
|
|
|
expected := func() map[int]bool {
|
|
|
|
if ps.Cancel {
|
|
|
|
return map[int]bool{0: false, 1: false, 2: false}
|
|
|
|
} else {
|
|
|
|
return map[int]bool{0: true, 1: true, 2: true}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
for !reflect.DeepEqual(completes, expected) {
|
2018-11-27 23:32:44 +00:00
|
|
|
_v := <-psc.Values
|
|
|
|
v := _v.(PieceStateChange)
|
|
|
|
completes[v.Index] = v.Complete
|
2016-02-26 11:10:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTorrentDownloadAll(t *testing.T) {
|
|
|
|
testDownloadCancel(t, testDownloadCancelParams{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTorrentDownloadAllThenCancel(t *testing.T) {
|
|
|
|
testDownloadCancel(t, testDownloadCancelParams{
|
|
|
|
Cancel: true,
|
|
|
|
})
|
|
|
|
}
|
2016-03-22 02:09:02 +00:00
|
|
|
|
|
|
|
// Ensure that it's an error for a peer to send an invalid have message.
|
|
|
|
func TestPeerInvalidHave(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2016-03-22 02:09:02 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2016-08-26 10:29:05 +00:00
|
|
|
info := metainfo.Info{
|
|
|
|
PieceLength: 1,
|
|
|
|
Pieces: make([]byte, 20),
|
|
|
|
Files: []metainfo.FileInfo{{Length: 1}},
|
2016-05-09 05:47:39 +00:00
|
|
|
}
|
2016-08-26 10:29:05 +00:00
|
|
|
infoBytes, err := bencode.Marshal(info)
|
|
|
|
require.NoError(t, err)
|
2016-05-09 05:47:39 +00:00
|
|
|
tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
|
2016-08-26 10:29:05 +00:00
|
|
|
InfoBytes: infoBytes,
|
|
|
|
InfoHash: metainfo.HashBytes(infoBytes),
|
2017-09-18 02:15:14 +00:00
|
|
|
Storage: badStorage{},
|
2016-03-22 02:09:02 +00:00
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, _new)
|
|
|
|
defer tt.Drop()
|
2020-02-21 00:07:50 +00:00
|
|
|
cn := &PeerConn{
|
2016-04-03 08:40:43 +00:00
|
|
|
t: tt,
|
2016-03-22 02:09:02 +00:00
|
|
|
}
|
|
|
|
assert.NoError(t, cn.peerSentHave(0))
|
|
|
|
assert.Error(t, cn.peerSentHave(1))
|
|
|
|
}
|
2016-03-28 09:38:30 +00:00
|
|
|
|
|
|
|
func TestPieceCompletedInStorageButNotClient(t *testing.T) {
|
|
|
|
greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(greetingTempDir)
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-03-28 09:38:30 +00:00
|
|
|
cfg.DataDir = greetingTempDir
|
2017-06-01 12:57:08 +00:00
|
|
|
seeder, err := NewClient(TestingConfig())
|
2016-03-28 09:38:30 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
seeder.AddTorrentSpec(&TorrentSpec{
|
2016-08-26 10:29:05 +00:00
|
|
|
InfoBytes: greetingMetainfo.InfoBytes,
|
2016-03-28 09:38:30 +00:00
|
|
|
})
|
|
|
|
}
|
2016-05-22 12:45:08 +00:00
|
|
|
|
2016-05-24 09:35:23 +00:00
|
|
|
// Check that when the listen port is 0, all the protocols listened on have
|
|
|
|
// the same port, and it isn't zero.
|
|
|
|
func TestClientDynamicListenPortAllProtocols(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(TestingConfig())
|
2016-05-24 09:35:23 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2018-04-12 01:41:07 +00:00
|
|
|
port := cl.LocalPort()
|
|
|
|
assert.NotEqual(t, 0, port)
|
2020-02-20 05:47:37 +00:00
|
|
|
cl.eachListener(func(s Listener) bool {
|
2018-04-12 01:41:07 +00:00
|
|
|
assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
|
|
|
|
return true
|
|
|
|
})
|
2016-05-24 09:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestClientDynamicListenTCPOnly(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-05-24 09:35:23 +00:00
|
|
|
cfg.DisableUTP = true
|
2018-11-04 06:43:47 +00:00
|
|
|
cfg.DisableTCP = false
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-05-24 09:35:23 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2018-04-12 01:41:07 +00:00
|
|
|
assert.NotEqual(t, 0, cl.LocalPort())
|
2016-05-24 09:35:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestClientDynamicListenUTPOnly(t *testing.T) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-05-24 09:35:23 +00:00
|
|
|
cfg.DisableTCP = true
|
2018-11-04 06:43:47 +00:00
|
|
|
cfg.DisableUTP = false
|
2017-06-01 12:57:08 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-05-24 09:35:23 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
2018-04-12 01:41:07 +00:00
|
|
|
assert.NotEqual(t, 0, cl.LocalPort())
|
2016-07-05 22:30:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func totalConns(tts []*Torrent) (ret int) {
|
|
|
|
for _, tt := range tts {
|
2018-07-25 03:41:50 +00:00
|
|
|
tt.cl.lock()
|
2016-07-05 22:30:34 +00:00
|
|
|
ret += len(tt.conns)
|
2018-07-25 03:41:50 +00:00
|
|
|
tt.cl.unlock()
|
2016-07-05 22:30:34 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetMaxEstablishedConn(t *testing.T) {
|
|
|
|
var tts []*Torrent
|
2016-08-26 10:29:05 +00:00
|
|
|
ih := testutil.GreetingMetaInfo().HashInfoBytes()
|
2018-06-16 06:30:04 +00:00
|
|
|
cfg := TestingConfig()
|
|
|
|
cfg.DisableAcceptRateLimiting = true
|
|
|
|
cfg.dropDuplicatePeerIds = true
|
2016-07-05 22:30:34 +00:00
|
|
|
for i := range iter.N(3) {
|
2018-06-16 06:30:04 +00:00
|
|
|
cl, err := NewClient(cfg)
|
2016-07-05 22:30:34 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
tt, _ := cl.AddTorrentInfoHash(ih)
|
|
|
|
tt.SetMaxEstablishedConns(2)
|
2018-06-26 09:54:48 +00:00
|
|
|
defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i))()
|
2016-07-05 22:30:34 +00:00
|
|
|
tts = append(tts, tt)
|
|
|
|
}
|
|
|
|
addPeers := func() {
|
2018-02-11 04:14:31 +00:00
|
|
|
for _, tt := range tts {
|
|
|
|
for _, _tt := range tts {
|
|
|
|
// if tt != _tt {
|
2018-04-12 01:41:07 +00:00
|
|
|
tt.AddClientPeer(_tt.cl)
|
2018-02-11 04:14:31 +00:00
|
|
|
// }
|
2016-07-05 22:30:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
waitTotalConns := func(num int) {
|
|
|
|
for totalConns(tts) != num {
|
2018-02-11 04:14:31 +00:00
|
|
|
addPeers()
|
2016-07-05 22:30:34 +00:00
|
|
|
time.Sleep(time.Millisecond)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addPeers()
|
|
|
|
waitTotalConns(6)
|
|
|
|
tts[0].SetMaxEstablishedConns(1)
|
|
|
|
waitTotalConns(4)
|
|
|
|
tts[0].SetMaxEstablishedConns(0)
|
|
|
|
waitTotalConns(2)
|
|
|
|
tts[0].SetMaxEstablishedConns(1)
|
|
|
|
addPeers()
|
|
|
|
waitTotalConns(4)
|
|
|
|
tts[0].SetMaxEstablishedConns(2)
|
|
|
|
addPeers()
|
|
|
|
waitTotalConns(6)
|
|
|
|
}
|
2016-09-16 14:01:15 +00:00
|
|
|
|
2019-07-19 03:04:10 +00:00
|
|
|
// Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
|
|
|
|
// client, and returns a magnet link.
|
2016-09-16 14:01:15 +00:00
|
|
|
func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
|
2016-09-21 11:17:22 +00:00
|
|
|
os.MkdirAll(dir, 0770)
|
2016-09-21 11:02:18 +00:00
|
|
|
file, err := os.Create(filepath.Join(dir, name))
|
2016-09-16 14:01:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
file.Write([]byte(name))
|
2016-09-20 08:39:36 +00:00
|
|
|
file.Close()
|
2016-09-16 14:01:15 +00:00
|
|
|
mi := metainfo.MetaInfo{}
|
|
|
|
mi.SetDefaults()
|
2016-09-20 08:39:36 +00:00
|
|
|
info := metainfo.Info{PieceLength: 256 * 1024}
|
2016-09-21 11:02:18 +00:00
|
|
|
err = info.BuildFromFilePath(filepath.Join(dir, name))
|
2016-09-16 14:01:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
mi.InfoBytes, err = bencode.Marshal(info)
|
|
|
|
require.NoError(t, err)
|
|
|
|
magnet := mi.Magnet(name, mi.HashInfoBytes()).String()
|
|
|
|
tr, err := cl.AddTorrent(&mi)
|
|
|
|
require.NoError(t, err)
|
2017-09-15 09:22:32 +00:00
|
|
|
require.True(t, tr.Seeding())
|
|
|
|
tr.VerifyData()
|
2016-09-16 14:01:15 +00:00
|
|
|
return magnet
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://github.com/anacrolix/torrent/issues/114
|
|
|
|
func TestMultipleTorrentsWithEncryption(t *testing.T) {
|
2019-07-19 03:23:36 +00:00
|
|
|
testSeederLeecherPair(
|
|
|
|
t,
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.Preferred = true
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = true
|
|
|
|
},
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = false
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that the leecher can download a torrent in its entirety from the seeder. Note that the
|
|
|
|
// seeder config is done first.
|
|
|
|
func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg := TestingConfig()
|
2016-09-16 14:01:15 +00:00
|
|
|
cfg.Seed = true
|
2016-09-21 11:02:18 +00:00
|
|
|
cfg.DataDir = filepath.Join(cfg.DataDir, "server")
|
2016-09-16 14:01:15 +00:00
|
|
|
os.Mkdir(cfg.DataDir, 0755)
|
2019-07-19 03:23:36 +00:00
|
|
|
seeder(cfg)
|
2017-06-01 12:57:08 +00:00
|
|
|
server, err := NewClient(cfg)
|
2016-09-16 14:01:15 +00:00
|
|
|
require.NoError(t, err)
|
2016-09-21 11:02:18 +00:00
|
|
|
defer server.Close()
|
2018-06-26 09:54:48 +00:00
|
|
|
defer testutil.ExportStatusWriter(server, "s")()
|
2016-09-16 14:01:15 +00:00
|
|
|
magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
|
2019-07-19 03:23:36 +00:00
|
|
|
// Extra torrents are added to test the seeder having to match incoming obfuscated headers
|
|
|
|
// against more than one torrent. See issue #114
|
2016-09-16 14:01:15 +00:00
|
|
|
makeMagnet(t, server, cfg.DataDir, "test2")
|
2019-07-19 03:23:36 +00:00
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
|
|
|
|
}
|
2017-06-01 12:57:08 +00:00
|
|
|
cfg = TestingConfig()
|
2016-09-21 11:02:18 +00:00
|
|
|
cfg.DataDir = filepath.Join(cfg.DataDir, "client")
|
2019-07-19 03:23:36 +00:00
|
|
|
leecher(cfg)
|
2017-06-01 12:57:08 +00:00
|
|
|
client, err := NewClient(cfg)
|
2016-09-16 14:01:15 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
defer client.Close()
|
2018-06-26 09:54:48 +00:00
|
|
|
defer testutil.ExportStatusWriter(client, "c")()
|
2016-09-16 14:01:15 +00:00
|
|
|
tr, err := client.AddMagnet(magnet1)
|
|
|
|
require.NoError(t, err)
|
2018-04-12 01:41:07 +00:00
|
|
|
tr.AddClientPeer(server)
|
2016-09-20 08:39:36 +00:00
|
|
|
<-tr.GotInfo()
|
2016-09-16 14:01:15 +00:00
|
|
|
tr.DownloadAll()
|
|
|
|
client.WaitAll()
|
|
|
|
}
|
2017-09-13 14:25:29 +00:00
|
|
|
|
2019-07-19 03:23:36 +00:00
|
|
|
// This appears to be the situation with the S3 BitTorrent client.
|
|
|
|
func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
|
|
|
|
// Leecher prefers obfuscation, but the seeder does not allow it.
|
|
|
|
testSeederLeecherPair(
|
|
|
|
t,
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.Preferred = false
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = true
|
|
|
|
},
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.Preferred = true
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = false
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
|
|
|
|
// Leecher prefers no obfuscation, but the seeder enforces it.
|
|
|
|
testSeederLeecherPair(
|
|
|
|
t,
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.Preferred = true
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = true
|
|
|
|
},
|
|
|
|
func(cfg *ClientConfig) {
|
|
|
|
cfg.HeaderObfuscationPolicy.Preferred = false
|
|
|
|
cfg.HeaderObfuscationPolicy.RequirePreferred = false
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2017-09-13 14:25:29 +00:00
|
|
|
func TestClientAddressInUse(t *testing.T) {
|
2018-07-25 07:11:09 +00:00
|
|
|
s, _ := NewUtpSocket("udp", ":50007", nil)
|
2017-09-13 14:25:29 +00:00
|
|
|
if s != nil {
|
|
|
|
defer s.Close()
|
|
|
|
}
|
2018-04-12 05:06:53 +00:00
|
|
|
cfg := TestingConfig().SetListenAddr(":50007")
|
2017-09-13 14:25:29 +00:00
|
|
|
cl, err := NewClient(cfg)
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Nil(t, cl)
|
|
|
|
}
|
2018-11-04 06:42:12 +00:00
|
|
|
|
|
|
|
func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
|
|
|
|
cc := TestingConfig()
|
|
|
|
cc.DisableUTP = true
|
|
|
|
cc.NoDHT = false
|
|
|
|
cl, err := NewClient(cc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
assert.NotEmpty(t, cl.DhtServers())
|
|
|
|
}
|
2019-10-11 06:34:07 +00:00
|
|
|
|
|
|
|
func TestIssue335(t *testing.T) {
|
|
|
|
dir, mi := testutil.GreetingTestTorrent()
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
cfg := TestingConfig()
|
|
|
|
cfg.Seed = false
|
|
|
|
cfg.Debug = true
|
|
|
|
cfg.DataDir = dir
|
|
|
|
comp, err := storage.NewBoltPieceCompletion(dir)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer comp.Close()
|
|
|
|
cfg.DefaultStorage = storage.NewMMapWithCompletion(dir, comp)
|
|
|
|
cl, err := NewClient(cfg)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
tor, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, new)
|
|
|
|
require.True(t, cl.WaitAll())
|
|
|
|
tor.Drop()
|
2020-02-20 00:09:57 +00:00
|
|
|
_, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
|
2019-10-11 06:34:07 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, new)
|
|
|
|
require.True(t, cl.WaitAll())
|
|
|
|
}
|
2020-02-20 05:57:28 +00:00
|
|
|
|
|
|
|
func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
|
|
|
|
cfg := TestingConfig()
|
|
|
|
cfg.DisableTCP = true
|
|
|
|
cfg.DisableUTP = true
|
|
|
|
cfg.NoDHT = false
|
|
|
|
cl, err := NewClient(cfg)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer cl.Close()
|
|
|
|
assert.Empty(t, cl.listeners)
|
|
|
|
assert.NotEmpty(t, cl.DhtServers())
|
|
|
|
}
|