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)
33 require.Empty(t, cl.Close())
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)
43 require.Empty(t, cl.Close())
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 cl.init(TestingConfig(t))
87 storage.NewFileWithCompletion(t.TempDir(), storage.NewMapPieceCompletion()),
91 err := tor.setInfoBytesLocked(mi.InfoBytes)
93 require.NoError(t, err)
94 require.Len(t, tor.pieces, 3)
95 tor.pendAllChunkSpecs(0)
97 assert.EqualValues(t, 3, tor.pieceNumPendingChunks(0))
99 assert.EqualValues(t, ChunkSpec{4, 1}, chunkIndexSpec(2, tor.pieceLength(0), tor.chunkSize))
102 func TestReducedDialTimeout(t *testing.T) {
103 cfg := NewDefaultClientConfig()
104 for _, _case := range []struct {
108 ExpectedReduced time.Duration
110 {cfg.NominalDialTimeout, 40, 0, cfg.NominalDialTimeout},
111 {cfg.NominalDialTimeout, 40, 1, cfg.NominalDialTimeout},
112 {cfg.NominalDialTimeout, 40, 39, cfg.NominalDialTimeout},
113 {cfg.NominalDialTimeout, 40, 40, cfg.NominalDialTimeout / 2},
114 {cfg.NominalDialTimeout, 40, 80, cfg.NominalDialTimeout / 3},
115 {cfg.NominalDialTimeout, 40, 4000, cfg.NominalDialTimeout / 101},
117 reduced := reducedDialTimeout(cfg.MinDialTimeout, _case.Max, _case.HalfOpenLimit, _case.PendingPeers)
118 expected := _case.ExpectedReduced
119 if expected < cfg.MinDialTimeout {
120 expected = cfg.MinDialTimeout
122 if reduced != expected {
123 t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
128 func TestAddDropManyTorrents(t *testing.T) {
129 cl, err := NewClient(TestingConfig(t))
130 require.NoError(t, err)
132 for i := 0; i < 1000; i += 1 {
134 binary.PutVarint(spec.InfoHash[:], int64(i))
135 tt, new, err := cl.AddTorrentSpec(&spec)
136 assert.NoError(t, err)
142 func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl {
143 return storage.NewResourcePiecesOpts(
144 fc.AsResourceProvider(),
145 storage.ResourcePiecesOpts{
146 LeaveIncompleteChunks: true,
151 func TestMergingTrackersByAddingSpecs(t *testing.T) {
152 cl, err := NewClient(TestingConfig(t))
153 require.NoError(t, err)
155 spec := TorrentSpec{}
156 T, new, _ := cl.AddTorrentSpec(&spec)
160 spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
161 _, new, _ = cl.AddTorrentSpec(&spec)
163 assert.EqualValues(t, [][]string{{"http://a"}, {"udp://b"}}, T.metainfo.AnnounceList)
164 // Because trackers are disabled in TestingConfig.
165 assert.EqualValues(t, 0, len(T.trackerAnnouncers))
168 // We read from a piece which is marked completed, but is missing data.
169 func TestCompletedPieceWrongSize(t *testing.T) {
170 cfg := TestingConfig(t)
171 cfg.DefaultStorage = badStorage{}
172 cl, err := NewClient(cfg)
173 require.NoError(t, err)
175 info := metainfo.Info{
177 Pieces: make([]byte, 20),
178 Files: []metainfo.FileInfo{
179 {Path: []string{"greeting"}, Length: 13},
182 b, err := bencode.Marshal(info)
183 require.NoError(t, err)
184 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
186 InfoHash: metainfo.HashBytes(b),
188 require.NoError(t, err)
193 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
196 func BenchmarkAddLargeTorrent(b *testing.B) {
197 cfg := TestingConfig(b)
198 cfg.DisableTCP = true
199 cfg.DisableUTP = true
200 cl, err := NewClient(cfg)
201 require.NoError(b, err)
204 for i := 0; i < b.N; i += 1 {
205 t, err := cl.AddTorrentFromFile("testdata/bootstrap.dat.torrent")
213 func TestResponsive(t *testing.T) {
214 seederDataDir, mi := testutil.GreetingTestTorrent()
215 defer os.RemoveAll(seederDataDir)
216 cfg := TestingConfig(t)
218 cfg.DataDir = seederDataDir
219 seeder, err := NewClient(cfg)
222 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
223 seederTorrent.VerifyData()
224 leecherDataDir, err := ioutil.TempDir("", "")
226 defer os.RemoveAll(leecherDataDir)
227 cfg = TestingConfig(t)
228 cfg.DataDir = leecherDataDir
229 leecher, err := NewClient(cfg)
231 defer leecher.Close()
232 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
233 ret = TorrentSpecFromMetaInfo(mi)
237 leecherTorrent.AddClientPeer(seeder)
238 reader := leecherTorrent.NewReader()
240 reader.SetReadahead(0)
241 reader.SetResponsive()
243 _, err = reader.Seek(3, io.SeekStart)
244 require.NoError(t, err)
245 _, err = io.ReadFull(reader, b)
247 assert.EqualValues(t, "lo", string(b))
248 _, err = reader.Seek(11, io.SeekStart)
249 require.NoError(t, err)
250 n, err := io.ReadFull(reader, b)
252 assert.EqualValues(t, 2, n)
253 assert.EqualValues(t, "d\n", string(b))
256 func TestTorrentDroppedDuringResponsiveRead(t *testing.T) {
257 seederDataDir, mi := testutil.GreetingTestTorrent()
258 defer os.RemoveAll(seederDataDir)
259 cfg := TestingConfig(t)
261 cfg.DataDir = seederDataDir
262 seeder, err := NewClient(cfg)
265 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
266 seederTorrent.VerifyData()
267 leecherDataDir, err := ioutil.TempDir("", "")
269 defer os.RemoveAll(leecherDataDir)
270 cfg = TestingConfig(t)
271 cfg.DataDir = leecherDataDir
272 leecher, err := NewClient(cfg)
274 defer leecher.Close()
275 leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
276 ret = TorrentSpecFromMetaInfo(mi)
280 leecherTorrent.AddClientPeer(seeder)
281 reader := leecherTorrent.NewReader()
283 reader.SetReadahead(0)
284 reader.SetResponsive()
286 _, err = reader.Seek(3, io.SeekStart)
287 require.NoError(t, err)
288 _, err = io.ReadFull(reader, b)
290 assert.EqualValues(t, "lo", string(b))
291 go leecherTorrent.Drop()
292 _, err = reader.Seek(11, io.SeekStart)
293 require.NoError(t, err)
294 n, err := reader.Read(b)
295 assert.EqualError(t, err, "torrent closed")
296 assert.EqualValues(t, 0, n)
299 func TestDhtInheritBlocklist(t *testing.T) {
300 ipl := iplist.New(nil)
301 require.NotNil(t, ipl)
302 cfg := TestingConfig(t)
303 cfg.IPBlocklist = ipl
305 cl, err := NewClient(cfg)
306 require.NoError(t, err)
309 cl.eachDhtServer(func(s DhtServer) {
311 assert.Equal(t, ipl, s.(AnacrolixDhtServerWrapper).Server.IPBlocklist())
314 assert.EqualValues(t, 2, numServers)
317 // Check that stuff is merged in subsequent AddTorrentSpec for the same
319 func TestAddTorrentSpecMerging(t *testing.T) {
320 cl, err := NewClient(TestingConfig(t))
321 require.NoError(t, err)
323 dir, mi := testutil.GreetingTestTorrent()
324 defer os.RemoveAll(dir)
325 tt, new, err := cl.AddTorrentSpec(&TorrentSpec{
326 InfoHash: mi.HashInfoBytes(),
328 require.NoError(t, err)
330 require.Nil(t, tt.Info())
331 _, new, err = cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
332 require.NoError(t, err)
333 require.False(t, new)
334 require.NotNil(t, tt.Info())
337 func TestTorrentDroppedBeforeGotInfo(t *testing.T) {
338 dir, mi := testutil.GreetingTestTorrent()
340 cl, _ := NewClient(TestingConfig(t))
342 tt, _, _ := cl.AddTorrentSpec(&TorrentSpec{
343 InfoHash: mi.HashInfoBytes(),
346 assert.EqualValues(t, 0, len(cl.Torrents()))
354 func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) {
355 for i := 0; i < info.NumPieces(); i += 1 {
357 ts.Piece(p).WriteAt(b[p.Offset():p.Offset()+p.Length()], 0)
361 func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) {
362 fileCacheDir, err := ioutil.TempDir("", "")
363 require.NoError(t, err)
364 defer os.RemoveAll(fileCacheDir)
365 fileCache, err := filecache.NewCache(fileCacheDir)
366 require.NoError(t, err)
367 greetingDataTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
368 defer os.RemoveAll(greetingDataTempDir)
369 filePieceStore := csf(fileCache)
370 info, err := greetingMetainfo.UnmarshalInfo()
371 require.NoError(t, err)
372 ih := greetingMetainfo.HashInfoBytes()
373 greetingData, err := storage.NewClient(filePieceStore).OpenTorrent(&info, ih)
374 require.NoError(t, err)
375 writeTorrentData(greetingData, info, []byte(testutil.GreetingFileContents))
376 // require.Equal(t, len(testutil.GreetingFileContents), written)
377 // require.NoError(t, err)
378 for i := 0; i < info.NumPieces(); i++ {
380 if alreadyCompleted {
381 require.NoError(t, greetingData.Piece(p).MarkComplete())
384 cfg := TestingConfig(t)
385 // TODO: Disable network option?
386 cfg.DisableTCP = true
387 cfg.DisableUTP = true
388 cfg.DefaultStorage = filePieceStore
389 cl, err := NewClient(cfg)
390 require.NoError(t, err)
392 tt, err := cl.AddTorrent(greetingMetainfo)
393 require.NoError(t, err)
394 psrs := tt.PieceStateRuns()
395 assert.Len(t, psrs, 1)
396 assert.EqualValues(t, 3, psrs[0].Length)
397 assert.Equal(t, alreadyCompleted, psrs[0].Complete)
398 if alreadyCompleted {
400 quicktest.Check(t, iotest.TestReader(r, []byte(testutil.GreetingFileContents)), quicktest.IsNil)
404 func TestAddTorrentPiecesAlreadyCompleted(t *testing.T) {
405 testAddTorrentPriorPieceCompletion(t, true, fileCachePieceResourceStorage)
408 func TestAddTorrentPiecesNotAlreadyCompleted(t *testing.T) {
409 testAddTorrentPriorPieceCompletion(t, false, fileCachePieceResourceStorage)
412 func TestAddMetainfoWithNodes(t *testing.T) {
413 cfg := TestingConfig(t)
414 cfg.ListenHost = func(string) string { return "" }
416 cfg.DhtStartingNodes = func(string) dht.StartingNodesGetter { return func() ([]dht.Addr, error) { return nil, nil } }
417 // For now, we want to just jam the nodes into the table, without verifying them first. Also the
418 // DHT code doesn't support mixing secure and insecure nodes if security is enabled (yet).
419 // cfg.DHTConfig.NoSecurity = true
420 cl, err := NewClient(cfg)
421 require.NoError(t, err)
423 sum := func() (ret int64) {
424 cl.eachDhtServer(func(s DhtServer) {
425 ret += s.Stats().(dht.ServerStats).OutboundQueriesAttempted
429 assert.EqualValues(t, 0, sum())
430 tt, err := cl.AddTorrentFromFile("metainfo/testdata/issue_65a.torrent")
431 require.NoError(t, err)
432 // Nodes are not added or exposed in Torrent's metainfo. We just randomly
433 // check if the announce-list is here instead. TODO: Add nodes.
434 assert.Len(t, tt.metainfo.AnnounceList, 5)
435 // There are 6 nodes in the torrent file.
436 for sum() != int64(6*len(cl.dhtServers)) {
437 time.Sleep(time.Millisecond)
441 type testDownloadCancelParams struct {
442 SetLeecherStorageCapacity bool
443 LeecherStorageCapacity int64
447 func testDownloadCancel(t *testing.T, ps testDownloadCancelParams) {
448 greetingTempDir, mi := testutil.GreetingTestTorrent()
449 defer os.RemoveAll(greetingTempDir)
450 cfg := TestingConfig(t)
452 cfg.DataDir = greetingTempDir
453 seeder, err := NewClient(cfg)
454 require.NoError(t, err)
456 defer testutil.ExportStatusWriter(seeder, "s", t)()
457 seederTorrent, _, _ := seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
458 seederTorrent.VerifyData()
459 leecherDataDir, err := ioutil.TempDir("", "")
460 require.NoError(t, err)
461 defer os.RemoveAll(leecherDataDir)
462 fc, err := filecache.NewCache(leecherDataDir)
463 require.NoError(t, err)
464 if ps.SetLeecherStorageCapacity {
465 fc.SetCapacity(ps.LeecherStorageCapacity)
467 cfg.DefaultStorage = storage.NewResourcePieces(fc.AsResourceProvider())
468 cfg.DataDir = leecherDataDir
469 leecher, err := NewClient(cfg)
470 require.NoError(t, err)
471 defer leecher.Close()
472 defer testutil.ExportStatusWriter(leecher, "l", t)()
473 leecherGreeting, new, err := leecher.AddTorrentSpec(func() (ret *TorrentSpec) {
474 ret = TorrentSpecFromMetaInfo(mi)
478 require.NoError(t, err)
480 psc := leecherGreeting.SubscribePieceStateChanges()
483 leecherGreeting.cl.lock()
484 leecherGreeting.downloadPiecesLocked(0, leecherGreeting.numPieces())
486 leecherGreeting.cancelPiecesLocked(0, leecherGreeting.NumPieces(), "")
488 leecherGreeting.cl.unlock()
489 done := make(chan struct{})
491 go leecherGreeting.AddClientPeer(seeder)
492 completes := make(map[int]bool, 3)
493 expected := func() map[int]bool {
495 return map[int]bool{0: false, 1: false, 2: false}
497 return map[int]bool{0: true, 1: true, 2: true}
500 for !reflect.DeepEqual(completes, expected) {
502 v := _v.(PieceStateChange)
503 completes[v.Index] = v.Complete
507 func TestTorrentDownloadAll(t *testing.T) {
508 testDownloadCancel(t, testDownloadCancelParams{})
511 func TestTorrentDownloadAllThenCancel(t *testing.T) {
512 testDownloadCancel(t, testDownloadCancelParams{
517 // Ensure that it's an error for a peer to send an invalid have message.
518 func TestPeerInvalidHave(t *testing.T) {
519 cfg := TestingConfig(t)
520 cfg.DropMutuallyCompletePeers = false
521 cl, err := NewClient(cfg)
522 require.NoError(t, err)
524 info := metainfo.Info{
526 Pieces: make([]byte, 20),
527 Files: []metainfo.FileInfo{{Length: 1}},
529 infoBytes, err := bencode.Marshal(info)
530 require.NoError(t, err)
531 tt, _new, err := cl.AddTorrentSpec(&TorrentSpec{
532 InfoBytes: infoBytes,
533 InfoHash: metainfo.HashBytes(infoBytes),
534 Storage: badStorage{},
536 require.NoError(t, err)
539 cn := &PeerConn{Peer: Peer{
545 assert.NoError(t, cn.peerSentHave(0))
546 assert.Error(t, cn.peerSentHave(1))
549 func TestPieceCompletedInStorageButNotClient(t *testing.T) {
550 greetingTempDir, greetingMetainfo := testutil.GreetingTestTorrent()
551 defer os.RemoveAll(greetingTempDir)
552 cfg := TestingConfig(t)
553 cfg.DataDir = greetingTempDir
554 seeder, err := NewClient(TestingConfig(t))
555 require.NoError(t, err)
556 seeder.AddTorrentSpec(&TorrentSpec{
557 InfoBytes: greetingMetainfo.InfoBytes,
561 // Check that when the listen port is 0, all the protocols listened on have
562 // the same port, and it isn't zero.
563 func TestClientDynamicListenPortAllProtocols(t *testing.T) {
564 cl, err := NewClient(TestingConfig(t))
565 require.NoError(t, err)
567 port := cl.LocalPort()
568 assert.NotEqual(t, 0, port)
569 cl.eachListener(func(s Listener) bool {
570 assert.Equal(t, port, missinggo.AddrPort(s.Addr()))
575 func TestClientDynamicListenTCPOnly(t *testing.T) {
576 cfg := TestingConfig(t)
577 cfg.DisableUTP = true
578 cfg.DisableTCP = false
579 cl, err := NewClient(cfg)
580 require.NoError(t, err)
582 assert.NotEqual(t, 0, cl.LocalPort())
585 func TestClientDynamicListenUTPOnly(t *testing.T) {
586 cfg := TestingConfig(t)
587 cfg.DisableTCP = true
588 cfg.DisableUTP = false
589 cl, err := NewClient(cfg)
590 require.NoError(t, err)
592 assert.NotEqual(t, 0, cl.LocalPort())
595 func totalConns(tts []*Torrent) (ret int) {
596 for _, tt := range tts {
604 func TestSetMaxEstablishedConn(t *testing.T) {
606 ih := testutil.GreetingMetaInfo().HashInfoBytes()
607 cfg := TestingConfig(t)
608 cfg.DisableAcceptRateLimiting = true
609 cfg.DropDuplicatePeerIds = true
610 for i := 0; i < 3; i += 1 {
611 cl, err := NewClient(cfg)
612 require.NoError(t, err)
614 tt, _ := cl.AddTorrentInfoHash(ih)
615 tt.SetMaxEstablishedConns(2)
616 defer testutil.ExportStatusWriter(cl, fmt.Sprintf("%d", i), t)()
617 tts = append(tts, tt)
620 for _, tt := range tts {
621 for _, _tt := range tts {
623 tt.AddClientPeer(_tt.cl)
628 waitTotalConns := func(num int) {
629 for totalConns(tts) != num {
631 time.Sleep(time.Millisecond)
636 tts[0].SetMaxEstablishedConns(1)
638 tts[0].SetMaxEstablishedConns(0)
640 tts[0].SetMaxEstablishedConns(1)
643 tts[0].SetMaxEstablishedConns(2)
648 // Creates a file containing its own name as data. Make a metainfo from that, adds it to the given
649 // client, and returns a magnet link.
650 func makeMagnet(t *testing.T, cl *Client, dir string, name string) string {
651 os.MkdirAll(dir, 0o770)
652 file, err := os.Create(filepath.Join(dir, name))
653 require.NoError(t, err)
654 file.Write([]byte(name))
656 mi := metainfo.MetaInfo{}
658 info := metainfo.Info{PieceLength: 256 * 1024}
659 err = info.BuildFromFilePath(filepath.Join(dir, name))
660 require.NoError(t, err)
661 mi.InfoBytes, err = bencode.Marshal(info)
662 require.NoError(t, err)
663 magnet := mi.Magnet(nil, &info).String()
664 tr, err := cl.AddTorrent(&mi)
665 require.NoError(t, err)
666 require.True(t, tr.Seeding())
671 // https://github.com/anacrolix/torrent/issues/114
672 func TestMultipleTorrentsWithEncryption(t *testing.T) {
673 testSeederLeecherPair(
675 func(cfg *ClientConfig) {
676 cfg.HeaderObfuscationPolicy.Preferred = true
677 cfg.HeaderObfuscationPolicy.RequirePreferred = true
679 func(cfg *ClientConfig) {
680 cfg.HeaderObfuscationPolicy.RequirePreferred = false
685 // Test that the leecher can download a torrent in its entirety from the seeder. Note that the
686 // seeder config is done first.
687 func testSeederLeecherPair(t *testing.T, seeder func(*ClientConfig), leecher func(*ClientConfig)) {
688 cfg := TestingConfig(t)
690 cfg.DataDir = filepath.Join(cfg.DataDir, "server")
691 os.Mkdir(cfg.DataDir, 0o755)
693 server, err := NewClient(cfg)
694 require.NoError(t, err)
696 defer testutil.ExportStatusWriter(server, "s", t)()
697 magnet1 := makeMagnet(t, server, cfg.DataDir, "test1")
698 // Extra torrents are added to test the seeder having to match incoming obfuscated headers
699 // against more than one torrent. See issue #114
700 makeMagnet(t, server, cfg.DataDir, "test2")
701 for i := 0; i < 100; i++ {
702 makeMagnet(t, server, cfg.DataDir, fmt.Sprintf("test%d", i+2))
704 cfg = TestingConfig(t)
705 cfg.DataDir = filepath.Join(cfg.DataDir, "client")
707 client, err := NewClient(cfg)
708 require.NoError(t, err)
710 defer testutil.ExportStatusWriter(client, "c", t)()
711 tr, err := client.AddMagnet(magnet1)
712 require.NoError(t, err)
713 tr.AddClientPeer(server)
719 // This appears to be the situation with the S3 BitTorrent client.
720 func TestObfuscatedHeaderFallbackSeederDisallowsLeecherPrefers(t *testing.T) {
721 // Leecher prefers obfuscation, but the seeder does not allow it.
722 testSeederLeecherPair(
724 func(cfg *ClientConfig) {
725 cfg.HeaderObfuscationPolicy.Preferred = false
726 cfg.HeaderObfuscationPolicy.RequirePreferred = true
728 func(cfg *ClientConfig) {
729 cfg.HeaderObfuscationPolicy.Preferred = true
730 cfg.HeaderObfuscationPolicy.RequirePreferred = false
735 func TestObfuscatedHeaderFallbackSeederRequiresLeecherPrefersNot(t *testing.T) {
736 // Leecher prefers no obfuscation, but the seeder enforces it.
737 testSeederLeecherPair(
739 func(cfg *ClientConfig) {
740 cfg.HeaderObfuscationPolicy.Preferred = true
741 cfg.HeaderObfuscationPolicy.RequirePreferred = true
743 func(cfg *ClientConfig) {
744 cfg.HeaderObfuscationPolicy.Preferred = false
745 cfg.HeaderObfuscationPolicy.RequirePreferred = false
750 func TestClientAddressInUse(t *testing.T) {
751 s, _ := NewUtpSocket("udp", ":50007", nil)
755 cfg := TestingConfig(t).SetListenAddr(":50007")
756 cl, err := NewClient(cfg)
757 require.Error(t, err)
761 func TestClientHasDhtServersWhenUtpDisabled(t *testing.T) {
762 cc := TestingConfig(t)
765 cl, err := NewClient(cc)
766 require.NoError(t, err)
768 assert.NotEmpty(t, cl.DhtServers())
771 func TestClientDisabledImplicitNetworksButDhtEnabled(t *testing.T) {
772 cfg := TestingConfig(t)
773 cfg.DisableTCP = true
774 cfg.DisableUTP = true
776 cl, err := NewClient(cfg)
777 require.NoError(t, err)
779 assert.Empty(t, cl.listeners)
780 assert.NotEmpty(t, cl.DhtServers())