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 // The default config will put crap in the working directory.
39 origDir, _ := os.Getwd()
40 defer os.Chdir(origDir)
42 cl, err := NewClient(nil)
43 require.NoError(t, err)
47 func TestAddDropTorrent(t *testing.T) {
48 cl, err := NewClient(TestingConfig(t))
49 require.NoError(t, err)
51 dir, mi := testutil.GreetingTestTorrent()
52 defer os.RemoveAll(dir)
53 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
54 require.NoError(t, err)
56 tt.SetMaxEstablishedConns(0)
57 tt.SetMaxEstablishedConns(1)
61 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
66 func TestAddTorrentNoUsableURLs(t *testing.T) {
71 func TestAddPeersToUnknownTorrent(t *testing.T) {
76 func TestPieceHashSize(t *testing.T) {
77 assert.Equal(t, 20, pieceHash.Size())
80 func TestTorrentInitialState(t *testing.T) {
81 dir, mi := testutil.GreetingTestTorrent()
82 defer os.RemoveAll(dir)
84 config: TestingConfig(t),
89 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
93 err := tor.setInfoBytesLocked(mi.InfoBytes)
95 require.NoError(t, err)
96 require.Len(t, tor.pieces, 3)
97 tor.pendAllChunkSpecs(0)
99 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
101 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
104 func TestReducedDialTimeout(t *testing.T) {
105 cfg := NewDefaultClientConfig()
106 for _, _case := range []struct {
110 ExpectedReduced time.Duration
112 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
113 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
114 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
115 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
116 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
117 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
119 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
120 expected := _case.ExpectedReduced
121 if expected < cfg.MinDialTimeout {
122 expected = cfg.MinDialTimeout
124 if reduced != expected {
125 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
130 func TestAddDropManyTorrents(t *testing.T) {
131 cl, err := NewClient(TestingConfig(t))
132 require.NoError(t, err)
134 for i := range iter.N(1000) {
136 binary.PutVarint(spec.InfoHash[:], int64(i))
137 tt, new, err := cl.AddTorrentSpec(&spec)
138 assert.NoError(t, err)
144 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
145 return storage.NewResourcePiecesOpts(
146 fc.AsResourceProvider(),
147 storage.ResourcePiecesOpts{
148 LeaveIncompleteChunks: true,
153 func TestMergingTrackersByAddingSpecs(t *testing.T) {
154 cl, err := NewClient(TestingConfig(t))
155 require.NoError(t, err)
157 spec := TorrentSpec{}
158 T, new, _ := cl.AddTorrentSpec(&spec)
162 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
163 _, new, _ = cl.AddTorrentSpec(&spec)
165 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
166 // Because trackers are disabled in TestingConfig.
167 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
170 // We read from a piece which is marked completed, but is missing data.
171 func TestCompletedPieceWrongSize(t *testing.T) {
172 cfg := TestingConfig(t)
173 cfg.DefaultStorage = badStorage{}
174 cl, err := NewClient(cfg)
175 require.NoError(t, err)
177 info := metainfo.Info{
179 Pieces: make([]byte, 20),
180 Files: []metainfo.FileInfo{
181 {Path: []string{"greeting"}, Length: 13},
184 b, err := bencode.Marshal(info)
185 require.NoError(t, err)
186 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
188 InfoHash: metainfo.HashBytes(b),
190 require.NoError(t, err)
195 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
198 func BenchmarkAddLargeTorrent(b *testing.B) {
199 cfg := TestingConfig(b)
200 cfg.DisableTCP = true
201 cfg.DisableUTP = true
202 cl, err := NewClient(cfg)
203 require.NoError(b, err)
206 for range iter.N(b.N) {
207 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
215 func TestResponsive(t *testing.T) {
216 seederDataDir, mi := testutil.GreetingTestTorrent()
217 defer os.RemoveAll(seederDataDir)
218 cfg := TestingConfig(t)
220 cfg.DataDir = seederDataDir
221 seeder, err := NewClient(cfg)
224 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
225 seederTorrent.VerifyData()
226 leecherDataDir, err := ioutil.TempDir("", "")
228 defer os.RemoveAll(leecherDataDir)
229 cfg = TestingConfig(t)
230 cfg.DataDir = leecherDataDir
231 leecher, err := NewClient(cfg)
233 defer leecher.Close()
234 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
235 ret = TorrentSpecFromMetaInfo(mi)
239 leecherTorrent.AddClientPeer(seeder)
240 reader := leecherTorrent.NewReader()
242 reader.SetReadahead(0)
243 reader.SetResponsive()
245 _, err = reader.Seek(3, io.SeekStart)
246 require.NoError(t, err)
247 _, err = io.ReadFull(reader, b)
249 assert.EqualValues(t, "lo", string(b))
250 _, err = reader.Seek(11, io.SeekStart)
251 require.NoError(t, err)
252 n, err := io.ReadFull(reader, b)
254 assert.EqualValues(t, 2, n)
255 assert.EqualValues(t, "d\n", string(b))
258 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
259 seederDataDir, mi := testutil.GreetingTestTorrent()
260 defer os.RemoveAll(seederDataDir)
261 cfg := TestingConfig(t)
263 cfg.DataDir = seederDataDir
264 seeder, err := NewClient(cfg)
267 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
268 seederTorrent.VerifyData()
269 leecherDataDir, err := ioutil.TempDir("", "")
271 defer os.RemoveAll(leecherDataDir)
272 cfg = TestingConfig(t)
273 cfg.DataDir = leecherDataDir
274 leecher, err := NewClient(cfg)
276 defer leecher.Close()
277 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
278 ret = TorrentSpecFromMetaInfo(mi)
282 leecherTorrent.AddClientPeer(seeder)
283 reader := leecherTorrent.NewReader()
285 reader.SetReadahead(0)
286 reader.SetResponsive()
288 _, err = reader.Seek(3, io.SeekStart)
289 require.NoError(t, err)
290 _, err = io.ReadFull(reader, b)
292 assert.EqualValues(t, "lo", string(b))
293 go leecherTorrent.Drop()
294 _, err = reader.Seek(11, io.SeekStart)
295 require.NoError(t, err)
296 n, err := reader.Read(b)
297 assert.EqualError(t, err, "torrent closed")
298 assert.EqualValues(t, 0, n)
301 func TestDhtInheritBlocklist(t *testing.T) {
302 ipl := iplist.New(nil)
303 require.NotNil(t, ipl)
304 cfg := TestingConfig(t)
305 cfg.IPBlocklist = ipl
307 cl, err := NewClient(cfg)
308 require.NoError(t, err)
311 cl.eachDhtServer(func(s DhtServer) {
313 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
316 assert.EqualValues(t, 2, numServers)
319 // Check that stuff is merged in subsequent AddTorrentSpec for the same
321 func TestAddTorrentSpecMerging(t *testing.T) {
322 cl, err := NewClient(TestingConfig(t))
323 require.NoError(t, err)
325 dir, mi := testutil.GreetingTestTorrent()
326 defer os.RemoveAll(dir)
327 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
328 InfoHash: mi.HashInfoBytes(),
330 require.NoError(t, err)
332 require.Nil(t, tt.Info())
333 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
334 require.NoError(t, err)
335 require.False(t, new)
336 require.NotNil(t, tt.Info())
339 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
340 dir, mi := testutil.GreetingTestTorrent()
342 cl, _ := NewClient(TestingConfig(t))
344 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
345 InfoHash: mi.HashInfoBytes(),
348 assert.EqualValues(t, 0, len(cl.Torrents()))
356 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
357 for i := range iter.N(info.NumPieces()) {
359 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
363 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
364 fileCacheDir, err := ioutil.TempDir("", "")
365 require.NoError(t, err)
366 defer os.RemoveAll(fileCacheDir)
367 fileCache, err := filecache.NewCache(fileCacheDir)
368 require.NoError(t, err)
369 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
370 defer os.RemoveAll(greetingDataTempDir)
371 filePieceStore := csf(fileCache)
372 info, err := greetingMetainfo.UnmarshalInfo()
373 require.NoError(t, err)
374 ih := greetingMetainfo.HashInfoBytes()
375 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
376 require.NoError(t, err)
377 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
378 // require.Equal(t, len(testutil.GreetingFileContents), written)
379 // require.NoError(t, err)
380 for i := 0; i < info.NumPieces(); i++ {
382 if alreadyCompleted {
383 require.NoError(t, greetingData.Piece(p).MarkComplete())
386 cfg := TestingConfig(t)
387 // TODO: Disable network option?
388 cfg.DisableTCP = true
389 cfg.DisableUTP = true
390 cfg.DefaultStorage = filePieceStore
391 cl, err := NewClient(cfg)
392 require.NoError(t, err)
394 tt, err := cl.AddTorrent(greetingMetainfo)
395 require.NoError(t, err)
396 psrs := tt.PieceStateRuns()
397 assert.Len(t, psrs, 1)
398 assert.EqualValues(t, 3, psrs[0].Length)
399 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
400 if alreadyCompleted {
402 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
406 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
407 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
410 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
411 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
414 func TestAddMetainfoWithNodes(t *testing.T) {
415 cfg := TestingConfig(t)
416 cfg.ListenHost = func(string) string { return "" }
418 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
419 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
420 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
421 // cfg.DHTConfig.NoSecurity = true
422 cl, err := NewClient(cfg)
423 require.NoError(t, err)
425 sum := func() (ret int64) {
426 cl.eachDhtServer(func(s DhtServer) {
427 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
431 assert.EqualValues(t, 0, sum())
432 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
433 require.NoError(t, err)
434 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
435 // check if the announce-list is here instead. TODO: Add nodes.
436 assert.Len(t, tt.metainfo.AnnounceList, 5)
437 // There are 6 nodes in the torrent file.
438 for sum() != int64(6*len(cl.dhtServers)) {
439 time.Sleep(time.Millisecond)
443 type testDownloadCancelParams struct {
444 SetLeecherStorageCapacity bool
445 LeecherStorageCapacity int64
449 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
450 greetingTempDir, mi := testutil.GreetingTestTorrent()
451 defer os.RemoveAll(greetingTempDir)
452 cfg := TestingConfig(t)
454 cfg.DataDir = greetingTempDir
455 seeder, err := NewClient(cfg)
456 require.NoError(t, err)
458 defer testutil.ExportStatusWriter(seeder, "s", t)()
459 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
460 seederTorrent.VerifyData()
461 leecherDataDir, err := ioutil.TempDir("", "")
462 require.NoError(t, err)
463 defer os.RemoveAll(leecherDataDir)
464 fc, err := filecache.NewCache(leecherDataDir)
465 require.NoError(t, err)
466 if ps.SetLeecherStorageCapacity {
467 fc.SetCapacity(ps.LeecherStorageCapacity)
469 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
470 cfg.DataDir = leecherDataDir
471 leecher, err := NewClient(cfg)
472 require.NoError(t, err)
473 defer leecher.Close()
474 defer testutil.ExportStatusWriter(leecher, "l", t)()
475 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
476 ret = TorrentSpecFromMetaInfo(mi)
480 require.NoError(t, err)
482 psc := leecherGreeting.SubscribePieceStateChanges()
485 leecherGreeting.cl.lock()
486 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
488 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
490 leecherGreeting.cl.unlock()
491 done := make(chan struct{})
493 go leecherGreeting.AddClientPeer(seeder)
494 completes := make(map[int]bool, 3)
495 expected := func() map[int]bool {
497 return map[int]bool{0: false, 1: false, 2: false}
499 return map[int]bool{0: true, 1: true, 2: true}
502 for !reflect.DeepEqual(completes, expected) {
504 v := _v.(PieceStateChange)
505 completes[v.Index] = v.Complete
509 func TestTorrentDownloadAll(t *testing.T) {
510 testDownloadCancel(t, testDownloadCancelParams{})
513 func TestTorrentDownloadAllThenCancel(t *testing.T) {
514 testDownloadCancel(t, testDownloadCancelParams{
519 // Ensure that it's an error for a peer to send an invalid have message.
520 func TestPeerInvalidHave(t *testing.T) {
521 cfg := TestingConfig(t)
522 cfg.DropMutuallyCompletePeers = false
523 cl, err := NewClient(cfg)
524 require.NoError(t, err)
526 info := metainfo.Info{
528 Pieces: make([]byte, 20),
529 Files: []metainfo.FileInfo{{Length: 1}},
531 infoBytes, err := bencode.Marshal(info)
532 require.NoError(t, err)
533 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
534 InfoBytes: infoBytes,
535 InfoHash: metainfo.HashBytes(infoBytes),
536 Storage: badStorage{},
538 require.NoError(t, err)
541 cn := &PeerConn{Peer: Peer{
547 assert.NoError(t, cn.peerSentHave(0))
548 assert.Error(t, cn.peerSentHave(1))
551 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
552 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
553 defer os.RemoveAll(greetingTempDir)
554 cfg := TestingConfig(t)
555 cfg.DataDir = greetingTempDir
556 seeder, err := NewClient(TestingConfig(t))
557 require.NoError(t, err)
558 seeder.AddTorrentSpec(&TorrentSpec{
559 InfoBytes: greetingMetainfo.InfoBytes,
563 // Check that when the listen port is 0, all the protocols listened on have
564 // the same port, and it isn't zero.
565 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
566 cl, err := NewClient(TestingConfig(t))
567 require.NoError(t, err)
569 port := cl.LocalPort()
570 assert.NotEqual(t, 0, port)
571 cl.eachListener(func(s Listener) bool {
572 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
577 func TestClientDynamicListenTCPOnly(t *testing.T) {
578 cfg := TestingConfig(t)
579 cfg.DisableUTP = true
580 cfg.DisableTCP = false
581 cl, err := NewClient(cfg)
582 require.NoError(t, err)
584 assert.NotEqual(t, 0, cl.LocalPort())
587 func TestClientDynamicListenUTPOnly(t *testing.T) {
588 cfg := TestingConfig(t)
589 cfg.DisableTCP = true
590 cfg.DisableUTP = false
591 cl, err := NewClient(cfg)
592 require.NoError(t, err)
594 assert.NotEqual(t, 0, cl.LocalPort())
597 func totalConns(tts []*Torrent) (ret int) {
598 for _, tt := range tts {
606 func TestSetMaxEstablishedConn(t *testing.T) {
608 ih := testutil.GreetingMetaInfo().HashInfoBytes()
609 cfg := TestingConfig(t)
610 cfg.DisableAcceptRateLimiting = true
611 cfg.DropDuplicatePeerIds = true
612 for i := range iter.N(3) {
613 cl, err := NewClient(cfg)
614 require.NoError(t, err)
616 tt, _ := cl.AddTorrentInfoHash(ih)
617 tt.SetMaxEstablishedConns(2)
618 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
619 tts = append(tts, tt)
622 for _, tt := range tts {
623 for _, _tt := range tts {
625 tt.AddClientPeer(_tt.cl)
630 waitTotalConns := func(num int) {
631 for totalConns(tts) != num {
633 time.Sleep(time.Millisecond)
638 tts[0].SetMaxEstablishedConns(1)
640 tts[0].SetMaxEstablishedConns(0)
642 tts[0].SetMaxEstablishedConns(1)
645 tts[0].SetMaxEstablishedConns(2)
650 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
651 // client, and returns a magnet link.
652 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
653 os.MkdirAll(dir, 0770)
654 file, err := os.Create(filepath.Join(dir, name))
655 require.NoError(t, err)
656 file.Write([]byte(name))
658 mi := metainfo.MetaInfo{}
660 info := metainfo.Info{PieceLength: 256 * 1024}
661 err = info.BuildFromFilePath(filepath.Join(dir, name))
662 require.NoError(t, err)
663 mi.InfoBytes, err = bencode.Marshal(info)
664 require.NoError(t, err)
665 magnet := mi.Magnet(nil, &info).String()
666 tr, err := cl.AddTorrent(&mi)
667 require.NoError(t, err)
668 require.True(t, tr.Seeding())
673 // https://github.com/anacrolix/torrent/issues/114
674 func TestMultipleTorrentsWithEncryption(t *testing.T) {
675 testSeederLeecherPair(
677 func(cfg *ClientConfig) {
678 cfg.HeaderObfuscationPolicy.Preferred = true
679 cfg.HeaderObfuscationPolicy.RequirePreferred = true
681 func(cfg *ClientConfig) {
682 cfg.HeaderObfuscationPolicy.RequirePreferred = false
687 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
688 // seeder config is done first.
689 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
690 cfg := TestingConfig(t)
692 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
693 os.Mkdir(cfg.DataDir, 0755)
695 server, err := NewClient(cfg)
696 require.NoError(t, err)
698 defer testutil.ExportStatusWriter(server, "s", t)()
699 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
700 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
701 // against more than one torrent. See issue #114
702 makeMagnet(t, server, cfg.DataDir, "test2")
703 for i := 0; i < 100; i++ {
704 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
706 cfg = TestingConfig(t)
707 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
709 client, err := NewClient(cfg)
710 require.NoError(t, err)
712 defer testutil.ExportStatusWriter(client, "c", t)()
713 tr, err := client.AddMagnet(magnet1)
714 require.NoError(t, err)
715 tr.AddClientPeer(server)
721 // This appears to be the situation with the S3 BitTorrent client.
722 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
723 // Leecher prefers obfuscation, but the seeder does not allow it.
724 testSeederLeecherPair(
726 func(cfg *ClientConfig) {
727 cfg.HeaderObfuscationPolicy.Preferred = false
728 cfg.HeaderObfuscationPolicy.RequirePreferred = true
730 func(cfg *ClientConfig) {
731 cfg.HeaderObfuscationPolicy.Preferred = true
732 cfg.HeaderObfuscationPolicy.RequirePreferred = false
737 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
738 // Leecher prefers no obfuscation, but the seeder enforces it.
739 testSeederLeecherPair(
741 func(cfg *ClientConfig) {
742 cfg.HeaderObfuscationPolicy.Preferred = true
743 cfg.HeaderObfuscationPolicy.RequirePreferred = true
745 func(cfg *ClientConfig) {
746 cfg.HeaderObfuscationPolicy.Preferred = false
747 cfg.HeaderObfuscationPolicy.RequirePreferred = false
752 func TestClientAddressInUse(t *testing.T) {
753 s, _ := NewUtpSocket("udp", ":50007", nil)
757 cfg := TestingConfig(t).SetListenAddr(":50007")
758 cl, err := NewClient(cfg)
759 require.Error(t, err)
763 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
764 cc := TestingConfig(t)
767 cl, err := NewClient(cc)
768 require.NoError(t, err)
770 assert.NotEmpty(t, cl.DhtServers())
773 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
774 cfg := TestingConfig(t)
775 cfg.DisableTCP = true
776 cfg.DisableUTP = true
778 cl, err := NewClient(cfg)
779 require.NoError(t, err)
781 assert.Empty(t, cl.listeners)
782 assert.NotEmpty(t, cl.DhtServers())