skoppu22 commented on a change in pull request #1428:
URL: https://github.com/apache/cassandra/pull/1428#discussion_r797931851



##########
File path: test/unit/org/apache/cassandra/gms/GossiperTest.java
##########
@@ -414,11 +417,95 @@ public void 
testNotFireDuplicatedNotificationsWithUpdateContainsOldAndNewState()
         {
             // clean up the gossip states
             Gossiper.instance.endpointStateMap.clear();
+            Gossiper.instance.gossipStateTransitionMap.clear();
             if (stateChangeListener != null)
                 Gossiper.instance.unregister(stateChangeListener);
         }
     }
 
+    @Test
+    public void testGossipStateTransitions() throws UnknownHostException
+    {
+        // only record 2 state transitions per peer for testing purposes
+        DatabaseDescriptor.setMaxGossipStateTransitionsSize(2);
+        VersionedValue.VersionedValueFactory valueFactory =
+            new 
VersionedValue.VersionedValueFactory(DatabaseDescriptor.getPartitioner());
+
+        
assertThat(Gossiper.instance.gossipStateTransitionMap.isEmpty()).as("Ensure the 
map is empty when we start the test")
+                                                                        
.isEqualTo(true);
+
+        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, 
hosts, hostIds, 3);
+        try
+        {
+            InetAddressAndPort remoteHostAddress1 = hosts.get(1);
+            EndpointState initialRemoteState = 
Gossiper.instance.getEndpointStateForEndpoint(remoteHostAddress1);
+            HeartBeatState initialRemoteHeartBeat = 
initialRemoteState.getHeartBeatState();
+            //Util.createInitialRing should have initialized remoteHost's 
HeartBeatState's generation to 1
+            assertThat(initialRemoteHeartBeat.getGeneration()).isEqualTo(1);
+
+            // Test begins
+            HeartBeatState proposedRemoteHeartBeat = new 
HeartBeatState(initialRemoteHeartBeat.getGeneration());
+            EndpointState proposedRemoteState = new 
EndpointState(proposedRemoteHeartBeat);
+            Token token = DatabaseDescriptor.getPartitioner().getRandomToken();
+            proposedRemoteState.addApplicationState(ApplicationState.STATUS, 
valueFactory.normal(Collections.singletonList(token)));
+
+            // STEP 1. register verifier and apply state with just STATUS
+            // simulate applying gossip state from a v3 peer
+            
Gossiper.instance.applyStateLocally(ImmutableMap.of(remoteHostAddress1, 
proposedRemoteState));
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.size()).isEqualTo(1);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress1).size()).isEqualTo(1);
+
+            // STEP 2. includes both STATUS and STATUS_WITH_PORT. The gossiper 
knows that the remote peer is now in v4
+            // update verifier and apply state again
+            
proposedRemoteState.addApplicationState(ApplicationState.STATUS_WITH_PORT, 
valueFactory.normal(Collections.singletonList(token)));
+            
Gossiper.instance.applyStateLocally(ImmutableMap.of(remoteHostAddress1, 
proposedRemoteState));
+
+            // we still have only 1 endpoint with 2 transitions
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.size()).isEqualTo(1);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress1).size()).isEqualTo(2);
+
+            // STEP 3. update the heartbeat state
+            proposedRemoteHeartBeat = new 
HeartBeatState(initialRemoteHeartBeat.getGeneration() + 
Gossiper.MAX_GENERATION_DIFFERENCE + 1);
+            proposedRemoteState = new EndpointState(proposedRemoteHeartBeat);
+            
Gossiper.instance.applyStateLocally(ImmutableMap.of(remoteHostAddress1, 
proposedRemoteState));
+
+            // we still have only 1 endpoint
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.size()).isEqualTo(1);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress1).size()).isEqualTo(2);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress1).peek().status).contains(":NORMAL,"
 + token);
+
+            InetAddressAndPort remoteHostAddress2 = hosts.get(2);
+            initialRemoteState = 
Gossiper.instance.getEndpointStateForEndpoint(remoteHostAddress2);
+            initialRemoteHeartBeat = initialRemoteState.getHeartBeatState();
+            //Util.createInitialRing should have initialized remoteHost's 
HeartBeatState's generation to 1 for
+            //the second host
+            assertThat(initialRemoteHeartBeat.getGeneration()).isEqualTo(1);
+
+            proposedRemoteHeartBeat = new 
HeartBeatState(initialRemoteHeartBeat.getGeneration());
+            proposedRemoteState = new EndpointState(proposedRemoteHeartBeat);
+            token = DatabaseDescriptor.getPartitioner().getRandomToken();
+            proposedRemoteState.addApplicationState(ApplicationState.STATUS, 
valueFactory.normal(Collections.singletonList(token)));
+
+            
Gossiper.instance.applyStateLocally(ImmutableMap.of(remoteHostAddress2, 
proposedRemoteState));
+
+            // now we have 2 endpoints in the gossipStateTransitionMap
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.size()).isEqualTo(2);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress1).size()).isEqualTo(2);
+            
assertThat(Gossiper.instance.gossipStateTransitionMap.get(remoteHostAddress2).size()).isEqualTo(1);
+
+            // the list of recent gossip state transtitions includes 2 
transitions from host 1 and 1 transition
+            // from host 2
+            List<GossipStateTransition> gossipStateTransitions = 
Gossiper.instance.recentGossipStateTransitions();
+            assertThat(gossipStateTransitions.size()).isEqualTo(3);

Review comment:
       Seems like removing a endpoint from membership is not tested,  we can 
add below lines to test that code path as well
   
   ```
              Gossiper.instance.replacedEndpoint(remoteHostAddress1);
               List<GossipStateTransition> gossipStateTransitionsAfterReplace = 
Gossiper.instance.recentGossipStateTransitions();
               
assertThat(gossipStateTransitionsAfterReplace.size()).isEqualTo(1);
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to