15 "github.com/frankban/quicktest"
16 "github.com/stretchr/testify/assert"
17 "github.com/stretchr/testify/require"
19 "github.com/anacrolix/dht/v2"
20 "github.com/anacrolix/missinggo/v2"
21 "github.com/anacrolix/missinggo/v2/filecache"
23 "github.com/anacrolix/torrent/bencode"
24 "github.com/anacrolix/torrent/internal/testutil"
25 "github.com/anacrolix/torrent/iplist"
26 "github.com/anacrolix/torrent/metainfo"
27 "github.com/anacrolix/torrent/storage"
30 func TestClientDefault(t *testing.T) {
31 cl, err := NewClient(TestingConfig(t))
32 require.NoError(t, err)
36 func TestClientNilConfig(t *testing.T) {
37 // The default config will put crap in the working directory.
38 origDir, _ := os.Getwd()
39 defer os.Chdir(origDir)
41 cl, err := NewClient(nil)
42 require.NoError(t, err)
46 func TestAddDropTorrent(t *testing.T) {
47 cl, err := NewClient(TestingConfig(t))
48 require.NoError(t, err)
50 dir, mi := testutil.GreetingTestTorrent()
51 defer os.RemoveAll(dir)
52 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
53 require.NoError(t, err)
55 tt.SetMaxEstablishedConns(0)
56 tt.SetMaxEstablishedConns(1)
60 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
65 func TestAddTorrentNoUsableURLs(t *testing.T) {
70 func TestAddPeersToUnknownTorrent(t *testing.T) {
75 func TestPieceHashSize(t *testing.T) {
76 assert.Equal(t, 20, pieceHash.Size())
79 func TestTorrentInitialState(t *testing.T) {
80 dir, mi := testutil.GreetingTestTorrent()
81 defer os.RemoveAll(dir)
83 config: TestingConfig(t),
88 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
92 err := tor.setInfoBytesLocked(mi.InfoBytes)
94 require.NoError(t, err)
95 require.Len(t, tor.pieces, 3)
96 tor.pendAllChunkSpecs(0)
98 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
100 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
103 func TestReducedDialTimeout(t *testing.T) {
104 cfg := NewDefaultClientConfig()
105 for _, _case := range []struct {
109 ExpectedReduced time.Duration
111 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
112 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
113 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
114 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
115 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
116 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
118 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
119 expected := _case.ExpectedReduced
120 if expected < cfg.MinDialTimeout {
121 expected = cfg.MinDialTimeout
123 if reduced != expected {
124 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
129 func TestAddDropManyTorrents(t *testing.T) {
130 cl, err := NewClient(TestingConfig(t))
131 require.NoError(t, err)
133 for i := 0; i < 1000; i += 1 {
135 binary.PutVarint(spec.InfoHash[:], int64(i))
136 tt, new, err := cl.AddTorrentSpec(&spec)
137 assert.NoError(t, err)
143 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
144 return storage.NewResourcePiecesOpts(
145 fc.AsResourceProvider(),
146 storage.ResourcePiecesOpts{
147 LeaveIncompleteChunks: true,
152 func TestMergingTrackersByAddingSpecs(t *testing.T) {
153 cl, err := NewClient(TestingConfig(t))
154 require.NoError(t, err)
156 spec := TorrentSpec{}
157 T, new, _ := cl.AddTorrentSpec(&spec)
161 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
162 _, new, _ = cl.AddTorrentSpec(&spec)
164 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
165 // Because trackers are disabled in TestingConfig.
166 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
169 // We read from a piece which is marked completed, but is missing data.
170 func TestCompletedPieceWrongSize(t *testing.T) {
171 cfg := TestingConfig(t)
172 cfg.DefaultStorage = badStorage{}
173 cl, err := NewClient(cfg)
174 require.NoError(t, err)
176 info := metainfo.Info{
178 Pieces: make([]byte, 20),
179 Files: []metainfo.FileInfo{
180 {Path: []string{"greeting"}, Length: 13},
183 b, err := bencode.Marshal(info)
184 require.NoError(t, err)
185 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
187 InfoHash: metainfo.HashBytes(b),
189 require.NoError(t, err)
194 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
197 func BenchmarkAddLargeTorrent(b *testing.B) {
198 cfg := TestingConfig(b)
199 cfg.DisableTCP = true
200 cfg.DisableUTP = true
201 cl, err := NewClient(cfg)
202 require.NoError(b, err)
205 for i := 0; i < b.N; i += 1 {
206 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
214 func TestResponsive(t *testing.T) {
215 seederDataDir, mi := testutil.GreetingTestTorrent()
216 defer os.RemoveAll(seederDataDir)
217 cfg := TestingConfig(t)
219 cfg.DataDir = seederDataDir
220 seeder, err := NewClient(cfg)
223 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
224 seederTorrent.VerifyData()
225 leecherDataDir, err := ioutil.TempDir("", "")
227 defer os.RemoveAll(leecherDataDir)
228 cfg = TestingConfig(t)
229 cfg.DataDir = leecherDataDir
230 leecher, err := NewClient(cfg)
232 defer leecher.Close()
233 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
234 ret = TorrentSpecFromMetaInfo(mi)
238 leecherTorrent.AddClientPeer(seeder)
239 reader := leecherTorrent.NewReader()
241 reader.SetReadahead(0)
242 reader.SetResponsive()
244 _, err = reader.Seek(3, io.SeekStart)
245 require.NoError(t, err)
246 _, err = io.ReadFull(reader, b)
248 assert.EqualValues(t, "lo", string(b))
249 _, err = reader.Seek(11, io.SeekStart)
250 require.NoError(t, err)
251 n, err := io.ReadFull(reader, b)
253 assert.EqualValues(t, 2, n)
254 assert.EqualValues(t, "d\n", string(b))
257 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
258 seederDataDir, mi := testutil.GreetingTestTorrent()
259 defer os.RemoveAll(seederDataDir)
260 cfg := TestingConfig(t)
262 cfg.DataDir = seederDataDir
263 seeder, err := NewClient(cfg)
266 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
267 seederTorrent.VerifyData()
268 leecherDataDir, err := ioutil.TempDir("", "")
270 defer os.RemoveAll(leecherDataDir)
271 cfg = TestingConfig(t)
272 cfg.DataDir = leecherDataDir
273 leecher, err := NewClient(cfg)
275 defer leecher.Close()
276 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
277 ret = TorrentSpecFromMetaInfo(mi)
281 leecherTorrent.AddClientPeer(seeder)
282 reader := leecherTorrent.NewReader()
284 reader.SetReadahead(0)
285 reader.SetResponsive()
287 _, err = reader.Seek(3, io.SeekStart)
288 require.NoError(t, err)
289 _, err = io.ReadFull(reader, b)
291 assert.EqualValues(t, "lo", string(b))
292 go leecherTorrent.Drop()
293 _, err = reader.Seek(11, io.SeekStart)
294 require.NoError(t, err)
295 n, err := reader.Read(b)
296 assert.EqualError(t, err, "torrent closed")
297 assert.EqualValues(t, 0, n)
300 func TestDhtInheritBlocklist(t *testing.T) {
301 ipl := iplist.New(nil)
302 require.NotNil(t, ipl)
303 cfg := TestingConfig(t)
304 cfg.IPBlocklist = ipl
306 cl, err := NewClient(cfg)
307 require.NoError(t, err)
310 cl.eachDhtServer(func(s DhtServer) {
312 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
315 assert.EqualValues(t, 2, numServers)
318 // Check that stuff is merged in subsequent AddTorrentSpec for the same
320 func TestAddTorrentSpecMerging(t *testing.T) {
321 cl, err := NewClient(TestingConfig(t))
322 require.NoError(t, err)
324 dir, mi := testutil.GreetingTestTorrent()
325 defer os.RemoveAll(dir)
326 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
327 InfoHash: mi.HashInfoBytes(),
329 require.NoError(t, err)
331 require.Nil(t, tt.Info())
332 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
333 require.NoError(t, err)
334 require.False(t, new)
335 require.NotNil(t, tt.Info())
338 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
339 dir, mi := testutil.GreetingTestTorrent()
341 cl, _ := NewClient(TestingConfig(t))
343 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
344 InfoHash: mi.HashInfoBytes(),
347 assert.EqualValues(t, 0, len(cl.Torrents()))
355 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
356 for i := 0; i < info.NumPieces(); i += 1 {
358 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
362 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
363 fileCacheDir, err := ioutil.TempDir("", "")
364 require.NoError(t, err)
365 defer os.RemoveAll(fileCacheDir)
366 fileCache, err := filecache.NewCache(fileCacheDir)
367 require.NoError(t, err)
368 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
369 defer os.RemoveAll(greetingDataTempDir)
370 filePieceStore := csf(fileCache)
371 info, err := greetingMetainfo.UnmarshalInfo()
372 require.NoError(t, err)
373 ih := greetingMetainfo.HashInfoBytes()
374 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
375 require.NoError(t, err)
376 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
377 // require.Equal(t, len(testutil.GreetingFileContents), written)
378 // require.NoError(t, err)
379 for i := 0; i < info.NumPieces(); i++ {
381 if alreadyCompleted {
382 require.NoError(t, greetingData.Piece(p).MarkComplete())
385 cfg := TestingConfig(t)
386 // TODO: Disable network option?
387 cfg.DisableTCP = true
388 cfg.DisableUTP = true
389 cfg.DefaultStorage = filePieceStore
390 cl, err := NewClient(cfg)
391 require.NoError(t, err)
393 tt, err := cl.AddTorrent(greetingMetainfo)
394 require.NoError(t, err)
395 psrs := tt.PieceStateRuns()
396 assert.Len(t, psrs, 1)
397 assert.EqualValues(t, 3, psrs[0].Length)
398 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
399 if alreadyCompleted {
401 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
405 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
406 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
409 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
410 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
413 func TestAddMetainfoWithNodes(t *testing.T) {
414 cfg := TestingConfig(t)
415 cfg.ListenHost = func(string) string { return "" }
417 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
418 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
419 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
420 // cfg.DHTConfig.NoSecurity = true
421 cl, err := NewClient(cfg)
422 require.NoError(t, err)
424 sum := func() (ret int64) {
425 cl.eachDhtServer(func(s DhtServer) {
426 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
430 assert.EqualValues(t, 0, sum())
431 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
432 require.NoError(t, err)
433 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
434 // check if the announce-list is here instead. TODO: Add nodes.
435 assert.Len(t, tt.metainfo.AnnounceList, 5)
436 // There are 6 nodes in the torrent file.
437 for sum() != int64(6*len(cl.dhtServers)) {
438 time.Sleep(time.Millisecond)
442 type testDownloadCancelParams struct {
443 SetLeecherStorageCapacity bool
444 LeecherStorageCapacity int64
448 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
449 greetingTempDir, mi := testutil.GreetingTestTorrent()
450 defer os.RemoveAll(greetingTempDir)
451 cfg := TestingConfig(t)
453 cfg.DataDir = greetingTempDir
454 seeder, err := NewClient(cfg)
455 require.NoError(t, err)
457 defer testutil.ExportStatusWriter(seeder, "s", t)()
458 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
459 seederTorrent.VerifyData()
460 leecherDataDir, err := ioutil.TempDir("", "")
461 require.NoError(t, err)
462 defer os.RemoveAll(leecherDataDir)
463 fc, err := filecache.NewCache(leecherDataDir)
464 require.NoError(t, err)
465 if ps.SetLeecherStorageCapacity {
466 fc.SetCapacity(ps.LeecherStorageCapacity)
468 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
469 cfg.DataDir = leecherDataDir
470 leecher, err := NewClient(cfg)
471 require.NoError(t, err)
472 defer leecher.Close()
473 defer testutil.ExportStatusWriter(leecher, "l", t)()
474 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
475 ret = TorrentSpecFromMetaInfo(mi)
479 require.NoError(t, err)
481 psc := leecherGreeting.SubscribePieceStateChanges()
484 leecherGreeting.cl.lock()
485 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
487 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces())
489 leecherGreeting.cl.unlock()
490 done := make(chan struct{})
492 go leecherGreeting.AddClientPeer(seeder)
493 completes := make(map[int]bool, 3)
494 expected := func() map[int]bool {
496 return map[int]bool{0: false, 1: false, 2: false}
498 return map[int]bool{0: true, 1: true, 2: true}
501 for !reflect.DeepEqual(completes, expected) {
503 v := _v.(PieceStateChange)
504 completes[v.Index] = v.Complete
508 func TestTorrentDownloadAll(t *testing.T) {
509 testDownloadCancel(t, testDownloadCancelParams{})
512 func TestTorrentDownloadAllThenCancel(t *testing.T) {
513 testDownloadCancel(t, testDownloadCancelParams{
518 // Ensure that it's an error for a peer to send an invalid have message.
519 func TestPeerInvalidHave(t *testing.T) {
520 cfg := TestingConfig(t)
521 cfg.DropMutuallyCompletePeers = false
522 cl, err := NewClient(cfg)
523 require.NoError(t, err)
525 info := metainfo.Info{
527 Pieces: make([]byte, 20),
528 Files: []metainfo.FileInfo{{Length: 1}},
530 infoBytes, err := bencode.Marshal(info)
531 require.NoError(t, err)
532 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
533 InfoBytes: infoBytes,
534 InfoHash: metainfo.HashBytes(infoBytes),
535 Storage: badStorage{},
537 require.NoError(t, err)
540 cn := &PeerConn{Peer: Peer{
546 assert.NoError(t, cn.peerSentHave(0))
547 assert.Error(t, cn.peerSentHave(1))
550 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
551 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
552 defer os.RemoveAll(greetingTempDir)
553 cfg := TestingConfig(t)
554 cfg.DataDir = greetingTempDir
555 seeder, err := NewClient(TestingConfig(t))
556 require.NoError(t, err)
557 seeder.AddTorrentSpec(&TorrentSpec{
558 InfoBytes: greetingMetainfo.InfoBytes,
562 // Check that when the listen port is 0, all the protocols listened on have
563 // the same port, and it isn't zero.
564 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
565 cl, err := NewClient(TestingConfig(t))
566 require.NoError(t, err)
568 port := cl.LocalPort()
569 assert.NotEqual(t, 0, port)
570 cl.eachListener(func(s Listener) bool {
571 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
576 func TestClientDynamicListenTCPOnly(t *testing.T) {
577 cfg := TestingConfig(t)
578 cfg.DisableUTP = true
579 cfg.DisableTCP = false
580 cl, err := NewClient(cfg)
581 require.NoError(t, err)
583 assert.NotEqual(t, 0, cl.LocalPort())
586 func TestClientDynamicListenUTPOnly(t *testing.T) {
587 cfg := TestingConfig(t)
588 cfg.DisableTCP = true
589 cfg.DisableUTP = false
590 cl, err := NewClient(cfg)
591 require.NoError(t, err)
593 assert.NotEqual(t, 0, cl.LocalPort())
596 func totalConns(tts []*Torrent) (ret int) {
597 for _, tt := range tts {
605 func TestSetMaxEstablishedConn(t *testing.T) {
607 ih := testutil.GreetingMetaInfo().HashInfoBytes()
608 cfg := TestingConfig(t)
609 cfg.DisableAcceptRateLimiting = true
610 cfg.DropDuplicatePeerIds = true
611 for i := 0; i < 3; i += 1 {
612 cl, err := NewClient(cfg)
613 require.NoError(t, err)
615 tt, _ := cl.AddTorrentInfoHash(ih)
616 tt.SetMaxEstablishedConns(2)
617 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
618 tts = append(tts, tt)
621 for _, tt := range tts {
622 for _, _tt := range tts {
624 tt.AddClientPeer(_tt.cl)
629 waitTotalConns := func(num int) {
630 for totalConns(tts) != num {
632 time.Sleep(time.Millisecond)
637 tts[0].SetMaxEstablishedConns(1)
639 tts[0].SetMaxEstablishedConns(0)
641 tts[0].SetMaxEstablishedConns(1)
644 tts[0].SetMaxEstablishedConns(2)
649 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
650 // client, and returns a magnet link.
651 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
652 os.MkdirAll(dir, 0770)
653 file, err := os.Create(filepath.Join(dir, name))
654 require.NoError(t, err)
655 file.Write([]byte(name))
657 mi := metainfo.MetaInfo{}
659 info := metainfo.Info{PieceLength: 256 * 1024}
660 err = info.BuildFromFilePath(filepath.Join(dir, name))
661 require.NoError(t, err)
662 mi.InfoBytes, err = bencode.Marshal(info)
663 require.NoError(t, err)
664 magnet := mi.Magnet(nil, &info).String()
665 tr, err := cl.AddTorrent(&mi)
666 require.NoError(t, err)
667 require.True(t, tr.Seeding())
672 // https://github.com/anacrolix/torrent/issues/114
673 func TestMultipleTorrentsWithEncryption(t *testing.T) {
674 testSeederLeecherPair(
676 func(cfg *ClientConfig) {
677 cfg.HeaderObfuscationPolicy.Preferred = true
678 cfg.HeaderObfuscationPolicy.RequirePreferred = true
680 func(cfg *ClientConfig) {
681 cfg.HeaderObfuscationPolicy.RequirePreferred = false
686 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
687 // seeder config is done first.
688 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
689 cfg := TestingConfig(t)
691 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
692 os.Mkdir(cfg.DataDir, 0755)
694 server, err := NewClient(cfg)
695 require.NoError(t, err)
697 defer testutil.ExportStatusWriter(server, "s", t)()
698 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
699 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
700 // against more than one torrent. See issue #114
701 makeMagnet(t, server, cfg.DataDir, "test2")
702 for i := 0; i < 100; i++ {
703 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
705 cfg = TestingConfig(t)
706 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
708 client, err := NewClient(cfg)
709 require.NoError(t, err)
711 defer testutil.ExportStatusWriter(client, "c", t)()
712 tr, err := client.AddMagnet(magnet1)
713 require.NoError(t, err)
714 tr.AddClientPeer(server)
720 // This appears to be the situation with the S3 BitTorrent client.
721 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
722 // Leecher prefers obfuscation, but the seeder does not allow it.
723 testSeederLeecherPair(
725 func(cfg *ClientConfig) {
726 cfg.HeaderObfuscationPolicy.Preferred = false
727 cfg.HeaderObfuscationPolicy.RequirePreferred = true
729 func(cfg *ClientConfig) {
730 cfg.HeaderObfuscationPolicy.Preferred = true
731 cfg.HeaderObfuscationPolicy.RequirePreferred = false
736 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
737 // Leecher prefers no obfuscation, but the seeder enforces it.
738 testSeederLeecherPair(
740 func(cfg *ClientConfig) {
741 cfg.HeaderObfuscationPolicy.Preferred = true
742 cfg.HeaderObfuscationPolicy.RequirePreferred = true
744 func(cfg *ClientConfig) {
745 cfg.HeaderObfuscationPolicy.Preferred = false
746 cfg.HeaderObfuscationPolicy.RequirePreferred = false
751 func TestClientAddressInUse(t *testing.T) {
752 s, _ := NewUtpSocket("udp", ":50007", nil)
756 cfg := TestingConfig(t).SetListenAddr(":50007")
757 cl, err := NewClient(cfg)
758 require.Error(t, err)
762 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
763 cc := TestingConfig(t)
766 cl, err := NewClient(cc)
767 require.NoError(t, err)
769 assert.NotEmpty(t, cl.DhtServers())
772 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
773 cfg := TestingConfig(t)
774 cfg.DisableTCP = true
775 cfg.DisableUTP = true
777 cl, err := NewClient(cfg)
778 require.NoError(t, err)
780 assert.Empty(t, cl.listeners)
781 assert.NotEmpty(t, cl.DhtServers())