+ tt.cl.unlock()
+}
+
+// Check the behaviour of Torrent.Metainfo when metadata is not completed.
+func TestTorrentMetainfoIncompleteMetadata(t *testing.T) {
+ cfg := TestingConfig(t)
+ cfg.Debug = true
+ // Disable this just because we manually initiate a connection without it.
+ cfg.MinPeerExtensions.SetBit(pp.ExtensionBitFast, false)
+ 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", fmt.Sprintf(":%d", cl.LocalPort()))
+ require.NoError(t, err)
+ defer nc.Close()
+
+ var pex PeerExtensionBits
+ pex.SetBit(pp.ExtensionBitLtep, true)
+ hr, err := pp.Handshake(nc, &ih, [20]byte{}, pex)
+ require.NoError(t, err)
+ assert.True(t, hr.PeerExtensionBits.GetBit(pp.ExtensionBitLtep))
+ assert.EqualValues(t, cl.PeerID(), hr.PeerID)
+ assert.EqualValues(t, ih, hr.Hash)
+
+ assert.EqualValues(t, 0, tt.metadataSize())
+
+ func() {
+ cl.lock()
+ defer cl.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)
+}
+
+func TestRelativeAvailabilityHaveNone(t *testing.T) {
+ c := qt.New(t)
+ var err error
+ cl := Client{
+ config: TestingConfig(t),
+ }
+ tt := Torrent{
+ cl: &cl,
+ logger: log.Default,
+ gotMetainfoC: make(chan struct{}),
+ }
+ tt.setChunkSize(2)
+ g.MakeMapIfNil(&tt.conns)
+ pc := PeerConn{}
+ pc.t = &tt
+ pc.peerImpl = &pc
+ pc.initRequestState()
+ g.InitNew(&pc.callbacks)
+ tt.conns[&pc] = struct{}{}
+ err = pc.peerSentHave(0)
+ c.Assert(err, qt.IsNil)
+ info := testutil.Greeting.Info(5)
+ err = tt.setInfo(&info)
+ c.Assert(err, qt.IsNil)
+ tt.onSetInfo()
+ err = pc.peerSentHaveNone()
+ c.Assert(err, qt.IsNil)
+ var wg sync.WaitGroup
+ tt.close(&wg)
+ tt.assertAllPiecesRelativeAvailabilityZero()