16 "github.com/frankban/quicktest"
17 "github.com/stretchr/testify/assert"
18 "github.com/stretchr/testify/require"
20 "github.com/anacrolix/log"
22 "github.com/anacrolix/dht/v2"
23 "github.com/anacrolix/missinggo/v2"
24 "github.com/anacrolix/missinggo/v2/filecache"
26 "github.com/anacrolix/torrent/bencode"
27 "github.com/anacrolix/torrent/internal/testutil"
28 "github.com/anacrolix/torrent/iplist"
29 "github.com/anacrolix/torrent/metainfo"
30 "github.com/anacrolix/torrent/storage"
33 func TestClientDefault(t *testing.T) {
34 cl, err := NewClient(TestingConfig(t))
35 require.NoError(t, err)
36 require.Empty(t, cl.Close())
39 func TestClientNilConfig(t *testing.T) {
40 // The default config will put crap in the working directory.
41 origDir, _ := os.Getwd()
42 defer os.Chdir(origDir)
44 cl, err := NewClient(nil)
45 require.NoError(t, err)
46 require.Empty(t, cl.Close())
49 func TestAddDropTorrent(t *testing.T) {
50 cl, err := NewClient(TestingConfig(t))
51 require.NoError(t, err)
53 dir, mi := testutil.GreetingTestTorrent()
54 defer os.RemoveAll(dir)
55 tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
56 require.NoError(t, err)
58 tt.SetMaxEstablishedConns(0)
59 tt.SetMaxEstablishedConns(1)
63 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
68 func TestAddTorrentNoUsableURLs(t *testing.T) {
73 func TestAddPeersToUnknownTorrent(t *testing.T) {
78 func TestPieceHashSize(t *testing.T) {
79 assert.Equal(t, 20, pieceHash.Size())
82 func TestTorrentInitialState(t *testing.T) {
83 dir, mi := testutil.GreetingTestTorrent()
84 defer os.RemoveAll(dir)
86 cl.init(TestingConfig(t))
90 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
94 err := tor.setInfoBytesLocked(mi.InfoBytes)
96 require.NoError(t, err)
97 require.Len(t, tor.pieces, 3)
98 tor.pendAllChunkSpecs(0)
100 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
102 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
105 func TestReducedDialTimeout(t *testing.T) {
106 cfg := NewDefaultClientConfig()
107 for _, _case := range []struct {
111 ExpectedReduced time.Duration
113 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
114 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
115 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
116 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
117 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
118 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
120 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
121 expected := _case.ExpectedReduced
122 if expected < cfg.MinDialTimeout {
123 expected = cfg.MinDialTimeout
125 if reduced != expected {
126 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
131 func TestAddDropManyTorrents(t *testing.T) {
132 cl, err := NewClient(TestingConfig(t))
133 require.NoError(t, err)
135 for i := 0; i < 1000; i += 1 {
137 binary.PutVarint(spec.InfoHash[:], int64(i))
138 tt, new, err := cl.AddTorrentSpec(&spec)
139 assert.NoError(t, err)
145 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
146 return storage.NewResourcePiecesOpts(
147 fc.AsResourceProvider(),
148 storage.ResourcePiecesOpts{
149 LeaveIncompleteChunks: true,
154 func TestMergingTrackersByAddingSpecs(t *testing.T) {
155 cl, err := NewClient(TestingConfig(t))
156 require.NoError(t, err)
158 spec := TorrentSpec{}
159 T, new, _ := cl.AddTorrentSpec(&spec)
163 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
164 _, new, _ = cl.AddTorrentSpec(&spec)
166 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
167 // Because trackers are disabled in TestingConfig.
168 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
171 // We read from a piece which is marked completed, but is missing data.
172 func TestCompletedPieceWrongSize(t *testing.T) {
173 cfg := TestingConfig(t)
174 cfg.DefaultStorage = badStorage{}
175 cl, err := NewClient(cfg)
176 require.NoError(t, err)
178 info := metainfo.Info{
180 Pieces: make([]byte, 20),
181 Files: []metainfo.FileInfo{
182 {Path: []string{"greeting"}, Length: 13},
185 b, err := bencode.Marshal(info)
186 require.NoError(t, err)
187 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
189 InfoHash: metainfo.HashBytes(b),
191 require.NoError(t, err)
196 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
199 func BenchmarkAddLargeTorrent(b *testing.B) {
200 cfg := TestingConfig(b)
201 cfg.DisableTCP = true
202 cfg.DisableUTP = true
203 cl, err := NewClient(cfg)
204 require.NoError(b, err)
207 for i := 0; i < b.N; i += 1 {
208 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
216 func TestResponsive(t *testing.T) {
217 seederDataDir, mi := testutil.GreetingTestTorrent()
218 defer os.RemoveAll(seederDataDir)
219 cfg := TestingConfig(t)
221 cfg.DataDir = seederDataDir
222 seeder, err := NewClient(cfg)
225 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
226 seederTorrent.VerifyData()
227 leecherDataDir := t.TempDir()
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 := t.TempDir()
269 cfg = TestingConfig(t)
270 cfg.DataDir = leecherDataDir
271 leecher, err := NewClient(cfg)
273 defer leecher.Close()
274 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
275 ret = TorrentSpecFromMetaInfo(mi)
279 leecherTorrent.AddClientPeer(seeder)
280 reader := leecherTorrent.NewReader()
282 reader.SetReadahead(0)
283 reader.SetResponsive()
285 _, err = reader.Seek(3, io.SeekStart)
286 require.NoError(t, err)
287 _, err = io.ReadFull(reader, b)
289 assert.EqualValues(t, "lo", string(b))
290 _, err = reader.Seek(11, io.SeekStart)
291 require.NoError(t, err)
292 leecherTorrent.Drop()
293 n, err := reader.Read(b)
294 assert.EqualError(t, err, "torrent closed")
295 assert.EqualValues(t, 0, n)
298 func TestDhtInheritBlocklist(t *testing.T) {
299 ipl := iplist.New(nil)
300 require.NotNil(t, ipl)
301 cfg := TestingConfig(t)
302 cfg.IPBlocklist = ipl
304 cl, err := NewClient(cfg)
305 require.NoError(t, err)
308 cl.eachDhtServer(func(s DhtServer) {
310 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
313 assert.EqualValues(t, 2, numServers)
316 // Check that stuff is merged in subsequent AddTorrentSpec for the same
318 func TestAddTorrentSpecMerging(t *testing.T) {
319 cl, err := NewClient(TestingConfig(t))
320 require.NoError(t, err)
322 dir, mi := testutil.GreetingTestTorrent()
323 defer os.RemoveAll(dir)
324 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
325 InfoHash: mi.HashInfoBytes(),
327 require.NoError(t, err)
329 require.Nil(t, tt.Info())
330 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
331 require.NoError(t, err)
332 require.False(t, new)
333 require.NotNil(t, tt.Info())
336 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
337 dir, mi := testutil.GreetingTestTorrent()
339 cl, _ := NewClient(TestingConfig(t))
341 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
342 InfoHash: mi.HashInfoBytes(),
345 assert.EqualValues(t, 0, len(cl.Torrents()))
353 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
354 for i := 0; i < info.NumPieces(); i += 1 {
356 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
360 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
361 fileCacheDir := t.TempDir()
362 fileCache, err := filecache.NewCache(fileCacheDir)
363 require.NoError(t, err)
364 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
365 defer os.RemoveAll(greetingDataTempDir)
366 filePieceStore := csf(fileCache)
367 info, err := greetingMetainfo.UnmarshalInfo()
368 require.NoError(t, err)
369 ih := greetingMetainfo.HashInfoBytes()
370 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
371 require.NoError(t, err)
372 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
373 // require.Equal(t, len(testutil.GreetingFileContents), written)
374 // require.NoError(t, err)
375 for i := 0; i < info.NumPieces(); i++ {
377 if alreadyCompleted {
378 require.NoError(t, greetingData.Piece(p).MarkComplete())
381 cfg := TestingConfig(t)
382 // TODO: Disable network option?
383 cfg.DisableTCP = true
384 cfg.DisableUTP = true
385 cfg.DefaultStorage = filePieceStore
386 cl, err := NewClient(cfg)
387 require.NoError(t, err)
389 tt, err := cl.AddTorrent(greetingMetainfo)
390 require.NoError(t, err)
391 psrs := tt.PieceStateRuns()
392 assert.Len(t, psrs, 1)
393 assert.EqualValues(t, 3, psrs[0].Length)
394 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
395 if alreadyCompleted {
397 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
401 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
402 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
405 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
406 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
409 func TestAddMetainfoWithNodes(t *testing.T) {
410 cfg := TestingConfig(t)
411 cfg.ListenHost = func(string) string { return "" }
413 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
414 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
415 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
416 // cfg.DHTConfig.NoSecurity = true
417 cl, err := NewClient(cfg)
418 require.NoError(t, err)
420 sum := func() (ret int64) {
421 cl.eachDhtServer(func(s DhtServer) {
422 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
426 assert.EqualValues(t, 0, sum())
427 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
428 require.NoError(t, err)
429 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
430 // check if the announce-list is here instead. TODO: Add nodes.
431 assert.Len(t, tt.metainfo.AnnounceList, 5)
432 // There are 6 nodes in the torrent file.
433 for sum() != int64(6*len(cl.dhtServers)) {
434 time.Sleep(time.Millisecond)
438 type testDownloadCancelParams struct {
439 SetLeecherStorageCapacity bool
440 LeecherStorageCapacity int64
444 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
445 greetingTempDir, mi := testutil.GreetingTestTorrent()
446 defer os.RemoveAll(greetingTempDir)
447 cfg := TestingConfig(t)
449 cfg.DataDir = greetingTempDir
450 seeder, err := NewClient(cfg)
451 require.NoError(t, err)
453 defer testutil.ExportStatusWriter(seeder, "s", t)()
454 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
455 seederTorrent.VerifyData()
456 leecherDataDir := t.TempDir()
457 fc, err := filecache.NewCache(leecherDataDir)
458 require.NoError(t, err)
459 if ps.SetLeecherStorageCapacity {
460 fc.SetCapacity(ps.LeecherStorageCapacity)
462 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
463 cfg.DataDir = leecherDataDir
464 leecher, err := NewClient(cfg)
465 require.NoError(t, err)
466 defer leecher.Close()
467 defer testutil.ExportStatusWriter(leecher, "l", t)()
468 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
469 ret = TorrentSpecFromMetaInfo(mi)
473 require.NoError(t, err)
475 psc := leecherGreeting.SubscribePieceStateChanges()
478 leecherGreeting.cl.lock()
479 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
481 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces(), "")
483 leecherGreeting.cl.unlock()
484 done := make(chan struct{})
486 go leecherGreeting.AddClientPeer(seeder)
487 completes := make(map[int]bool, 3)
488 expected := func() map[int]bool {
490 return map[int]bool{0: false, 1: false, 2: false}
492 return map[int]bool{0: true, 1: true, 2: true}
495 for !reflect.DeepEqual(completes, expected) {
497 completes[v.Index] = v.Complete
501 func TestTorrentDownloadAll(t *testing.T) {
502 testDownloadCancel(t, testDownloadCancelParams{})
505 func TestTorrentDownloadAllThenCancel(t *testing.T) {
506 testDownloadCancel(t, testDownloadCancelParams{
511 // Ensure that it's an error for a peer to send an invalid have message.
512 func TestPeerInvalidHave(t *testing.T) {
513 cfg := TestingConfig(t)
514 cfg.DropMutuallyCompletePeers = false
515 cl, err := NewClient(cfg)
516 require.NoError(t, err)
518 info := metainfo.Info{
520 Pieces: make([]byte, 20),
521 Files: []metainfo.FileInfo{{Length: 1}},
523 infoBytes, err := bencode.Marshal(info)
524 require.NoError(t, err)
525 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
526 InfoBytes: infoBytes,
527 InfoHash: metainfo.HashBytes(infoBytes),
528 Storage: badStorage{},
530 require.NoError(t, err)
533 cn := &PeerConn{Peer: Peer{
535 callbacks: &cfg.Callbacks,
537 tt.conns[cn] = struct{}{}
541 assert.NoError(t, cn.peerSentHave(0))
542 assert.Error(t, cn.peerSentHave(1))
545 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
546 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
547 defer os.RemoveAll(greetingTempDir)
548 cfg := TestingConfig(t)
549 cfg.DataDir = greetingTempDir
550 seeder, err := NewClient(TestingConfig(t))
551 require.NoError(t, err)
552 seeder.AddTorrentSpec(&TorrentSpec{
553 InfoBytes: greetingMetainfo.InfoBytes,
557 // Check that when the listen port is 0, all the protocols listened on have
558 // the same port, and it isn't zero.
559 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
560 cl, err := NewClient(TestingConfig(t))
561 require.NoError(t, err)
563 port := cl.LocalPort()
564 assert.NotEqual(t, 0, port)
565 cl.eachListener(func(s Listener) bool {
566 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
571 func TestClientDynamicListenTCPOnly(t *testing.T) {
572 cfg := TestingConfig(t)
573 cfg.DisableUTP = true
574 cfg.DisableTCP = false
575 cl, err := NewClient(cfg)
576 require.NoError(t, err)
578 assert.NotEqual(t, 0, cl.LocalPort())
581 func TestClientDynamicListenUTPOnly(t *testing.T) {
582 cfg := TestingConfig(t)
583 cfg.DisableTCP = true
584 cfg.DisableUTP = false
585 cl, err := NewClient(cfg)
586 require.NoError(t, err)
588 assert.NotEqual(t, 0, cl.LocalPort())
591 func totalConns(tts []*Torrent) (ret int) {
592 for _, tt := range tts {
600 func TestSetMaxEstablishedConn(t *testing.T) {
602 ih := testutil.GreetingMetaInfo().HashInfoBytes()
603 cfg := TestingConfig(t)
604 cfg.DisableAcceptRateLimiting = true
605 cfg.DropDuplicatePeerIds = true
606 for i := 0; i < 3; i += 1 {
607 cl, err := NewClient(cfg)
608 require.NoError(t, err)
610 tt, _ := cl.AddTorrentInfoHash(ih)
611 tt.SetMaxEstablishedConns(2)
612 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
613 tts = append(tts, tt)
616 for _, tt := range tts {
617 for _, _tt := range tts {
619 tt.AddClientPeer(_tt.cl)
624 waitTotalConns := func(num int) {
625 for totalConns(tts) != num {
627 time.Sleep(time.Millisecond)
632 tts[0].SetMaxEstablishedConns(1)
634 tts[0].SetMaxEstablishedConns(0)
636 tts[0].SetMaxEstablishedConns(1)
639 tts[0].SetMaxEstablishedConns(2)
644 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
645 // client, and returns a magnet link.
646 func makeMagnet(t *testing.T, cl *Client, dir, name string) string {
647 os.MkdirAll(dir, 0o770)
648 file, err := os.Create(filepath.Join(dir, name))
649 require.NoError(t, err)
650 file.Write([]byte(name))
652 mi := metainfo.MetaInfo{}
654 info := metainfo.Info{PieceLength: 256 * 1024}
655 err = info.BuildFromFilePath(filepath.Join(dir, name))
656 require.NoError(t, err)
657 mi.InfoBytes, err = bencode.Marshal(info)
658 require.NoError(t, err)
659 magnet := mi.Magnet(nil, &info).String()
660 tr, err := cl.AddTorrent(&mi)
661 require.NoError(t, err)
662 require.True(t, tr.Seeding())
667 // https://github.com/anacrolix/torrent/issues/114
668 func TestMultipleTorrentsWithEncryption(t *testing.T) {
669 testSeederLeecherPair(
671 func(cfg *ClientConfig) {
672 cfg.HeaderObfuscationPolicy.Preferred = true
673 cfg.HeaderObfuscationPolicy.RequirePreferred = true
675 func(cfg *ClientConfig) {
676 cfg.HeaderObfuscationPolicy.RequirePreferred = false
681 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
682 // seeder config is done first.
683 func testSeederLeecherPair(t *testing.T, seeder, leecher func(*ClientConfig)) {
684 cfg := TestingConfig(t)
686 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
687 os.Mkdir(cfg.DataDir, 0o755)
689 server, err := NewClient(cfg)
690 require.NoError(t, err)
692 defer testutil.ExportStatusWriter(server, "s", t)()
693 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
694 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
695 // against more than one torrent. See issue #114
696 makeMagnet(t, server, cfg.DataDir, "test2")
697 for i := 0; i < 100; i++ {
698 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
700 cfg = TestingConfig(t)
701 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
703 client, err := NewClient(cfg)
704 require.NoError(t, err)
706 defer testutil.ExportStatusWriter(client, "c", t)()
707 tr, err := client.AddMagnet(magnet1)
708 require.NoError(t, err)
709 tr.AddClientPeer(server)
715 // This appears to be the situation with the S3 BitTorrent client.
716 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
717 // Leecher prefers obfuscation, but the seeder does not allow it.
718 testSeederLeecherPair(
720 func(cfg *ClientConfig) {
721 cfg.HeaderObfuscationPolicy.Preferred = false
722 cfg.HeaderObfuscationPolicy.RequirePreferred = true
724 func(cfg *ClientConfig) {
725 cfg.HeaderObfuscationPolicy.Preferred = true
726 cfg.HeaderObfuscationPolicy.RequirePreferred = false
731 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
732 // Leecher prefers no obfuscation, but the seeder enforces it.
733 testSeederLeecherPair(
735 func(cfg *ClientConfig) {
736 cfg.HeaderObfuscationPolicy.Preferred = true
737 cfg.HeaderObfuscationPolicy.RequirePreferred = true
739 func(cfg *ClientConfig) {
740 cfg.HeaderObfuscationPolicy.Preferred = false
741 cfg.HeaderObfuscationPolicy.RequirePreferred = false
746 func TestClientAddressInUse(t *testing.T) {
747 s, _ := NewUtpSocket("udp", ":50007", nil, log.Default)
751 cfg := TestingConfig(t).SetListenAddr(":50007")
752 cl, err := NewClient(cfg)
753 require.Error(t, err)
757 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
758 cc := TestingConfig(t)
761 cl, err := NewClient(cc)
762 require.NoError(t, err)
764 assert.NotEmpty(t, cl.DhtServers())
767 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
768 cfg := TestingConfig(t)
769 cfg.DisableTCP = true
770 cfg.DisableUTP = true
772 cl, err := NewClient(cfg)
773 require.NoError(t, err)
775 assert.Empty(t, cl.listeners)
776 assert.NotEmpty(t, cl.DhtServers())
779 func TestBadPeerIpPort(t *testing.T) {
780 for _, tc := range []struct {
787 {"empty both", nil, 0, true, func(*Client) {}},
788 {"empty/nil ip", nil, 6666, true, func(*Client) {}},
791 net.ParseIP("127.0.0.1/32"),
796 "in doppleganger addresses",
797 net.ParseIP("127.0.0.1/32"),
801 cl.dopplegangerAddrs["10.0.0.1:2322"] = struct{}{}
806 net.ParseIP("10.0.0.1"),
810 cl.ipBlockList = iplist.New([]iplist.Range{
811 iplist.Range{First: net.ParseIP("10.0.0.1"), Last: net.ParseIP("10.0.0.255")},
817 net.ParseIP("10.0.0.1"),
821 ipAddr, ok := netip.AddrFromSlice(net.ParseIP("10.0.0.1"))
823 cl.badPeerIPs = map[netip.Addr]struct{}{}
824 cl.badPeerIPs[ipAddr] = struct{}{}
829 net.ParseIP("10.0.0.1"),
835 t.Run(tc.title, func(t *testing.T) {
836 cfg := TestingConfig(t)
837 cfg.DisableTCP = true
838 cfg.DisableUTP = true
840 cl, err := NewClient(cfg)
841 require.NoError(t, err)
845 require.Equal(t, tc.expectedOk, cl.badPeerIPPort(tc.ip, tc.port))