14 "github.com/frankban/quicktest"
15 "github.com/stretchr/testify/assert"
16 "github.com/stretchr/testify/require"
18 "github.com/anacrolix/dht/v2"
19 "github.com/anacrolix/missinggo/v2"
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(t))
31 require.NoError(t, err)
32 require.Empty(t, cl.Close())
35 func TestClientNilConfig(t *testing.T) {
36 // The default config will put crap in the working directory.
37 origDir, _ := os.Getwd()
38 defer os.Chdir(origDir)
40 cl, err := NewClient(nil)
41 require.NoError(t, err)
42 require.Empty(t, cl.Close())
45 func TestAddDropTorrent(t *testing.T) {
46 cl, err := NewClient(TestingConfig(t))
47 require.NoError(t, err)
49 dir, mi := testutil.GreetingTestTorrent()
50 defer os.RemoveAll(dir)
51 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
52 require.NoError(t, err)
54 tt.SetMaxEstablishedConns(0)
55 tt.SetMaxEstablishedConns(1)
59 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
64 func TestAddTorrentNoUsableURLs(t *testing.T) {
69 func TestAddPeersToUnknownTorrent(t *testing.T) {
74 func TestPieceHashSize(t *testing.T) {
75 assert.Equal(t, 20, pieceHash.Size())
78 func TestTorrentInitialState(t *testing.T) {
79 dir, mi := testutil.GreetingTestTorrent()
80 defer os.RemoveAll(dir)
82 cl.init(TestingConfig(t))
86 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
90 err := tor.setInfoBytesLocked(mi.InfoBytes)
92 require.NoError(t, err)
93 require.Len(t, tor.pieces, 3)
94 tor.pendAllChunkSpecs(0)
96 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
98 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
101 func TestReducedDialTimeout(t *testing.T) {
102 cfg := NewDefaultClientConfig()
103 for _, _case := range []struct {
107 ExpectedReduced time.Duration
109 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
110 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
111 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
112 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
113 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
114 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
116 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
117 expected := _case.ExpectedReduced
118 if expected < cfg.MinDialTimeout {
119 expected = cfg.MinDialTimeout
121 if reduced != expected {
122 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
127 func TestAddDropManyTorrents(t *testing.T) {
128 cl, err := NewClient(TestingConfig(t))
129 require.NoError(t, err)
131 for i := 0; i < 1000; i += 1 {
133 binary.PutVarint(spec.InfoHash[:], int64(i))
134 tt, new, err := cl.AddTorrentSpec(&spec)
135 assert.NoError(t, err)
141 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
142 return storage.NewResourcePiecesOpts(
143 fc.AsResourceProvider(),
144 storage.ResourcePiecesOpts{
145 LeaveIncompleteChunks: true,
150 func TestMergingTrackersByAddingSpecs(t *testing.T) {
151 cl, err := NewClient(TestingConfig(t))
152 require.NoError(t, err)
154 spec := TorrentSpec{}
155 T, new, _ := cl.AddTorrentSpec(&spec)
159 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
160 _, new, _ = cl.AddTorrentSpec(&spec)
162 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
163 // Because trackers are disabled in TestingConfig.
164 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
167 // We read from a piece which is marked completed, but is missing data.
168 func TestCompletedPieceWrongSize(t *testing.T) {
169 cfg := TestingConfig(t)
170 cfg.DefaultStorage = badStorage{}
171 cl, err := NewClient(cfg)
172 require.NoError(t, err)
174 info := metainfo.Info{
176 Pieces: make([]byte, 20),
177 Files: []metainfo.FileInfo{
178 {Path: []string{"greeting"}, Length: 13},
181 b, err := bencode.Marshal(info)
182 require.NoError(t, err)
183 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
185 InfoHash: metainfo.HashBytes(b),
187 require.NoError(t, err)
192 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
195 func BenchmarkAddLargeTorrent(b *testing.B) {
196 cfg := TestingConfig(b)
197 cfg.DisableTCP = true
198 cfg.DisableUTP = true
199 cl, err := NewClient(cfg)
200 require.NoError(b, err)
203 for i := 0; i < b.N; i += 1 {
204 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
212 func TestResponsive(t *testing.T) {
213 seederDataDir, mi := testutil.GreetingTestTorrent()
214 defer os.RemoveAll(seederDataDir)
215 cfg := TestingConfig(t)
217 cfg.DataDir = seederDataDir
218 seeder, err := NewClient(cfg)
221 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
222 seederTorrent.VerifyData()
223 leecherDataDir := t.TempDir()
224 cfg = TestingConfig(t)
225 cfg.DataDir = leecherDataDir
226 leecher, err := NewClient(cfg)
228 defer leecher.Close()
229 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
230 ret = TorrentSpecFromMetaInfo(mi)
234 leecherTorrent.AddClientPeer(seeder)
235 reader := leecherTorrent.NewReader()
237 reader.SetReadahead(0)
238 reader.SetResponsive()
240 _, err = reader.Seek(3, io.SeekStart)
241 require.NoError(t, err)
242 _, err = io.ReadFull(reader, b)
244 assert.EqualValues(t, "lo", string(b))
245 _, err = reader.Seek(11, io.SeekStart)
246 require.NoError(t, err)
247 n, err := io.ReadFull(reader, b)
249 assert.EqualValues(t, 2, n)
250 assert.EqualValues(t, "d\n", string(b))
253 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
254 seederDataDir, mi := testutil.GreetingTestTorrent()
255 defer os.RemoveAll(seederDataDir)
256 cfg := TestingConfig(t)
258 cfg.DataDir = seederDataDir
259 seeder, err := NewClient(cfg)
262 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
263 seederTorrent.VerifyData()
264 leecherDataDir := t.TempDir()
265 cfg = TestingConfig(t)
266 cfg.DataDir = leecherDataDir
267 leecher, err := NewClient(cfg)
269 defer leecher.Close()
270 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
271 ret = TorrentSpecFromMetaInfo(mi)
275 leecherTorrent.AddClientPeer(seeder)
276 reader := leecherTorrent.NewReader()
278 reader.SetReadahead(0)
279 reader.SetResponsive()
281 _, err = reader.Seek(3, io.SeekStart)
282 require.NoError(t, err)
283 _, err = io.ReadFull(reader, b)
285 assert.EqualValues(t, "lo", string(b))
286 _, err = reader.Seek(11, io.SeekStart)
287 require.NoError(t, err)
288 leecherTorrent.Drop()
289 n, err := reader.Read(b)
290 assert.EqualError(t, err, "torrent closed")
291 assert.EqualValues(t, 0, n)
294 func TestDhtInheritBlocklist(t *testing.T) {
295 ipl := iplist.New(nil)
296 require.NotNil(t, ipl)
297 cfg := TestingConfig(t)
298 cfg.IPBlocklist = ipl
300 cl, err := NewClient(cfg)
301 require.NoError(t, err)
304 cl.eachDhtServer(func(s DhtServer) {
306 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
309 assert.EqualValues(t, 2, numServers)
312 // Check that stuff is merged in subsequent AddTorrentSpec for the same
314 func TestAddTorrentSpecMerging(t *testing.T) {
315 cl, err := NewClient(TestingConfig(t))
316 require.NoError(t, err)
318 dir, mi := testutil.GreetingTestTorrent()
319 defer os.RemoveAll(dir)
320 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
321 InfoHash: mi.HashInfoBytes(),
323 require.NoError(t, err)
325 require.Nil(t, tt.Info())
326 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
327 require.NoError(t, err)
328 require.False(t, new)
329 require.NotNil(t, tt.Info())
332 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
333 dir, mi := testutil.GreetingTestTorrent()
335 cl, _ := NewClient(TestingConfig(t))
337 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
338 InfoHash: mi.HashInfoBytes(),
341 assert.EqualValues(t, 0, len(cl.Torrents()))
349 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
350 for i := 0; i < info.NumPieces(); i += 1 {
352 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
356 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
357 fileCacheDir := t.TempDir()
358 fileCache, err := filecache.NewCache(fileCacheDir)
359 require.NoError(t, err)
360 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
361 defer os.RemoveAll(greetingDataTempDir)
362 filePieceStore := csf(fileCache)
363 info, err := greetingMetainfo.UnmarshalInfo()
364 require.NoError(t, err)
365 ih := greetingMetainfo.HashInfoBytes()
366 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
367 require.NoError(t, err)
368 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
369 // require.Equal(t, len(testutil.GreetingFileContents), written)
370 // require.NoError(t, err)
371 for i := 0; i < info.NumPieces(); i++ {
373 if alreadyCompleted {
374 require.NoError(t, greetingData.Piece(p).MarkComplete())
377 cfg := TestingConfig(t)
378 // TODO: Disable network option?
379 cfg.DisableTCP = true
380 cfg.DisableUTP = true
381 cfg.DefaultStorage = filePieceStore
382 cl, err := NewClient(cfg)
383 require.NoError(t, err)
385 tt, err := cl.AddTorrent(greetingMetainfo)
386 require.NoError(t, err)
387 psrs := tt.PieceStateRuns()
388 assert.Len(t, psrs, 1)
389 assert.EqualValues(t, 3, psrs[0].Length)
390 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
391 if alreadyCompleted {
393 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
397 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
398 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
401 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
402 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
405 func TestAddMetainfoWithNodes(t *testing.T) {
406 cfg := TestingConfig(t)
407 cfg.ListenHost = func(string) string { return "" }
409 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
410 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
411 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
412 // cfg.DHTConfig.NoSecurity = true
413 cl, err := NewClient(cfg)
414 require.NoError(t, err)
416 sum := func() (ret int64) {
417 cl.eachDhtServer(func(s DhtServer) {
418 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
422 assert.EqualValues(t, 0, sum())
423 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
424 require.NoError(t, err)
425 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
426 // check if the announce-list is here instead. TODO: Add nodes.
427 assert.Len(t, tt.metainfo.AnnounceList, 5)
428 // There are 6 nodes in the torrent file.
429 for sum() != int64(6*len(cl.dhtServers)) {
430 time.Sleep(time.Millisecond)
434 type testDownloadCancelParams struct {
435 SetLeecherStorageCapacity bool
436 LeecherStorageCapacity int64
440 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
441 greetingTempDir, mi := testutil.GreetingTestTorrent()
442 defer os.RemoveAll(greetingTempDir)
443 cfg := TestingConfig(t)
445 cfg.DataDir = greetingTempDir
446 seeder, err := NewClient(cfg)
447 require.NoError(t, err)
449 defer testutil.ExportStatusWriter(seeder, "s", t)()
450 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
451 seederTorrent.VerifyData()
452 leecherDataDir := t.TempDir()
453 fc, err := filecache.NewCache(leecherDataDir)
454 require.NoError(t, err)
455 if ps.SetLeecherStorageCapacity {
456 fc.SetCapacity(ps.LeecherStorageCapacity)
458 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
459 cfg.DataDir = leecherDataDir
460 leecher, err := NewClient(cfg)
461 require.NoError(t, err)
462 defer leecher.Close()
463 defer testutil.ExportStatusWriter(leecher, "l", t)()
464 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
465 ret = TorrentSpecFromMetaInfo(mi)
469 require.NoError(t, err)
471 psc := leecherGreeting.SubscribePieceStateChanges()
474 leecherGreeting.cl.lock()
475 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
477 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces(), "")
479 leecherGreeting.cl.unlock()
480 done := make(chan struct{})
482 go leecherGreeting.AddClientPeer(seeder)
483 completes := make(map[int]bool, 3)
484 expected := func() map[int]bool {
486 return map[int]bool{0: false, 1: false, 2: false}
488 return map[int]bool{0: true, 1: true, 2: true}
491 for !reflect.DeepEqual(completes, expected) {
493 v := _v.(PieceStateChange)
494 completes[v.Index] = v.Complete
498 func TestTorrentDownloadAll(t *testing.T) {
499 testDownloadCancel(t, testDownloadCancelParams{})
502 func TestTorrentDownloadAllThenCancel(t *testing.T) {
503 testDownloadCancel(t, testDownloadCancelParams{
508 // Ensure that it's an error for a peer to send an invalid have message.
509 func TestPeerInvalidHave(t *testing.T) {
510 cfg := TestingConfig(t)
511 cfg.DropMutuallyCompletePeers = false
512 cl, err := NewClient(cfg)
513 require.NoError(t, err)
515 info := metainfo.Info{
517 Pieces: make([]byte, 20),
518 Files: []metainfo.FileInfo{{Length: 1}},
520 infoBytes, err := bencode.Marshal(info)
521 require.NoError(t, err)
522 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
523 InfoBytes: infoBytes,
524 InfoHash: metainfo.HashBytes(infoBytes),
525 Storage: badStorage{},
527 require.NoError(t, err)
530 cn := &PeerConn{Peer: Peer{
532 callbacks: &cfg.Callbacks,
534 tt.conns[cn] = struct{}{}
538 assert.NoError(t, cn.peerSentHave(0))
539 assert.Error(t, cn.peerSentHave(1))
542 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
543 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
544 defer os.RemoveAll(greetingTempDir)
545 cfg := TestingConfig(t)
546 cfg.DataDir = greetingTempDir
547 seeder, err := NewClient(TestingConfig(t))
548 require.NoError(t, err)
549 seeder.AddTorrentSpec(&TorrentSpec{
550 InfoBytes: greetingMetainfo.InfoBytes,
554 // Check that when the listen port is 0, all the protocols listened on have
555 // the same port, and it isn't zero.
556 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
557 cl, err := NewClient(TestingConfig(t))
558 require.NoError(t, err)
560 port := cl.LocalPort()
561 assert.NotEqual(t, 0, port)
562 cl.eachListener(func(s Listener) bool {
563 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
568 func TestClientDynamicListenTCPOnly(t *testing.T) {
569 cfg := TestingConfig(t)
570 cfg.DisableUTP = true
571 cfg.DisableTCP = false
572 cl, err := NewClient(cfg)
573 require.NoError(t, err)
575 assert.NotEqual(t, 0, cl.LocalPort())
578 func TestClientDynamicListenUTPOnly(t *testing.T) {
579 cfg := TestingConfig(t)
580 cfg.DisableTCP = true
581 cfg.DisableUTP = false
582 cl, err := NewClient(cfg)
583 require.NoError(t, err)
585 assert.NotEqual(t, 0, cl.LocalPort())
588 func totalConns(tts []*Torrent) (ret int) {
589 for _, tt := range tts {
597 func TestSetMaxEstablishedConn(t *testing.T) {
599 ih := testutil.GreetingMetaInfo().HashInfoBytes()
600 cfg := TestingConfig(t)
601 cfg.DisableAcceptRateLimiting = true
602 cfg.DropDuplicatePeerIds = true
603 for i := 0; i < 3; i += 1 {
604 cl, err := NewClient(cfg)
605 require.NoError(t, err)
607 tt, _ := cl.AddTorrentInfoHash(ih)
608 tt.SetMaxEstablishedConns(2)
609 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
610 tts = append(tts, tt)
613 for _, tt := range tts {
614 for _, _tt := range tts {
616 tt.AddClientPeer(_tt.cl)
621 waitTotalConns := func(num int) {
622 for totalConns(tts) != num {
624 time.Sleep(time.Millisecond)
629 tts[0].SetMaxEstablishedConns(1)
631 tts[0].SetMaxEstablishedConns(0)
633 tts[0].SetMaxEstablishedConns(1)
636 tts[0].SetMaxEstablishedConns(2)
641 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
642 // client, and returns a magnet link.
643 func makeMagnet(t *testing.T, cl *Client, dir, name string) string {
644 os.MkdirAll(dir, 0o770)
645 file, err := os.Create(filepath.Join(dir, name))
646 require.NoError(t, err)
647 file.Write([]byte(name))
649 mi := metainfo.MetaInfo{}
651 info := metainfo.Info{PieceLength: 256 * 1024}
652 err = info.BuildFromFilePath(filepath.Join(dir, name))
653 require.NoError(t, err)
654 mi.InfoBytes, err = bencode.Marshal(info)
655 require.NoError(t, err)
656 magnet := mi.Magnet(nil, &info).String()
657 tr, err := cl.AddTorrent(&mi)
658 require.NoError(t, err)
659 require.True(t, tr.Seeding())
664 // https://github.com/anacrolix/torrent/issues/114
665 func TestMultipleTorrentsWithEncryption(t *testing.T) {
666 testSeederLeecherPair(
668 func(cfg *ClientConfig) {
669 cfg.HeaderObfuscationPolicy.Preferred = true
670 cfg.HeaderObfuscationPolicy.RequirePreferred = true
672 func(cfg *ClientConfig) {
673 cfg.HeaderObfuscationPolicy.RequirePreferred = false
678 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
679 // seeder config is done first.
680 func testSeederLeecherPair(t *testing.T, seeder, leecher func(*ClientConfig)) {
681 cfg := TestingConfig(t)
683 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
684 os.Mkdir(cfg.DataDir, 0o755)
686 server, err := NewClient(cfg)
687 require.NoError(t, err)
689 defer testutil.ExportStatusWriter(server, "s", t)()
690 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
691 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
692 // against more than one torrent. See issue #114
693 makeMagnet(t, server, cfg.DataDir, "test2")
694 for i := 0; i < 100; i++ {
695 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
697 cfg = TestingConfig(t)
698 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
700 client, err := NewClient(cfg)
701 require.NoError(t, err)
703 defer testutil.ExportStatusWriter(client, "c", t)()
704 tr, err := client.AddMagnet(magnet1)
705 require.NoError(t, err)
706 tr.AddClientPeer(server)
712 // This appears to be the situation with the S3 BitTorrent client.
713 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
714 // Leecher prefers obfuscation, but the seeder does not allow it.
715 testSeederLeecherPair(
717 func(cfg *ClientConfig) {
718 cfg.HeaderObfuscationPolicy.Preferred = false
719 cfg.HeaderObfuscationPolicy.RequirePreferred = true
721 func(cfg *ClientConfig) {
722 cfg.HeaderObfuscationPolicy.Preferred = true
723 cfg.HeaderObfuscationPolicy.RequirePreferred = false
728 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
729 // Leecher prefers no obfuscation, but the seeder enforces it.
730 testSeederLeecherPair(
732 func(cfg *ClientConfig) {
733 cfg.HeaderObfuscationPolicy.Preferred = true
734 cfg.HeaderObfuscationPolicy.RequirePreferred = true
736 func(cfg *ClientConfig) {
737 cfg.HeaderObfuscationPolicy.Preferred = false
738 cfg.HeaderObfuscationPolicy.RequirePreferred = false
743 func TestClientAddressInUse(t *testing.T) {
744 s, _ := NewUtpSocket("udp", ":50007", nil)
748 cfg := TestingConfig(t).SetListenAddr(":50007")
749 cl, err := NewClient(cfg)
750 require.Error(t, err)
754 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
755 cc := TestingConfig(t)
758 cl, err := NewClient(cc)
759 require.NoError(t, err)
761 assert.NotEmpty(t, cl.DhtServers())
764 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
765 cfg := TestingConfig(t)
766 cfg.DisableTCP = true
767 cfg.DisableUTP = true
769 cl, err := NewClient(cfg)
770 require.NoError(t, err)
772 assert.Empty(t, cl.listeners)
773 assert.NotEmpty(t, cl.DhtServers())