]> Sergey Matveev's repositories - btrtrc.git/blob - client_test.go
Add piece blob torrent.Data storage, and move testutil to internal/, add basic transf...
[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         "github.com/anacrolix/libtorgo/metainfo"
16
17         "github.com/bradfitz/iter"
18
19         "bitbucket.org/anacrolix/go.torrent/internal/testutil"
20         "bitbucket.org/anacrolix/go.torrent/util"
21         "bitbucket.org/anacrolix/utp"
22         "github.com/anacrolix/libtorgo/bencode"
23 )
24
25 var TestingConfig = Config{
26         ListenAddr:           ":0",
27         NoDHT:                true,
28         DisableTrackers:      true,
29         NoDefaultBlocklist:   true,
30         DisableMetainfoCache: true,
31 }
32
33 func TestClientDefault(t *testing.T) {
34         cl, err := NewClient(&Config{
35                 NoDefaultBlocklist: true,
36                 ListenAddr:         ":0",
37         })
38         if err != nil {
39                 t.Fatal(err)
40         }
41         cl.Stop()
42 }
43
44 func TestAddDropTorrent(t *testing.T) {
45         cl, err := NewClient(&Config{
46                 ListenAddr: "localhost:0",
47         })
48         if err != nil {
49                 t.Fatal(err)
50         }
51         defer cl.Stop()
52         dir, mi := testutil.GreetingTestTorrent()
53         defer os.RemoveAll(dir)
54         tt, err := cl.AddTorrent(mi)
55         if err != nil {
56                 t.Fatal(err)
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         }(), nil, 0)
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(&Config{
222                         ListenAddr: ":0",
223                 })
224                 if err != nil {
225                         t.Fatal(err)
226                 }
227                 defer cl.Stop()
228         }
229 }
230
231 func TestAddDropManyTorrents(t *testing.T) {
232         cl, _ := NewClient(&TestingConfig)
233         defer cl.Stop()
234         var m Magnet
235         for i := range iter.N(1000) {
236                 binary.PutVarint(m.InfoHash[:], int64(i))
237                 cl.AddMagnet(m.String())
238         }
239 }
240
241 func TestClientTransfer(t *testing.T) {
242         greetingTempDir, mi := testutil.GreetingTestTorrent()
243         defer os.RemoveAll(greetingTempDir)
244         cfg := TestingConfig
245         cfg.DataDir = greetingTempDir
246         seeder, err := NewClient(&cfg)
247         if err != nil {
248                 t.Fatal(err)
249         }
250         defer seeder.Stop()
251         seeder.AddTorrent(mi)
252         leecherDataDir, err := ioutil.TempDir("", "")
253         if err != nil {
254                 t.Fatal(err)
255         }
256         defer os.RemoveAll(leecherDataDir)
257         cfg.TorrentDataOpener = func(info *metainfo.Info) (Data, error) {
258                 return blob.TorrentData(info, leecherDataDir), nil
259         }
260         leecher, _ := NewClient(&cfg)
261         defer leecher.Stop()
262         leecherGreeting, _ := leecher.AddTorrent(mi)
263         leecherGreeting.AddPeers([]Peer{
264                 Peer{
265                         IP:   util.AddrIP(seeder.ListenAddr()),
266                         Port: util.AddrPort(seeder.ListenAddr()),
267                 },
268         })
269         _greeting, err := ioutil.ReadAll(io.NewSectionReader(leecherGreeting, 0, leecherGreeting.Length()))
270         if err != nil {
271                 t.Fatal(err)
272         }
273         greeting := string(_greeting)
274         if greeting != testutil.GreetingFileContents {
275                 t.Fatal(":(")
276         }
277 }