package io.eguan.vold; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * Licensed 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. * #L% */ import static org.junit.Assert.assertEquals; import io.eguan.vold.Vold; import io.eguan.vold.VoldConfigurationContext; import io.eguan.vold.VoldLocation; import io.eguan.vold.VoldPeers; import io.eguan.vold.VoldPeers.Schedulable; import io.eguan.vold.model.Constants; import io.eguan.vold.model.VvrManagerMXBean; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; public class TestMultiVoldRemovePeersWithQuorum extends TestMultiVoldAbstractPeers { /** * TimerTask to auto stop a instead of exiting after a scheduled delay. * */ static final class VoldSuicideTaskForTest extends TimerTask implements Schedulable { private static final Logger LOGGER = Constants.LOGGER; private static final long SUICIDE_DELAY = 20 * 1000;// 20 second delay private static Timer suicideTimer = new Timer(); private final Vold voldToStop; VoldSuicideTaskForTest(final Vold toStop) { super(); voldToStop = Objects.requireNonNull(toStop, "Vold to stop can't be NULL !!!"); } @Override public final void run() { try { voldToStop.stop(); } catch (final IOException e) { LOGGER.error("Error on vold stop"); } } /** * Schedule auto exit of vold. */ @Override public final void schedule() { suicideTimer.schedule(this, SUICIDE_DELAY); } } static void tweakVoldSuicideTask(final Vold voldToStop) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException { final Field voldPeers = Vold.class.getDeclaredField("voldPeers"); voldPeers.setAccessible(true); final Field suicideTask = VoldPeers.class.getDeclaredField("suicideTask"); suicideTask.setAccessible(true); suicideTask.set(null, new VoldSuicideTaskForTest(voldToStop)); } static boolean isVoldStarted(final Vold voldToStop) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException { final Field voldStarted = Vold.class.getDeclaredField("started"); voldStarted.setAccessible(true); return voldStarted.getBoolean(voldToStop); } @Test public void testConnectTreePeersAndRemove() throws Exception { vold1 = initVold(helper1, server1, voldMxBeanObjectName1); vold2 = initVold(helper2, server2, voldMxBeanObjectName2); vold3 = initVold(helper3, server3, voldMxBeanObjectName3); tweakVoldSuicideTask(vold3); // change peers list to have a quorum with node1 and node2 // node3 is configured with correct peers list to be add it to this quorum final VoldLocation node1 = vold1.getVoldLocation(); final VoldLocation node2 = vold2.getVoldLocation(); final VoldLocation node3 = vold3.getVoldLocation(); final ArrayList<VoldLocation> peers1 = new ArrayList<>(); final ArrayList<VoldLocation> peers2 = new ArrayList<>(); final ArrayList<VoldLocation> peers3 = new ArrayList<>(); peers1.add(node2); peers2.add(node1); peers3.add(node1); peers3.add(node2); changePeersList(vold1, peers1); changePeersList(vold2, peers2); changePeersList(vold3, peers3); // start quorum (node1 and node2) vold1.start(); vold2.start(); Assert.assertTrue((VvrManagerMXBean) server1.waitMXBean(helper1.newVvrManagerObjectName()) != null); Assert.assertTrue((VvrManagerMXBean) server2.waitMXBean(helper2.newVvrManagerObjectName()) != null); // add node3 to quorum (node1 and node2) // randomly choose between node1 and node2 // for adding node3 as it shall be the same if (Math.random() < 0.5) { addPeer(vold1, node3); } else { addPeer(vold2, node3); } final String expectedPeerList1 = node2.toString() + "," + node3.toString(); final String expectedPeerList2 = node1.toString() + "," + node3.toString(); final VoldConfigurationContext voldContext = VoldConfigurationContext.getInstance(); // check node3 was added in list of peers from quorum (node1 and node2) assertEquals(expectedPeerList1, getPeersList(vold1, voldContext)); assertEquals(expectedPeerList2, getPeersList(vold2, voldContext)); vold3.start(); Assert.assertTrue((VvrManagerMXBean) server3.waitMXBean(helper3.newVvrManagerObjectName()) != null); Assert.assertTrue(isVoldStarted(vold3)); removePeer(vold3, node3);// node3 suicide ... vold1.stop(); vold2.stop(); Assert.assertFalse(isVoldStarted(vold3)); for (int i = 0; i < nodeStarted.length; i++) { nodeStarted[i] = false; } } }