@@ -1391,6 +1391,79 @@ func TestReplicateRogueRemovedNode(t *testing.T) {
13911391 finishWG .Wait ()
13921392}
13931393
1394+ func TestReplicateRemovedNodeDisruptiveElection (t * testing.T ) {
1395+ defer leaktest .AfterTest (t )()
1396+
1397+ mtc := startMultiTestContext (t , 4 )
1398+ defer mtc .Stop ()
1399+
1400+ // Move the first range from the first node to the other three.
1401+ rangeID := roachpb .RangeID (1 )
1402+ mtc .replicateRange (rangeID , 1 , 2 , 3 )
1403+ mtc .unreplicateRange (rangeID , 0 )
1404+ mtc .expireLeaderLeases ()
1405+
1406+ // Write on the second node, to ensure that the other nodes have
1407+ // established leadership after the first node's removal.
1408+ incArgs := incrementArgs ([]byte ("a" ), 5 )
1409+ if _ , err := client .SendWrapped (mtc .distSenders [1 ], nil , & incArgs ); err != nil {
1410+ t .Fatal (err )
1411+ }
1412+
1413+ // Save the current term, which is the latest among the live stores.
1414+ findTerm := func () uint64 {
1415+ var term uint64
1416+ for i := 1 ; i < 4 ; i ++ {
1417+ s := mtc .stores [i ].RaftStatus (rangeID )
1418+ if s .Term > term {
1419+ term = s .Term
1420+ }
1421+ }
1422+ return term
1423+ }
1424+ term := findTerm ()
1425+ if term == 0 {
1426+ t .Fatalf ("expected non-zero term" )
1427+ }
1428+
1429+ replica0 := roachpb.ReplicaDescriptor {
1430+ ReplicaID : roachpb .ReplicaID (mtc .stores [0 ].StoreID ()),
1431+ NodeID : roachpb .NodeID (mtc .stores [0 ].StoreID ()),
1432+ StoreID : mtc .stores [0 ].StoreID (),
1433+ }
1434+ replica1 := roachpb.ReplicaDescriptor {
1435+ ReplicaID : roachpb .ReplicaID (mtc .stores [1 ].StoreID ()),
1436+ NodeID : roachpb .NodeID (mtc .stores [1 ].StoreID ()),
1437+ StoreID : mtc .stores [1 ].StoreID (),
1438+ }
1439+ // Simulate an election triggered by the removed node.
1440+ if err := mtc .transports [0 ].Send (& storage.RaftMessageRequest {
1441+ GroupID : rangeID ,
1442+ ToReplica : replica1 ,
1443+ FromReplica : replica0 ,
1444+ Message : raftpb.Message {
1445+ From : uint64 (replica0 .ReplicaID ),
1446+ To : uint64 (replica1 .ReplicaID ),
1447+ Type : raftpb .MsgVote ,
1448+ Term : term + 1 ,
1449+ },
1450+ }); err != nil {
1451+ t .Fatal (err )
1452+ }
1453+
1454+ // Wait a bit for the message to be processed.
1455+ // TODO(bdarnell): This will be easier to test without waiting
1456+ // when #5789 is done.
1457+ time .Sleep (10 * time .Millisecond )
1458+
1459+ // The message should have been discarded without triggering an
1460+ // election or changing the term.
1461+ newTerm := findTerm ()
1462+ if term != newTerm {
1463+ t .Errorf ("expected term to be constant, but changed from %v to %v" , term , newTerm )
1464+ }
1465+ }
1466+
13941467func TestReplicateReAddAfterDown (t * testing.T ) {
13951468 defer leaktest .AfterTest (t )()
13961469
0 commit comments