+
+func TestApplyRequestStateWriteBufferConstraints(t *testing.T) {
+ c := qt.New(t)
+ c.Check(interestedMsgLen, qt.Equals, 5)
+ c.Check(requestMsgLen, qt.Equals, 17)
+ c.Check(maxLocalToRemoteRequests >= 8, qt.IsTrue)
+ c.Logf("max local to remote requests: %v", maxLocalToRemoteRequests)
+}
+
+func peerConnForPreferredNetworkDirection(
+ localPeerId, remotePeerId int,
+ outgoing, utp, ipv6 bool,
+) *PeerConn {
+ pc := PeerConn{}
+ pc.outgoing = outgoing
+ if utp {
+ pc.Network = "udp"
+ }
+ if ipv6 {
+ pc.RemoteAddr = &net.TCPAddr{IP: net.ParseIP("::420")}
+ } else {
+ pc.RemoteAddr = &net.TCPAddr{IP: net.IPv4(1, 2, 3, 4)}
+ }
+ binary.BigEndian.PutUint64(pc.PeerID[:], uint64(remotePeerId))
+ cl := Client{}
+ binary.BigEndian.PutUint64(cl.peerID[:], uint64(localPeerId))
+ pc.t = &Torrent{cl: &cl}
+ return &pc
+}
+
+func TestPreferredNetworkDirection(t *testing.T) {
+ pc := peerConnForPreferredNetworkDirection
+ c := qt.New(t)
+
+ // Prefer outgoing to lower peer ID
+
+ c.Check(
+ pc(1, 2, true, false, false).hasPreferredNetworkOver(pc(1, 2, false, false, false)),
+ qt.IsFalse,
+ )
+ c.Check(
+ pc(1, 2, false, false, false).hasPreferredNetworkOver(pc(1, 2, true, false, false)),
+ qt.IsTrue,
+ )
+ c.Check(
+ pc(2, 1, false, false, false).hasPreferredNetworkOver(pc(2, 1, true, false, false)),
+ qt.IsFalse,
+ )
+
+ // Don't prefer uTP
+ c.Check(
+ pc(1, 2, false, true, false).hasPreferredNetworkOver(pc(1, 2, false, false, false)),
+ qt.IsFalse,
+ )
+ // Prefer IPv6
+ c.Check(
+ pc(1, 2, false, false, false).hasPreferredNetworkOver(pc(1, 2, false, false, true)),
+ qt.IsFalse,
+ )
+ // No difference
+ c.Check(
+ pc(1, 2, false, false, false).hasPreferredNetworkOver(pc(1, 2, false, false, false)),
+ qt.IsFalse,
+ )
+}
+
+func TestReceiveLargeRequest(t *testing.T) {
+ c := qt.New(t)
+ cl := newTestingClient(t)
+ pc := cl.newConnection(nil, newConnectionOpts{network: "test"})
+ tor := cl.newTorrentForTesting()
+ tor.info = &metainfo.Info{PieceLength: 3 << 20}
+ pc.setTorrent(tor)
+ tor._completedPieces.Add(0)
+ pc.PeerExtensionBytes.SetBit(pp.ExtensionBitFast, true)
+ pc.choking = false
+ pc.initMessageWriter()
+ req := Request{}
+ req.Length = defaultChunkSize
+ c.Assert(pc.fastEnabled(), qt.IsTrue)
+ c.Check(pc.onReadRequest(req, false), qt.IsNil)
+ c.Check(pc.peerRequests, qt.HasLen, 1)
+ req.Length = 2 << 20
+ c.Check(pc.onReadRequest(req, false), qt.IsNil)
+ c.Check(pc.peerRequests, qt.HasLen, 2)
+ pc.peerRequests = nil
+ pc.t.cl.config.UploadRateLimiter = rate.NewLimiter(1, defaultChunkSize)
+ req.Length = defaultChunkSize
+ c.Check(pc.onReadRequest(req, false), qt.IsNil)
+ c.Check(pc.peerRequests, qt.HasLen, 1)
+ req.Length = 2 << 20
+ c.Check(pc.onReadRequest(req, false), qt.IsNil)
+ c.Check(pc.messageWriter.writeBuffer.Len(), qt.Equals, 17)
+}
+
+func TestChunkOverflowsPiece(t *testing.T) {
+ c := qt.New(t)
+ check := func(begin, length, limit pp.Integer, expected bool) {
+ c.Check(chunkOverflowsPiece(ChunkSpec{begin, length}, limit), qt.Equals, expected)
+ }
+ check(2, 3, 1, true)
+ check(2, pp.IntegerMax, 1, true)
+ check(2, pp.IntegerMax, 3, true)
+ check(2, pp.IntegerMax, pp.IntegerMax, true)
+ check(2, pp.IntegerMax-2, pp.IntegerMax, false)
+}