]> Sergey Matveev's repositories - btrtrc.git/blob - client_test.go
Apply sortimports
[btrtrc.git] / client_test.go
1 package torrent
2
3 import (
4         "encoding/binary"
5         "fmt"
6         "io/ioutil"
7         "log"
8         "net"
9         "os"
10         "testing"
11         "time"
12
13         "github.com/anacrolix/utp"
14         "github.com/bradfitz/iter"
15         "gopkg.in/check.v1"
16
17         "github.com/anacrolix/torrent/bencode"
18         "github.com/anacrolix/torrent/data/blob"
19         "github.com/anacrolix/torrent/internal/testutil"
20         "github.com/anacrolix/torrent/util"
21 )
22
23 func init() {
24         log.SetFlags(log.LstdFlags | log.Lshortfile)
25 }
26
27 var TestingConfig = Config{
28         ListenAddr:           "localhost:0",
29         NoDHT:                true,
30         DisableTrackers:      true,
31         NoDefaultBlocklist:   true,
32         DisableMetainfoCache: true,
33 }
34
35 func TestClientDefault(t *testing.T) {
36         cl, err := NewClient(&TestingConfig)
37         if err != nil {
38                 t.Fatal(err)
39         }
40         cl.Close()
41 }
42
43 func TestAddDropTorrent(t *testing.T) {
44         cl, err := NewClient(&TestingConfig)
45         if err != nil {
46                 t.Fatal(err)
47         }
48         defer cl.Close()
49         dir, mi := testutil.GreetingTestTorrent()
50         defer os.RemoveAll(dir)
51         tt, new, err := cl.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
52         if err != nil {
53                 t.Fatal(err)
54         }
55         if !new {
56                 t.FailNow()
57         }
58         tt.Drop()
59 }
60
61 func TestAddTorrentNoSupportedTrackerSchemes(t *testing.T) {
62         t.SkipNow()
63 }
64
65 func TestAddTorrentNoUsableURLs(t *testing.T) {
66         t.SkipNow()
67 }
68
69 func TestAddPeersToUnknownTorrent(t *testing.T) {
70         t.SkipNow()
71 }
72
73 func TestPieceHashSize(t *testing.T) {
74         if pieceHash.Size() != 20 {
75                 t.FailNow()
76         }
77 }
78
79 func TestTorrentInitialState(t *testing.T) {
80         dir, mi := testutil.GreetingTestTorrent()
81         defer os.RemoveAll(dir)
82         tor, err := newTorrent(func() (ih InfoHash) {
83                 util.CopyExact(ih[:], mi.Info.Hash)
84                 return
85         }())
86         if err != nil {
87                 t.Fatal(err)
88         }
89         err = tor.setMetadata(&mi.Info.Info, mi.Info.Bytes, nil)
90         if err != nil {
91                 t.Fatal(err)
92         }
93         if len(tor.Pieces) != 3 {
94                 t.Fatal("wrong number of pieces")
95         }
96         p := tor.Pieces[0]
97         tor.pendAllChunkSpecs(0)
98         if len(p.PendingChunkSpecs) != 1 {
99                 t.Fatalf("should only be 1 chunk: %v", p.PendingChunkSpecs)
100         }
101         // TODO: Set chunkSize to 2, to test odd/even silliness.
102         if false {
103                 if _, ok := p.PendingChunkSpecs[chunkSpec{
104                         Length: 13,
105                 }]; !ok {
106                         t.Fatal("pending chunk spec is incorrect")
107                 }
108         }
109 }
110
111 func TestUnmarshalPEXMsg(t *testing.T) {
112         var m peerExchangeMessage
113         if err := bencode.Unmarshal([]byte("d5:added12:\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0ce"), &m); err != nil {
114                 t.Fatal(err)
115         }
116         if len(m.Added) != 2 {
117                 t.FailNow()
118         }
119         if m.Added[0].Port != 0x506 {
120                 t.FailNow()
121         }
122 }
123
124 func TestReducedDialTimeout(t *testing.T) {
125         for _, _case := range []struct {
126                 Max             time.Duration
127                 HalfOpenLimit   int
128                 PendingPeers    int
129                 ExpectedReduced time.Duration
130         }{
131                 {nominalDialTimeout, 40, 0, nominalDialTimeout},
132                 {nominalDialTimeout, 40, 1, nominalDialTimeout},
133                 {nominalDialTimeout, 40, 39, nominalDialTimeout},
134                 {nominalDialTimeout, 40, 40, nominalDialTimeout / 2},
135                 {nominalDialTimeout, 40, 80, nominalDialTimeout / 3},
136                 {nominalDialTimeout, 40, 4000, nominalDialTimeout / 101},
137         } {
138                 reduced := reducedDialTimeout(_case.Max, _case.HalfOpenLimit, _case.PendingPeers)
139                 expected := _case.ExpectedReduced
140                 if expected < minDialTimeout {
141                         expected = minDialTimeout
142                 }
143                 if reduced != expected {
144                         t.Fatalf("expected %s, got %s", _case.ExpectedReduced, reduced)
145                 }
146         }
147 }
148
149 func TestUTPRawConn(t *testing.T) {
150         l, err := utp.NewSocket("")
151         if err != nil {
152                 t.Fatal(err)
153         }
154         defer l.Close()
155         go func() {
156                 for {
157                         _, err := l.Accept()
158                         if err != nil {
159                                 break
160                         }
161                 }
162         }()
163         // Connect a UTP peer to see if the RawConn will still work.
164         utpPeer, err := func() *utp.Socket {
165                 s, _ := utp.NewSocket("")
166                 return s
167         }().Dial(fmt.Sprintf("localhost:%d", util.AddrPort(l.Addr())))
168         if err != nil {
169                 t.Fatalf("error dialing utp listener: %s", err)
170         }
171         defer utpPeer.Close()
172         peer, err := net.ListenPacket("udp", ":0")
173         if err != nil {
174                 t.Fatal(err)
175         }
176         defer peer.Close()
177
178         msgsReceived := 0
179         const N = 5000 // How many messages to send.
180         readerStopped := make(chan struct{})
181         // The reader goroutine.
182         go func() {
183                 defer close(readerStopped)
184                 b := make([]byte, 500)
185                 for i := 0; i < N; i++ {
186                         n, _, err := l.PacketConn().ReadFrom(b)
187                         if err != nil {
188                                 t.Fatalf("error reading from raw conn: %s", err)
189                         }
190                         msgsReceived++
191                         var d int
192                         fmt.Sscan(string(b[:n]), &d)
193                         if d != i {
194                                 log.Printf("got wrong number: expected %d, got %d", i, d)
195                         }
196                 }
197         }()
198         udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", util.AddrPort(l.Addr())))
199         if err != nil {
200                 t.Fatal(err)
201         }
202         for i := 0; i < N; i++ {
203                 _, err := peer.WriteTo([]byte(fmt.Sprintf("%d", i)), udpAddr)
204                 if err != nil {
205                         t.Fatal(err)
206                 }
207                 time.Sleep(time.Microsecond)
208         }
209         select {
210         case <-readerStopped:
211         case <-time.After(time.Second):
212                 t.Fatal("reader timed out")
213         }
214         if msgsReceived != N {
215                 t.Fatalf("messages received: %d", msgsReceived)
216         }
217 }
218
219 func TestTwoClientsArbitraryPorts(t *testing.T) {
220         for i := 0; i < 2; i++ {
221                 cl, err := NewClient(&TestingConfig)
222                 if err != nil {
223                         t.Fatal(err)
224                 }
225                 defer cl.Close()
226         }
227 }
228
229 func TestAddDropManyTorrents(t *testing.T) {
230         cl, _ := NewClient(&TestingConfig)
231         defer cl.Close()
232         for i := range iter.N(1000) {
233                 var spec TorrentSpec
234                 binary.PutVarint(spec.InfoHash[:], int64(i))
235                 tt, new, err := cl.AddTorrentSpec(&spec)
236                 if err != nil {
237                         t.Error(err)
238                 }
239                 if !new {
240                         t.FailNow()
241                 }
242                 defer tt.Drop()
243         }
244 }
245
246 func TestClientTransfer(t *testing.T) {
247         greetingTempDir, mi := testutil.GreetingTestTorrent()
248         defer os.RemoveAll(greetingTempDir)
249         cfg := TestingConfig
250         cfg.DataDir = greetingTempDir
251         seeder, err := NewClient(&cfg)
252         if err != nil {
253                 t.Fatal(err)
254         }
255         defer seeder.Close()
256         seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
257         leecherDataDir, err := ioutil.TempDir("", "")
258         if err != nil {
259                 t.Fatal(err)
260         }
261         defer os.RemoveAll(leecherDataDir)
262         // cfg.TorrentDataOpener = func(info *metainfo.Info) (data.Data, error) {
263         //      return blob.TorrentData(info, leecherDataDir), nil
264         // }
265         cfg.TorrentDataOpener = blob.NewStore(leecherDataDir).OpenTorrent
266         leecher, _ := NewClient(&cfg)
267         defer leecher.Close()
268         leecherGreeting, _, _ := leecher.AddTorrentSpec(TorrentSpecFromMetaInfo(mi))
269         leecherGreeting.AddPeers([]Peer{
270                 Peer{
271                         IP:   util.AddrIP(seeder.ListenAddr()),
272                         Port: util.AddrPort(seeder.ListenAddr()),
273                 },
274         })
275         r := leecherGreeting.NewReader()
276         defer r.Close()
277         _greeting, err := ioutil.ReadAll(r)
278         if err != nil {
279                 t.Fatalf("%q %s", string(_greeting), err)
280         }
281         greeting := string(_greeting)
282         if greeting != testutil.GreetingFileContents {
283                 t.Fatal(":(")
284         }
285 }
286
287 func TestReadaheadPieces(t *testing.T) {
288         for _, case_ := range []struct {
289                 readaheadBytes, pieceLength int64
290                 readaheadPieces             int
291         }{
292                 {5 * 1024 * 1024, 256 * 1024, 19},
293                 {5 * 1024 * 1024, 5 * 1024 * 1024, 0},
294                 {5*1024*1024 - 1, 5 * 1024 * 1024, 0},
295                 {5 * 1024 * 1024, 5*1024*1024 - 1, 1},
296                 {0, 5 * 1024 * 1024, -1},
297                 {5 * 1024 * 1024, 1048576, 4},
298         } {
299                 if readaheadPieces(case_.readaheadBytes, case_.pieceLength) != case_.readaheadPieces {
300                         t.Fatalf("case failed: %v", case_)
301                 }
302         }
303 }
304
305 func (suite) TestMergingTrackersByAddingSpecs(c *check.C) {
306         cl, _ := NewClient(&TestingConfig)
307         defer cl.Close()
308         spec := TorrentSpec{}
309         T, new, _ := cl.AddTorrentSpec(&spec)
310         if !new {
311                 c.FailNow()
312         }
313         spec.Trackers = [][]string{{"http://a"}, {"udp://b"}}
314         _, new, _ = cl.AddTorrentSpec(&spec)
315         if new {
316                 c.FailNow()
317         }
318         c.Assert(T.Trackers[0][0].URL(), check.Equals, "http://a")
319         c.Assert(T.Trackers[1][0].URL(), check.Equals, "udp://b")
320 }