mirror of
https://github.com/btcsuite/btcd.git
synced 2026-08-13 12:32:51 +02:00
integration: stabilize pre-verack disconnect cycles
In this commit, we make the pre-verack lifecycle test count only peers that btcd has admitted and processed through version exchange. The source handshake limit can close a rapid follow-up socket while the previous disconnect is still unwinding. This made the client-side version write fail with EPIPE before the intended lifecycle path ran. We now wait for a version response from btcd, retry rejected attempts under a deadline, and still disconnect without sending verack. This preserves all 50 peerDone without peerAdd cycles while removing the scheduler-dependent admission race from the test.
This commit is contained in:
parent
7e9414fa6c
commit
76ba88422f
1 changed files with 58 additions and 19 deletions
|
|
@ -357,22 +357,27 @@ func TestSyncManagerRaceCorruption(t *testing.T) {
|
||||||
done, heightBefore, heightAfter)
|
done, heightBefore, heightAfter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dialAndSendVersion connects to nodeAddr and sends a version
|
// dialPreVerackPeer connects to nodeAddr and exchanges version messages without
|
||||||
// message, returning the open connection. The caller is
|
// sending verack. The caller is responsible for closing the returned
|
||||||
// responsible for closing it.
|
// connection.
|
||||||
func dialAndSendVersion(
|
func dialPreVerackPeer(nodeAddr string) (net.Conn, error) {
|
||||||
t *testing.T, nodeAddr string,
|
|
||||||
) net.Conn {
|
|
||||||
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
conn, err := net.DialTimeout("tcp", nodeAddr, 5*time.Second)
|
conn, err := net.DialTimeout("tcp", nodeAddr, 5*time.Second)
|
||||||
require.NoError(t, err)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
connected := false
|
||||||
|
defer func() {
|
||||||
|
if !connected {
|
||||||
|
_ = conn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
_ = conn.SetDeadline(time.Now().Add(5 * time.Second))
|
_ = conn.SetDeadline(time.Now().Add(5 * time.Second))
|
||||||
|
|
||||||
nodeTCP, err := net.ResolveTCPAddr("tcp", nodeAddr)
|
nodeTCP, err := net.ResolveTCPAddr("tcp", nodeAddr)
|
||||||
require.NoError(t, err)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
you := wire.NewNetAddress(
|
you := wire.NewNetAddress(
|
||||||
nodeTCP, wire.SFNodeNetwork|wire.SFNodeWitness,
|
nodeTCP, wire.SFNodeNetwork|wire.SFNodeWitness,
|
||||||
|
|
@ -391,9 +396,22 @@ func dialAndSendVersion(
|
||||||
err = wire.WriteMessage(
|
err = wire.WriteMessage(
|
||||||
conn, msgVersion, wire.ProtocolVersion, wire.SimNet,
|
conn, msgVersion, wire.ProtocolVersion, wire.SimNet,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return conn
|
msg, _, err := wire.ReadMessage(
|
||||||
|
conn, wire.ProtocolVersion, wire.SimNet,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, ok := msg.(*wire.MsgVersion); !ok {
|
||||||
|
return nil, fmt.Errorf("expected version message, got %T", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = true
|
||||||
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPreVerackDisconnect verifies that a peer disconnecting
|
// TestPreVerackDisconnect verifies that a peer disconnecting
|
||||||
|
|
@ -409,15 +427,36 @@ func TestPreVerackDisconnect(t *testing.T) {
|
||||||
|
|
||||||
nodeAddr := harness.P2PAddress()
|
nodeAddr := harness.P2PAddress()
|
||||||
|
|
||||||
// Connect and send version, then disconnect before receiving or
|
// Connect and exchange version messages, then disconnect without sending
|
||||||
// sending verack. This is expected to produce a peerDone without
|
// verack. This is expected to produce a peerDone without a preceding
|
||||||
// a preceding peerAdd in the lifecycle channel.
|
// peerAdd in the lifecycle channel.
|
||||||
const preVerackAttempts = 50
|
const (
|
||||||
|
preVerackAttempts = 50
|
||||||
|
preVerackRetryTimeout = 5 * time.Second
|
||||||
|
preVerackRetryDelay = 10 * time.Millisecond
|
||||||
|
)
|
||||||
|
|
||||||
|
retries := 0
|
||||||
for i := 0; i < preVerackAttempts; i++ {
|
for i := 0; i < preVerackAttempts; i++ {
|
||||||
conn := dialAndSendVersion(t, nodeAddr)
|
deadline := time.Now().Add(preVerackRetryTimeout)
|
||||||
conn.Close()
|
for {
|
||||||
|
conn, err := dialPreVerackPeer(nodeAddr)
|
||||||
|
if err == nil {
|
||||||
|
require.NoError(t, conn.Close())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().After(deadline) {
|
||||||
|
t.Fatalf("pre-verack attempt %d did not complete: %v",
|
||||||
|
i+1, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
retries++
|
||||||
|
time.Sleep(preVerackRetryDelay)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
t.Logf("completed %d pre-verack disconnects with %d retries",
|
||||||
|
preVerackAttempts, retries)
|
||||||
|
|
||||||
// Allow the node time to process all the disconnects.
|
// Allow the node time to process all the disconnects.
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue