/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.distributed.internal.membership.gms.fd; import org.apache.geode.distributed.internal.*; import org.apache.geode.distributed.internal.membership.InternalDistributedMember; import org.apache.geode.distributed.internal.membership.NetView; import org.apache.geode.distributed.internal.membership.gms.GMSMember; import org.apache.geode.distributed.internal.membership.gms.ServiceConfig; import org.apache.geode.distributed.internal.membership.gms.Services; import org.apache.geode.distributed.internal.membership.gms.Services.Stopper; import org.apache.geode.distributed.internal.membership.gms.fd.GMSHealthMonitor.ClientSocketHandler; import org.apache.geode.distributed.internal.membership.gms.interfaces.JoinLeave; import org.apache.geode.distributed.internal.membership.gms.interfaces.Manager; import org.apache.geode.distributed.internal.membership.gms.interfaces.Messenger; import org.apache.geode.distributed.internal.membership.gms.messages.HeartbeatMessage; import org.apache.geode.distributed.internal.membership.gms.messages.HeartbeatRequestMessage; import org.apache.geode.distributed.internal.membership.gms.messages.SuspectMembersMessage; import org.apache.geode.distributed.internal.membership.gms.messages.SuspectRequest; import org.apache.geode.internal.net.SocketCreator; import org.apache.geode.internal.Version; import org.apache.geode.internal.net.SocketCreatorFactory; import org.apache.geode.test.junit.categories.FlakyTest; import org.apache.geode.test.junit.categories.IntegrationTest; import org.apache.geode.test.junit.categories.MembershipTest; import org.jgroups.util.UUID; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.*; import com.jayway.awaitility.Awaitility; @Category({IntegrationTest.class, MembershipTest.class}) public class GMSHealthMonitorJUnitTest { private Services services; private ServiceConfig mockConfig; private DistributionConfig mockDistConfig; private List<InternalDistributedMember> mockMembers; private Messenger messenger; private JoinLeave joinLeave; private GMSHealthMonitor gmsHealthMonitor; private Manager manager; private long statsId = 123; final long memberTimeout = 1000l; private int[] portRange = new int[] {0, 65535}; private boolean useGMSHealthMonitorTestClass = false; private final int myAddressIndex = 3; @Before public void initMocks() throws UnknownHostException { // System.setProperty("gemfire.bind-address", "localhost"); mockDistConfig = mock(DistributionConfig.class); mockConfig = mock(ServiceConfig.class); messenger = mock(Messenger.class); joinLeave = mock(JoinLeave.class); manager = mock(Manager.class); services = mock(Services.class); Stopper stopper = mock(Stopper.class); Properties nonDefault = new Properties(); nonDefault.put(ACK_WAIT_THRESHOLD, "1"); nonDefault.put(ACK_SEVERE_ALERT_THRESHOLD, "10"); nonDefault.put(DISABLE_TCP, "true"); nonDefault.put(MCAST_PORT, "0"); nonDefault.put(MCAST_TTL, "0"); nonDefault.put(LOG_FILE, ""); nonDefault.put(LOG_LEVEL, "fine"); nonDefault.put(MEMBER_TIMEOUT, "2000"); nonDefault.put(LOCATORS, "localhost[10344]"); DM dm = mock(DM.class); SocketCreatorFactory.setDistributionConfig(new DistributionConfigImpl(new Properties())); InternalDistributedSystem system = InternalDistributedSystem.newInstanceForTesting(dm, nonDefault); when(mockConfig.getDistributionConfig()).thenReturn(mockDistConfig); when(mockConfig.getMemberTimeout()).thenReturn(memberTimeout); when(mockConfig.getMembershipPortRange()).thenReturn(portRange); when(services.getConfig()).thenReturn(mockConfig); when(services.getMessenger()).thenReturn(messenger); when(services.getJoinLeave()).thenReturn(joinLeave); when(services.getCancelCriterion()).thenReturn(stopper); when(services.getManager()).thenReturn(manager); when(services.getStatistics()).thenReturn(new DistributionStats(system, statsId)); when(stopper.isCancelInProgress()).thenReturn(false); if (mockMembers == null) { mockMembers = new ArrayList<InternalDistributedMember>(); for (int i = 0; i < 7; i++) { InternalDistributedMember mbr = new InternalDistributedMember("localhost", 8888 + i); if (i == 0 || i == 1) { mbr.setVmKind(DistributionManager.LOCATOR_DM_TYPE); mbr.getNetMember().setPreferredForCoordinator(true); } mockMembers.add(mbr); } } when(joinLeave.getMemberID()).thenReturn(mockMembers.get(myAddressIndex)); when(messenger.getMemberID()).thenReturn(mockMembers.get(myAddressIndex)); gmsHealthMonitor = new GMSHealthMonitorTest(); gmsHealthMonitor.init(services); gmsHealthMonitor.start(); } @After public void tearDown() { gmsHealthMonitor.stop(); SocketCreatorFactory.close(); // System.getProperties().remove("gemfire.bind-address"); } @Test public void testHMServiceStarted() throws IOException { InternalDistributedMember mbr = new InternalDistributedMember(SocketCreator.getLocalHost(), 12345); mbr.setVmViewId(1); when(messenger.getMemberID()).thenReturn(mbr); gmsHealthMonitor.started(); NetView v = new NetView(mbr, 1, mockMembers); gmsHealthMonitor.processMessage(new HeartbeatRequestMessage(mbr, 1)); verify(messenger, atLeastOnce()).send(any(HeartbeatMessage.class)); Assert.assertEquals(1, gmsHealthMonitor.getStats().getHeartbeatRequestsReceived()); Assert.assertEquals(1, gmsHealthMonitor.getStats().getHeartbeatsSent()); } /** * checks who is next neighbor */ @Test public void testHMNextNeighborVerify() throws IOException { installAView(); Assert.assertEquals(mockMembers.get(myAddressIndex + 1), gmsHealthMonitor.getNextNeighbor()); } // @Category(FlakyTest.class) // GEODE-2073 @Test public void testHMNextNeighborAfterTimeout() throws Exception { System.out.println("testHMNextNeighborAfterTimeout starting"); installAView(); InternalDistributedMember initialNeighbor = mockMembers.get(myAddressIndex + 1); // allow the monitor to give up on the initial "next neighbor" and // move on to the one after it long giveup = System.currentTimeMillis() + (2 * memberTimeout) + 1500; InternalDistributedMember neighbor = gmsHealthMonitor.getNextNeighbor(); while (System.currentTimeMillis() < giveup && neighbor == initialNeighbor) { Thread.sleep(50); neighbor = gmsHealthMonitor.getNextNeighbor(); } // neighbor should change. In order to not be a flaky test we don't demand // that it be myAddressIndex+2 but just require that the neighbor being // monitored has changed System.out.println("testHMNextNeighborAfterTimeout ending"); Assert.assertNotNull(gmsHealthMonitor.getView()); Assert.assertNotEquals("neighbor to not be " + neighbor + "; my ID is " + mockMembers.get(myAddressIndex) + "; view=" + gmsHealthMonitor.getView(), initialNeighbor, neighbor); } /** * it checks neighbor before member-timeout, it should be same */ @Test public void testHMNextNeighborBeforeTimeout() throws IOException { installAView(); // Should we remove these sleeps and force the checkmember directly instead of waiting? try { // member-timeout is 1000 ms. We initiate a check and choose // a new neighbor at 500 ms Thread.sleep(memberTimeout / GMSHealthMonitor.LOGICAL_INTERVAL - 100); } catch (InterruptedException e) { } // neighbor should be same System.out.println("next neighbor is " + gmsHealthMonitor.getNextNeighbor() + "\nmy address is " + mockMembers.get(myAddressIndex) + "\nview is " + joinLeave.getView()); Assert.assertEquals(mockMembers.get(myAddressIndex + 1), gmsHealthMonitor.getNextNeighbor()); } /*** * checks whether member-check thread sends suspectMembers message */ @Test public void testSuspectMembersCalledThroughMemberCheckThread() throws Exception { installAView(); // when the view is installed we start a heartbeat timeout. After // that expires we request a heartbeat Thread.sleep(3 * memberTimeout + 100); System.out.println("testSuspectMembersCalledThroughMemberCheckThread ending"); assertTrue(gmsHealthMonitor.isSuspectMember(mockMembers.get(myAddressIndex + 1))); Assert.assertTrue(gmsHealthMonitor.getStats().getHeartbeatRequestsSent() > 0); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsSent() > 0); } private NetView installAView() { System.out.println("installAView starting"); NetView v = new NetView(mockMembers.get(0), 2, mockMembers); // 3rd is current member when(messenger.getMemberID()).thenReturn(mockMembers.get(myAddressIndex)); gmsHealthMonitor.started(); gmsHealthMonitor.installView(v); return v; } private void setFailureDetectionPorts(NetView v) { java.util.Iterator<InternalDistributedMember> itr = mockMembers.iterator(); int port = 7899; while (itr.hasNext()) { v.setFailureDetectionPort(itr.next(), port++); } } /*** * checks ping thread didn't sends suspectMembers message before timeout */ @Test public void testSuspectMembersNotCalledThroughPingThreadBeforeTimeout() { installAView(); InternalDistributedMember neighbor = gmsHealthMonitor.getNextNeighbor(); try { // member-timeout is 1000 ms // plus 100 ms for ack Thread.sleep(memberTimeout - 200); } catch (InterruptedException e) { } assertFalse(gmsHealthMonitor.isSuspectMember(neighbor)); } /*** * Checks whether suspect thread sends suspectMembers message */ @Test public void testSuspectMembersCalledThroughSuspectThread() throws Exception { installAView(); gmsHealthMonitor.suspect(mockMembers.get(1), "Not responding"); Thread.sleep(GMSHealthMonitor.MEMBER_SUSPECT_COLLECTION_INTERVAL + 1000); verify(messenger, atLeastOnce()).send(any(SuspectMembersMessage.class)); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsSent() > 0); } /*** * Checks suspect thread doesn't sends suspectMembers message before timeout */ @Test public void testSuspectMembersNotCalledThroughSuspectThreadBeforeTimeout() { installAView(); gmsHealthMonitor.suspect(mockMembers.get(1), "Not responding"); try { // suspect thread timeout is 200 ms Thread.sleep(100l); } catch (InterruptedException e) { } verify(messenger, atLeastOnce()).send(isA(SuspectMembersMessage.class)); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsSent() > 0); } /*** * Send remove member message after doing final check, ping Timeout */ @Test public void testRemoveMemberCalled() throws Exception { System.out.println("testRemoveMemberCalled starting"); NetView v = new NetView(mockMembers.get(0), 2, mockMembers); // 3rd is current member when(messenger.getMemberID()).thenReturn(mockMembers.get(0)); // coordinator and local member gmsHealthMonitor.started(); gmsHealthMonitor.installView(v); Thread.sleep(memberTimeout / GMSHealthMonitor.LOGICAL_INTERVAL); ArrayList<InternalDistributedMember> recipient = new ArrayList<InternalDistributedMember>(); recipient.add(mockMembers.get(0)); ArrayList<SuspectRequest> as = new ArrayList<SuspectRequest>(); SuspectRequest sr = new SuspectRequest(mockMembers.get(1), "Not Responding");// removing member // 1 as.add(sr); SuspectMembersMessage sm = new SuspectMembersMessage(recipient, as); sm.setSender(mockMembers.get(0)); gmsHealthMonitor.processMessage(sm); Awaitility.await("waiting for remove(member) to be invoked") .atMost(3 * memberTimeout, TimeUnit.SECONDS).until(() -> { verify(joinLeave, atLeastOnce()).remove(any(InternalDistributedMember.class), any(String.class)); }); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsReceived() > 0); } /*** * Shouldn't send remove member message before doing final check, or before ping Timeout */ @Test public void testRemoveMemberNotCalledBeforeTimeout() { System.out.println("testRemoveMemberNotCalledBeforeTimeout starting"); NetView v = new NetView(mockMembers.get(0), 2, mockMembers); // 3rd is current member when(messenger.getMemberID()).thenReturn(mockMembers.get(0)); // coordinator and local member when(joinLeave.getMemberID()).thenReturn(mockMembers.get(0)); // coordinator and local member gmsHealthMonitor.started(); gmsHealthMonitor.installView(v); ArrayList<InternalDistributedMember> recipient = new ArrayList<InternalDistributedMember>(); recipient.add(mockMembers.get(0)); ArrayList<SuspectRequest> as = new ArrayList<SuspectRequest>(); SuspectRequest sr = new SuspectRequest(mockMembers.get(1), "Not Responding");// removing member // 1 as.add(sr); SuspectMembersMessage sm = new SuspectMembersMessage(recipient, as); sm.setSender(mockMembers.get(0)); gmsHealthMonitor.processMessage(sm); try { // this happens after final check, ping timeout Thread.sleep(memberTimeout - 100); } catch (InterruptedException e) { } System.out.println("testRemoveMemberNotCalledBeforeTimeout ending"); verify(joinLeave, never()).remove(any(InternalDistributedMember.class), any(String.class)); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsReceived() > 0); } /*** * Send remove member message after doing final check for coordinator, ping timeout This test * trying to remove coordinator */ @Test public void testRemoveMemberCalledAfterDoingFinalCheckOnCoordinator() throws Exception { NetView v = new NetView(mockMembers.get(0), 2, mockMembers); // preferred coordinators are 0 and 1 when(messenger.getMemberID()).thenReturn(mockMembers.get(1));// next preferred coordinator gmsHealthMonitor.started(); gmsHealthMonitor.installView(v); Thread.sleep(memberTimeout / GMSHealthMonitor.LOGICAL_INTERVAL); ArrayList<InternalDistributedMember> recipient = new ArrayList<InternalDistributedMember>(); recipient.add(mockMembers.get(0)); recipient.add(mockMembers.get(1)); ArrayList<SuspectRequest> as = new ArrayList<SuspectRequest>(); SuspectRequest sr = new SuspectRequest(mockMembers.get(0), "Not Responding");// removing // coordinator as.add(sr); SuspectMembersMessage sm = new SuspectMembersMessage(recipient, as); sm.setSender(mockMembers.get(myAddressIndex + 1));// member 4 sends suspect message gmsHealthMonitor.processMessage(sm); // this happens after final check, ping timeout = 1000 ms Thread.sleep(memberTimeout + 200); verify(joinLeave, atLeastOnce()).remove(any(InternalDistributedMember.class), any(String.class)); Assert.assertTrue(gmsHealthMonitor.getStats().getSuspectsReceived() > 0); } /*** * validates HealthMonitor.CheckIfAvailable api */ @Test public void testCheckIfAvailableNoHeartBeatDontRemoveMember() { installAView(); long startTime = System.currentTimeMillis(); boolean retVal = gmsHealthMonitor.checkIfAvailable(mockMembers.get(1), "Not responding", true); long timeTaken = System.currentTimeMillis() - startTime; assertFalse("CheckIfAvailable should have return false", retVal); assertTrue("This should have taken member ping timeout 100ms but it took " + timeTaken, timeTaken >= gmsHealthMonitor.memberTimeout); } @Test public void testCheckIfAvailableWithSimulatedHeartBeat() { NetView v = installAView(); InternalDistributedMember memberToCheck = mockMembers.get(1); HeartbeatMessage fakeHeartbeat = new HeartbeatMessage(); fakeHeartbeat.setSender(memberToCheck); when(messenger.send(any(HeartbeatRequestMessage.class))).then(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { gmsHealthMonitor.processMessage(fakeHeartbeat); return null; } }); boolean retVal = gmsHealthMonitor.checkIfAvailable(memberToCheck, "Not responding", true); assertTrue("CheckIfAvailable should have return true", retVal); } @Test public void testCheckIfAvailableWithSimulatedHeartBeatWithTcpCheck() { System.out.println("testCheckIfAvailableWithSimulatedHeartBeatWithTcpCheck"); useGMSHealthMonitorTestClass = true; try { NetView v = installAView(); setFailureDetectionPorts(v); InternalDistributedMember memberToCheck = mockMembers.get(1); boolean retVal = gmsHealthMonitor.checkIfAvailable(memberToCheck, "Not responding", true); assertTrue("CheckIfAvailable should have return true", retVal); } finally { useGMSHealthMonitorTestClass = false; } } @Test public void testShutdown() { installAView(); gmsHealthMonitor.stop(); try { // this happens after final check, membertimeout = 1000 Thread.sleep(100l); } catch (InterruptedException e) { } assertTrue("HeathMonitor should have shutdown", gmsHealthMonitor.isShutdown()); } @Test public void testCreateServerSocket() throws Exception { try (ServerSocket socket = gmsHealthMonitor.createServerSocket(InetAddress.getLocalHost(), portRange)) { Assert.assertTrue( portRange[0] <= socket.getLocalPort() && socket.getLocalPort() <= portRange[1]); } } @Test public void testCreateServerSocketPortRangeInvalid() throws Exception { try (ServerSocket socket = gmsHealthMonitor.createServerSocket(InetAddress.getLocalHost(), new int[] {-1, -1})) { Assert.fail("socket was created with invalid port range"); } catch (IllegalArgumentException e) { } } @Test public void testClientSocketHandler() throws Exception { int viewId = 2; long msb = 3; long lsb = 4; GMSMember otherMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb); GMSMember gmsMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb); executeTestClientSocketHandler(gmsMember, otherMember, GMSHealthMonitor.OK); } @Test public void testClientSocketHandlerWhenMsbDoNotMatch() throws Exception { int viewId = 2; long msb = 3; long lsb = 4; GMSMember otherMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb + 1, lsb); GMSMember gmsMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb); executeTestClientSocketHandler(gmsMember, otherMember, GMSHealthMonitor.ERROR); } @Test public void testClientSocketHandlerWhenLsbDoNotMatch() throws Exception { int viewId = 2; long msb = 3; long lsb = 4; GMSMember otherMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb + 1); GMSMember gmsMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb); executeTestClientSocketHandler(gmsMember, otherMember, GMSHealthMonitor.ERROR); } @Test public void testClientSocketHandlerWhenViewIdDoNotMatch() throws Exception { int viewId = 2; long msb = 3; long lsb = 4; GMSMember otherMember = createGMSMember(Version.CURRENT_ORDINAL, viewId + 1, msb, lsb); GMSMember gmsMember = createGMSMember(Version.CURRENT_ORDINAL, viewId, msb, lsb); executeTestClientSocketHandler(gmsMember, otherMember, GMSHealthMonitor.ERROR); } public void executeTestClientSocketHandler(GMSMember gmsMember, GMSMember otherMember, int expectedResult) throws Exception { // We have already set the view id in the member but when creating the IDM it resets it to -1 // for some reason int viewId = gmsMember.getVmViewId(); InternalDistributedMember testMember = new InternalDistributedMember("localhost", 9000, Version.CURRENT, gmsMember); // We set to our expected test viewId in the IDM as well as reseting the gms member testMember.setVmViewId(viewId); gmsMember.setBirthViewId(viewId); // Set up the incoming/received bytes. We just wrap output streams and write out the gms member // information byte[] receivedBytes = writeMemberToBytes(otherMember); InputStream mockInputStream = new ByteArrayInputStream(receivedBytes); // configure the mock to return the mocked incoming bytes and provide an outputstream that we // will check Socket fakeSocket = mock(Socket.class); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); when(fakeSocket.getInputStream()).thenReturn(mockInputStream); when(fakeSocket.getOutputStream()).thenReturn(outputStream); // run the socket handler gmsHealthMonitor.setLocalAddress(testMember); ClientSocketHandler handler = gmsHealthMonitor.new ClientSocketHandler(fakeSocket); handler.run(); // verify the written bytes are as expected DataInputStream dis = new DataInputStream(new ByteArrayInputStream(outputStream.toByteArray())); int byteReply = dis.read(); Assert.assertEquals(expectedResult, byteReply); Assert.assertTrue(gmsHealthMonitor.getStats().getFinalCheckResponsesSent() > 0); Assert.assertTrue(gmsHealthMonitor.getStats().getTcpFinalCheckResponsesSent() > 0); } @Test public void testBeSickAndPlayDead() throws Exception { NetView v = new NetView(mockMembers.get(0), 2, mockMembers); gmsHealthMonitor.installView(v); gmsHealthMonitor.beSick(); // a sick member will not respond to a heartbeat request HeartbeatRequestMessage req = new HeartbeatRequestMessage(mockMembers.get(0), 10); req.setSender(mockMembers.get(0)); gmsHealthMonitor.processMessage(req); verify(messenger, never()).send(isA(HeartbeatMessage.class)); // a sick member will not record a heartbeat from another member HeartbeatMessage hb = new HeartbeatMessage(-1); hb.setSender(mockMembers.get(0)); gmsHealthMonitor.processMessage(hb); assertTrue(gmsHealthMonitor.memberTimeStamps.get(hb.getSender()) == null); // a sick member will not take action on a Suspect message from another member SuspectMembersMessage smm = mock(SuspectMembersMessage.class); Error err = new AssertionError("expected suspect message to be ignored"); when(smm.getMembers()).thenThrow(err); when(smm.getSender()).thenThrow(err); when(smm.getDSFID()).thenCallRealMethod(); gmsHealthMonitor.processMessage(smm); } @Test public void testDoTCPCheckMemberWithOkStatus() throws Exception { executeTestDoTCPCheck(GMSHealthMonitor.OK, true); } @Test public void testDoTCPCheckMemberWithErrorStatus() throws Exception { executeTestDoTCPCheck(GMSHealthMonitor.ERROR, false); } @Test public void testDoTCPCheckMemberWithUnkownStatus() throws Exception { executeTestDoTCPCheck(GMSHealthMonitor.ERROR + 100, false); } private void executeTestDoTCPCheck(int receivedStatus, boolean expectedResult) throws Exception { InternalDistributedMember otherMember = createInternalDistributedMember(Version.CURRENT_ORDINAL, 0, 1, 1); InternalDistributedMember gmsMember = createInternalDistributedMember(Version.CURRENT_ORDINAL, 0, 1, 1); // Set up the incoming/received bytes. We just wrap output streams and write out the gms member // information ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(receivedStatus); byte[] receivedBytes = baos.toByteArray(); InputStream mockInputStream = new ByteArrayInputStream(receivedBytes); Socket fakeSocket = mock(Socket.class); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); when(fakeSocket.getInputStream()).thenReturn(mockInputStream); when(fakeSocket.getOutputStream()).thenReturn(outputStream); when(fakeSocket.isConnected()).thenReturn(true); Assert.assertEquals(expectedResult, gmsHealthMonitor.doTCPCheckMember(otherMember, fakeSocket)); Assert.assertTrue(gmsHealthMonitor.getStats().getFinalCheckRequestsSent() > 0); Assert.assertTrue(gmsHealthMonitor.getStats().getTcpFinalCheckRequestsSent() > 0); Assert.assertTrue(gmsHealthMonitor.getStats().getFinalCheckResponsesReceived() > 0); Assert.assertTrue(gmsHealthMonitor.getStats().getTcpFinalCheckResponsesReceived() > 0); // we can check to see if the gms member information was written out by the tcp check byte[] bytesWritten = outputStream.toByteArray(); Assert.assertArrayEquals(writeMemberToBytes((GMSMember) gmsMember.getNetMember()), bytesWritten); } private InternalDistributedMember createInternalDistributedMember(short version, int viewId, long msb, long lsb) throws UnknownHostException { GMSMember gmsMember = createGMSMember(version, viewId, msb, lsb); InternalDistributedMember idm = new InternalDistributedMember("localhost", 9000, Version.CURRENT, gmsMember); // We set to our expected test viewId in the IDM as well as reseting the gms member idm.setVmViewId(viewId); gmsMember.setBirthViewId(viewId); return idm; } private GMSMember createGMSMember(short version, int viewId, long msb, long lsb) throws UnknownHostException { GMSMember gmsMember = new GMSMember(); gmsMember.setVersionOrdinal(version); gmsMember.setBirthViewId(viewId); gmsMember.setUUID(new UUID(msb, lsb)); gmsMember.setInetAddr(InetAddress.getLocalHost()); return gmsMember; } private byte[] writeMemberToBytes(GMSMember gmsMember) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dataReceive = new DataOutputStream(baos); gmsHealthMonitor.writeMemberToStream(gmsMember, dataReceive); return baos.toByteArray(); } public class GMSHealthMonitorTest extends GMSHealthMonitor { @Override boolean doTCPCheckMember(InternalDistributedMember suspectMember, int port) { if (useGMSHealthMonitorTestClass) { HeartbeatMessage fakeHeartbeat = new HeartbeatMessage(); fakeHeartbeat.setSender(suspectMember); gmsHealthMonitor.processMessage(fakeHeartbeat); return false; } return super.doTCPCheckMember(suspectMember, port); } } }