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/v2"
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(t))
33 require.NoError(t, err)
37 func TestClientNilConfig(t *testing.T) {
38 cl, err := NewClient(nil)
39 require.NoError(t, err)
43 func TestAddDropTorrent(t *testing.T) {
44 cl, err := NewClient(TestingConfig(t))
45 require.NoError(t, err)
47 dir, mi := testutil.GreetingTestTorrent()
48 defer os.RemoveAll(dir)
49 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
50 require.NoError(t, err)
52 tt.SetMaxEstablishedConns(0)
53 tt.SetMaxEstablishedConns(1)
57 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
62 func TestAddTorrentNoUsableURLs(t *testing.T) {
67 func TestAddPeersToUnknownTorrent(t *testing.T) {
72 func TestPieceHashSize(t *testing.T) {
73 assert.Equal(t, 20, pieceHash.Size())
76 func TestTorrentInitialState(t *testing.T) {
77 dir, mi := testutil.GreetingTestTorrent()
78 defer os.RemoveAll(dir)
80 config: TestingConfig(t),
85 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
89 err := tor.setInfoBytes(mi.InfoBytes)
91 require.NoError(t, err)
92 require.Len(t, tor.pieces, 3)
93 tor.pendAllChunkSpecs(0)
95 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
97 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
100 func TestReducedDialTimeout(t *testing.T) {
101 cfg := NewDefaultClientConfig()
102 for _, _case := range []struct {
106 ExpectedReduced time.Duration
108 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
109 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
110 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
111 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
112 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
113 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
115 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
116 expected := _case.ExpectedReduced
117 if expected < cfg.MinDialTimeout {
118 expected = cfg.MinDialTimeout
120 if reduced != expected {
121 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
126 func TestAddDropManyTorrents(t *testing.T) {
127 cl, err := NewClient(TestingConfig(t))
128 require.NoError(t, err)
130 for i := range iter.N(1000) {
132 binary.PutVarint(spec.InfoHash[:], int64(i))
133 tt, new, err := cl.AddTorrentSpec(&spec)
134 assert.NoError(t, err)
140 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
141 return storage.NewResourcePiecesOpts(
142 fc.AsResourceProvider(),
143 storage.ResourcePiecesOpts{
144 LeaveIncompleteChunks: true,
149 func TestMergingTrackersByAddingSpecs(t *testing.T) {
150 cl, err := NewClient(TestingConfig(t))
151 require.NoError(t, err)
153 spec := TorrentSpec{}
154 T, new, _ := cl.AddTorrentSpec(&spec)
158 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
159 _, new, _ = cl.AddTorrentSpec(&spec)
161 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
162 // Because trackers are disabled in TestingConfig.
163 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
166 // We read from a piece which is marked completed, but is missing data.
167 func TestCompletedPieceWrongSize(t *testing.T) {
168 cfg := TestingConfig(t)
169 cfg.DefaultStorage = badStorage{}
170 cl, err := NewClient(cfg)
171 require.NoError(t, err)
173 info := metainfo.Info{
175 Pieces: make([]byte, 20),
176 Files: []metainfo.FileInfo{
177 {Path: []string{"greeting"}, Length: 13},
180 b, err := bencode.Marshal(info)
181 require.NoError(t, err)
182 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
184 InfoHash: metainfo.HashBytes(b),
186 require.NoError(t, err)
191 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
194 func BenchmarkAddLargeTorrent(b *testing.B) {
195 cfg := TestingConfig(b)
196 cfg.DisableTCP = true
197 cfg.DisableUTP = true
198 cl, err := NewClient(cfg)
199 require.NoError(b, err)
202 for range iter.N(b.N) {
203 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
211 func TestResponsive(t *testing.T) {
212 seederDataDir, mi := testutil.GreetingTestTorrent()
213 defer os.RemoveAll(seederDataDir)
214 cfg := TestingConfig(t)
216 cfg.DataDir = seederDataDir
217 seeder, err := NewClient(cfg)
220 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
221 seederTorrent.VerifyData()
222 leecherDataDir, err := ioutil.TempDir("", "")
224 defer os.RemoveAll(leecherDataDir)
225 cfg = TestingConfig(t)
226 cfg.DataDir = leecherDataDir
227 leecher, err := NewClient(cfg)
229 defer leecher.Close()
230 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
231 ret = TorrentSpecFromMetaInfo(mi)
235 leecherTorrent.AddClientPeer(seeder)
236 reader := leecherTorrent.NewReader()
238 reader.SetReadahead(0)
239 reader.SetResponsive()
241 _, err = reader.Seek(3, io.SeekStart)
242 require.NoError(t, err)
243 _, err = io.ReadFull(reader, b)
245 assert.EqualValues(t, "lo", string(b))
246 _, err = reader.Seek(11, io.SeekStart)
247 require.NoError(t, err)
248 n, err := io.ReadFull(reader, b)
250 assert.EqualValues(t, 2, n)
251 assert.EqualValues(t, "d\n", string(b))
254 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
255 seederDataDir, mi := testutil.GreetingTestTorrent()
256 defer os.RemoveAll(seederDataDir)
257 cfg := TestingConfig(t)
259 cfg.DataDir = seederDataDir
260 seeder, err := NewClient(cfg)
263 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
264 seederTorrent.VerifyData()
265 leecherDataDir, err := ioutil.TempDir("", "")
267 defer os.RemoveAll(leecherDataDir)
268 cfg = TestingConfig(t)
269 cfg.DataDir = leecherDataDir
270 leecher, err := NewClient(cfg)
272 defer leecher.Close()
273 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
274 ret = TorrentSpecFromMetaInfo(mi)
278 leecherTorrent.AddClientPeer(seeder)
279 reader := leecherTorrent.NewReader()
281 reader.SetReadahead(0)
282 reader.SetResponsive()
284 _, err = reader.Seek(3, io.SeekStart)
285 require.NoError(t, err)
286 _, err = io.ReadFull(reader, b)
288 assert.EqualValues(t, "lo", string(b))
289 go leecherTorrent.Drop()
290 _, err = reader.Seek(11, io.SeekStart)
291 require.NoError(t, err)
292 n, err := reader.Read(b)
293 assert.EqualError(t, err, "torrent closed")
294 assert.EqualValues(t, 0, n)
297 func TestDhtInheritBlocklist(t *testing.T) {
298 ipl := iplist.New(nil)
299 require.NotNil(t, ipl)
300 cfg := TestingConfig(t)
301 cfg.IPBlocklist = ipl
303 cl, err := NewClient(cfg)
304 require.NoError(t, err)
307 cl.eachDhtServer(func(s DhtServer) {
309 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
312 assert.EqualValues(t, 2, numServers)
315 // Check that stuff is merged in subsequent AddTorrentSpec for the same
317 func TestAddTorrentSpecMerging(t *testing.T) {
318 cl, err := NewClient(TestingConfig(t))
319 require.NoError(t, err)
321 dir, mi := testutil.GreetingTestTorrent()
322 defer os.RemoveAll(dir)
323 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
324 InfoHash: mi.HashInfoBytes(),
326 require.NoError(t, err)
328 require.Nil(t, tt.Info())
329 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
330 require.NoError(t, err)
331 require.False(t, new)
332 require.NotNil(t, tt.Info())
335 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
336 dir, mi := testutil.GreetingTestTorrent()
338 cl, _ := NewClient(TestingConfig(t))
340 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
341 InfoHash: mi.HashInfoBytes(),
344 assert.EqualValues(t, 0, len(cl.Torrents()))
352 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
353 for i := range iter.N(info.NumPieces()) {
355 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
359 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
360 fileCacheDir, err := ioutil.TempDir("", "")
361 require.NoError(t, err)
362 defer os.RemoveAll(fileCacheDir)
363 fileCache, err := filecache.NewCache(fileCacheDir)
364 require.NoError(t, err)
365 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
366 defer os.RemoveAll(greetingDataTempDir)
367 filePieceStore := csf(fileCache)
368 info, err := greetingMetainfo.UnmarshalInfo()
369 require.NoError(t, err)
370 ih := greetingMetainfo.HashInfoBytes()
371 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
372 require.NoError(t, err)
373 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
374 // require.Equal(t, len(testutil.GreetingFileContents), written)
375 // require.NoError(t, err)
376 for i := 0; i < info.NumPieces(); i++ {
378 if alreadyCompleted {
379 require.NoError(t, greetingData.Piece(p).MarkComplete())
382 cfg := TestingConfig(t)
383 // TODO: Disable network option?
384 cfg.DisableTCP = true
385 cfg.DisableUTP = true
386 cfg.DefaultStorage = filePieceStore
387 cl, err := NewClient(cfg)
388 require.NoError(t, err)
390 tt, err := cl.AddTorrent(greetingMetainfo)
391 require.NoError(t, err)
392 psrs := tt.PieceStateRuns()
393 assert.Len(t, psrs, 1)
394 assert.EqualValues(t, 3, psrs[0].Length)
395 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
396 if alreadyCompleted {
398 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
402 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
403 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
406 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
407 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
410 func TestAddMetainfoWithNodes(t *testing.T) {
411 cfg := TestingConfig(t)
412 cfg.ListenHost = func(string) string { return "" }
414 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
415 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
416 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
417 // cfg.DHTConfig.NoSecurity = true
418 cl, err := NewClient(cfg)
419 require.NoError(t, err)
421 sum := func() (ret int64) {
422 cl.eachDhtServer(func(s DhtServer) {
423 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
427 assert.EqualValues(t, 0, sum())
428 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
429 require.NoError(t, err)
430 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
431 // check if the announce-list is here instead. TODO: Add nodes.
432 assert.Len(t, tt.metainfo.AnnounceList, 5)
433 // There are 6 nodes in the torrent file.
434 for sum() != int64(6*len(cl.dhtServers)) {
435 time.Sleep(time.Millisecond)
439 type testDownloadCancelParams struct {
440 SetLeecherStorageCapacity bool
441 LeecherStorageCapacity int64
445 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
446 greetingTempDir, mi := testutil.GreetingTestTorrent()
447 defer os.RemoveAll(greetingTempDir)
448 cfg := TestingConfig(t)
450 cfg.DataDir = greetingTempDir
451 seeder, err := NewClient(cfg)
452 require.NoError(t, err)
454 defer testutil.ExportStatusWriter(seeder, "s", t)()
455 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
456 seederTorrent.VerifyData()
457 leecherDataDir, err := ioutil.TempDir("", "")
458 require.NoError(t, err)
459 defer os.RemoveAll(leecherDataDir)
460 fc, err := filecache.NewCache(leecherDataDir)
461 require.NoError(t, err)
462 if ps.SetLeecherStorageCapacity {
463 fc.SetCapacity(ps.LeecherStorageCapacity)
465 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
466 cfg.DataDir = leecherDataDir
467 leecher, err := NewClient(cfg)
468 require.NoError(t, err)
469 defer leecher.Close()
470 defer testutil.ExportStatusWriter(leecher, "l", t)()
471 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
472 ret = TorrentSpecFromMetaInfo(mi)
476 require.NoError(t, err)
478 psc := leecherGreeting.SubscribePieceStateChanges()
481 leecherGreeting.cl.lock()
482 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
484 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
486 leecherGreeting.cl.unlock()
487 done := make(chan struct{})
489 go leecherGreeting.AddClientPeer(seeder)
490 completes := make(map[int]bool, 3)
491 expected := func() map[int]bool {
493 return map[int]bool{0: false, 1: false, 2: false}
495 return map[int]bool{0: true, 1: true, 2: true}
498 for !reflect.DeepEqual(completes, expected) {
500 v := _v.(PieceStateChange)
501 completes[v.Index] = v.Complete
505 func TestTorrentDownloadAll(t *testing.T) {
506 testDownloadCancel(t, testDownloadCancelParams{})
509 func TestTorrentDownloadAllThenCancel(t *testing.T) {
510 testDownloadCancel(t, testDownloadCancelParams{
515 // Ensure that it's an error for a peer to send an invalid have message.
516 func TestPeerInvalidHave(t *testing.T) {
517 cfg := TestingConfig(t)
518 cfg.DropMutuallyCompletePeers = false
519 cl, err := NewClient(cfg)
520 require.NoError(t, err)
522 info := metainfo.Info{
524 Pieces: make([]byte, 20),
525 Files: []metainfo.FileInfo{{Length: 1}},
527 infoBytes, err := bencode.Marshal(info)
528 require.NoError(t, err)
529 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
530 InfoBytes: infoBytes,
531 InfoHash: metainfo.HashBytes(infoBytes),
532 Storage: badStorage{},
534 require.NoError(t, err)
537 cn := &PeerConn{Peer: Peer{
543 assert.NoError(t, cn.peerSentHave(0))
544 assert.Error(t, cn.peerSentHave(1))
547 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
548 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
549 defer os.RemoveAll(greetingTempDir)
550 cfg := TestingConfig(t)
551 cfg.DataDir = greetingTempDir
552 seeder, err := NewClient(TestingConfig(t))
553 require.NoError(t, err)
554 seeder.AddTorrentSpec(&TorrentSpec{
555 InfoBytes: greetingMetainfo.InfoBytes,
559 // Check that when the listen port is 0, all the protocols listened on have
560 // the same port, and it isn't zero.
561 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
562 cl, err := NewClient(TestingConfig(t))
563 require.NoError(t, err)
565 port := cl.LocalPort()
566 assert.NotEqual(t, 0, port)
567 cl.eachListener(func(s Listener) bool {
568 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
573 func TestClientDynamicListenTCPOnly(t *testing.T) {
574 cfg := TestingConfig(t)
575 cfg.DisableUTP = true
576 cfg.DisableTCP = false
577 cl, err := NewClient(cfg)
578 require.NoError(t, err)
580 assert.NotEqual(t, 0, cl.LocalPort())
583 func TestClientDynamicListenUTPOnly(t *testing.T) {
584 cfg := TestingConfig(t)
585 cfg.DisableTCP = true
586 cfg.DisableUTP = false
587 cl, err := NewClient(cfg)
588 require.NoError(t, err)
590 assert.NotEqual(t, 0, cl.LocalPort())
593 func totalConns(tts []*Torrent) (ret int) {
594 for _, tt := range tts {
602 func TestSetMaxEstablishedConn(t *testing.T) {
604 ih := testutil.GreetingMetaInfo().HashInfoBytes()
605 cfg := TestingConfig(t)
606 cfg.DisableAcceptRateLimiting = true
607 cfg.DropDuplicatePeerIds = true
608 for i := range iter.N(3) {
609 cl, err := NewClient(cfg)
610 require.NoError(t, err)
612 tt, _ := cl.AddTorrentInfoHash(ih)
613 tt.SetMaxEstablishedConns(2)
614 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
615 tts = append(tts, tt)
618 for _, tt := range tts {
619 for _, _tt := range tts {
621 tt.AddClientPeer(_tt.cl)
626 waitTotalConns := func(num int) {
627 for totalConns(tts) != num {
629 time.Sleep(time.Millisecond)
634 tts[0].SetMaxEstablishedConns(1)
636 tts[0].SetMaxEstablishedConns(0)
638 tts[0].SetMaxEstablishedConns(1)
641 tts[0].SetMaxEstablishedConns(2)
646 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
647 // client, and returns a magnet link.
648 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
649 os.MkdirAll(dir, 0770)
650 file, err := os.Create(filepath.Join(dir, name))
651 require.NoError(t, err)
652 file.Write([]byte(name))
654 mi := metainfo.MetaInfo{}
656 info := metainfo.Info{PieceLength: 256 * 1024}
657 err = info.BuildFromFilePath(filepath.Join(dir, name))
658 require.NoError(t, err)
659 mi.InfoBytes, err = bencode.Marshal(info)
660 require.NoError(t, err)
661 magnet := mi.Magnet(nil, &info).String()
662 tr, err := cl.AddTorrent(&mi)
663 require.NoError(t, err)
664 require.True(t, tr.Seeding())
669 // https://github.com/anacrolix/torrent/issues/114
670 func TestMultipleTorrentsWithEncryption(t *testing.T) {
671 testSeederLeecherPair(
673 func(cfg *ClientConfig) {
674 cfg.HeaderObfuscationPolicy.Preferred = true
675 cfg.HeaderObfuscationPolicy.RequirePreferred = true
677 func(cfg *ClientConfig) {
678 cfg.HeaderObfuscationPolicy.RequirePreferred = false
683 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
684 // seeder config is done first.
685 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
686 cfg := TestingConfig(t)
688 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
689 os.Mkdir(cfg.DataDir, 0755)
691 server, err := NewClient(cfg)
692 require.NoError(t, err)
694 defer testutil.ExportStatusWriter(server, "s", t)()
695 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
696 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
697 // against more than one torrent. See issue #114
698 makeMagnet(t, server, cfg.DataDir, "test2")
699 for i := 0; i < 100; i++ {
700 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
702 cfg = TestingConfig(t)
703 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
705 client, err := NewClient(cfg)
706 require.NoError(t, err)
708 defer testutil.ExportStatusWriter(client, "c", t)()
709 tr, err := client.AddMagnet(magnet1)
710 require.NoError(t, err)
711 tr.AddClientPeer(server)
717 // This appears to be the situation with the S3 BitTorrent client.
718 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
719 // Leecher prefers obfuscation, but the seeder does not allow it.
720 testSeederLeecherPair(
722 func(cfg *ClientConfig) {
723 cfg.HeaderObfuscationPolicy.Preferred = false
724 cfg.HeaderObfuscationPolicy.RequirePreferred = true
726 func(cfg *ClientConfig) {
727 cfg.HeaderObfuscationPolicy.Preferred = true
728 cfg.HeaderObfuscationPolicy.RequirePreferred = false
733 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
734 // Leecher prefers no obfuscation, but the seeder enforces it.
735 testSeederLeecherPair(
737 func(cfg *ClientConfig) {
738 cfg.HeaderObfuscationPolicy.Preferred = true
739 cfg.HeaderObfuscationPolicy.RequirePreferred = true
741 func(cfg *ClientConfig) {
742 cfg.HeaderObfuscationPolicy.Preferred = false
743 cfg.HeaderObfuscationPolicy.RequirePreferred = false
748 func TestClientAddressInUse(t *testing.T) {
749 s, _ := NewUtpSocket("udp", ":50007", nil)
753 cfg := TestingConfig(t).SetListenAddr(":50007")
754 cl, err := NewClient(cfg)
755 require.Error(t, err)
759 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
760 cc := TestingConfig(t)
763 cl, err := NewClient(cc)
764 require.NoError(t, err)
766 assert.NotEmpty(t, cl.DhtServers())
769 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
770 cfg := TestingConfig(t)
771 cfg.DisableTCP = true
772 cfg.DisableUTP = true
774 cl, err := NewClient(cfg)
775 require.NoError(t, err)
777 assert.Empty(t, cl.listeners)
778 assert.NotEmpty(t, cl.DhtServers())