14 "github.com/bradfitz/iter"
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
18 "github.com/anacrolix/dht/v2"
19 "github.com/anacrolix/missinggo"
20 "github.com/anacrolix/missinggo/v2/filecache"
22 "github.com/anacrolix/torrent/bencode"
23 "github.com/anacrolix/torrent/internal/testutil"
24 "github.com/anacrolix/torrent/iplist"
25 "github.com/anacrolix/torrent/metainfo"
26 "github.com/anacrolix/torrent/storage"
29 func TestClientDefault(t *testing.T) {
30 cl, err := NewClient(TestingConfig())
31 require.NoError(t, err)
35 func TestClientNilConfig(t *testing.T) {
36 cl, err := NewClient(nil)
37 require.NoError(t, err)
41 func TestBoltPieceCompletionClosedWhenClientClosed(t *testing.T) {
42 cfg := TestingConfig()
43 pc, err := storage.NewBoltPieceCompletion(cfg.DataDir)
44 require.NoError(t, err)
45 ci := storage.NewFileWithCompletion(cfg.DataDir, pc)
47 cfg.DefaultStorage = ci
48 cl, err := NewClient(cfg)
49 require.NoError(t, err)
51 // And again, https://github.com/anacrolix/torrent/issues/158
52 cl, err = NewClient(cfg)
53 require.NoError(t, err)
57 func TestAddDropTorrent(t *testing.T) {
58 cl, err := NewClient(TestingConfig())
59 require.NoError(t, err)
61 dir, mi := testutil.GreetingTestTorrent()
62 defer os.RemoveAll(dir)
63 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
64 require.NoError(t, err)
66 tt.SetMaxEstablishedConns(0)
67 tt.SetMaxEstablishedConns(1)
71 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
76 func TestAddTorrentNoUsableURLs(t *testing.T) {
81 func TestAddPeersToUnknownTorrent(t *testing.T) {
86 func TestPieceHashSize(t *testing.T) {
87 assert.Equal(t, 20, pieceHash.Size())
90 func TestTorrentInitialState(t *testing.T) {
91 dir, mi := testutil.GreetingTestTorrent()
92 defer os.RemoveAll(dir)
94 config: TestingConfig(),
99 storage.NewFileWithCompletion(TestingTempDir.NewSub(), storage.NewMapPieceCompletion()),
103 err := tor.setInfoBytes(mi.InfoBytes)
105 require.NoError(t, err)
106 require.Len(t, tor.pieces, 3)
107 tor.pendAllChunkSpecs(0)
109 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
111 assert.EqualValues(t, chunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
114 func TestReducedDialTimeout(t *testing.T) {
115 cfg := NewDefaultClientConfig()
116 for _, _case := range []struct {
120 ExpectedReduced time.Duration
122 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
123 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
124 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
125 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
126 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
127 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
129 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
130 expected := _case.ExpectedReduced
131 if expected < cfg.MinDialTimeout {
132 expected = cfg.MinDialTimeout
134 if reduced != expected {
135 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
140 func TestAddDropManyTorrents(t *testing.T) {
141 cl, err := NewClient(TestingConfig())
142 require.NoError(t, err)
144 for i := range iter.N(1000) {
146 binary.PutVarint(spec.InfoHash[:], int64(i))
147 tt, new, err := cl.AddTorrentSpec(&spec)
148 assert.NoError(t, err)
154 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImplCloser {
155 return storage.NewResourcePieces(fc.AsResourceProvider())
158 func TestMergingTrackersByAddingSpecs(t *testing.T) {
159 cl, err := NewClient(TestingConfig())
160 require.NoError(t, err)
162 spec := TorrentSpec{}
163 T, new, _ := cl.AddTorrentSpec(&spec)
167 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
168 _, new, _ = cl.AddTorrentSpec(&spec)
170 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
171 // Because trackers are disabled in TestingConfig.
172 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
175 // We read from a piece which is marked completed, but is missing data.
176 func TestCompletedPieceWrongSize(t *testing.T) {
177 cfg := TestingConfig()
178 cfg.DefaultStorage = badStorage{}
179 cl, err := NewClient(cfg)
180 require.NoError(t, err)
182 info := metainfo.Info{
184 Pieces: make([]byte, 20),
185 Files: []metainfo.FileInfo{
186 {Path: []string{"greeting"}, Length: 13},
189 b, err := bencode.Marshal(info)
190 require.NoError(t, err)
191 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
193 InfoHash: metainfo.HashBytes(b),
195 require.NoError(t, err)
200 b, err = ioutil.ReadAll(r)
202 assert.NoError(t, err)
205 func BenchmarkAddLargeTorrent(b *testing.B) {
206 cfg := TestingConfig()
207 cfg.DisableTCP = true
208 cfg.DisableUTP = true
209 cl, err := NewClient(cfg)
210 require.NoError(b, err)
213 for range iter.N(b.N) {
214 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
222 func TestResponsive(t *testing.T) {
223 seederDataDir, mi := testutil.GreetingTestTorrent()
224 defer os.RemoveAll(seederDataDir)
225 cfg := TestingConfig()
227 cfg.DataDir = seederDataDir
228 seeder, err := NewClient(cfg)
231 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
232 seederTorrent.VerifyData()
233 leecherDataDir, err := ioutil.TempDir("", "")
235 defer os.RemoveAll(leecherDataDir)
236 cfg = TestingConfig()
237 cfg.DataDir = leecherDataDir
238 leecher, err := NewClient(cfg)
240 defer leecher.Close()
241 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
242 ret = TorrentSpecFromMetaInfo(mi)
246 leecherTorrent.AddClientPeer(seeder)
247 reader := leecherTorrent.NewReader()
249 reader.SetReadahead(0)
250 reader.SetResponsive()
252 _, err = reader.Seek(3, io.SeekStart)
253 require.NoError(t, err)
254 _, err = io.ReadFull(reader, b)
256 assert.EqualValues(t, "lo", string(b))
257 _, err = reader.Seek(11, io.SeekStart)
258 require.NoError(t, err)
259 n, err := io.ReadFull(reader, b)
261 assert.EqualValues(t, 2, n)
262 assert.EqualValues(t, "d\n", string(b))
265 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
266 seederDataDir, mi := testutil.GreetingTestTorrent()
267 defer os.RemoveAll(seederDataDir)
268 cfg := TestingConfig()
270 cfg.DataDir = seederDataDir
271 seeder, err := NewClient(cfg)
274 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
275 seederTorrent.VerifyData()
276 leecherDataDir, err := ioutil.TempDir("", "")
278 defer os.RemoveAll(leecherDataDir)
279 cfg = TestingConfig()
280 cfg.DataDir = leecherDataDir
281 leecher, err := NewClient(cfg)
283 defer leecher.Close()
284 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
285 ret = TorrentSpecFromMetaInfo(mi)
289 leecherTorrent.AddClientPeer(seeder)
290 reader := leecherTorrent.NewReader()
292 reader.SetReadahead(0)
293 reader.SetResponsive()
295 _, err = reader.Seek(3, io.SeekStart)
296 require.NoError(t, err)
297 _, err = io.ReadFull(reader, b)
299 assert.EqualValues(t, "lo", string(b))
300 go leecherTorrent.Drop()
301 _, err = reader.Seek(11, io.SeekStart)
302 require.NoError(t, err)
303 n, err := reader.Read(b)
304 assert.EqualError(t, err, "torrent closed")
305 assert.EqualValues(t, 0, n)
308 func TestDhtInheritBlocklist(t *testing.T) {
309 ipl := iplist.New(nil)
310 require.NotNil(t, ipl)
311 cfg := TestingConfig()
312 cfg.IPBlocklist = ipl
314 cl, err := NewClient(cfg)
315 require.NoError(t, err)
318 cl.eachDhtServer(func(s DhtServer) {
320 assert.Equal(t, ipl, s.(anacrolixDhtServerWrapper).Server.IPBlocklist())
323 assert.EqualValues(t, 2, numServers)
326 // Check that stuff is merged in subsequent AddTorrentSpec for the same
328 func TestAddTorrentSpecMerging(t *testing.T) {
329 cl, err := NewClient(TestingConfig())
330 require.NoError(t, err)
332 dir, mi := testutil.GreetingTestTorrent()
333 defer os.RemoveAll(dir)
334 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
335 InfoHash: mi.HashInfoBytes(),
337 require.NoError(t, err)
339 require.Nil(t, tt.Info())
340 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
341 require.NoError(t, err)
342 require.False(t, new)
343 require.NotNil(t, tt.Info())
346 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
347 dir, mi := testutil.GreetingTestTorrent()
349 cl, _ := NewClient(TestingConfig())
351 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
352 InfoHash: mi.HashInfoBytes(),
355 assert.EqualValues(t, 0, len(cl.Torrents()))
363 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
364 for i := range iter.N(info.NumPieces()) {
366 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
370 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImplCloser) {
371 fileCacheDir, err := ioutil.TempDir("", "")
372 require.NoError(t, err)
373 defer os.RemoveAll(fileCacheDir)
374 fileCache, err := filecache.NewCache(fileCacheDir)
375 require.NoError(t, err)
376 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
377 defer os.RemoveAll(greetingDataTempDir)
378 filePieceStore := csf(fileCache)
379 defer filePieceStore.Close()
380 info, err := greetingMetainfo.UnmarshalInfo()
381 require.NoError(t, err)
382 ih := greetingMetainfo.HashInfoBytes()
383 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
384 require.NoError(t, err)
385 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
386 // require.Equal(t, len(testutil.GreetingFileContents), written)
387 // require.NoError(t, err)
388 for i := 0; i < info.NumPieces(); i++ {
390 if alreadyCompleted {
391 require.NoError(t, greetingData.Piece(p).MarkComplete())
394 cfg := TestingConfig()
395 // TODO: Disable network option?
396 cfg.DisableTCP = true
397 cfg.DisableUTP = true
398 cfg.DefaultStorage = filePieceStore
399 cl, err := NewClient(cfg)
400 require.NoError(t, err)
402 tt, err := cl.AddTorrent(greetingMetainfo)
403 require.NoError(t, err)
404 psrs := tt.PieceStateRuns()
405 assert.Len(t, psrs, 1)
406 assert.EqualValues(t, 3, psrs[0].Length)
407 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
408 if alreadyCompleted {
410 b, err := ioutil.ReadAll(r)
411 assert.NoError(t, err)
412 assert.EqualValues(t, testutil.GreetingFileContents, b)
416 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
417 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
420 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
421 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
424 func TestAddMetainfoWithNodes(t *testing.T) {
425 cfg := TestingConfig()
426 cfg.ListenHost = func(string) string { return "" }
428 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
429 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
430 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
431 // cfg.DHTConfig.NoSecurity = true
432 cl, err := NewClient(cfg)
433 require.NoError(t, err)
435 sum := func() (ret int64) {
436 cl.eachDhtServer(func(s DhtServer) {
437 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
441 assert.EqualValues(t, 0, sum())
442 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
443 require.NoError(t, err)
444 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
445 // check if the announce-list is here instead. TODO: Add nodes.
446 assert.Len(t, tt.metainfo.AnnounceList, 5)
447 // There are 6 nodes in the torrent file.
448 for sum() != int64(6*len(cl.dhtServers)) {
449 time.Sleep(time.Millisecond)
453 type testDownloadCancelParams struct {
454 SetLeecherStorageCapacity bool
455 LeecherStorageCapacity int64
459 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
460 greetingTempDir, mi := testutil.GreetingTestTorrent()
461 defer os.RemoveAll(greetingTempDir)
462 cfg := TestingConfig()
464 cfg.DataDir = greetingTempDir
465 seeder, err := NewClient(cfg)
466 require.NoError(t, err)
468 defer testutil.ExportStatusWriter(seeder, "s", t)()
469 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
470 seederTorrent.VerifyData()
471 leecherDataDir, err := ioutil.TempDir("", "")
472 require.NoError(t, err)
473 defer os.RemoveAll(leecherDataDir)
474 fc, err := filecache.NewCache(leecherDataDir)
475 require.NoError(t, err)
476 if ps.SetLeecherStorageCapacity {
477 fc.SetCapacity(ps.LeecherStorageCapacity)
479 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
480 cfg.DataDir = leecherDataDir
481 leecher, err := NewClient(cfg)
482 require.NoError(t, err)
483 defer leecher.Close()
484 defer testutil.ExportStatusWriter(leecher, "l", t)()
485 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
486 ret = TorrentSpecFromMetaInfo(mi)
490 require.NoError(t, err)
492 psc := leecherGreeting.SubscribePieceStateChanges()
495 leecherGreeting.cl.lock()
496 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
498 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
500 leecherGreeting.cl.unlock()
501 done := make(chan struct{})
503 go leecherGreeting.AddClientPeer(seeder)
504 completes := make(map[int]bool, 3)
505 expected := func() map[int]bool {
507 return map[int]bool{0: false, 1: false, 2: false}
509 return map[int]bool{0: true, 1: true, 2: true}
512 for !reflect.DeepEqual(completes, expected) {
514 v := _v.(PieceStateChange)
515 completes[v.Index] = v.Complete
519 func TestTorrentDownloadAll(t *testing.T) {
520 testDownloadCancel(t, testDownloadCancelParams{})
523 func TestTorrentDownloadAllThenCancel(t *testing.T) {
524 testDownloadCancel(t, testDownloadCancelParams{
529 // Ensure that it's an error for a peer to send an invalid have message.
530 func TestPeerInvalidHave(t *testing.T) {
531 cl, err := NewClient(TestingConfig())
532 require.NoError(t, err)
534 info := metainfo.Info{
536 Pieces: make([]byte, 20),
537 Files: []metainfo.FileInfo{{Length: 1}},
539 infoBytes, err := bencode.Marshal(info)
540 require.NoError(t, err)
541 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
542 InfoBytes: infoBytes,
543 InfoHash: metainfo.HashBytes(infoBytes),
544 Storage: badStorage{},
546 require.NoError(t, err)
549 cn := &PeerConn{peer: peer{
552 assert.NoError(t, cn.peerSentHave(0))
553 assert.Error(t, cn.peerSentHave(1))
556 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
557 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
558 defer os.RemoveAll(greetingTempDir)
559 cfg := TestingConfig()
560 cfg.DataDir = greetingTempDir
561 seeder, err := NewClient(TestingConfig())
562 require.NoError(t, err)
563 seeder.AddTorrentSpec(&TorrentSpec{
564 InfoBytes: greetingMetainfo.InfoBytes,
568 // Check that when the listen port is 0, all the protocols listened on have
569 // the same port, and it isn't zero.
570 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
571 cl, err := NewClient(TestingConfig())
572 require.NoError(t, err)
574 port := cl.LocalPort()
575 assert.NotEqual(t, 0, port)
576 cl.eachListener(func(s Listener) bool {
577 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
582 func TestClientDynamicListenTCPOnly(t *testing.T) {
583 cfg := TestingConfig()
584 cfg.DisableUTP = true
585 cfg.DisableTCP = false
586 cl, err := NewClient(cfg)
587 require.NoError(t, err)
589 assert.NotEqual(t, 0, cl.LocalPort())
592 func TestClientDynamicListenUTPOnly(t *testing.T) {
593 cfg := TestingConfig()
594 cfg.DisableTCP = true
595 cfg.DisableUTP = false
596 cl, err := NewClient(cfg)
597 require.NoError(t, err)
599 assert.NotEqual(t, 0, cl.LocalPort())
602 func totalConns(tts []*Torrent) (ret int) {
603 for _, tt := range tts {
611 func TestSetMaxEstablishedConn(t *testing.T) {
613 ih := testutil.GreetingMetaInfo().HashInfoBytes()
614 cfg := TestingConfig()
615 cfg.DisableAcceptRateLimiting = true
616 cfg.DropDuplicatePeerIds = true
617 for i := range iter.N(3) {
618 cl, err := NewClient(cfg)
619 require.NoError(t, err)
621 tt, _ := cl.AddTorrentInfoHash(ih)
622 tt.SetMaxEstablishedConns(2)
623 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
624 tts = append(tts, tt)
627 for _, tt := range tts {
628 for _, _tt := range tts {
630 tt.AddClientPeer(_tt.cl)
635 waitTotalConns := func(num int) {
636 for totalConns(tts) != num {
638 time.Sleep(time.Millisecond)
643 tts[0].SetMaxEstablishedConns(1)
645 tts[0].SetMaxEstablishedConns(0)
647 tts[0].SetMaxEstablishedConns(1)
650 tts[0].SetMaxEstablishedConns(2)
655 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
656 // client, and returns a magnet link.
657 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
658 os.MkdirAll(dir, 0770)
659 file, err := os.Create(filepath.Join(dir, name))
660 require.NoError(t, err)
661 file.Write([]byte(name))
663 mi := metainfo.MetaInfo{}
665 info := metainfo.Info{PieceLength: 256 * 1024}
666 err = info.BuildFromFilePath(filepath.Join(dir, name))
667 require.NoError(t, err)
668 mi.InfoBytes, err = bencode.Marshal(info)
669 require.NoError(t, err)
670 magnet := mi.Magnet(name, mi.HashInfoBytes()).String()
671 tr, err := cl.AddTorrent(&mi)
672 require.NoError(t, err)
673 require.True(t, tr.Seeding())
678 // https://github.com/anacrolix/torrent/issues/114
679 func TestMultipleTorrentsWithEncryption(t *testing.T) {
680 testSeederLeecherPair(
682 func(cfg *ClientConfig) {
683 cfg.HeaderObfuscationPolicy.Preferred = true
684 cfg.HeaderObfuscationPolicy.RequirePreferred = true
686 func(cfg *ClientConfig) {
687 cfg.HeaderObfuscationPolicy.RequirePreferred = false
692 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
693 // seeder config is done first.
694 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
695 cfg := TestingConfig()
697 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
698 os.Mkdir(cfg.DataDir, 0755)
700 server, err := NewClient(cfg)
701 require.NoError(t, err)
703 defer testutil.ExportStatusWriter(server, "s", t)()
704 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
705 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
706 // against more than one torrent. See issue #114
707 makeMagnet(t, server, cfg.DataDir, "test2")
708 for i := 0; i < 100; i++ {
709 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
711 cfg = TestingConfig()
712 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
714 client, err := NewClient(cfg)
715 require.NoError(t, err)
717 defer testutil.ExportStatusWriter(client, "c", t)()
718 tr, err := client.AddMagnet(magnet1)
719 require.NoError(t, err)
720 tr.AddClientPeer(server)
726 // This appears to be the situation with the S3 BitTorrent client.
727 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
728 // Leecher prefers obfuscation, but the seeder does not allow it.
729 testSeederLeecherPair(
731 func(cfg *ClientConfig) {
732 cfg.HeaderObfuscationPolicy.Preferred = false
733 cfg.HeaderObfuscationPolicy.RequirePreferred = true
735 func(cfg *ClientConfig) {
736 cfg.HeaderObfuscationPolicy.Preferred = true
737 cfg.HeaderObfuscationPolicy.RequirePreferred = false
742 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
743 // Leecher prefers no obfuscation, but the seeder enforces it.
744 testSeederLeecherPair(
746 func(cfg *ClientConfig) {
747 cfg.HeaderObfuscationPolicy.Preferred = true
748 cfg.HeaderObfuscationPolicy.RequirePreferred = true
750 func(cfg *ClientConfig) {
751 cfg.HeaderObfuscationPolicy.Preferred = false
752 cfg.HeaderObfuscationPolicy.RequirePreferred = false
757 func TestClientAddressInUse(t *testing.T) {
758 s, _ := NewUtpSocket("udp", ":50007", nil)
762 cfg := TestingConfig().SetListenAddr(":50007")
763 cl, err := NewClient(cfg)
764 require.Error(t, err)
768 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
769 cc := TestingConfig()
772 cl, err := NewClient(cc)
773 require.NoError(t, err)
775 assert.NotEmpty(t, cl.DhtServers())
778 func TestIssue335(t *testing.T) {
779 dir, mi := testutil.GreetingTestTorrent()
780 defer os.RemoveAll(dir)
781 cfg := TestingConfig()
785 comp, err := storage.NewBoltPieceCompletion(dir)
786 require.NoError(t, err)
788 cfg.DefaultStorage = storage.NewMMapWithCompletion(dir, comp)
789 cl, err := NewClient(cfg)
790 require.NoError(t, err)
792 tor, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
793 require.NoError(t, err)
795 require.True(t, cl.WaitAll())
797 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
798 require.NoError(t, err)
800 require.True(t, cl.WaitAll())
803 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
804 cfg := TestingConfig()
805 cfg.DisableTCP = true
806 cfg.DisableUTP = true
808 cl, err := NewClient(cfg)
809 require.NoError(t, err)
811 assert.Empty(t, cl.listeners)
812 assert.NotEmpty(t, cl.DhtServers())