]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Add a test for behaviour after getting metadata_size and before GotInfo
authorMatt Joiner <anacrolix@gmail.com>
Wed, 8 Nov 2017 08:31:10 +0000 (19:31 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 8 Nov 2017 08:31:10 +0000 (19:31 +1100)
#208

client.go
torrent.go
torrent_test.go

index ee2c8a3abbe40650c92690908be9eff24b3afb37..6a8b6216413f9f96e0f2b701785b6af2de9a973b 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1031,6 +1031,9 @@ func (cl *Client) newTorrent(ih metainfo.Hash, specStorage storage.ClientImpl) (
 
                networkingEnabled: true,
                requestStrategy:   2,
+               metadataChanged: sync.Cond{
+                       L: &cl.mu,
+               },
        }
        t.setChunkSize(defaultChunkSize)
        return
index 0060cff13c62561711d17e6d5746af4bae037f79..78df5f2e73988ce55fcbe30788ae55260f772b6d 100644 (file)
@@ -92,6 +92,7 @@ type Torrent struct {
        // Name used if the info name isn't available. Should be cleared when the
        // Info does become available.
        displayName string
+
        // The bencoded bytes of the info dict. This is actively manipulated if
        // the info bytes aren't initially available, and we try to fetch them
        // from peers.
@@ -99,6 +100,7 @@ type Torrent struct {
        // Each element corresponds to the 16KiB metadata pieces. If true, we have
        // received that piece.
        metadataCompletedChunks []bool
+       metadataChanged         sync.Cond
 
        // Set when .Info is obtained.
        gotMetainfo missinggo.Event
@@ -373,6 +375,7 @@ func (t *Torrent) setMetadataSize(bytes int64) (err error) {
        }
        t.metadataBytes = make([]byte, bytes)
        t.metadataCompletedChunks = make([]bool, (bytes+(1<<14)-1)/(1<<14))
+       t.metadataChanged.Broadcast()
        for c := range t.conns {
                c.requestPendingMetadata()
        }
index 4c5ac447c6826eb441d79dd46b15f10e48e242e9..00f5949803bafa8548a5f70addf12c35bc946487 100644 (file)
@@ -1,6 +1,7 @@
 package torrent
 
 import (
+       "net"
        "os"
        "path/filepath"
        "testing"
@@ -13,11 +14,11 @@ import (
        "github.com/anacrolix/torrent/bencode"
        "github.com/anacrolix/torrent/internal/testutil"
        "github.com/anacrolix/torrent/metainfo"
-       "github.com/anacrolix/torrent/peer_protocol"
+       pp "github.com/anacrolix/torrent/peer_protocol"
        "github.com/anacrolix/torrent/storage"
 )
 
-func r(i, b, l peer_protocol.Integer) request {
+func r(i, b, l pp.Integer) request {
        return request{i, chunkSpec{b, l}}
 }
 
@@ -156,3 +157,60 @@ func TestPieceHashFailed(t *testing.T) {
        require.False(t, tt.pieceAllDirty(1))
        tt.cl.mu.Unlock()
 }
+
+// Check the behaviour of Torrent.Metainfo when metadata is not completed.
+func TestTorrentMetainfoIncompleteMetadata(t *testing.T) {
+       cfg := TestingConfig()
+       cfg.Debug = true
+       cl, err := NewClient(cfg)
+       require.NoError(t, err)
+       defer cl.Close()
+
+       mi := testutil.GreetingMetaInfo()
+       ih := mi.HashInfoBytes()
+
+       tt, _ := cl.AddTorrentInfoHash(ih)
+       assert.Nil(t, tt.Metainfo().InfoBytes)
+       assert.False(t, tt.haveAllMetadataPieces())
+
+       nc, err := net.Dial("tcp", cl.ListenAddr().String())
+       require.NoError(t, err)
+       defer nc.Close()
+
+       var pex peerExtensionBytes
+       pex.SetBit(ExtensionBitExtended)
+       hr, ok, err := handshake(nc, &ih, [20]byte{}, pex)
+       require.NoError(t, err)
+       assert.True(t, ok)
+       assert.True(t, hr.peerExtensionBytes.GetBit(ExtensionBitExtended))
+       assert.EqualValues(t, cl.PeerID(), hr.peerID)
+       assert.Equal(t, ih, hr.Hash)
+
+       assert.EqualValues(t, 0, tt.metadataSize())
+
+       func() {
+               cl.mu.Lock()
+               defer cl.mu.Unlock()
+               go func() {
+                       _, err = nc.Write(pp.Message{
+                               Type:       pp.Extended,
+                               ExtendedID: pp.HandshakeExtendedID,
+                               ExtendedPayload: func() []byte {
+                                       d := map[string]interface{}{
+                                               "metadata_size": len(mi.InfoBytes),
+                                       }
+                                       b, err := bencode.Marshal(d)
+                                       if err != nil {
+                                               panic(err)
+                                       }
+                                       return b
+                               }(),
+                       }.MustMarshalBinary())
+                       require.NoError(t, err)
+               }()
+               tt.metadataChanged.Wait()
+       }()
+       assert.Equal(t, make([]byte, len(mi.InfoBytes)), tt.metadataBytes)
+       assert.False(t, tt.haveAllMetadataPieces())
+       assert.Nil(t, tt.Metainfo().InfoBytes)
+}