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