/* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.mdsal.singleton.dom.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.Before; import org.junit.Test; import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService; import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; /** * Synchronous test suite. */ public class DOMClusterSingletonServiceProviderImplTest extends AbstractDOMClusterServiceProviderTest { /** * Initialization functionality for every Tests in this suite. * * @throws CandidateAlreadyRegisteredException if the condition does not meet */ @Override @Before public void setup() throws CandidateAlreadyRegisteredException { super.setup(); } /** * Test GoldPath for takeLeadership with ownership result MASTER {@link ClusterSingletonService}. * * @throws Exception if the condition does not meet */ @Test public void takeDoubleLeadershipClusterSingletonServiceTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave()); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEosEntityListReg, never()).close(); verify(mockEntityCandReg, never()).close(); verify(mockDoubleEntityCandReg).close(); } /** * Test checks unexpected change for MASTER-TO-SLAVE double Candidate role change. * * @throws Exception if the condition does not meet */ @Test public void unexpectedLostLeadershipDoubleCandidateTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave()); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToSlave()); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg, never()).close(); verify(mockDoubleEntityCandReg, never()).close(); reg.close(); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg, atLeastOnce()).close(); verify(mockDoubleEntityCandReg).close(); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave()); verify(mockEntityCandReg).close(); verify(mockEosDoubleEntityListReg, never()).close(); } /** * Test checks inJeopardy Cluster Node state for Master Instance. * * @throws Exception if the condition does not meet */ @Test public void inJeopardyMasterTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getInitDoubleEntityToSlave()); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToJeopardy()); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg, never()).close(); verify(mockDoubleEntityCandReg, never()).close(); } /** * Test checks close processing for {@link ClusterSingletonServiceRegistration}. * * @throws Exception if the condition does not meet */ @Test public void closeClusterSingletonServiceRegistrationMasterTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); reg.close(); clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave()); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg).close(); verify(mockDoubleEntityCandReg).close(); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); } /** * Test checks close processing for {@link ClusterSingletonServiceRegistration}. * * @throws Exception if the condition does not meet */ @Test public void closeClusterSingletonServiceRegistrationMasterCloseWithNotificationTimesTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); reg.close(); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg, atLeastOnce()).close(); verify(mockDoubleEntityCandReg).close(); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); } /** * Test checks close processing for {@link ClusterSingletonServiceRegistration}. * * @throws Exception if the condition does not meet */ @Test public void closeClusterSingletonServiceRegistrationMasterCloseCoupleTimesTest() throws Exception { final ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); reg.close(); reg.close(); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg).close(); verify(mockDoubleEntityCandReg).close(); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave()); verify(mockEosDoubleEntityListReg, never()).close(); } /** * Verify that closing a group does not prevent next incarnation of it to be registered and the next incarnation * will become active once the old incarnation finishes cleaning up. */ @Test public void testTwoIncarnations() throws Exception { ClusterSingletonServiceRegistration reg = clusterSingletonServiceProvider .registerClusterSingletonService(clusterSingletonService); assertNotNull(reg); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService.getServiceState()); verify(mockEos).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos).registerCandidate(DOUBLE_ENTITY); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService.getServiceState()); // Close, triggers unregistration, but we will not continue with it. reg.close(); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); verify(mockEntityCandReg).close(); verify(mockDoubleEntityCandReg).close(); assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); // Instantiate the next incarnation reg = clusterSingletonServiceProvider.registerClusterSingletonService(clusterSingletonService2); verify(mockEos).registerCandidate(ENTITY); assertEquals(TestClusterSingletonServiceState.INITIALIZED, clusterSingletonService2.getServiceState()); // Drive the old incarnation to closure, resetting mocks as needed clusterSingletonServiceProvider.ownershipChanged(getEntityToSlave()); verify(mockEosDoubleEntityListReg, never()).close(); // Reset mocks for reuse. The next change should see the previous group terminate and the next incarnation // to start coming up clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToSlave()); verify(mockEos, times(2)).registerCandidate(ENTITY); clusterSingletonServiceProvider.ownershipChanged(getEntityToMaster()); verify(mockEos, times(2)).registerCandidate(DOUBLE_ENTITY); clusterSingletonServiceProvider.ownershipChanged(getDoubleEntityToMaster()); assertEquals(TestClusterSingletonServiceState.STARTED, clusterSingletonService2.getServiceState()); // Check for potential service mixup assertEquals(TestClusterSingletonServiceState.DESTROYED, clusterSingletonService.getServiceState()); verify(mockEosEntityListReg, never()).close(); verify(mockEosDoubleEntityListReg, never()).close(); } }