15 "github.com/bradfitz/iter"
16 "github.com/frankban/quicktest"
17 "github.com/stretchr/testify/assert"
18 "github.com/stretchr/testify/require"
20 "github.com/anacrolix/dht/v2"
21 "github.com/anacrolix/missinggo"
22 "github.com/anacrolix/missinggo/v2/filecache"
24 "github.com/anacrolix/torrent/bencode"
25 "github.com/anacrolix/torrent/internal/testutil"
26 "github.com/anacrolix/torrent/iplist"
27 "github.com/anacrolix/torrent/metainfo"
28 "github.com/anacrolix/torrent/storage"
31 func TestClientDefault(t *testing.T) {
32 cl, err := NewClient(TestingConfig())
33 require.NoError(t, err)
37 func TestClientNilConfig(t *testing.T) {
38 cl, err := NewClient(nil)
39 require.NoError(t, err)
43 func TestBoltPieceCompletionClosedWhenClientClosed(t *testing.T) {
44 cfg := TestingConfig()
45 pc, err := storage.NewBoltPieceCompletion(cfg.DataDir)
46 require.NoError(t, err)
47 ci := storage.NewFileWithCompletion(cfg.DataDir, pc)
49 cfg.DefaultStorage = ci
50 cl, err := NewClient(cfg)
51 require.NoError(t, err)
53 // And again, https://github.com/anacrolix/torrent/issues/158
54 cl, err = NewClient(cfg)
55 require.NoError(t, err)
59 func TestAddDropTorrent(t *testing.T) {
60 cl, err := NewClient(TestingConfig())
61 require.NoError(t, err)
63 dir, mi := testutil.GreetingTestTorrent()
64 defer os.RemoveAll(dir)
65 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
66 require.NoError(t, err)
68 tt.SetMaxEstablishedConns(0)
69 tt.SetMaxEstablishedConns(1)
73 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
78 func TestAddTorrentNoUsableURLs(t *testing.T) {
83 func TestAddPeersToUnknownTorrent(t *testing.T) {
88 func TestPieceHashSize(t *testing.T) {
89 assert.Equal(t, 20, pieceHash.Size())
92 func TestTorrentInitialState(t *testing.T) {
93 dir, mi := testutil.GreetingTestTorrent()
94 defer os.RemoveAll(dir)
96 config: TestingConfig(),
101 storage.NewFileWithCompletion(TestingTempDir.NewSub(), storage.NewMapPieceCompletion()),
105 err := tor.setInfoBytes(mi.InfoBytes)
107 require.NoError(t, err)
108 require.Len(t, tor.pieces, 3)
109 tor.pendAllChunkSpecs(0)
111 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
113 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
116 func TestReducedDialTimeout(t *testing.T) {
117 cfg := NewDefaultClientConfig()
118 for _, _case := range []struct {
122 ExpectedReduced time.Duration
124 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
125 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
126 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
127 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
128 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
129 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
131 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
132 expected := _case.ExpectedReduced
133 if expected < cfg.MinDialTimeout {
134 expected = cfg.MinDialTimeout
136 if reduced != expected {
137 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
142 func TestAddDropManyTorrents(t *testing.T) {
143 cl, err := NewClient(TestingConfig())
144 require.NoError(t, err)
146 for i := range iter.N(1000) {
148 binary.PutVarint(spec.InfoHash[:], int64(i))
149 tt, new, err := cl.AddTorrentSpec(&spec)
150 assert.NoError(t, err)
156 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
157 return storage.NewResourcePiecesOpts(
158 fc.AsResourceProvider(),
159 storage.ResourcePiecesOpts{
160 LeaveIncompleteChunks: true,
165 func TestMergingTrackersByAddingSpecs(t *testing.T) {
166 cl, err := NewClient(TestingConfig())
167 require.NoError(t, err)
169 spec := TorrentSpec{}
170 T, new, _ := cl.AddTorrentSpec(&spec)
174 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
175 _, new, _ = cl.AddTorrentSpec(&spec)
177 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
178 // Because trackers are disabled in TestingConfig.
179 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
182 // We read from a piece which is marked completed, but is missing data.
183 func TestCompletedPieceWrongSize(t *testing.T) {
184 cfg := TestingConfig()
185 cfg.DefaultStorage = badStorage{}
186 cl, err := NewClient(cfg)
187 require.NoError(t, err)
189 info := metainfo.Info{
191 Pieces: make([]byte, 20),
192 Files: []metainfo.FileInfo{
193 {Path: []string{"greeting"}, Length: 13},
196 b, err := bencode.Marshal(info)
197 require.NoError(t, err)
198 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
200 InfoHash: metainfo.HashBytes(b),
202 require.NoError(t, err)
207 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
210 func BenchmarkAddLargeTorrent(b *testing.B) {
211 cfg := TestingConfig()
212 cfg.DisableTCP = true
213 cfg.DisableUTP = true
214 cl, err := NewClient(cfg)
215 require.NoError(b, err)
218 for range iter.N(b.N) {
219 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
227 func TestResponsive(t *testing.T) {
228 seederDataDir, mi := testutil.GreetingTestTorrent()
229 defer os.RemoveAll(seederDataDir)
230 cfg := TestingConfig()
232 cfg.DataDir = seederDataDir
233 seeder, err := NewClient(cfg)
236 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
237 seederTorrent.VerifyData()
238 leecherDataDir, err := ioutil.TempDir("", "")
240 defer os.RemoveAll(leecherDataDir)
241 cfg = TestingConfig()
242 cfg.DataDir = leecherDataDir
243 leecher, err := NewClient(cfg)
245 defer leecher.Close()
246 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
247 ret = TorrentSpecFromMetaInfo(mi)
251 leecherTorrent.AddClientPeer(seeder)
252 reader := leecherTorrent.NewReader()
254 reader.SetReadahead(0)
255 reader.SetResponsive()
257 _, err = reader.Seek(3, io.SeekStart)
258 require.NoError(t, err)
259 _, err = io.ReadFull(reader, b)
261 assert.EqualValues(t, "lo", string(b))
262 _, err = reader.Seek(11, io.SeekStart)
263 require.NoError(t, err)
264 n, err := io.ReadFull(reader, b)
266 assert.EqualValues(t, 2, n)
267 assert.EqualValues(t, "d\n", string(b))
270 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
271 seederDataDir, mi := testutil.GreetingTestTorrent()
272 defer os.RemoveAll(seederDataDir)
273 cfg := TestingConfig()
275 cfg.DataDir = seederDataDir
276 seeder, err := NewClient(cfg)
279 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
280 seederTorrent.VerifyData()
281 leecherDataDir, err := ioutil.TempDir("", "")
283 defer os.RemoveAll(leecherDataDir)
284 cfg = TestingConfig()
285 cfg.DataDir = leecherDataDir
286 leecher, err := NewClient(cfg)
288 defer leecher.Close()
289 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
290 ret = TorrentSpecFromMetaInfo(mi)
294 leecherTorrent.AddClientPeer(seeder)
295 reader := leecherTorrent.NewReader()
297 reader.SetReadahead(0)
298 reader.SetResponsive()
300 _, err = reader.Seek(3, io.SeekStart)
301 require.NoError(t, err)
302 _, err = io.ReadFull(reader, b)
304 assert.EqualValues(t, "lo", string(b))
305 go leecherTorrent.Drop()
306 _, err = reader.Seek(11, io.SeekStart)
307 require.NoError(t, err)
308 n, err := reader.Read(b)
309 assert.EqualError(t, err, "torrent closed")
310 assert.EqualValues(t, 0, n)
313 func TestDhtInheritBlocklist(t *testing.T) {
314 ipl := iplist.New(nil)
315 require.NotNil(t, ipl)
316 cfg := TestingConfig()
317 cfg.IPBlocklist = ipl
319 cl, err := NewClient(cfg)
320 require.NoError(t, err)
323 cl.eachDhtServer(func(s DhtServer) {
325 assert.Equal(t, ipl, s.(anacrolixDhtServerWrapper).Server.IPBlocklist())
328 assert.EqualValues(t, 2, numServers)
331 // Check that stuff is merged in subsequent AddTorrentSpec for the same
333 func TestAddTorrentSpecMerging(t *testing.T) {
334 cl, err := NewClient(TestingConfig())
335 require.NoError(t, err)
337 dir, mi := testutil.GreetingTestTorrent()
338 defer os.RemoveAll(dir)
339 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
340 InfoHash: mi.HashInfoBytes(),
342 require.NoError(t, err)
344 require.Nil(t, tt.Info())
345 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
346 require.NoError(t, err)
347 require.False(t, new)
348 require.NotNil(t, tt.Info())
351 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
352 dir, mi := testutil.GreetingTestTorrent()
354 cl, _ := NewClient(TestingConfig())
356 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
357 InfoHash: mi.HashInfoBytes(),
360 assert.EqualValues(t, 0, len(cl.Torrents()))
368 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
369 for i := range iter.N(info.NumPieces()) {
371 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
375 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
376 fileCacheDir, err := ioutil.TempDir("", "")
377 require.NoError(t, err)
378 defer os.RemoveAll(fileCacheDir)
379 fileCache, err := filecache.NewCache(fileCacheDir)
380 require.NoError(t, err)
381 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
382 defer os.RemoveAll(greetingDataTempDir)
383 filePieceStore := csf(fileCache)
384 info, err := greetingMetainfo.UnmarshalInfo()
385 require.NoError(t, err)
386 ih := greetingMetainfo.HashInfoBytes()
387 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
388 require.NoError(t, err)
389 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
390 // require.Equal(t, len(testutil.GreetingFileContents), written)
391 // require.NoError(t, err)
392 for i := 0; i < info.NumPieces(); i++ {
394 if alreadyCompleted {
395 require.NoError(t, greetingData.Piece(p).MarkComplete())
398 cfg := TestingConfig()
399 // TODO: Disable network option?
400 cfg.DisableTCP = true
401 cfg.DisableUTP = true
402 cfg.DefaultStorage = filePieceStore
403 cl, err := NewClient(cfg)
404 require.NoError(t, err)
406 tt, err := cl.AddTorrent(greetingMetainfo)
407 require.NoError(t, err)
408 psrs := tt.PieceStateRuns()
409 assert.Len(t, psrs, 1)
410 assert.EqualValues(t, 3, psrs[0].Length)
411 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
412 if alreadyCompleted {
414 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
418 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
419 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
422 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
423 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
426 func TestAddMetainfoWithNodes(t *testing.T) {
427 cfg := TestingConfig()
428 cfg.ListenHost = func(string) string { return "" }
430 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
431 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
432 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
433 // cfg.DHTConfig.NoSecurity = true
434 cl, err := NewClient(cfg)
435 require.NoError(t, err)
437 sum := func() (ret int64) {
438 cl.eachDhtServer(func(s DhtServer) {
439 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
443 assert.EqualValues(t, 0, sum())
444 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
445 require.NoError(t, err)
446 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
447 // check if the announce-list is here instead. TODO: Add nodes.
448 assert.Len(t, tt.metainfo.AnnounceList, 5)
449 // There are 6 nodes in the torrent file.
450 for sum() != int64(6*len(cl.dhtServers)) {
451 time.Sleep(time.Millisecond)
455 type testDownloadCancelParams struct {
456 SetLeecherStorageCapacity bool
457 LeecherStorageCapacity int64
461 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
462 greetingTempDir, mi := testutil.GreetingTestTorrent()
463 defer os.RemoveAll(greetingTempDir)
464 cfg := TestingConfig()
466 cfg.DataDir = greetingTempDir
467 seeder, err := NewClient(cfg)
468 require.NoError(t, err)
470 defer testutil.ExportStatusWriter(seeder, "s", t)()
471 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
472 seederTorrent.VerifyData()
473 leecherDataDir, err := ioutil.TempDir("", "")
474 require.NoError(t, err)
475 defer os.RemoveAll(leecherDataDir)
476 fc, err := filecache.NewCache(leecherDataDir)
477 require.NoError(t, err)
478 if ps.SetLeecherStorageCapacity {
479 fc.SetCapacity(ps.LeecherStorageCapacity)
481 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
482 cfg.DataDir = leecherDataDir
483 leecher, err := NewClient(cfg)
484 require.NoError(t, err)
485 defer leecher.Close()
486 defer testutil.ExportStatusWriter(leecher, "l", t)()
487 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
488 ret = TorrentSpecFromMetaInfo(mi)
492 require.NoError(t, err)
494 psc := leecherGreeting.SubscribePieceStateChanges()
497 leecherGreeting.cl.lock()
498 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
500 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
502 leecherGreeting.cl.unlock()
503 done := make(chan struct{})
505 go leecherGreeting.AddClientPeer(seeder)
506 completes := make(map[int]bool, 3)
507 expected := func() map[int]bool {
509 return map[int]bool{0: false, 1: false, 2: false}
511 return map[int]bool{0: true, 1: true, 2: true}
514 for !reflect.DeepEqual(completes, expected) {
516 v := _v.(PieceStateChange)
517 completes[v.Index] = v.Complete
521 func TestTorrentDownloadAll(t *testing.T) {
522 testDownloadCancel(t, testDownloadCancelParams{})
525 func TestTorrentDownloadAllThenCancel(t *testing.T) {
526 testDownloadCancel(t, testDownloadCancelParams{
531 // Ensure that it's an error for a peer to send an invalid have message.
532 func TestPeerInvalidHave(t *testing.T) {
533 cfg := TestingConfig()
534 cfg.DropMutuallyCompletePeers = false
535 cl, err := NewClient(cfg)
536 require.NoError(t, err)
538 info := metainfo.Info{
540 Pieces: make([]byte, 20),
541 Files: []metainfo.FileInfo{{Length: 1}},
543 infoBytes, err := bencode.Marshal(info)
544 require.NoError(t, err)
545 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
546 InfoBytes: infoBytes,
547 InfoHash: metainfo.HashBytes(infoBytes),
548 Storage: badStorage{},
550 require.NoError(t, err)
553 cn := &PeerConn{Peer: Peer{
557 assert.NoError(t, cn.peerSentHave(0))
558 assert.Error(t, cn.peerSentHave(1))
561 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
562 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
563 defer os.RemoveAll(greetingTempDir)
564 cfg := TestingConfig()
565 cfg.DataDir = greetingTempDir
566 seeder, err := NewClient(TestingConfig())
567 require.NoError(t, err)
568 seeder.AddTorrentSpec(&TorrentSpec{
569 InfoBytes: greetingMetainfo.InfoBytes,
573 // Check that when the listen port is 0, all the protocols listened on have
574 // the same port, and it isn't zero.
575 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
576 cl, err := NewClient(TestingConfig())
577 require.NoError(t, err)
579 port := cl.LocalPort()
580 assert.NotEqual(t, 0, port)
581 cl.eachListener(func(s Listener) bool {
582 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
587 func TestClientDynamicListenTCPOnly(t *testing.T) {
588 cfg := TestingConfig()
589 cfg.DisableUTP = true
590 cfg.DisableTCP = false
591 cl, err := NewClient(cfg)
592 require.NoError(t, err)
594 assert.NotEqual(t, 0, cl.LocalPort())
597 func TestClientDynamicListenUTPOnly(t *testing.T) {
598 cfg := TestingConfig()
599 cfg.DisableTCP = true
600 cfg.DisableUTP = false
601 cl, err := NewClient(cfg)
602 require.NoError(t, err)
604 assert.NotEqual(t, 0, cl.LocalPort())
607 func totalConns(tts []*Torrent) (ret int) {
608 for _, tt := range tts {
616 func TestSetMaxEstablishedConn(t *testing.T) {
618 ih := testutil.GreetingMetaInfo().HashInfoBytes()
619 cfg := TestingConfig()
620 cfg.DisableAcceptRateLimiting = true
621 cfg.DropDuplicatePeerIds = true
622 for i := range iter.N(3) {
623 cl, err := NewClient(cfg)
624 require.NoError(t, err)
626 tt, _ := cl.AddTorrentInfoHash(ih)
627 tt.SetMaxEstablishedConns(2)
628 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
629 tts = append(tts, tt)
632 for _, tt := range tts {
633 for _, _tt := range tts {
635 tt.AddClientPeer(_tt.cl)
640 waitTotalConns := func(num int) {
641 for totalConns(tts) != num {
643 time.Sleep(time.Millisecond)
648 tts[0].SetMaxEstablishedConns(1)
650 tts[0].SetMaxEstablishedConns(0)
652 tts[0].SetMaxEstablishedConns(1)
655 tts[0].SetMaxEstablishedConns(2)
660 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
661 // client, and returns a magnet link.
662 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
663 os.MkdirAll(dir, 0770)
664 file, err := os.Create(filepath.Join(dir, name))
665 require.NoError(t, err)
666 file.Write([]byte(name))
668 mi := metainfo.MetaInfo{}
670 info := metainfo.Info{PieceLength: 256 * 1024}
671 err = info.BuildFromFilePath(filepath.Join(dir, name))
672 require.NoError(t, err)
673 mi.InfoBytes, err = bencode.Marshal(info)
674 require.NoError(t, err)
675 magnet := mi.Magnet(name, mi.HashInfoBytes()).String()
676 tr, err := cl.AddTorrent(&mi)
677 require.NoError(t, err)
678 require.True(t, tr.Seeding())
683 // https://github.com/anacrolix/torrent/issues/114
684 func TestMultipleTorrentsWithEncryption(t *testing.T) {
685 testSeederLeecherPair(
687 func(cfg *ClientConfig) {
688 cfg.HeaderObfuscationPolicy.Preferred = true
689 cfg.HeaderObfuscationPolicy.RequirePreferred = true
691 func(cfg *ClientConfig) {
692 cfg.HeaderObfuscationPolicy.RequirePreferred = false
697 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
698 // seeder config is done first.
699 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
700 cfg := TestingConfig()
702 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
703 os.Mkdir(cfg.DataDir, 0755)
705 server, err := NewClient(cfg)
706 require.NoError(t, err)
708 defer testutil.ExportStatusWriter(server, "s", t)()
709 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
710 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
711 // against more than one torrent. See issue #114
712 makeMagnet(t, server, cfg.DataDir, "test2")
713 for i := 0; i < 100; i++ {
714 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
716 cfg = TestingConfig()
717 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
719 client, err := NewClient(cfg)
720 require.NoError(t, err)
722 defer testutil.ExportStatusWriter(client, "c", t)()
723 tr, err := client.AddMagnet(magnet1)
724 require.NoError(t, err)
725 tr.AddClientPeer(server)
731 // This appears to be the situation with the S3 BitTorrent client.
732 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
733 // Leecher prefers obfuscation, but the seeder does not allow it.
734 testSeederLeecherPair(
736 func(cfg *ClientConfig) {
737 cfg.HeaderObfuscationPolicy.Preferred = false
738 cfg.HeaderObfuscationPolicy.RequirePreferred = true
740 func(cfg *ClientConfig) {
741 cfg.HeaderObfuscationPolicy.Preferred = true
742 cfg.HeaderObfuscationPolicy.RequirePreferred = false
747 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
748 // Leecher prefers no obfuscation, but the seeder enforces it.
749 testSeederLeecherPair(
751 func(cfg *ClientConfig) {
752 cfg.HeaderObfuscationPolicy.Preferred = true
753 cfg.HeaderObfuscationPolicy.RequirePreferred = true
755 func(cfg *ClientConfig) {
756 cfg.HeaderObfuscationPolicy.Preferred = false
757 cfg.HeaderObfuscationPolicy.RequirePreferred = false
762 func TestClientAddressInUse(t *testing.T) {
763 s, _ := NewUtpSocket("udp", ":50007", nil)
767 cfg := TestingConfig().SetListenAddr(":50007")
768 cl, err := NewClient(cfg)
769 require.Error(t, err)
773 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
774 cc := TestingConfig()
777 cl, err := NewClient(cc)
778 require.NoError(t, err)
780 assert.NotEmpty(t, cl.DhtServers())
783 func TestIssue335(t *testing.T) {
784 dir, mi := testutil.GreetingTestTorrent()
785 defer os.RemoveAll(dir)
786 cfg := TestingConfig()
790 comp, err := storage.NewBoltPieceCompletion(dir)
791 require.NoError(t, err)
793 cfg.DefaultStorage = storage.NewMMapWithCompletion(dir, comp)
794 cl, err := NewClient(cfg)
795 require.NoError(t, err)
797 tor, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
798 require.NoError(t, err)
800 require.True(t, cl.WaitAll())
802 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
803 require.NoError(t, err)
805 require.True(t, cl.WaitAll())
808 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
809 cfg := TestingConfig()
810 cfg.DisableTCP = true
811 cfg.DisableUTP = true
813 cl, err := NewClient(cfg)
814 require.NoError(t, err)
816 assert.Empty(t, cl.listeners)
817 assert.NotEmpty(t, cl.DhtServers())